FIR: Preserve K1 behavior for synthetic properties on raw type

^KT-54502 Fixed
This commit is contained in:
Denis.Zharkov
2022-10-20 13:05:25 +02:00
committed by Space Team
parent 7b15b28ee2
commit c0e0900344
7 changed files with 88 additions and 2 deletions
@@ -24223,6 +24223,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/rawTypeInUpperBound.kt");
}
@Test
@TestMetadata("rawTypeSyntheticExtensions.kt")
public void testRawTypeSyntheticExtensions() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/rawTypeSyntheticExtensions.kt");
}
@Test
@TestMetadata("rawWithInProjection.kt")
public void testRawWithInProjection() throws Exception {
@@ -24223,6 +24223,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/rawTypeInUpperBound.kt");
}
@Test
@TestMetadata("rawTypeSyntheticExtensions.kt")
public void testRawTypeSyntheticExtensions() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/rawTypeSyntheticExtensions.kt");
}
@Test
@TestMetadata("rawWithInProjection.kt")
public void testRawWithInProjection() throws Exception {
@@ -24223,6 +24223,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/rawTypeInUpperBound.kt");
}
@Test
@TestMetadata("rawTypeSyntheticExtensions.kt")
public void testRawTypeSyntheticExtensions() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/rawTypeSyntheticExtensions.kt");
}
@Test
@TestMetadata("rawWithInProjection.kt")
public void testRawWithInProjection() throws Exception {
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.lowerBoundIfFlexible
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.model.*
@@ -850,3 +851,18 @@ private fun ConeKotlinType.eraseAsUpperBound(
else -> error("unexpected Java type parameter upper bound kind: $this")
}
fun ConeKotlinType.isRaw(): Boolean = lowerBoundIfFlexible().attributes.contains(CompilerConeAttributes.RawType)
fun ConeKotlinType.convertToNonRawVersion(): ConeKotlinType {
if (!isRaw()) return this
if (this is ConeFlexibleType) {
return ConeFlexibleType(
lowerBound.withAttributes(this.attributes.remove(CompilerConeAttributes.RawType)),
upperBound,
)
}
return withAttributes(attributes.remove(CompilerConeAttributes.RawType))
}
@@ -105,10 +105,31 @@ class MemberScopeTowerLevel(
}
if (givenExtensionReceiverOptions.isEmpty()) {
val dispatchReceiverType = dispatchReceiverValue.type
val useSiteForSyntheticScope: FirTypeScope
val typeForSyntheticScope: ConeKotlinType
// In K1, synthetic properties were working a bit differently
// - On first step they've been built on the per-class level
// - Then, they've been handled as regular extensions with specific receiver value
// In K2, we build those properties using specific use-site scope of given receiver
// And that gives us different results in case of raw types (since we've got special scopes for them)
// So, here we decide to preserve the K1 behavior just by converting the type to its non-raw version
if (dispatchReceiverType.isRaw()) {
typeForSyntheticScope = dispatchReceiverType.convertToNonRawVersion()
useSiteForSyntheticScope =
typeForSyntheticScope.scope(session, scopeSession, FakeOverrideTypeCalculator.DoNothing)
?: error("No scope for flexible type scope, while it's not null for $dispatchReceiverType")
} else {
typeForSyntheticScope = dispatchReceiverType
useSiteForSyntheticScope = scope
}
val withSynthetic = FirSyntheticPropertiesScope.createIfSyntheticNamesProviderIsDefined(
session,
dispatchReceiverValue.type,
scope
typeForSyntheticScope,
useSiteForSyntheticScope,
)
withSynthetic?.processScopeMembers { symbol ->
empty = false
@@ -320,6 +341,7 @@ class ScopeTowerLevel(
(implicitReceiverValue.type as? ConeClassLikeType)?.fullyExpandedType(session)?.lookupTag == lookupTag
}
}
else -> {
bodyResolveComponents.implicitReceiverStack.lastDispatchReceiver()
}
@@ -0,0 +1,24 @@
// SKIP_TXT
// FIR_IDENTICAL
// FILE: Generic.java
import java.util.List;
public class Generic<T extends Generic> {
// Returns Raw type
public static Generic create() { return null; }
public List<String> getFoo() { return null; }
public T getChild() { return null; }
public List<Generic> getChildren() { return null; }
}
// FILE: main.kt
fun main() {
val generic = Generic.create() // has a type of Generic<(raw) Any..Any?>
generic.getFoo() // has return type List<(raw) Any..Any?>
generic.getFoo()[0].<!UNRESOLVED_REFERENCE!>length<!> // Unresolved "length"
generic.foo[0].length // OK
generic.child.children[0].foo[0].length // OK
}
@@ -24229,6 +24229,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/rawTypeInUpperBound.kt");
}
@Test
@TestMetadata("rawTypeSyntheticExtensions.kt")
public void testRawTypeSyntheticExtensions() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/rawTypeSyntheticExtensions.kt");
}
@Test
@TestMetadata("rawWithInProjection.kt")
public void testRawWithInProjection() throws Exception {