[FIR] Introduce ConeDynamicType
This commit is contained in:
+1
-3
@@ -45,9 +45,7 @@ object FirTopLevelTypeAliasChecker : FirTypeAliasChecker() {
|
||||
val expandedTypeRef = declaration.expandedTypeRef
|
||||
val fullyExpandedType = expandedTypeRef.coneType.fullyExpandedType(context.session)
|
||||
|
||||
if (containsTypeParameter(fullyExpandedType) ||
|
||||
fullyExpandedType is ConeErrorType && fullyExpandedType.diagnostic is ConeUnsupportedDynamicType
|
||||
) {
|
||||
if (containsTypeParameter(fullyExpandedType) || fullyExpandedType is ConeDynamicType) {
|
||||
reporter.reportOn(
|
||||
declaration.expandedTypeRef.source,
|
||||
FirErrors.TYPEALIAS_SHOULD_EXPAND_TO_CLASS,
|
||||
|
||||
@@ -80,9 +80,9 @@ open class ConeFlexibleType(
|
||||
|
||||
final override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as ConeFlexibleType
|
||||
// I suppose dynamic type (see below) and flexible type should use the same equals,
|
||||
// because ft<Any?, Nothing> should never be created
|
||||
if (other !is ConeFlexibleType) return false
|
||||
|
||||
if (lowerBound != other.lowerBound) return false
|
||||
if (upperBound != other.upperBound) return false
|
||||
@@ -97,6 +97,16 @@ open class ConeFlexibleType(
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresOptIn(message = "Please use ConeDynamicType.create instead")
|
||||
annotation class DynamicTypeConstructor
|
||||
|
||||
class ConeDynamicType @DynamicTypeConstructor constructor(
|
||||
lowerBound: ConeSimpleKotlinType,
|
||||
upperBound: ConeSimpleKotlinType
|
||||
) : ConeFlexibleType(lowerBound, upperBound), DynamicTypeMarker {
|
||||
companion object
|
||||
}
|
||||
|
||||
fun ConeSimpleKotlinType.unwrapDefinitelyNotNull(): ConeSimpleKotlinType {
|
||||
return when (this) {
|
||||
is ConeDefinitelyNotNullType -> original
|
||||
|
||||
@@ -30,6 +30,11 @@ fun ConeKotlinType.render(): String {
|
||||
is ConeLookupTagBasedType -> {
|
||||
"${renderAttributes()}${lookupTag.name.asString()}"
|
||||
}
|
||||
is ConeDynamicType -> {
|
||||
buildString {
|
||||
append("dynamic")
|
||||
}
|
||||
}
|
||||
is ConeFlexibleType -> {
|
||||
buildString {
|
||||
append("ft<")
|
||||
|
||||
+9
-1
@@ -115,7 +115,15 @@ class FirTypeDeserializer(
|
||||
if (proto.hasFlexibleTypeCapabilitiesId()) {
|
||||
val lowerBound = simpleType(proto, attributes)
|
||||
val upperBound = simpleType(proto.flexibleUpperBound(typeTable)!!, attributes)
|
||||
return ConeFlexibleType(lowerBound!!, upperBound!!)
|
||||
|
||||
val isDynamic = lowerBound == moduleData.session.builtinTypes.nothingType.coneType &&
|
||||
upperBound == moduleData.session.builtinTypes.nullableAnyType.coneType
|
||||
|
||||
return if (isDynamic) {
|
||||
ConeDynamicType.create(moduleData.session)
|
||||
} else {
|
||||
ConeFlexibleType(lowerBound!!, upperBound!!)
|
||||
}
|
||||
}
|
||||
|
||||
return simpleType(proto, attributes) ?: ConeErrorType(ConeSimpleDiagnostic("?!id:0", DiagnosticKind.DeserializationError))
|
||||
|
||||
@@ -44,6 +44,7 @@ fun ConeClassLikeType.fullyExpandedType(
|
||||
fun ConeKotlinType.fullyExpandedType(
|
||||
useSiteSession: FirSession
|
||||
): ConeKotlinType = when (this) {
|
||||
is ConeDynamicType -> this
|
||||
is ConeFlexibleType ->
|
||||
ConeFlexibleType(lowerBound.fullyExpandedType(useSiteSession), upperBound.fullyExpandedType(useSiteSession))
|
||||
is ConeClassLikeType -> fullyExpandedType(useSiteSession)
|
||||
|
||||
@@ -108,9 +108,9 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
||||
return this is ConeErrorType && this.isUninferredParameter
|
||||
}
|
||||
|
||||
override fun FlexibleTypeMarker.asDynamicType(): DynamicTypeMarker? {
|
||||
override fun FlexibleTypeMarker.asDynamicType(): ConeDynamicType? {
|
||||
assert(this is ConeKotlinType)
|
||||
return null // TODO
|
||||
return this as? ConeDynamicType
|
||||
}
|
||||
|
||||
override fun FlexibleTypeMarker.asRawType(): RawTypeMarker? {
|
||||
|
||||
@@ -94,6 +94,11 @@ fun ConeDefinitelyNotNullType.Companion.create(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(DynamicTypeConstructor::class)
|
||||
fun ConeDynamicType.Companion.create(session: FirSession): ConeDynamicType =
|
||||
ConeDynamicType(session.builtinTypes.nothingType.type, session.builtinTypes.nullableAnyType.type)
|
||||
|
||||
|
||||
fun ConeKotlinType.makeConeTypeDefinitelyNotNullOrNotNull(
|
||||
typeContext: ConeTypeContext,
|
||||
avoidComprehensiveCheck: Boolean = false,
|
||||
@@ -124,6 +129,7 @@ fun <T : ConeKotlinType> T.withArguments(arguments: Array<out ConeTypeProjection
|
||||
fun <T : ConeKotlinType> T.withArguments(replacement: (ConeTypeProjection) -> ConeTypeProjection) =
|
||||
withArguments(typeArguments.map(replacement).toTypedArray())
|
||||
|
||||
@OptIn(DynamicTypeConstructor::class)
|
||||
fun <T : ConeKotlinType> T.withAttributes(attributes: ConeAttributes): T {
|
||||
if (this.attributes == attributes) {
|
||||
return this
|
||||
@@ -136,6 +142,7 @@ fun <T : ConeKotlinType> T.withAttributes(attributes: ConeAttributes): T {
|
||||
is ConeDefinitelyNotNullType -> ConeDefinitelyNotNullType(original.withAttributes(attributes))
|
||||
is ConeTypeParameterTypeImpl -> ConeTypeParameterTypeImpl(lookupTag, nullability.isNullable, attributes)
|
||||
is ConeRawType -> ConeRawType(lowerBound.withAttributes(attributes), upperBound.withAttributes(attributes))
|
||||
is ConeDynamicType -> ConeDynamicType(lowerBound.withAttributes(attributes), upperBound.withAttributes(attributes))
|
||||
is ConeFlexibleType -> ConeFlexibleType(lowerBound.withAttributes(attributes), upperBound.withAttributes(attributes))
|
||||
is ConeTypeVariableType -> ConeTypeVariableType(nullability, lookupTag, attributes)
|
||||
is ConeCapturedType -> ConeCapturedType(
|
||||
@@ -165,6 +172,7 @@ fun <T : ConeKotlinType> T.withNullability(
|
||||
is ConeErrorType -> this
|
||||
is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, typeArguments, nullability.isNullable, attributes)
|
||||
is ConeTypeParameterTypeImpl -> ConeTypeParameterTypeImpl(lookupTag, nullability.isNullable, attributes)
|
||||
is ConeDynamicType -> this
|
||||
is ConeFlexibleType -> {
|
||||
if (nullability == ConeNullability.UNKNOWN) {
|
||||
if (lowerBound.nullability != upperBound.nullability || lowerBound.nullability == ConeNullability.UNKNOWN) {
|
||||
|
||||
+1
-1
@@ -523,7 +523,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
) to (result as? TypeResolutionResult.Resolved)?.typeCandidate?.diagnostic
|
||||
}
|
||||
is FirFunctionTypeRef -> createFunctionalType(typeRef) to null
|
||||
is FirDynamicTypeRef -> ConeErrorType(ConeUnsupportedDynamicType()) to null
|
||||
is FirDynamicTypeRef -> ConeDynamicType.create(session) to null
|
||||
is FirIntersectionTypeRef -> {
|
||||
val leftType = typeRef.leftType.coneType
|
||||
val rightType = typeRef.rightType.coneType
|
||||
|
||||
Vendored
+1
-1
@@ -42,7 +42,7 @@ fun test(i: Inv<Nothing>, iUnit: Inv<Unit>) {
|
||||
}
|
||||
launch {
|
||||
@Suppress("UNSUPPORTED")
|
||||
run<dynamic> <!ARGUMENT_TYPE_MISMATCH!>{ "" }<!>
|
||||
run<dynamic> { "" }
|
||||
}
|
||||
|
||||
if (iUnit is String) {
|
||||
|
||||
+12
-12
@@ -221,18 +221,18 @@ fun case_13() {
|
||||
val x3 = null as MutableList<Int>
|
||||
val x4 = select(null as List<Int>, null)
|
||||
|
||||
val result_1 = select(x1, <!ARGUMENT_TYPE_MISMATCH!>x2<!>, x3, x4)
|
||||
val result_2 = select(<!ARGUMENT_TYPE_MISMATCH!>x2<!>, x1)
|
||||
val result_3 = select(<!ARGUMENT_TYPE_MISMATCH!>x2<!>, x1, x3)
|
||||
val result_4 = select(x3, <!ARGUMENT_TYPE_MISMATCH!>x2<!>)
|
||||
val result_5 = select(x4, <!ARGUMENT_TYPE_MISMATCH!>x2<!>)
|
||||
val result_6 = select(x4, x3, <!ARGUMENT_TYPE_MISMATCH!>x2<!>)
|
||||
val result_7 = select(A(x1), A(<!ARGUMENT_TYPE_MISMATCH!>x2<!>), A(x3), A(x4))
|
||||
val result_8 = select(A(<!ARGUMENT_TYPE_MISMATCH!>x2<!>), A(x1))
|
||||
val result_9 = select(A(<!ARGUMENT_TYPE_MISMATCH!>x2<!>), A(x1), A(x3))
|
||||
val result_10 = select(A(x3), A(<!ARGUMENT_TYPE_MISMATCH!>x2<!>))
|
||||
val result_11 = select(A(x4), A(<!ARGUMENT_TYPE_MISMATCH!>x2<!>))
|
||||
val result_12 = select(A(x4), A(x3), A(<!ARGUMENT_TYPE_MISMATCH!>x2<!>))
|
||||
val result_1 = select(x1, x2, x3, x4)
|
||||
val result_2 = select(x2, x1)
|
||||
val result_3 = select(x2, x1, x3)
|
||||
val result_4 = select(x3, x2)
|
||||
val result_5 = select(x4, x2)
|
||||
val result_6 = select(x4, x3, x2)
|
||||
val result_7 = select(A(x1), A(x2), A(x3), A(x4))
|
||||
val result_8 = select(A(x2), A(x1))
|
||||
val result_9 = select(A(x2), A(x1), A(x3))
|
||||
val result_10 = select(A(x3), A(x2))
|
||||
val result_11 = select(A(x4), A(x2))
|
||||
val result_12 = select(A(x4), A(x3), A(x2))
|
||||
|
||||
result_1
|
||||
result_2
|
||||
|
||||
+12
-12
@@ -221,18 +221,18 @@ fun case_13() {
|
||||
val x3 = null as MutableList<Int>
|
||||
val x4 = select(null as List<Int>, null)
|
||||
|
||||
val result_1 = select(x1, <!ARGUMENT_TYPE_MISMATCH!>x2<!>, x3, x4)
|
||||
val result_2 = select(<!ARGUMENT_TYPE_MISMATCH!>x2<!>, x1)
|
||||
val result_3 = select(<!ARGUMENT_TYPE_MISMATCH!>x2<!>, x1, x3)
|
||||
val result_4 = select(x3, <!ARGUMENT_TYPE_MISMATCH!>x2<!>)
|
||||
val result_5 = select(x4, <!ARGUMENT_TYPE_MISMATCH!>x2<!>)
|
||||
val result_6 = select(x4, x3, <!ARGUMENT_TYPE_MISMATCH!>x2<!>)
|
||||
val result_7 = select(A(x1), A(<!ARGUMENT_TYPE_MISMATCH!>x2<!>), A(x3), A(x4))
|
||||
val result_8 = select(A(<!ARGUMENT_TYPE_MISMATCH!>x2<!>), A(x1))
|
||||
val result_9 = select(A(<!ARGUMENT_TYPE_MISMATCH!>x2<!>), A(x1), A(x3))
|
||||
val result_10 = select(A(x3), A(<!ARGUMENT_TYPE_MISMATCH!>x2<!>))
|
||||
val result_11 = select(A(x4), A(<!ARGUMENT_TYPE_MISMATCH!>x2<!>))
|
||||
val result_12 = select(A(x4), A(x3), A(<!ARGUMENT_TYPE_MISMATCH!>x2<!>))
|
||||
val result_1 = select(x1, x2, x3, x4)
|
||||
val result_2 = select(x2, x1)
|
||||
val result_3 = select(x2, x1, x3)
|
||||
val result_4 = select(x3, x2)
|
||||
val result_5 = select(x4, x2)
|
||||
val result_6 = select(x4, x3, x2)
|
||||
val result_7 = select(A(x1), A(x2), A(x3), A(x4))
|
||||
val result_8 = select(A(x2), A(x1))
|
||||
val result_9 = select(A(x2), A(x1), A(x3))
|
||||
val result_10 = select(A(x3), A(x2))
|
||||
val result_11 = select(A(x4), A(x2))
|
||||
val result_12 = select(A(x4), A(x3), A(x2))
|
||||
|
||||
result_1
|
||||
result_2
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNSUPPORTED
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
|
||||
expect class Foo {
|
||||
constructor(p: Any)
|
||||
|
||||
fun f1(s: String): Int
|
||||
|
||||
fun f2(s: List<String>?): MutableMap<Boolean?, Foo>
|
||||
|
||||
fun <T : Set<Number>> f3(t: T): T?
|
||||
}
|
||||
|
||||
// MODULE: m2-js()()(m1-common)
|
||||
// FILE: js.kt
|
||||
|
||||
// TODO: do not suppress UNSUPPORTED once JS files in multi-platform tests are analyzed with JS analyzer facade
|
||||
|
||||
actual class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> {
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual constructor(p: dynamic) {}<!>
|
||||
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual fun f1(s: dynamic): dynamic = null!!<!>
|
||||
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual fun f2(s: dynamic): MutableMap<Boolean?, Foo> = null!!<!>
|
||||
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual fun <T : Set<Number>> f3(t: T): dynamic = null!!<!>
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNSUPPORTED
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
|
||||
Reference in New Issue
Block a user