[FIR] Introduce ConeDynamicType

This commit is contained in:
Nikolay Lunyak
2021-12-17 18:09:54 +03:00
committed by teamcity
parent e763197c3e
commit be9e97d044
13 changed files with 66 additions and 63 deletions
@@ -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<")
@@ -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) {
@@ -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
@@ -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) {
@@ -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
@@ -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