diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelTypeAliasChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelTypeAliasChecker.kt index 944a6b6da0f..88277e4702f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelTypeAliasChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelTypeAliasChecker.kt @@ -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, diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt index 5ae2e8abab0..3b1a3a8cb0b 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt @@ -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 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 diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/TypeRenderer.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/TypeRenderer.kt index 3c20cd6170b..7bf93a70370 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/TypeRenderer.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/TypeRenderer.kt @@ -30,6 +30,11 @@ fun ConeKotlinType.render(): String { is ConeLookupTagBasedType -> { "${renderAttributes()}${lookupTag.name.asString()}" } + is ConeDynamicType -> { + buildString { + append("dynamic") + } + } is ConeFlexibleType -> { buildString { append("ft<") diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt index e64c6d8357c..c9050e906fa 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt @@ -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)) diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/TypeExpansionUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/TypeExpansionUtils.kt index ea96b2e839f..7581a602542 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/TypeExpansionUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/TypeExpansionUtils.kt @@ -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) diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt index 0a79b86e6e2..bbe87ec5cca 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt @@ -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? { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt index bc018dc63e5..44a5698f11b 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt @@ -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.withArguments(arguments: Array T.withArguments(replacement: (ConeTypeProjection) -> ConeTypeProjection) = withArguments(typeArguments.map(replacement).toTypedArray()) +@OptIn(DynamicTypeConstructor::class) fun T.withAttributes(attributes: ConeAttributes): T { if (this.attributes == attributes) { return this @@ -136,6 +142,7 @@ fun 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.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) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt index 2f790b5013d..710f308fb0a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt @@ -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 diff --git a/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionToUnitWithNothingType.fir.kt b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionToUnitWithNothingType.fir.kt index 129443ceb90..d75cf202f8e 100644 --- a/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionToUnitWithNothingType.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionToUnitWithNothingType.fir.kt @@ -42,7 +42,7 @@ fun test(i: Inv, iUnit: Inv) { } launch { @Suppress("UNSUPPORTED") - run { "" } + run { "" } } if (iUnit is String) { diff --git a/compiler/testData/diagnostics/tests/inference/upperBounds/flexibilityInCommonSuperTypeCalculation.fir.kt b/compiler/testData/diagnostics/tests/inference/upperBounds/flexibilityInCommonSuperTypeCalculation.fir.kt index 3672992af62..e8d8a8bb02d 100644 --- a/compiler/testData/diagnostics/tests/inference/upperBounds/flexibilityInCommonSuperTypeCalculation.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/upperBounds/flexibilityInCommonSuperTypeCalculation.fir.kt @@ -221,18 +221,18 @@ fun case_13() { val x3 = null as MutableList val x4 = select(null as List, null) - 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)) + 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 diff --git a/compiler/testData/diagnostics/tests/inference/upperBounds/flexibilityInCommonSuperTypeCalculation.ni.fir.kt b/compiler/testData/diagnostics/tests/inference/upperBounds/flexibilityInCommonSuperTypeCalculation.ni.fir.kt index 314b48179dd..fa91611dd6a 100644 --- a/compiler/testData/diagnostics/tests/inference/upperBounds/flexibilityInCommonSuperTypeCalculation.ni.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/upperBounds/flexibilityInCommonSuperTypeCalculation.ni.fir.kt @@ -221,18 +221,18 @@ fun case_13() { val x3 = null as MutableList val x4 = select(null as List, null) - 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)) + 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 diff --git a/compiler/testData/diagnostics/tests/multiplatform/implDynamic.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/implDynamic.fir.kt deleted file mode 100644 index 95cf62ad94b..00000000000 --- a/compiler/testData/diagnostics/tests/multiplatform/implDynamic.fir.kt +++ /dev/null @@ -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?): MutableMap - - fun > 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 Foo { - actual constructor(p: dynamic) {} - - actual fun f1(s: dynamic): dynamic = null!! - - actual fun f2(s: dynamic): MutableMap = null!! - - actual fun > f3(t: T): dynamic = null!! -} diff --git a/compiler/testData/diagnostics/tests/multiplatform/implDynamic.kt b/compiler/testData/diagnostics/tests/multiplatform/implDynamic.kt index 7d4289cd403..7ecc503897e 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/implDynamic.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/implDynamic.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNSUPPORTED // MODULE: m1-common // FILE: common.kt