Allow inferring property type from its getter
#KT-550 Fixed
This commit is contained in:
@@ -678,7 +678,7 @@ class DeclarationsChecker(
|
|||||||
trace.report(MUST_BE_INITIALIZED_OR_BE_ABSTRACT.on(property))
|
trace.report(MUST_BE_INITIALIZED_OR_BE_ABSTRACT.on(property))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (property.typeReference == null) {
|
else if (noExplicitTypeOrGetterType(property)) {
|
||||||
trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property))
|
trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property))
|
||||||
}
|
}
|
||||||
if (backingFieldRequired && !inTrait && propertyDescriptor.isLateInit && !isUninitialized) {
|
if (backingFieldRequired && !inTrait && propertyDescriptor.isLateInit && !isUninitialized) {
|
||||||
@@ -690,6 +690,10 @@ class DeclarationsChecker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun noExplicitTypeOrGetterType(property: KtProperty) =
|
||||||
|
property.typeReference == null
|
||||||
|
&& (property.getter == null || (property.getter!!.hasBlockBody() && property.getter!!.returnTypeReference == null))
|
||||||
|
|
||||||
fun checkFunction(function: KtNamedFunction, functionDescriptor: SimpleFunctionDescriptor) {
|
fun checkFunction(function: KtNamedFunction, functionDescriptor: SimpleFunctionDescriptor) {
|
||||||
val typeParameterList = function.typeParameterList
|
val typeParameterList = function.typeParameterList
|
||||||
val nameIdentifier = function.nameIdentifier
|
val nameIdentifier = function.nameIdentifier
|
||||||
|
|||||||
@@ -814,11 +814,18 @@ public class DescriptorResolver {
|
|||||||
DescriptorFactory.createExtensionReceiverParameterForCallable(propertyDescriptor, receiverType);
|
DescriptorFactory.createExtensionReceiverParameterForCallable(propertyDescriptor, receiverType);
|
||||||
|
|
||||||
LexicalScope scopeForInitializer = ScopeUtils.makeScopeForPropertyInitializer(scopeWithTypeParameters, propertyDescriptor);
|
LexicalScope scopeForInitializer = ScopeUtils.makeScopeForPropertyInitializer(scopeWithTypeParameters, propertyDescriptor);
|
||||||
KotlinType type = variableTypeAndInitializerResolver.resolveType(
|
KotlinType typeIfKnown = variableTypeAndInitializerResolver.resolveTypeNullable(
|
||||||
propertyDescriptor, scopeForInitializer,
|
propertyDescriptor, scopeForInitializer,
|
||||||
property, dataFlowInfo, true, trace
|
property, dataFlowInfo, true, trace
|
||||||
);
|
);
|
||||||
|
|
||||||
|
PropertyGetterDescriptorImpl getter = resolvePropertyGetterDescriptor(
|
||||||
|
scopeWithTypeParameters, property, propertyDescriptor, annotationSplitter, trace, typeIfKnown);
|
||||||
|
|
||||||
|
KotlinType type = typeIfKnown != null ? typeIfKnown : getter.getReturnType();
|
||||||
|
|
||||||
|
assert type != null : "At least getter type must be initialized via resolvePropertyGetterDescriptor";
|
||||||
|
|
||||||
variableTypeAndInitializerResolver.setConstantForVariableIfNeeded(
|
variableTypeAndInitializerResolver.setConstantForVariableIfNeeded(
|
||||||
propertyDescriptor, scopeForInitializer, property, dataFlowInfo, type, trace
|
propertyDescriptor, scopeForInitializer, property, dataFlowInfo, type, trace
|
||||||
);
|
);
|
||||||
@@ -826,8 +833,6 @@ public class DescriptorResolver {
|
|||||||
propertyDescriptor.setType(type, typeParameterDescriptors, getDispatchReceiverParameterIfNeeded(containingDeclaration),
|
propertyDescriptor.setType(type, typeParameterDescriptors, getDispatchReceiverParameterIfNeeded(containingDeclaration),
|
||||||
receiverDescriptor);
|
receiverDescriptor);
|
||||||
|
|
||||||
PropertyGetterDescriptorImpl getter = resolvePropertyGetterDescriptor(
|
|
||||||
scopeWithTypeParameters, property, propertyDescriptor, annotationSplitter, trace);
|
|
||||||
PropertySetterDescriptor setter = resolvePropertySetterDescriptor(
|
PropertySetterDescriptor setter = resolvePropertySetterDescriptor(
|
||||||
scopeWithTypeParameters, property, propertyDescriptor, annotationSplitter, trace);
|
scopeWithTypeParameters, property, propertyDescriptor, annotationSplitter, trace);
|
||||||
|
|
||||||
@@ -963,10 +968,12 @@ public class DescriptorResolver {
|
|||||||
@NotNull KtProperty property,
|
@NotNull KtProperty property,
|
||||||
@NotNull PropertyDescriptor propertyDescriptor,
|
@NotNull PropertyDescriptor propertyDescriptor,
|
||||||
@NotNull AnnotationSplitter annotationSplitter,
|
@NotNull AnnotationSplitter annotationSplitter,
|
||||||
BindingTrace trace
|
BindingTrace trace,
|
||||||
|
@Nullable KotlinType propertyTypeIfKnown
|
||||||
) {
|
) {
|
||||||
PropertyGetterDescriptorImpl getterDescriptor;
|
PropertyGetterDescriptorImpl getterDescriptor;
|
||||||
KtPropertyAccessor getter = property.getGetter();
|
KtPropertyAccessor getter = property.getGetter();
|
||||||
|
KotlinType getterType;
|
||||||
if (getter != null) {
|
if (getter != null) {
|
||||||
Annotations getterAnnotations = new CompositeAnnotations(CollectionsKt.listOf(
|
Annotations getterAnnotations = new CompositeAnnotations(CollectionsKt.listOf(
|
||||||
annotationSplitter.getAnnotationsForTarget(PROPERTY_GETTER),
|
annotationSplitter.getAnnotationsForTarget(PROPERTY_GETTER),
|
||||||
@@ -980,33 +987,34 @@ public class DescriptorResolver {
|
|||||||
property.hasModifier(KtTokens.INLINE_KEYWORD) || getter.hasModifier(KtTokens.INLINE_KEYWORD),
|
property.hasModifier(KtTokens.INLINE_KEYWORD) || getter.hasModifier(KtTokens.INLINE_KEYWORD),
|
||||||
CallableMemberDescriptor.Kind.DECLARATION, null, KotlinSourceElementKt.toSourceElement(getter)
|
CallableMemberDescriptor.Kind.DECLARATION, null, KotlinSourceElementKt.toSourceElement(getter)
|
||||||
);
|
);
|
||||||
KotlinType returnType =
|
getterType = determineGetterReturnType(scopeWithTypeParameters, trace, getterDescriptor, getter, propertyTypeIfKnown);
|
||||||
determineGetterReturnType(scopeWithTypeParameters, trace, getterDescriptor, getter, propertyDescriptor.getType());
|
|
||||||
getterDescriptor.initialize(returnType);
|
|
||||||
trace.record(BindingContext.PROPERTY_ACCESSOR, getter, getterDescriptor);
|
trace.record(BindingContext.PROPERTY_ACCESSOR, getter, getterDescriptor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Annotations getterAnnotations = annotationSplitter.getAnnotationsForTarget(PROPERTY_GETTER);
|
Annotations getterAnnotations = annotationSplitter.getAnnotationsForTarget(PROPERTY_GETTER);
|
||||||
getterDescriptor = DescriptorFactory.createGetter(propertyDescriptor, getterAnnotations, !property.hasDelegate(),
|
getterDescriptor = DescriptorFactory.createGetter(propertyDescriptor, getterAnnotations, !property.hasDelegate(),
|
||||||
/* isExternal = */ false, property.hasModifier(KtTokens.INLINE_KEYWORD));
|
/* isExternal = */ false, property.hasModifier(KtTokens.INLINE_KEYWORD));
|
||||||
getterDescriptor.initialize(propertyDescriptor.getType());
|
getterType = propertyTypeIfKnown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getterDescriptor.initialize(getterType != null ? getterType : VariableTypeAndInitializerResolver.STUB_FOR_PROPERTY_WITHOUT_TYPE);
|
||||||
|
|
||||||
return getterDescriptor;
|
return getterDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nullable
|
||||||
private KotlinType determineGetterReturnType(
|
private KotlinType determineGetterReturnType(
|
||||||
@NotNull LexicalScope scope,
|
@NotNull LexicalScope scope,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@NotNull PropertyGetterDescriptor getterDescriptor,
|
@NotNull PropertyGetterDescriptor getterDescriptor,
|
||||||
@NotNull KtPropertyAccessor getter,
|
@NotNull KtPropertyAccessor getter,
|
||||||
@NotNull KotlinType propertyType
|
@Nullable KotlinType propertyTypeIfKnown
|
||||||
) {
|
) {
|
||||||
KtTypeReference returnTypeReference = getter.getReturnTypeReference();
|
KtTypeReference returnTypeReference = getter.getReturnTypeReference();
|
||||||
if (returnTypeReference != null) {
|
if (returnTypeReference != null) {
|
||||||
KotlinType explicitReturnType = typeResolver.resolveType(scope, returnTypeReference, trace, true);
|
KotlinType explicitReturnType = typeResolver.resolveType(scope, returnTypeReference, trace, true);
|
||||||
if (!TypeUtils.equalTypes(explicitReturnType, propertyType)) {
|
if (propertyTypeIfKnown != null && !TypeUtils.equalTypes(explicitReturnType, propertyTypeIfKnown)) {
|
||||||
trace.report(WRONG_GETTER_RETURN_TYPE.on(returnTypeReference, propertyType, explicitReturnType));
|
trace.report(WRONG_GETTER_RETURN_TYPE.on(returnTypeReference, propertyTypeIfKnown, explicitReturnType));
|
||||||
}
|
}
|
||||||
return explicitReturnType;
|
return explicitReturnType;
|
||||||
}
|
}
|
||||||
@@ -1020,7 +1028,7 @@ public class DescriptorResolver {
|
|||||||
return inferReturnTypeFromExpressionBody(trace, scope, DataFlowInfoFactory.EMPTY, getter, getterDescriptor);
|
return inferReturnTypeFromExpressionBody(trace, scope, DataFlowInfoFactory.EMPTY, getter, getterDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return propertyType;
|
return propertyTypeIfKnown;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
+22
-7
@@ -43,6 +43,10 @@ class VariableTypeAndInitializerResolver(
|
|||||||
private val constantExpressionEvaluator: ConstantExpressionEvaluator,
|
private val constantExpressionEvaluator: ConstantExpressionEvaluator,
|
||||||
private val delegatedPropertyResolver: DelegatedPropertyResolver
|
private val delegatedPropertyResolver: DelegatedPropertyResolver
|
||||||
) {
|
) {
|
||||||
|
companion object {
|
||||||
|
@JvmField
|
||||||
|
val STUB_FOR_PROPERTY_WITHOUT_TYPE = ErrorUtils.createErrorType("No type, no body")
|
||||||
|
}
|
||||||
|
|
||||||
fun resolveType(
|
fun resolveType(
|
||||||
variableDescriptor: VariableDescriptorWithInitializerImpl,
|
variableDescriptor: VariableDescriptorWithInitializerImpl,
|
||||||
@@ -52,8 +56,24 @@ class VariableTypeAndInitializerResolver(
|
|||||||
notLocal: Boolean,
|
notLocal: Boolean,
|
||||||
trace: BindingTrace
|
trace: BindingTrace
|
||||||
): KotlinType {
|
): KotlinType {
|
||||||
val propertyTypeRef = variable.typeReference
|
resolveTypeNullable(variableDescriptor, scopeForInitializer, variable, dataFlowInfo, notLocal, trace)?.let { return it }
|
||||||
|
|
||||||
|
if (!notLocal) {
|
||||||
|
trace.report(VARIABLE_WITH_NO_TYPE_NO_INITIALIZER.on(variable))
|
||||||
|
}
|
||||||
|
|
||||||
|
return STUB_FOR_PROPERTY_WITHOUT_TYPE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resolveTypeNullable(
|
||||||
|
variableDescriptor: VariableDescriptorWithInitializerImpl,
|
||||||
|
scopeForInitializer: LexicalScope,
|
||||||
|
variable: KtVariableDeclaration,
|
||||||
|
dataFlowInfo: DataFlowInfo,
|
||||||
|
notLocal: Boolean,
|
||||||
|
trace: BindingTrace
|
||||||
|
): KotlinType? {
|
||||||
|
val propertyTypeRef = variable.typeReference
|
||||||
return when {
|
return when {
|
||||||
propertyTypeRef != null -> typeResolver.resolveType(scopeForInitializer, propertyTypeRef, trace, true)
|
propertyTypeRef != null -> typeResolver.resolveType(scopeForInitializer, propertyTypeRef, trace, true)
|
||||||
|
|
||||||
@@ -74,12 +94,7 @@ class VariableTypeAndInitializerResolver(
|
|||||||
|
|
||||||
else -> resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace)
|
else -> resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> null
|
||||||
if (!notLocal) {
|
|
||||||
trace.report(VARIABLE_WITH_NO_TYPE_NO_INITIALIZER.on(variable))
|
|
||||||
}
|
|
||||||
ErrorUtils.createErrorType("No type, no body")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
val x get() = "O"
|
||||||
|
|
||||||
|
class A {
|
||||||
|
val y get() = "K"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() = x + A().y
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
class A {
|
|
||||||
<!PROPERTY_WITH_NO_TYPE_NO_INITIALIZER!>val a<!> get() = <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a<!>
|
|
||||||
}
|
|
||||||
+1
-1
@@ -24,7 +24,7 @@ class Foo {
|
|||||||
|
|
||||||
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>public val <!EXPOSED_PROPERTY_TYPE!>publicProperty<!><!> = object : MyClass(), MyTrait {}
|
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>public val <!EXPOSED_PROPERTY_TYPE!>publicProperty<!><!> = object : MyClass(), MyTrait {}
|
||||||
|
|
||||||
<!PROPERTY_WITH_NO_TYPE_NO_INITIALIZER!>val propertyWithGetter<!>
|
val <!EXPOSED_PROPERTY_TYPE!>propertyWithGetter<!>
|
||||||
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>get()<!> = object: MyClass(), MyTrait {}
|
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>get()<!> = object: MyClass(), MyTrait {}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ public final class Foo {
|
|||||||
internal final val internal2Property: Foo.internal2Property.<no name provided>
|
internal final val internal2Property: Foo.internal2Property.<no name provided>
|
||||||
public final val internalProperty: Foo.internalProperty.<no name provided>
|
public final val internalProperty: Foo.internalProperty.<no name provided>
|
||||||
private final val privateProperty: Foo.privateProperty.<no name provided>
|
private final val privateProperty: Foo.privateProperty.<no name provided>
|
||||||
public final val propertyWithGetter: [ERROR : No type, no body]
|
public final val propertyWithGetter: Foo.<get-propertyWithGetter>.<no name provided>
|
||||||
protected final val protectedProperty: Foo.protectedProperty.<no name provided>
|
protected final val protectedProperty: Foo.protectedProperty.<no name provided>
|
||||||
public final val publicProperty: Foo.publicProperty.<no name provided>
|
public final val publicProperty: Foo.publicProperty.<no name provided>
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
|||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
<!PROPERTY_WITH_NO_TYPE_NO_INITIALIZER!>val x<!> get() {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val x: [ERROR : No type, no body]
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
val x get() = <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>()
|
||||||
|
val y get() = <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>bar<!>()
|
||||||
|
|
||||||
|
fun <E> foo(): E = null!!
|
||||||
|
fun <E> bar(): List<E> = null!!
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val x: [ERROR : Error function type]
|
||||||
|
public val y: [ERROR : Error function type]
|
||||||
|
public fun </*0*/ E> bar(): kotlin.collections.List<E>
|
||||||
|
public fun </*0*/ E> foo(): E
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
// !CHECK_TYPE
|
||||||
|
val x get(): String = foo()
|
||||||
|
val y get(): List<Int> = bar()
|
||||||
|
val z get(): List<Int> {
|
||||||
|
return bar()
|
||||||
|
}
|
||||||
|
|
||||||
|
<!MUST_BE_INITIALIZED!>val u<!> get(): String = field
|
||||||
|
|
||||||
|
fun <E> foo(): E = null!!
|
||||||
|
fun <E> bar(): List<E> = null!!
|
||||||
|
|
||||||
|
|
||||||
|
fun baz() {
|
||||||
|
x checkType { _<String>() }
|
||||||
|
y checkType { _<List<Int>>() }
|
||||||
|
z checkType { _<List<Int>>() }
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val u: kotlin.String
|
||||||
|
public val x: kotlin.String
|
||||||
|
public val y: kotlin.collections.List<kotlin.Int>
|
||||||
|
public val z: kotlin.collections.List<kotlin.Int>
|
||||||
|
public fun </*0*/ E> bar(): kotlin.collections.List<E>
|
||||||
|
public fun baz(): kotlin.Unit
|
||||||
|
public fun </*0*/ E> foo(): E
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
// !CHECK_TYPE
|
||||||
|
class A {
|
||||||
|
val x get() = 1
|
||||||
|
val y get() = id(1)
|
||||||
|
val y2 get() = id(id(2))
|
||||||
|
val z get() = l("")
|
||||||
|
val z2 get() = l(id(l("")))
|
||||||
|
|
||||||
|
val <T> T.u get() = id(this)
|
||||||
|
}
|
||||||
|
fun <E> id(x: E) = x
|
||||||
|
fun <E> l(<!UNUSED_PARAMETER!>x<!>: E): List<E> = null!!
|
||||||
|
|
||||||
|
fun foo(a: A) {
|
||||||
|
a.x checkType { _<Int>() }
|
||||||
|
a.y checkType { _<Int>() }
|
||||||
|
a.y2 checkType { _<Int>() }
|
||||||
|
a.z checkType { _<List<String>>() }
|
||||||
|
a.z2 checkType { _<List<List<String>>>() }
|
||||||
|
|
||||||
|
with(a) {
|
||||||
|
1.u checkType { _<Int>() }
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun foo(/*0*/ a: A): kotlin.Unit
|
||||||
|
public fun </*0*/ E> id(/*0*/ x: E): E
|
||||||
|
public fun </*0*/ E> l(/*0*/ x: E): kotlin.collections.List<E>
|
||||||
|
|
||||||
|
public final class A {
|
||||||
|
public constructor A()
|
||||||
|
public final val x: kotlin.Int
|
||||||
|
public final val y: kotlin.Int
|
||||||
|
public final val y2: kotlin.Int
|
||||||
|
public final val z: kotlin.collections.List<kotlin.String>
|
||||||
|
public final val z2: kotlin.collections.List<kotlin.collections.List<kotlin.String>>
|
||||||
|
public final val </*0*/ T> T.u: T
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
// !CHECK_TYPE
|
||||||
|
val x get() = null
|
||||||
|
val <!IMPLICIT_NOTHING_PROPERTY_TYPE!>y<!> get() = null!!
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
<!DEBUG_INFO_CONSTANT!>x<!> checkType { _<Nothing?>() }
|
||||||
|
y <!UNREACHABLE_CODE!>checkType { _<Nothing>() }<!>
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val x: kotlin.Nothing?
|
||||||
|
public val y: kotlin.Nothing
|
||||||
|
public fun foo(): kotlin.Unit
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
// !CHECK_TYPE
|
||||||
|
object Outer {
|
||||||
|
private var x
|
||||||
|
get() = object : CharSequence {
|
||||||
|
override val length: Int
|
||||||
|
get() = 0
|
||||||
|
|
||||||
|
override fun get(index: Int): Char {
|
||||||
|
checkSubtype<CharSequence>(<!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>x<!>)
|
||||||
|
return ' '
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun subSequence(startIndex: Int, endIndex: Int) = ""
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set(q) {
|
||||||
|
checkSubtype<CharSequence>(x)
|
||||||
|
y = q
|
||||||
|
x = q
|
||||||
|
}
|
||||||
|
|
||||||
|
private var y = <!DEBUG_INFO_LEAKING_THIS!>x<!>
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
x = y
|
||||||
|
|
||||||
|
checkSubtype<CharSequence>(x)
|
||||||
|
checkSubtype<CharSequence>(y)
|
||||||
|
|
||||||
|
x.bar()
|
||||||
|
y.bar()
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-3
@@ -1,9 +1,11 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
public final class A {
|
public object Outer {
|
||||||
public constructor A()
|
private constructor Outer()
|
||||||
public final val a: [ERROR : No type, no body]
|
private final var x: Outer.<get-x>.<no name provided>
|
||||||
|
private final var y: Outer.<get-x>.<no name provided>
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final fun foo(): kotlin.Unit
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
// !CHECK_TYPE
|
||||||
|
interface A {
|
||||||
|
val x: Int
|
||||||
|
|
||||||
|
val z: Comparable<*>
|
||||||
|
}
|
||||||
|
|
||||||
|
open class B {
|
||||||
|
open var y = ""
|
||||||
|
|
||||||
|
open val z: CharSequence = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
class C : B(), A {
|
||||||
|
override val x
|
||||||
|
get() = 1
|
||||||
|
|
||||||
|
override var y
|
||||||
|
get() = super.y
|
||||||
|
set(value) {
|
||||||
|
value checkType { _<String>() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override var z
|
||||||
|
get() = ""
|
||||||
|
set(value) {
|
||||||
|
value checkType { _<String>() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(c: C) {
|
||||||
|
c.x checkType { _<Int>() }
|
||||||
|
c.y checkType { _<String>() }
|
||||||
|
c.z checkType { _<String>() }
|
||||||
|
|
||||||
|
c.y = ""
|
||||||
|
c.y = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>
|
||||||
|
|
||||||
|
c.z = ""
|
||||||
|
c.z = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>
|
||||||
|
}
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun foo(/*0*/ c: C): kotlin.Unit
|
||||||
|
|
||||||
|
public interface A {
|
||||||
|
public abstract val x: kotlin.Int
|
||||||
|
public abstract val z: kotlin.Comparable<*>
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public open class B {
|
||||||
|
public constructor B()
|
||||||
|
public open var y: kotlin.String
|
||||||
|
public open val z: kotlin.CharSequence
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class C : B, A {
|
||||||
|
public constructor C()
|
||||||
|
public open override /*1*/ val x: kotlin.Int
|
||||||
|
public open override /*1*/ var y: kotlin.String
|
||||||
|
public open override /*2*/ var z: kotlin.String
|
||||||
|
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
// !CHECK_TYPE
|
||||||
|
|
||||||
|
val x get() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>x<!>
|
||||||
|
|
||||||
|
class A {
|
||||||
|
val y get() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>y<!>
|
||||||
|
|
||||||
|
val a get() = <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>b<!>
|
||||||
|
val b get() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>a<!>
|
||||||
|
|
||||||
|
val z1 get() = id(<!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>z1<!>)
|
||||||
|
val z2 get() = l(<!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>z2<!>)
|
||||||
|
|
||||||
|
val u get() = <!UNRESOLVED_REFERENCE!>field<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <E> id(x: E) = x
|
||||||
|
fun <E> l(<!UNUSED_PARAMETER!>x<!>: E): List<E> = null!!
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val x: [ERROR : Error function type]
|
||||||
|
public fun </*0*/ E> id(/*0*/ x: E): E
|
||||||
|
public fun </*0*/ E> l(/*0*/ x: E): kotlin.collections.List<E>
|
||||||
|
|
||||||
|
public final class A {
|
||||||
|
public constructor A()
|
||||||
|
public final val a: [ERROR : Error function type]
|
||||||
|
public final val b: [ERROR : Error function type]
|
||||||
|
public final val u: [ERROR : Error function type]
|
||||||
|
public final val y: [ERROR : Error function type]
|
||||||
|
public final val z1: [ERROR : Error function type]
|
||||||
|
public final val z2: [ERROR : Error function type]
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
// !CHECK_TYPE
|
||||||
|
val x get() = 1
|
||||||
|
val y get() = id(1)
|
||||||
|
val y2 get() = id(id(2))
|
||||||
|
val z get() = l("")
|
||||||
|
val z2 get() = l(id(l("")))
|
||||||
|
|
||||||
|
val <T> T.u get() = id(this)
|
||||||
|
|
||||||
|
fun <E> id(x: E) = x
|
||||||
|
fun <E> l(<!UNUSED_PARAMETER!>x<!>: E): List<E> = null!!
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
x checkType { _<Int>() }
|
||||||
|
y checkType { _<Int>() }
|
||||||
|
y2 checkType { _<Int>() }
|
||||||
|
z checkType { _<List<String>>() }
|
||||||
|
z2 checkType { _<List<List<String>>>() }
|
||||||
|
|
||||||
|
1.u checkType { _<Int>() }
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val x: kotlin.Int
|
||||||
|
public val y: kotlin.Int
|
||||||
|
public val y2: kotlin.Int
|
||||||
|
public val z: kotlin.collections.List<kotlin.String>
|
||||||
|
public val z2: kotlin.collections.List<kotlin.collections.List<kotlin.String>>
|
||||||
|
public val </*0*/ T> T.u: T
|
||||||
|
public fun foo(): kotlin.Unit
|
||||||
|
public fun </*0*/ E> id(/*0*/ x: E): E
|
||||||
|
public fun </*0*/ E> l(/*0*/ x: E): kotlin.collections.List<E>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// !CHECK_TYPE
|
||||||
|
var x
|
||||||
|
get() = 1
|
||||||
|
set(q) {
|
||||||
|
q checkType { _<Int>() }
|
||||||
|
}
|
||||||
|
|
||||||
|
<!MUST_BE_INITIALIZED!>var noSetter<!>
|
||||||
|
get() = 1
|
||||||
|
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
x checkType { _<Int>() }
|
||||||
|
noSetter checkType { _<Int>() }
|
||||||
|
|
||||||
|
x = 1
|
||||||
|
x = <!TYPE_MISMATCH!>""<!>
|
||||||
|
|
||||||
|
noSetter = 2
|
||||||
|
noSetter = <!TYPE_MISMATCH!>""<!>
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public var noSetter: kotlin.Int
|
||||||
|
public var x: kotlin.Int
|
||||||
|
public fun foo(): kotlin.Unit
|
||||||
+6
@@ -11189,6 +11189,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeInferredFromGetter.kt")
|
||||||
|
public void testTypeInferredFromGetter() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/properties/typeInferredFromGetter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/properties/const")
|
@TestMetadata("compiler/testData/codegen/box/properties/const")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -572,12 +572,6 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("RecursiveGetter.kt")
|
|
||||||
public void testRecursiveGetter() throws Exception {
|
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/RecursiveGetter.kt");
|
|
||||||
doTest(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestMetadata("RecursiveResolve.kt")
|
@TestMetadata("RecursiveResolve.kt")
|
||||||
public void testRecursiveResolve() throws Exception {
|
public void testRecursiveResolve() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/RecursiveResolve.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/RecursiveResolve.kt");
|
||||||
@@ -14525,6 +14519,84 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/tests/properties")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Properties extends AbstractDiagnosticsTest {
|
||||||
|
public void testAllFilesPresentInProperties() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/properties"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/tests/properties/inferenceFromGetters")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class InferenceFromGetters extends AbstractDiagnosticsTest {
|
||||||
|
public void testAllFilesPresentInInferenceFromGetters() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/properties/inferenceFromGetters"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("blockBodyGetter.kt")
|
||||||
|
public void testBlockBodyGetter() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/properties/inferenceFromGetters/blockBodyGetter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("cantBeInferred.kt")
|
||||||
|
public void testCantBeInferred() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/properties/inferenceFromGetters/cantBeInferred.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("explicitGetterType.kt")
|
||||||
|
public void testExplicitGetterType() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/properties/inferenceFromGetters/explicitGetterType.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("members.kt")
|
||||||
|
public void testMembers() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/properties/inferenceFromGetters/members.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nullAsNothing.kt")
|
||||||
|
public void testNullAsNothing() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/properties/inferenceFromGetters/nullAsNothing.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("objectExpression.kt")
|
||||||
|
public void testObjectExpression() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/properties/inferenceFromGetters/objectExpression.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("overrides.kt")
|
||||||
|
public void testOverrides() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/properties/inferenceFromGetters/overrides.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("recursiveGetter.kt")
|
||||||
|
public void testRecursiveGetter() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/properties/inferenceFromGetters/recursiveGetter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("topLevel.kt")
|
||||||
|
public void testTopLevel() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/properties/inferenceFromGetters/topLevel.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("vars.kt")
|
||||||
|
public void testVars() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/properties/inferenceFromGetters/vars.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/qualifiedExpression")
|
@TestMetadata("compiler/testData/diagnostics/tests/qualifiedExpression")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -11189,6 +11189,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeInferredFromGetter.kt")
|
||||||
|
public void testTypeInferredFromGetter() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/properties/typeInferredFromGetter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/properties/const")
|
@TestMetadata("compiler/testData/codegen/box/properties/const")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// "Specify type explicitly" "false"
|
// "Specify type explicitly" "false"
|
||||||
// ERROR: This property must either have a type annotation, be initialized or be delegated
|
// ERROR: Type checking has run into a recursive problem. Easiest workaround: specify types of your declarations explicitly
|
||||||
// ACTION: Convert member to extension
|
// ACTION: Convert member to extension
|
||||||
// ACTION: Convert property to function
|
// ACTION: Convert property to function
|
||||||
// ACTION: Move to companion object
|
// ACTION: Move to companion object
|
||||||
|
|||||||
@@ -13760,6 +13760,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeInferredFromGetter.kt")
|
||||||
|
public void testTypeInferredFromGetter() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/properties/typeInferredFromGetter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/properties/const")
|
@TestMetadata("compiler/testData/codegen/box/properties/const")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user