[FIR] Correct support of projections and type aliases for UPPER_BOUND_VIOLATED, extend tests
This commit is contained in:
committed by
teamcityserver
parent
66e2b44272
commit
a26ffde820
+55
@@ -85,3 +85,58 @@ FILE: upperBoundViolated.kt
|
|||||||
public get(): R|NumberPhile<kotlin/Int>|
|
public get(): R|NumberPhile<kotlin/Int>|
|
||||||
public final val np2: R|NumberPhile<ERROR CLASS: Cannot infer argument for type parameter T>| = <Inapplicable(INAPPLICABLE): /NumberPhile.NumberPhile>#<R|ERROR CLASS: Cannot infer argument for type parameter T|>(String(Test))
|
public final val np2: R|NumberPhile<ERROR CLASS: Cannot infer argument for type parameter T>| = <Inapplicable(INAPPLICABLE): /NumberPhile.NumberPhile>#<R|ERROR CLASS: Cannot infer argument for type parameter T|>(String(Test))
|
||||||
public get(): R|NumberPhile<ERROR CLASS: Cannot infer argument for type parameter T>|
|
public get(): R|NumberPhile<ERROR CLASS: Cannot infer argument for type parameter T>|
|
||||||
|
public final class Test1<S1 : R|Test1<S1, K>|, K : R|kotlin/Any|> : R|kotlin/Any| {
|
||||||
|
public constructor<S1 : R|Test1<S1, K>|, K : R|kotlin/Any|>(): R|Test1<S1, K>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Test2<S2 : R|Test1<S2, *>|> : R|kotlin/Any| {
|
||||||
|
public constructor<S2 : R|Test1<S2, *>|>(): R|Test2<S2>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Test3<S3 : R|Test3<S3, in K>|, K : R|kotlin/Any|> : R|kotlin/Any| {
|
||||||
|
public constructor<S3 : R|Test3<S3, in K>|, K : R|kotlin/Any|>(): R|Test3<S3, K>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Test4<S4 : R|Test3<S4, out kotlin/Any>|> : R|kotlin/Any| {
|
||||||
|
public constructor<S4 : R|Test3<S4, out kotlin/Any>|>(): R|Test4<S4>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Test5<S5 : R|Test5<S5, in K>|, K : R|kotlin/Any|> : R|kotlin/Any| {
|
||||||
|
public constructor<S5 : R|Test5<S5, in K>|, K : R|kotlin/Any|>(): R|Test5<S5, K>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Test6<S6 : R|Test5<S6, in kotlin/Any>|> : R|kotlin/Any| {
|
||||||
|
public constructor<S6 : R|Test5<S6, in kotlin/Any>|>(): R|Test6<S6>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Test7<S7 : R|Test7<S7, in K>|, K : R|kotlin/CharSequence|> : R|kotlin/Any| {
|
||||||
|
public constructor<S7 : R|Test7<S7, in K>|, K : R|kotlin/CharSequence|>(): R|Test7<S7, K>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Test8<S8 : R|Test7<S8, in kotlin/Any>|> : R|kotlin/Any| {
|
||||||
|
public constructor<S8 : R|Test7<S8, in kotlin/Any>|>(): R|Test8<S8>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Class<V : R|kotlin/Any|> : R|kotlin/Any| {
|
||||||
|
public constructor<V : R|kotlin/Any|>(): R|Class<V>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final typealias Alias<V1> = R|(Class<V1>) -> kotlin/Boolean|
|
||||||
|
|||||||
+16
@@ -50,3 +50,19 @@ val test8 = NL<<!UPPER_BOUND_VIOLATED!>String<!>>()
|
|||||||
class NumberPhile<T: Number>(x: T)
|
class NumberPhile<T: Number>(x: T)
|
||||||
val np1 = NumberPhile(10)
|
val np1 = NumberPhile(10)
|
||||||
val np2 = NumberPhile(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)
|
val np2 = NumberPhile(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)
|
||||||
|
|
||||||
|
class Test1<S1 : Test1<S1, K>, K : Any>
|
||||||
|
class Test2<S2 : Test1<S2, *>>
|
||||||
|
|
||||||
|
class Test3<S3 : Test3<S3, in K>, K : Any>
|
||||||
|
class Test4<S4 : Test3<<!UPPER_BOUND_VIOLATED!>S4<!>, out Any>>
|
||||||
|
|
||||||
|
class Test5<S5 : Test5<S5, in K>, K : Any>
|
||||||
|
class Test6<S6 : Test5<S6, in Any>>
|
||||||
|
|
||||||
|
class Test7<S7 : Test7<S7, in K>, K : CharSequence>
|
||||||
|
class Test8<S8 : Test7<S8, <!UPPER_BOUND_VIOLATED!>in Any<!>>>
|
||||||
|
|
||||||
|
class Class<V : Any>
|
||||||
|
typealias Alias <V1> = (Class<V1>) -> Boolean
|
||||||
|
|
||||||
|
|||||||
+27
-4
@@ -47,7 +47,10 @@ object FirUpperBoundViolatedClassChecker : FirBasicDeclarationChecker() {
|
|||||||
checkUpperBoundViolated(declaration.expandedTypeRef, context, reporter, isIgnoreTypeParameters = true)
|
checkUpperBoundViolated(declaration.expandedTypeRef, context, reporter, isIgnoreTypeParameters = true)
|
||||||
} else if (declaration is FirCallableDeclaration<*>) {
|
} else if (declaration is FirCallableDeclaration<*>) {
|
||||||
if (declaration.returnTypeRef.source?.kind !is FirFakeSourceElementKind) {
|
if (declaration.returnTypeRef.source?.kind !is FirFakeSourceElementKind) {
|
||||||
checkUpperBoundViolated(declaration.returnTypeRef, context, reporter)
|
checkUpperBoundViolated(
|
||||||
|
declaration.returnTypeRef, context, reporter,
|
||||||
|
isIgnoreTypeParameters = context.containingDeclarations.lastOrNull() is FirTypeAlias
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,6 +166,14 @@ private fun checkUpperBoundViolated(
|
|||||||
substitution[typeParameterSymbol] = typeArgument.typeRef.coneType
|
substitution[typeParameterSymbol] = typeArgument.typeRef.coneType
|
||||||
} else if (typeArgument is ConeKotlinType) {
|
} else if (typeArgument is ConeKotlinType) {
|
||||||
substitution[typeParameterSymbol] = typeArgument.type
|
substitution[typeParameterSymbol] = typeArgument.type
|
||||||
|
} else if (typeArgument is ConeTypeProjection) {
|
||||||
|
val typeArgumentType = typeArgument.type
|
||||||
|
if (typeArgumentType != null) {
|
||||||
|
substitution[typeParameterSymbol] = typeArgumentType
|
||||||
|
} else {
|
||||||
|
substitution[typeParameterSymbol] =
|
||||||
|
ConeStubType(ConeTypeVariable("", typeParameterSymbol.toLookupTag()), ConeNullability.NOT_NULL)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +197,12 @@ private fun checkUpperBoundViolated(
|
|||||||
typeArgumentSource = typeRef.source
|
typeArgumentSource = typeRef.source
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
typeArgument = type.typeArguments[index] as? ConeKotlinType
|
val localTypeArgument = type.typeArguments[index]
|
||||||
|
if (localTypeArgument is ConeKotlinType) {
|
||||||
|
typeArgument = localTypeArgument
|
||||||
|
} else if (localTypeArgument is ConeKotlinTypeProjection) {
|
||||||
|
typeArgument = localTypeArgument.type
|
||||||
|
}
|
||||||
val typeArgumentRefAndSource = typeArgumentRefsAndSources?.elementAtOrNull(index)
|
val typeArgumentRefAndSource = typeArgumentRefsAndSources?.elementAtOrNull(index)
|
||||||
if (typeArgumentRefAndSource != null) {
|
if (typeArgumentRefAndSource != null) {
|
||||||
typeArgumentTypeRef = typeArgumentRefAndSource.typeRef
|
typeArgumentTypeRef = typeArgumentRefAndSource.typeRef
|
||||||
@@ -202,10 +218,17 @@ private fun checkUpperBoundViolated(
|
|||||||
|
|
||||||
if (typeArgument != null && typeArgumentSource != null) {
|
if (typeArgument != null && typeArgumentSource != null) {
|
||||||
if (!isIgnoreTypeParameters || (typeArgument.typeArguments.isEmpty() && typeArgument !is ConeTypeParameterType)) {
|
if (!isIgnoreTypeParameters || (typeArgument.typeArguments.isEmpty() && typeArgument !is ConeTypeParameterType)) {
|
||||||
val intersection = typeSystemContext.intersectTypes(typeParameterSymbols[index].fir.bounds.map { it.coneType }) as? ConeKotlinType
|
val intersection =
|
||||||
|
typeSystemContext.intersectTypes(typeParameterSymbols[index].fir.bounds.map { it.coneType }) as? ConeKotlinType
|
||||||
if (intersection != null) {
|
if (intersection != null) {
|
||||||
val upperBound = substitutor.substituteOrSelf(intersection)
|
val upperBound = substitutor.substituteOrSelf(intersection)
|
||||||
if (!AbstractTypeChecker.isSubtypeOf(typeSystemContext, typeArgument.type, upperBound, stubTypesEqualToAnything = false)) {
|
if (!AbstractTypeChecker.isSubtypeOf(
|
||||||
|
typeSystemContext,
|
||||||
|
typeArgument.type,
|
||||||
|
upperBound,
|
||||||
|
stubTypesEqualToAnything = true
|
||||||
|
)
|
||||||
|
) {
|
||||||
val factory =
|
val factory =
|
||||||
if (isTypeAlias) FirErrors.UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION else FirErrors.UPPER_BOUND_VIOLATED
|
if (isTypeAlias) FirErrors.UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION else FirErrors.UPPER_BOUND_VIOLATED
|
||||||
reporter.reportOn(typeArgumentSource, factory, upperBound, typeArgument.type, context)
|
reporter.reportOn(typeArgumentSource, factory, upperBound, typeArgument.type, context)
|
||||||
|
|||||||
Reference in New Issue
Block a user