[FE] Review fixes
This commit is contained in:
committed by
teamcity
parent
c71ae4301c
commit
e0a1f1c405
@@ -385,10 +385,10 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun KotlinTypeMarker.eraseContainingTypeParameters(): KotlinTypeMarker {
|
override fun KotlinTypeMarker.eraseContainingTypeParameters(): KotlinTypeMarker {
|
||||||
val erasedTypeParameters = this.extractTypeParameters()
|
val typeParameterErasureMap = this.extractTypeParameters()
|
||||||
.map { (it as ConeTypeParameterLookupTag).typeParameterSymbol }
|
.map { (it as ConeTypeParameterLookupTag).typeParameterSymbol }
|
||||||
.eraseToUpperBoundsAssociated(session, intersectUpperBounds = true, eraseRecursively = true)
|
.eraseToUpperBoundsAssociated(session, intersectUpperBounds = true, eraseRecursively = true)
|
||||||
return ConeSubstitutorByMap(erasedTypeParameters, session).safeSubstitute(this)
|
return ConeSubstitutorByMap(typeParameterErasureMap, session).safeSubstitute(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun TypeConstructorMarker.isTypeParameterTypeConstructor(): Boolean {
|
override fun TypeConstructorMarker.isTypeParameterTypeConstructor(): Boolean {
|
||||||
|
|||||||
@@ -580,10 +580,8 @@ internal object CheckLowPriorityInOverloadResolution : CheckerStage() {
|
|||||||
internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionStage() {
|
internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionStage() {
|
||||||
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) =
|
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) =
|
||||||
with(candidate.system.asConstraintSystemCompleterContext()) {
|
with(candidate.system.asConstraintSystemCompleterContext()) {
|
||||||
val typeVariables = candidate.system.notFixedTypeVariables.values.takeIf { it.isNotEmpty() } ?: return
|
for (variableWithConstraints in candidate.system.notFixedTypeVariables.values) {
|
||||||
|
val upperTypes = variableWithConstraints.constraints.extractUpperTypesToCheckIntersectionEmptiness()
|
||||||
for (variableWithConstraints in typeVariables) {
|
|
||||||
val upperTypes = variableWithConstraints.constraints.extractUpperTypes()
|
|
||||||
|
|
||||||
if (upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty()) {
|
if (upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty()) {
|
||||||
sink.yieldDiagnostic(
|
sink.yieldDiagnostic(
|
||||||
|
|||||||
+1
-1
@@ -964,7 +964,7 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(TYPE_INFERENCE_INCORPORATION_ERROR, "Type inference failed. Please try to specify type arguments explicitly.");
|
MAP.put(TYPE_INFERENCE_INCORPORATION_ERROR, "Type inference failed. Please try to specify type arguments explicitly.");
|
||||||
MAP.put(TYPE_INFERENCE_ONLY_INPUT_TYPES, "Type inference failed. The value of the type parameter {0} should be mentioned in input types " +
|
MAP.put(TYPE_INFERENCE_ONLY_INPUT_TYPES, "Type inference failed. The value of the type parameter {0} should be mentioned in input types " +
|
||||||
"(argument types, receiver type or expected type). Try to specify it explicitly.", NAME);
|
"(argument types, receiver type or expected type). Try to specify it explicitly.", NAME);
|
||||||
MAP.put(INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION, "Type argument for a type parameter {0} can''t be inferred because it''s upper bounded by incompatible types: {1}", TO_STRING, RENDER_COLLECTION_OF_TYPES);
|
MAP.put(INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION, "Type argument for a type parameter {0} can''t be inferred because it has incompatible upper bounds: {1}", TO_STRING, RENDER_COLLECTION_OF_TYPES);
|
||||||
MAP.put(TYPE_INFERENCE_UPPER_BOUND_VIOLATED, "{0}", TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER);
|
MAP.put(TYPE_INFERENCE_UPPER_BOUND_VIOLATED, "{0}", TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER);
|
||||||
MAP.put(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH, "Type inference failed. Expected type mismatch: inferred type is {1} but {0} was expected", RENDER_TYPE, RENDER_TYPE);
|
MAP.put(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH, "Type inference failed. Expected type mismatch: inferred type is {1} but {0} was expected", RENDER_TYPE, RENDER_TYPE);
|
||||||
MAP.put(TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG, "Please use spread operator to pass an array as vararg. It will be an error in 1.5.");
|
MAP.put(TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG, "Please use spread operator to pass an array as vararg. It will be an error in 1.5.");
|
||||||
|
|||||||
+1
-1
@@ -107,7 +107,7 @@ abstract class ConstraintSystemCompletionContext : VariableFixationFinder.Contex
|
|||||||
postponedArguments: List<T>
|
postponedArguments: List<T>
|
||||||
) = postponedArguments.firstOrNull { argument -> argument.inputTypes.all { containsOnlyFixedVariables(it) } }
|
) = postponedArguments.firstOrNull { argument -> argument.inputTypes.all { containsOnlyFixedVariables(it) } }
|
||||||
|
|
||||||
fun List<Constraint>.extractUpperTypes(): List<KotlinTypeMarker> =
|
fun List<Constraint>.extractUpperTypesToCheckIntersectionEmptiness(): List<KotlinTypeMarker> =
|
||||||
filter { constraint ->
|
filter { constraint ->
|
||||||
constraint.kind == ConstraintKind.UPPER && !constraint.type.contains {
|
constraint.kind == ConstraintKind.UPPER && !constraint.type.contains {
|
||||||
!it.typeConstructor().isClassTypeConstructor() && !it.typeConstructor().isTypeParameterTypeConstructor()
|
!it.typeConstructor().isClassTypeConstructor() && !it.typeConstructor().isTypeParameterTypeConstructor()
|
||||||
|
|||||||
+2
-2
@@ -113,7 +113,7 @@ class NewConstraintWarning(
|
|||||||
override val lowerType: KotlinTypeMarker,
|
override val lowerType: KotlinTypeMarker,
|
||||||
override val upperType: KotlinTypeMarker,
|
override val upperType: KotlinTypeMarker,
|
||||||
override val position: IncorporationConstraintPosition,
|
override val position: IncorporationConstraintPosition,
|
||||||
) : ConstraintSystemError(RESOLVED_WITH_WARNING), NewConstraintMismatch
|
) : ConstraintSystemError(RESOLVED), NewConstraintMismatch
|
||||||
|
|
||||||
class CapturedTypeFromSubtyping(
|
class CapturedTypeFromSubtyping(
|
||||||
val typeVariable: TypeVariableMarker,
|
val typeVariable: TypeVariableMarker,
|
||||||
@@ -143,7 +143,7 @@ sealed interface InferredEmptyIntersection {
|
|||||||
class InferredEmptyIntersectionWarning(
|
class InferredEmptyIntersectionWarning(
|
||||||
override val incompatibleTypes: Collection<KotlinTypeMarker>,
|
override val incompatibleTypes: Collection<KotlinTypeMarker>,
|
||||||
override val typeVariable: TypeVariableMarker
|
override val typeVariable: TypeVariableMarker
|
||||||
) : ConstraintSystemError(RESOLVED_WITH_WARNING), InferredEmptyIntersection
|
) : ConstraintSystemError(RESOLVED), InferredEmptyIntersection
|
||||||
|
|
||||||
class InferredEmptyIntersectionError(
|
class InferredEmptyIntersectionError(
|
||||||
override val incompatibleTypes: Collection<KotlinTypeMarker>,
|
override val incompatibleTypes: Collection<KotlinTypeMarker>,
|
||||||
|
|||||||
-1
@@ -29,7 +29,6 @@ enum class CandidateApplicability {
|
|||||||
PROPERTY_AS_OPERATOR, // using property of functional type as an operator. From resolution perspective, this is considered successful.
|
PROPERTY_AS_OPERATOR, // using property of functional type as an operator. From resolution perspective, this is considered successful.
|
||||||
RESOLVED_NEED_PRESERVE_COMPATIBILITY, // call resolved successfully, but using new features that changes resolve
|
RESOLVED_NEED_PRESERVE_COMPATIBILITY, // call resolved successfully, but using new features that changes resolve
|
||||||
RESOLVED_WITH_ERROR, // call has error, but it is still successful from resolution perspective
|
RESOLVED_WITH_ERROR, // call has error, but it is still successful from resolution perspective
|
||||||
RESOLVED_WITH_WARNING, // generally call is successful, but there are additional resolution warnings (e.g. for deprecation something)
|
|
||||||
RESOLVED, // call success or has uncompleted inference or in other words possible successful candidate
|
RESOLVED, // call success or has uncompleted inference or in other words possible successful candidate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-5
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.types.error.ErrorUtils
|
|||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
import org.jetbrains.kotlin.types.typeUtil.*
|
import org.jetbrains.kotlin.types.typeUtil.*
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.compactIfPossible
|
import org.jetbrains.kotlin.utils.addToStdlib.compactIfPossible
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
@@ -882,10 +881,8 @@ internal object CheckContextReceiversResolutionPart : ResolutionPart() {
|
|||||||
|
|
||||||
internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionPart() {
|
internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionPart() {
|
||||||
override fun ResolutionCandidate.process(workIndex: Int) = with(getSystem().asConstraintSystemCompleterContext()) {
|
override fun ResolutionCandidate.process(workIndex: Int) = with(getSystem().asConstraintSystemCompleterContext()) {
|
||||||
val typeVariables = getSystem().getBuilder().currentStorage().notFixedTypeVariables.values.takeIf { it.isNotEmpty() } ?: return
|
for (variableWithConstraints in getSystem().getBuilder().currentStorage().notFixedTypeVariables.values) {
|
||||||
|
val upperTypes = variableWithConstraints.constraints.extractUpperTypesToCheckIntersectionEmptiness()
|
||||||
for (variableWithConstraints in typeVariables) {
|
|
||||||
val upperTypes = variableWithConstraints.constraints.extractUpperTypes()
|
|
||||||
|
|
||||||
if (upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty()) {
|
if (upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty()) {
|
||||||
val isInferredEmptyIntersectionForbidden =
|
val isInferredEmptyIntersectionForbidden =
|
||||||
|
|||||||
+1
-1
@@ -7,6 +7,6 @@ fun <V> genericIn(x: In<V>) {}
|
|||||||
/selectFromCovariantAndContravariantTypes.kt:13:20: warning: parameter 'x' is never used
|
/selectFromCovariantAndContravariantTypes.kt:13:20: warning: parameter 'x' is never used
|
||||||
fun <V> genericOut(x: Out<V>) {}
|
fun <V> genericOut(x: Out<V>) {}
|
||||||
^
|
^
|
||||||
/selectFromCovariantAndContravariantTypes.kt:16:5: warning: type argument for a type parameter V can't be inferred because it's upper bounded by incompatible types: A, B. This will become an error in Kotlin 1.9
|
/selectFromCovariantAndContravariantTypes.kt:16:5: warning: type argument for a type parameter V can't be inferred because it has incompatible upper bounds: A, B. This will become an error in Kotlin 1.9
|
||||||
genericIn(select(a, b))
|
genericIn(select(a, b))
|
||||||
^
|
^
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/kt45461.kt:5:25: warning: parameter 'foo' is never used
|
/kt45461.kt:5:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/kt45461.kt:10:19: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: String, Int. This will become an error in Kotlin 1.9
|
/kt45461.kt:10:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, Int. This will become an error in Kotlin 1.9
|
||||||
Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/kt45461_12.kt:5:25: warning: parameter 'foo' is never used
|
/kt45461_12.kt:5:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/kt45461_12.kt:12:19: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: String, K. This will become an error in Kotlin 1.8
|
/kt45461_12.kt:12:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, K. This will become an error in Kotlin 1.9
|
||||||
Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/kt45461_15.kt:5:25: warning: parameter 'foo' is never used
|
/kt45461_15.kt:5:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/kt45461_15.kt:14:21: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: Inv<Int>, K. This will become an error in Kotlin 1.9
|
/kt45461_15.kt:14:21: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv<Int>, K. This will become an error in Kotlin 1.9
|
||||||
Bar<Inv<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<Inv<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/kt45461_19.kt:5:25: warning: parameter 'foo' is never used
|
/kt45461_19.kt:5:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/kt45461_19.kt:13:26: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: Out<Inv<Int>>, K. This will become an error in Kotlin 1.9
|
/kt45461_19.kt:13:26: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Out<Inv<Int>>, K. This will become an error in Kotlin 1.9
|
||||||
Bar<Out<Inv<Int>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<Out<Inv<Int>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
/kt45461_2.kt:8:10: warning: 'Int' is a final type, and thus a value of the type parameter is predetermined
|
/kt45461_2.kt:8:10: warning: 'Int' is a final type, and thus a value of the type parameter is predetermined
|
||||||
fun <K : Int> main() {
|
fun <K : Int> main() {
|
||||||
^
|
^
|
||||||
/kt45461_2.kt:10:19: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: String, K. This will become an error in Kotlin 1.9
|
/kt45461_2.kt:10:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, K. This will become an error in Kotlin 1.9
|
||||||
Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/kt45461_21.kt:5:25: warning: parameter 'foo' is never used
|
/kt45461_21.kt:5:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/kt45461_21.kt:13:25: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: In<Inv<Int>>, K. This will become an error in Kotlin 1.9
|
/kt45461_21.kt:13:25: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: In<Inv<Int>>, K. This will become an error in Kotlin 1.9
|
||||||
Bar<In<Inv<Int>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<In<Inv<Int>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
@@ -4,6 +4,6 @@
|
|||||||
/kt45461_24.kt:10:10: warning: 'Inv<out Inv<out Int>>' is a final type, and thus a value of the type parameter is predetermined
|
/kt45461_24.kt:10:10: warning: 'Inv<out Inv<out Int>>' is a final type, and thus a value of the type parameter is predetermined
|
||||||
fun <K : Inv<out Inv<out Int>>> main() {
|
fun <K : Inv<out Inv<out Int>>> main() {
|
||||||
^
|
^
|
||||||
/kt45461_24.kt:12:35: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: Inv<in Inv<in Number>>, K. This will become an error in Kotlin 1.9
|
/kt45461_24.kt:12:35: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv<in Inv<in Number>>, K. This will become an error in Kotlin 1.9
|
||||||
Bar<Inv<in Inv<in Number>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<Inv<in Inv<in Number>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
/kt45461_25.kt:11:34: error: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: String, K, Float
|
/kt45461_25.kt:11:34: error: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, K, Float
|
||||||
val x: Float = Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
val x: Float = Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/kt45461_26.kt:13:44: error: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: Out<String>, K, Out<Float>
|
/kt45461_26.kt:13:44: error: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Out<String>, K, Out<Float>
|
||||||
val x: Out<Float> = Bar<Out<String>>().takeFoo(foo)
|
val x: Out<Float> = Bar<Out<String>>().takeFoo(foo)
|
||||||
^
|
^
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/kt45461_5.kt:5:25: warning: parameter 'foo' is never used
|
/kt45461_5.kt:5:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/kt45461_5.kt:10:19: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: String, K. This will become an error in Kotlin 1.9
|
/kt45461_5.kt:10:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, K. This will become an error in Kotlin 1.9
|
||||||
Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
@@ -4,6 +4,6 @@
|
|||||||
/kt45461_8.kt:10:28: warning: 'Int' is a final type, and thus a value of the type parameter is predetermined
|
/kt45461_8.kt:10:28: warning: 'Int' is a final type, and thus a value of the type parameter is predetermined
|
||||||
fun <K : Inv<L>, L : N, N: Int> main() {
|
fun <K : Inv<L>, L : N, N: Int> main() {
|
||||||
^
|
^
|
||||||
/kt45461_8.kt:12:24: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: Inv<Number>, K. This will become an error in Kotlin 1.9
|
/kt45461_8.kt:12:24: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv<Number>, K. This will become an error in Kotlin 1.9
|
||||||
Bar<Inv<Number>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<Inv<Number>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/kt45461_9.kt:5:25: warning: parameter 'foo' is never used
|
/kt45461_9.kt:5:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/kt45461_9.kt:12:21: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: Inv<Int>, Inv<Number>. This will become an error in Kotlin 1.9
|
/kt45461_9.kt:12:21: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv<Int>, Inv<Number>. This will become an error in Kotlin 1.9
|
||||||
Bar<Inv<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<Inv<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
/kt48765.kt:4:52: warning: parameter 'x2' is never used
|
/kt48765.kt:4:52: warning: parameter 'x2' is never used
|
||||||
fun <T1: Number, T2: A<Float, T1>> foo(x1: T2, x2: T1) {}
|
fun <T1: Number, T2: A<Float, T1>> foo(x1: T2, x2: T1) {}
|
||||||
^
|
^
|
||||||
/kt48765.kt:8:13: warning: type argument for a type parameter T can't be inferred because it's upper bounded by incompatible types: String, Number. This will become an error in Kotlin 1.9
|
/kt48765.kt:8:13: warning: type argument for a type parameter T can't be inferred because it has incompatible upper bounds: String, Number. This will become an error in Kotlin 1.9
|
||||||
B().foo(x, foo())
|
B().foo(x, foo())
|
||||||
^
|
^
|
||||||
/kt48765.kt:12:9: warning: 'String' is a final type, and thus a value of the type parameter is predetermined
|
/kt48765.kt:12:9: warning: 'String' is a final type, and thus a value of the type parameter is predetermined
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/kt49661.kt:10:5: warning: type argument for a type parameter T can't be inferred because it's upper bounded by incompatible types: Foo, Int. This will become an error in Kotlin 1.9
|
/kt49661.kt:10:5: warning: type argument for a type parameter T can't be inferred because it has incompatible upper bounds: Foo, Int. This will become an error in Kotlin 1.9
|
||||||
f<Int> { g() }
|
f<Int> { g() }
|
||||||
^
|
^
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.types
|
package org.jetbrains.kotlin.types
|
||||||
|
|
||||||
enum class EmptyIntersectionTypeKind { NOT_EMPTY_INTERSECTION, MULTIPLE_CLASSES, SINGLE_FINAL_CLASS }
|
enum class EmptyIntersectionTypeKind { NOT_EMPTY_INTERSECTION, MULTIPLE_CLASSES } // TODO: add `SINGLE_FINAL_CLASS` later
|
||||||
|
|
||||||
fun EmptyIntersectionTypeKind.isDefinitelyEmpty(): Boolean = this == EmptyIntersectionTypeKind.MULTIPLE_CLASSES
|
fun EmptyIntersectionTypeKind.isDefinitelyEmpty(): Boolean = this == EmptyIntersectionTypeKind.MULTIPLE_CLASSES
|
||||||
|
|
||||||
fun EmptyIntersectionTypeKind.isPossibleEmpty(): Boolean = this == EmptyIntersectionTypeKind.SINGLE_FINAL_CLASS
|
|
||||||
|
|||||||
@@ -321,52 +321,47 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
if (this.isEmpty())
|
if (this.isEmpty())
|
||||||
return EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION
|
return EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION
|
||||||
|
|
||||||
val types = this.withIndex()
|
val types = this.toList()
|
||||||
|
|
||||||
for ((i, firstType) in types) {
|
for (i in 0 until types.size) {
|
||||||
if (!firstType.typeConstructor().mayCauseEmptyIntersection())
|
val firstType = types[i]
|
||||||
continue
|
if (!firstType.typeConstructor().mayCauseEmptyIntersection()) continue
|
||||||
|
|
||||||
val doesFirstTypeContainTypeParameters by lazy { firstType.contains { it.typeConstructor().isTypeParameterTypeConstructor() } }
|
|
||||||
val firstSubstitutedType by lazy { firstType.eraseContainingTypeParameters() }
|
val firstSubstitutedType by lazy { firstType.eraseContainingTypeParameters() }
|
||||||
|
|
||||||
for ((j, secondType) in types) {
|
for (j in i + 1 until types.size) {
|
||||||
if (i >= j || !secondType.typeConstructor().mayCauseEmptyIntersection()) continue
|
val secondType = types[j]
|
||||||
|
if (!secondType.typeConstructor().mayCauseEmptyIntersection()) continue
|
||||||
|
|
||||||
val doesSecondTypeContainTypeParameters = secondType.contains { it.typeConstructor().isTypeParameterTypeConstructor() }
|
val secondSubstitutedType = secondType.eraseContainingTypeParameters()
|
||||||
val secondSubstitutedType by lazy { secondType.eraseContainingTypeParameters() }
|
|
||||||
val anyContainingTypeParameter = doesFirstTypeContainTypeParameters || doesSecondTypeContainTypeParameters
|
|
||||||
|
|
||||||
when {
|
if (!canHaveCommonSubtype(firstSubstitutedType, secondSubstitutedType))
|
||||||
!anyContainingTypeParameter && !canHaveSubtype(listOf(firstType, secondType)) ->
|
return EmptyIntersectionTypeKind.MULTIPLE_CLASSES
|
||||||
return EmptyIntersectionTypeKind.MULTIPLE_CLASSES
|
|
||||||
anyContainingTypeParameter && !canHaveSubtype(listOf(firstSubstitutedType, secondSubstitutedType)) ->
|
|
||||||
return EmptyIntersectionTypeKind.MULTIPLE_CLASSES
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION
|
return EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun canHaveSubtype(types: List<KotlinTypeMarker>): Boolean {
|
private fun canHaveCommonSubtype(first: KotlinTypeMarker, second: KotlinTypeMarker): Boolean {
|
||||||
val expandedTypes = types.map {
|
fun extractIntersectionComponentsIfNeeded(type: KotlinTypeMarker) =
|
||||||
if (it.typeConstructor() is IntersectionTypeConstructorMarker) {
|
if (type.typeConstructor() is IntersectionTypeConstructorMarker) {
|
||||||
it.typeConstructor().supertypes().toList()
|
type.typeConstructor().supertypes().toList()
|
||||||
} else listOf(it)
|
} else listOf(type)
|
||||||
}.flatten().withIndex()
|
|
||||||
|
val expandedTypes = extractIntersectionComponentsIfNeeded(first) + extractIntersectionComponentsIfNeeded(second)
|
||||||
|
|
||||||
val typeCheckerState = newTypeCheckerState(errorTypesEqualToAnything = true, stubTypesEqualToAnything = true)
|
val typeCheckerState = newTypeCheckerState(errorTypesEqualToAnything = true, stubTypesEqualToAnything = true)
|
||||||
|
|
||||||
for ((i, firstType) in expandedTypes) {
|
for (i in 0 until expandedTypes.size) {
|
||||||
|
val firstType = expandedTypes[i]
|
||||||
val firstTypeConstructor = firstType.typeConstructor()
|
val firstTypeConstructor = firstType.typeConstructor()
|
||||||
|
|
||||||
if (!firstTypeConstructor.mayCauseEmptyIntersection())
|
if (!firstTypeConstructor.mayCauseEmptyIntersection())
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for ((j, secondType) in expandedTypes) {
|
for (j in i + 1 until expandedTypes.size) {
|
||||||
if (i >= j) continue
|
val secondType = expandedTypes[j]
|
||||||
|
|
||||||
val secondTypeConstructor = secondType.typeConstructor()
|
val secondTypeConstructor = secondType.typeConstructor()
|
||||||
|
|
||||||
if (!secondTypeConstructor.mayCauseEmptyIntersection())
|
if (!secondTypeConstructor.mayCauseEmptyIntersection())
|
||||||
@@ -375,14 +370,12 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
if (areEqualTypeConstructors(firstTypeConstructor, secondTypeConstructor) && secondTypeConstructor.parametersCount() == 0)
|
if (areEqualTypeConstructors(firstTypeConstructor, secondTypeConstructor) && secondTypeConstructor.parametersCount() == 0)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
// Below is determining having subtypes for two classes
|
|
||||||
// A class type may have only one supertype of class-based type constructor
|
|
||||||
val superTypeByFirstConstructor = AbstractTypeChecker.findCorrespondingSupertypes(
|
val superTypeByFirstConstructor = AbstractTypeChecker.findCorrespondingSupertypes(
|
||||||
typeCheckerState, firstType.lowerBoundIfFlexible(), secondTypeConstructor
|
typeCheckerState, firstType.lowerBoundIfFlexible(), secondTypeConstructor
|
||||||
).takeIf { it.isNotEmpty() }?.single()
|
).singleOrNull()
|
||||||
val superTypeBySecondConstructor = AbstractTypeChecker.findCorrespondingSupertypes(
|
val superTypeBySecondConstructor = AbstractTypeChecker.findCorrespondingSupertypes(
|
||||||
typeCheckerState, secondType.lowerBoundIfFlexible(), firstTypeConstructor
|
typeCheckerState, secondType.lowerBoundIfFlexible(), firstTypeConstructor
|
||||||
).takeIf { it.isNotEmpty() }?.single()
|
).singleOrNull()
|
||||||
|
|
||||||
if (superTypeByFirstConstructor == null && superTypeBySecondConstructor == null)
|
if (superTypeByFirstConstructor == null && superTypeBySecondConstructor == null)
|
||||||
return false
|
return false
|
||||||
@@ -390,7 +383,7 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
if (superTypeByFirstConstructor == null || superTypeBySecondConstructor == null)
|
if (superTypeByFirstConstructor == null || superTypeBySecondConstructor == null)
|
||||||
continue // first or second is actually subtype of another
|
continue // first or second is actually subtype of another
|
||||||
|
|
||||||
if (!areTypeArgumentsCompatibleToHaveSubtypes(superTypeByFirstConstructor, superTypeBySecondConstructor)) {
|
if (!checkArgumentsOfTypesToBeAbleToHaveCommonSubtype(superTypeByFirstConstructor, superTypeBySecondConstructor)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -417,20 +410,20 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
variance1: TypeVariance,
|
variance1: TypeVariance,
|
||||||
variance2: TypeVariance,
|
variance2: TypeVariance,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val argumentOfFirst = firstType.getArgument(argumentIndex).uncaptureIfNeeded()
|
fun getEffectiveVariance(type: KotlinTypeMarker): TypeVariance? {
|
||||||
val parameterOfFirst = firstType.typeConstructor().getParameter(argumentIndex)
|
val argument = type.getArgument(argumentIndex).uncaptureIfNeeded()
|
||||||
|
val parameter = type.typeConstructor().getParameter(argumentIndex)
|
||||||
|
return AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance())
|
||||||
|
}
|
||||||
|
|
||||||
val argumentOfSecond = secondType.getArgument(argumentIndex).uncaptureIfNeeded()
|
val effectiveVariance1 = getEffectiveVariance(firstType)
|
||||||
val parameterOfSecond = secondType.typeConstructor().getParameter(argumentIndex)
|
val effectiveVariance2 = getEffectiveVariance(secondType)
|
||||||
|
|
||||||
val effectiveVariance1 = AbstractTypeChecker.effectiveVariance(parameterOfFirst.getVariance(), argumentOfFirst.getVariance())
|
|
||||||
val effectiveVariance2 = AbstractTypeChecker.effectiveVariance(parameterOfSecond.getVariance(), argumentOfSecond.getVariance())
|
|
||||||
|
|
||||||
return (effectiveVariance1 == variance1 && effectiveVariance2 == variance2)
|
return (effectiveVariance1 == variance1 && effectiveVariance2 == variance2)
|
||||||
|| (effectiveVariance1 == variance2 && effectiveVariance2 == variance1)
|
|| (effectiveVariance1 == variance2 && effectiveVariance2 == variance1)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun areTypeArgumentsCompatibleToHaveSubtypes(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker): Boolean {
|
private fun checkArgumentsOfTypesToBeAbleToHaveCommonSubtype(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker): Boolean {
|
||||||
require(firstType.typeConstructor() == secondType.typeConstructor()) {
|
require(firstType.typeConstructor() == secondType.typeConstructor()) {
|
||||||
"Type constructors of the passed types should be the same to compare their arguments"
|
"Type constructors of the passed types should be the same to compare their arguments"
|
||||||
}
|
}
|
||||||
@@ -467,13 +460,13 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
if (!isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond)) {
|
if (!isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
} else if (!canHaveSubtype(listOf(argumentTypeOfFirst, argumentTypeOfSecond))) {
|
} else if (!canHaveCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.OUT, TypeVariance.OUT)
|
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.OUT, TypeVariance.OUT)
|
||||||
|| areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.IN, TypeVariance.IN) -> {
|
|| areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.IN, TypeVariance.IN) -> {
|
||||||
if (!canHaveSubtype(listOf(argumentTypeOfFirst, argumentTypeOfSecond))) {
|
if (!canHaveCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user