Fix compatibility of CapturedTypeConstructor and NewCapturedTypeConstructor

Now both of those classes implements one interface with `TypeProjection`
  property. That allows old captured type approximator use new captured types.

That change fixes tests related to diagnostics:
- SETTER_PROJECTED_OUT
- DEBUG_INFO_UNRESOLVED_WITH_TARGET
- UNRESOLVED_REFERENCE_WRONG_RECEIVER

Also `typeProjection` property renamed to `projection` according to naming in NI.
This commit is contained in:
Dmitriy Novozhilov
2019-01-21 14:53:26 +03:00
parent 42b333f6fd
commit 21f0557502
15 changed files with 53 additions and 48 deletions
@@ -489,7 +489,7 @@ object Renderers {
val typeParameter = typeVariableWithCapturedConstraint.originalTypeParameter
val upperBound = TypeIntersector.getUpperBoundsAsType(typeParameter)
assert(!KotlinBuiltIns.isNullableAny(upperBound) && capturedTypeConstructor.typeProjection.projectionKind == Variance.IN_VARIANCE) {
assert(!KotlinBuiltIns.isNullableAny(upperBound) && capturedTypeConstructor.projection.projectionKind == Variance.IN_VARIANCE) {
"There is the only reason to report TYPE_INFERENCE_CANNOT_CAPTURE_TYPES"
}
@@ -504,7 +504,7 @@ object Renderers {
newText().normal(
typeParameter.name.wrapIntoQuotes() +
" cannot capture " +
"${capturedTypeConstructor.typeProjection.toString().wrapIntoQuotes()}. " +
"${capturedTypeConstructor.projection.toString().wrapIntoQuotes()}. " +
explanation
)
)
@@ -5,5 +5,5 @@ interface A<T : A<T?>?> {
fun foo(): T?
}
fun testA(a: A<*>) {
a.foo() checkType { <!NI;DEBUG_INFO_UNRESOLVED_WITH_TARGET, NI;UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><A<*>?>() }
a.foo() checkType { _<A<*>?>() }
}
@@ -14,14 +14,14 @@ class A<E> {
fun test(a: A<out CharSequence>, z: Out<CharSequence>) {
a.foo {
val x: String = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!> // Should be no TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS
<!NI;TYPE_MISMATCH, TYPE_MISMATCH!>""<!>
<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, TYPE_MISMATCH!>""<!>
}
a.bar { <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, TYPE_MISMATCH!>Out<CharSequence>()<!> }
a.bar { Out() }
a.bar { <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, TYPE_MISMATCH!>z.<!NI;TYPE_MISMATCH!>id()<!><!> }
a.foo {
z.foobar(if (1 > 2) return@foo <!TYPE_MISMATCH!>""<!> else "")
<!NI;TYPE_MISMATCH, TYPE_MISMATCH!>""<!>
z.foobar(if (1 > 2) return@foo <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, TYPE_MISMATCH!>""<!> else "")
<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, TYPE_MISMATCH!>""<!>
}
}
@@ -13,15 +13,15 @@ class A<T> {
}
fun foo2(a: A<out CharSequence>, b: A<in CharSequence>) {
a.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo1<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Out<CharSequence>()<!>)
a.foo1<<!UPPER_BOUND_VIOLATED!>Out<CharSequence><!>>(Out())
a.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo1<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Out<CharSequence>()<!>)
a.foo1<<!UPPER_BOUND_VIOLATED!>Out<CharSequence><!>>(<!NI;TYPE_MISMATCH!>Out()<!>)
a.foo1(Out())
a.foo1(Out<Nothing>())
a.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>foo2<!>(<!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Inv<!>())
a.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<CharSequence>()<!>)
a.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv()<!>)
a.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>foo2<!>(<!NI;TYPE_MISMATCH!><!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Inv<!>()<!>)
a.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<CharSequence>()<!>)
a.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(<!NI;TYPE_MISMATCH!>Inv()<!>)
a.foo3(In())
a.foo3(In<CharSequence>())
@@ -31,13 +31,13 @@ fun foo2(a: A<out CharSequence>, b: A<in CharSequence>) {
b.foo1(Out<CharSequence>())
b.foo1<Out<CharSequence>>(Out())
b.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>foo2<!>(<!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Inv<!>())
b.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<CharSequence>()<!>)
b.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv()<!>)
b.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>foo2<!>(<!NI;TYPE_MISMATCH!><!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Inv<!>()<!>)
b.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<CharSequence>()<!>)
b.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(<!NI;TYPE_MISMATCH!>Inv()<!>)
b.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo3<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>In<CharSequence>()<!>)
b.foo3<<!UPPER_BOUND_VIOLATED!>In<CharSequence><!>>(In())
b.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo3<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>In<CharSequence>()<!>)
b.foo3<<!UPPER_BOUND_VIOLATED!>In<CharSequence><!>>(<!NI;TYPE_MISMATCH!>In()<!>)
b.foo3(In<Any?>())
b.foo3(In())
@@ -13,9 +13,9 @@ class Inv2<<!FINITE_BOUNDS_VIOLATION!>T : Inv2<in T><!>>(val x: T)
fun main(a: A<*>, j: JavaClass<*>, i2: Inv2<*>) {
// Probably it's too restrictive to suppose star projection type here as Any?,
// but looks like we can refine it later
a.foo() checkType { <!NI;DEBUG_INFO_UNRESOLVED_WITH_TARGET, NI;UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Any?>() }
j.foo() checkType { <!NI;DEBUG_INFO_UNRESOLVED_WITH_TARGET, NI;UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Any?>() }
i2.x checkType { <!NI;DEBUG_INFO_UNRESOLVED_WITH_TARGET, NI;UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Any?>() }
a.foo() checkType { _<Any?>() }
j.foo() checkType { _<Any?>() }
i2.x checkType { _<Any?>() }
j.bar(<!NI;CONSTANT_EXPECTED_TYPE_MISMATCH, OI;CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>, <!NI;CONSTANT_EXPECTED_TYPE_MISMATCH, OI;CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!>, <!NI;TYPE_MISMATCH, OI;TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>Any()<!>)
j.bar(null)
@@ -5,6 +5,6 @@ interface Tr<T> {
}
fun test(t: Tr<*>) {
<!OI;SETTER_PROJECTED_OUT!>t.v<!> = t
<!SETTER_PROJECTED_OUT!>t.v<!> = <!NI;TYPE_MISMATCH!>t<!>
t.v checkType { _<Tr<*>>() }
}
@@ -8,7 +8,7 @@ interface Tr<T> {
fun test(t: Tr<*>) {
t.v = null!!
<!OI;SETTER_PROJECTED_OUT!>t.v<!> = ""
<!OI;SETTER_PROJECTED_OUT!>t.v<!> = null
<!SETTER_PROJECTED_OUT!>t.v<!> = ""
<!SETTER_PROJECTED_OUT!>t.v<!> = null
t.v checkType { _<Any?>() }
}
@@ -7,5 +7,5 @@ interface Tr<T> {
fun test(t: Tr<out String>) {
// resolved as t.v = t.v + null!!, where type of right operand is String,
// so TYPE_MISMATCH: String is not <: of Captured(out String)
<!OI;SETTER_PROJECTED_OUT!>t.v<!> += null!!
<!SETTER_PROJECTED_OUT!>t.v<!> += null!!
}
+1 -1
View File
@@ -14,5 +14,5 @@ class Owner<in T> {
fun getT() = u
}
<!NI;TYPE_VARIANCE_CONFLICT!>fun foo(arg: Inner<*>)<!> = arg.getT()
fun foo(arg: Inner<*>) = arg.getT()
}
+2 -2
View File
@@ -3,7 +3,7 @@ package
public final class Owner</*0*/ in T> {
public constructor Owner</*0*/ in T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun foo(/*0*/ arg: Owner<T>.Inner<*>): T
public final fun foo(/*0*/ arg: Owner<T>.Inner<*>): kotlin.Any?
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
@@ -26,7 +26,7 @@ public interface Rec</*0*/ T : Rec<T>> {
public interface Super</*0*/ out U> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun foo(/*0*/ p: Rec<*>): Rec<out Rec<out Rec<out Rec<out Rec<out kotlin.Any?>>>>>
public open fun foo(/*0*/ p: Rec<*>): Rec<*>
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -17,9 +17,9 @@ interface B<R, T: B<List<R>, <!UPPER_BOUND_VIOLATED!>T<!>>> {
}
fun testB(b: B<*, *>) {
<!OI;TYPE_MISMATCH!>b<!>.r().checkType { _<Any?>() }
<!OI;TYPE_MISMATCH!>b<!>.t().checkType { <!NI;DEBUG_INFO_UNRESOLVED_WITH_TARGET, NI;UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><B<List<*>, *>>() }
<!OI;TYPE_MISMATCH!>b<!>.<!NI;DEBUG_INFO_UNRESOLVED_WITH_TARGET, NI;UNRESOLVED_REFERENCE_WRONG_RECEIVER!>r<!>().<!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>checkType<!> { <!NI;UNRESOLVED_REFERENCE!>_<!><Any?>() }
<!OI;TYPE_MISMATCH!>b<!>.<!NI;DEBUG_INFO_UNRESOLVED_WITH_TARGET, NI;UNRESOLVED_REFERENCE_WRONG_RECEIVER!>t<!>().<!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>checkType<!> { <!NI;UNRESOLVED_REFERENCE!>_<!><B<List<*>, *>>() }
<!OI;TYPE_MISMATCH!><!OI;TYPE_MISMATCH!>b<!>.t()<!>.r().size
<!OI;TYPE_MISMATCH!><!OI;TYPE_MISMATCH!>b<!>.<!NI;DEBUG_INFO_UNRESOLVED_WITH_TARGET, NI;UNRESOLVED_REFERENCE_WRONG_RECEIVER!>t<!>()<!>.<!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>r<!>().<!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>size<!>
}
@@ -27,22 +27,26 @@ import org.jetbrains.kotlin.types.Variance.OUT_VARIANCE
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
import org.jetbrains.kotlin.types.typeUtil.builtIns
class CapturedTypeConstructor(
val typeProjection: TypeProjection
) : TypeConstructor {
interface CapturedTypeConstructor : TypeConstructor {
val projection: TypeProjection
}
class CapturedTypeConstructorImpl(
override val projection: TypeProjection
) : CapturedTypeConstructor {
var newTypeConstructor: NewCapturedTypeConstructor? = null
init {
assert(typeProjection.projectionKind != Variance.INVARIANT) {
"Only nontrivial projections can be captured, not: $typeProjection"
assert(projection.projectionKind != Variance.INVARIANT) {
"Only nontrivial projections can be captured, not: $projection"
}
}
override fun getParameters(): List<TypeParameterDescriptor> = listOf()
override fun getSupertypes(): Collection<KotlinType> {
val superType = if (typeProjection.projectionKind == Variance.OUT_VARIANCE)
typeProjection.type
val superType = if (projection.projectionKind == Variance.OUT_VARIANCE)
projection.type
else
builtIns.nullableAnyType
return listOf(superType)
@@ -54,14 +58,14 @@ class CapturedTypeConstructor(
override fun getDeclarationDescriptor() = null
override fun toString() = "CapturedTypeConstructor($typeProjection)"
override fun toString() = "CapturedTypeConstructor($projection)"
override fun getBuiltIns(): KotlinBuiltIns = typeProjection.type.constructor.builtIns
override fun getBuiltIns(): KotlinBuiltIns = projection.type.constructor.builtIns
}
class CapturedType(
val typeProjection: TypeProjection,
override val constructor: CapturedTypeConstructor = CapturedTypeConstructor(typeProjection),
override val constructor: CapturedTypeConstructor = CapturedTypeConstructorImpl(typeProjection),
override val isMarkedNullable: Boolean = false,
override val annotations: Annotations = Annotations.EMPTY
) : SimpleType(), SubtypingRepresentatives {
@@ -98,10 +98,10 @@ private fun substituteCapturedTypesWithProjections(typeProjection: TypeProjectio
val typeSubstitutor = TypeSubstitutor.create(object : TypeConstructorSubstitution() {
override fun get(key: TypeConstructor): TypeProjection? {
val capturedTypeConstructor = key as? CapturedTypeConstructor ?: return null
if (capturedTypeConstructor.typeProjection.isStarProjection) {
return TypeProjectionImpl(Variance.OUT_VARIANCE, capturedTypeConstructor.typeProjection.type)
if (capturedTypeConstructor.projection.isStarProjection) {
return TypeProjectionImpl(Variance.OUT_VARIANCE, capturedTypeConstructor.projection.type)
}
return capturedTypeConstructor.typeProjection
return capturedTypeConstructor.projection
}
})
return typeSubstitutor.substituteWithoutApproximation(typeProjection)
@@ -127,7 +127,7 @@ fun approximateCapturedTypes(type: KotlinType): ApproximationBounds<KotlinType>
val typeConstructor = type.constructor
if (type.isCaptured()) {
val typeProjection = (typeConstructor as CapturedTypeConstructor).typeProjection
val typeProjection = (typeConstructor as CapturedTypeConstructor).projection
fun KotlinType.makeNullableIfNeeded() = TypeUtils.makeNullableIfNeeded(this, type.isMarkedNullable)
val bound = typeProjection.type.makeNullableIfNeeded()
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructor
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
@@ -145,7 +146,7 @@ class NewCapturedType(
NewCapturedType(captureStatus, constructor, lowerType, annotations, newNullability)
}
class NewCapturedTypeConstructor(val projection: TypeProjection, private var supertypes: List<UnwrappedType>? = null) : TypeConstructor {
class NewCapturedTypeConstructor(override val projection: TypeProjection, private var supertypes: List<UnwrappedType>? = null) : CapturedTypeConstructor {
fun initializeSupertypes(supertypes: List<UnwrappedType>) {
assert(this.supertypes == null) {
"Already initialized! oldValue = ${this.supertypes}, newValue = $supertypes"
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
import org.jetbrains.kotlin.descriptors.isFinalClass
import org.jetbrains.kotlin.resolve.calls.inference.CapturedType
import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructor
import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructorImpl
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.TypeCheckerContext.LowerCapturedTypePolicy.*
@@ -136,12 +136,12 @@ object NewKotlinTypeChecker : KotlinTypeChecker {
val constructor = type.constructor
when (constructor) {
// Type itself can be just SimpleTypeImpl, not CapturedType. see KT-16147
is CapturedTypeConstructor -> {
val lowerType = constructor.typeProjection.takeIf { it.projectionKind == Variance.IN_VARIANCE }?.type?.unwrap()
is CapturedTypeConstructorImpl -> {
val lowerType = constructor.projection.takeIf { it.projectionKind == Variance.IN_VARIANCE }?.type?.unwrap()
// it is incorrect calculate this type directly because of recursive star projections
if (constructor.newTypeConstructor == null) {
constructor.newTypeConstructor = NewCapturedTypeConstructor(constructor.typeProjection, constructor.supertypes.map { it.unwrap() })
constructor.newTypeConstructor = NewCapturedTypeConstructor(constructor.projection, constructor.supertypes.map { it.unwrap() })
}
return NewCapturedType(CaptureStatus.FOR_SUBTYPING, constructor.newTypeConstructor!!,
lowerType, type.annotations, type.isMarkedNullable)