diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index 9e6b2cec09e..3e720a6b3f5 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -28149,6 +28149,34 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/scopes/protectedVisibility/withSmartcast.kt"); } } + + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/scopes/variantProjections") + @TestDataPath("$PROJECT_ROOT") + public class VariantProjections { + @Test + public void testAllFilesPresentInVariantProjections() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/scopes/variantProjections"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform"); + } + + @Test + @TestMetadata("dataClassCopy.kt") + public void testDataClassCopy() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/variantProjections/dataClassCopy.kt"); + } + + @Test + @TestMetadata("interdependentStarProjections.kt") + public void testInterdependentStarProjections() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/variantProjections/interdependentStarProjections.kt"); + } + + @Test + @TestMetadata("unsafeVarianceAndCovariantProjection.kt") + public void testUnsafeVarianceAndCovariantProjection() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/variantProjections/unsafeVarianceAndCovariantProjection.kt"); + } + } } @Nested diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index 36bed8abf90..3c7a433aa18 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -28149,6 +28149,34 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/scopes/protectedVisibility/withSmartcast.kt"); } } + + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/scopes/variantProjections") + @TestDataPath("$PROJECT_ROOT") + public class VariantProjections { + @Test + public void testAllFilesPresentInVariantProjections() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/scopes/variantProjections"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform"); + } + + @Test + @TestMetadata("dataClassCopy.kt") + public void testDataClassCopy() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/variantProjections/dataClassCopy.kt"); + } + + @Test + @TestMetadata("interdependentStarProjections.kt") + public void testInterdependentStarProjections() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/variantProjections/interdependentStarProjections.kt"); + } + + @Test + @TestMetadata("unsafeVarianceAndCovariantProjection.kt") + public void testUnsafeVarianceAndCovariantProjection() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/variantProjections/unsafeVarianceAndCovariantProjection.kt"); + } + } } @Nested diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/complex.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/complex.dot index e68bd6e6ab2..61e266364b3 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/complex.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/complex.dot @@ -185,7 +185,7 @@ digraph complex_kt { color=blue 55 [label="Enter block"]; 56 [label="Access variable this@R|/firstIsInstanceOrNull|"]; - 57 [label="Function call: this@R|/firstIsInstanceOrNull|.R|SubstitutionOverride|>|()" style="filled" fillcolor=yellow]; + 57 [label="Function call: this@R|/firstIsInstanceOrNull|.R|SubstitutionOverride|>|()" style="filled" fillcolor=yellow]; 58 [label="Variable declaration: lval : R|kotlin/collections/Iterator|"]; subgraph cluster_19 { color=blue diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/complex.fir.txt b/compiler/fir/analysis-tests/testData/resolve/cfg/complex.fir.txt index 560e2100256..65905e471e7 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/complex.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/complex.fir.txt @@ -24,7 +24,7 @@ FILE: complex.kt } public final inline fun R|kotlin/collections/List<*>|.firstIsInstanceOrNull(): R|T?| { { - lval : R|kotlin/collections/Iterator| = this@R|/firstIsInstanceOrNull|.R|SubstitutionOverride|>|() + lval : R|kotlin/collections/Iterator| = this@R|/firstIsInstanceOrNull|.R|SubstitutionOverride|>|() while(R|/|.R|SubstitutionOverride|()) { lval element: R|kotlin/Any?| = R|/|.R|SubstitutionOverride|() { diff --git a/compiler/fir/analysis-tests/testData/resolve/typeAliasWithTypeArguments.fir.txt b/compiler/fir/analysis-tests/testData/resolve/typeAliasWithTypeArguments.fir.txt index a8fbfe5eed5..b6fa3dc7732 100644 --- a/compiler/fir/analysis-tests/testData/resolve/typeAliasWithTypeArguments.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/typeAliasWithTypeArguments.fir.txt @@ -77,7 +77,7 @@ FILE: typeAliasWithTypeArguments.kt public final fun test_6(a: R|A|, out1: R|Out1|, out2: R|Out1|, out3: R|Out1|): R|kotlin/Unit| { R|/out1|.R|SubstitutionOverride|().R|/A.foo|() R|/out2|.#().#() - R|/out3|.R|SubstitutionOverride|().R|/A.foo|() + R|/out3|.R|SubstitutionOverride|().R|/A.foo|() } public final fun test_7(a: R|A|, inv1: R|Invariant1|, inv2: R|Invariant1|, inv3: R|Invariant1|): R|kotlin/Unit| { R|/inv1|.R|SubstitutionOverride|().R|/A.foo|() diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index 29701d5bd17..c7378628e93 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -28149,6 +28149,34 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/scopes/protectedVisibility/withSmartcast.kt"); } } + + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/scopes/variantProjections") + @TestDataPath("$PROJECT_ROOT") + public class VariantProjections { + @Test + public void testAllFilesPresentInVariantProjections() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/scopes/variantProjections"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform"); + } + + @Test + @TestMetadata("dataClassCopy.kt") + public void testDataClassCopy() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/variantProjections/dataClassCopy.kt"); + } + + @Test + @TestMetadata("interdependentStarProjections.kt") + public void testInterdependentStarProjections() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/variantProjections/interdependentStarProjections.kt"); + } + + @Test + @TestMetadata("unsafeVarianceAndCovariantProjection.kt") + public void testUnsafeVarianceAndCovariantProjection() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/variantProjections/unsafeVarianceAndCovariantProjection.kt"); + } + } } @Nested diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index b02311885f1..6078b46b511 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -28161,6 +28161,34 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/scopes/protectedVisibility/withSmartcast.kt"); } } + + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/scopes/variantProjections") + @TestDataPath("$PROJECT_ROOT") + public class VariantProjections { + @Test + public void testAllFilesPresentInVariantProjections() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/scopes/variantProjections"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform"); + } + + @Test + @TestMetadata("dataClassCopy.kt") + public void testDataClassCopy() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/variantProjections/dataClassCopy.kt"); + } + + @Test + @TestMetadata("interdependentStarProjections.kt") + public void testInterdependentStarProjections() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/variantProjections/interdependentStarProjections.kt"); + } + + @Test + @TestMetadata("unsafeVarianceAndCovariantProjection.kt") + public void testUnsafeVarianceAndCovariantProjection() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/variantProjections/unsafeVarianceAndCovariantProjection.kt"); + } + } } @Nested diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirUpperBoundViolatedHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirUpperBoundViolatedHelpers.kt index 2b481492c7d..9c29402d0cb 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirUpperBoundViolatedHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirUpperBoundViolatedHelpers.kt @@ -21,7 +21,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.types.AbstractTypeChecker -import org.jetbrains.kotlin.types.TypeApproximatorConfiguration import kotlin.reflect.KClass /** @@ -88,14 +87,6 @@ private class FE10LikeConeSubstitutor( projection.type!!.updateNullabilityIfNeeded(type)?.withCombinedAttributesFrom(type) ?: return null - if (type.isUnsafeVarianceType(useSiteSession)) { - useSiteSession.typeApproximator.approximateToSuperType( - result, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference - )?.let { - return it.withProjection(projection) - } - } - return result.withProjection(projection) } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt index b49ce1f243a..4c52578b664 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt @@ -11,8 +11,11 @@ import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.utils.classId -import org.jetbrains.kotlin.fir.resolve.* +import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.createSubstitutionForScope +import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider +import org.jetbrains.kotlin.fir.resolve.scopeSessionKey import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope import org.jetbrains.kotlin.fir.scopes.FirTypeScope @@ -82,7 +85,7 @@ private fun wrapSubstitutionScopeIfNeed( // is called on an external type, like MyMap, // to determine parameter types properly (e.g. String, String instead of K, V) val platformTypeParameters = platformClass.typeParameters - val platformSubstitution = createSubstitution(platformTypeParameters, declaration.defaultType(), session) + val platformSubstitution = createSubstitutionForScope(platformTypeParameters, declaration.defaultType(), session) val substitutor = substitutorByMap(platformSubstitution, session) FirClassSubstitutionScope( session, useSiteMemberScope, PLATFORM_TYPE_PARAMETERS_SUBSTITUTION_SCOPE_KEY, substitutor, @@ -94,4 +97,3 @@ private fun wrapSubstitutionScopeIfNeed( } private val PLATFORM_TYPE_PARAMETERS_SUBSTITUTION_SCOPE_KEY = scopeSessionKey, FirTypeScope>() - diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt index 797e2c63671..5b94f8cb37f 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt @@ -119,7 +119,7 @@ private fun ConeClassLikeType.classScope( val substitutor = when { attributes.contains(CompilerConeAttributes.RawType) -> ConeRawScopeSubstitutor(useSiteSession) else -> substitutorByMap( - createSubstitution(fir.typeParameters, fullyExpandedType, useSiteSession), + createSubstitutionForScope(fir.typeParameters, fullyExpandedType, useSiteSession), useSiteSession, ) } diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt index 4aa7b22895c..12c6846b401 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt @@ -18,10 +18,11 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag -import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.types.TypeApproximatorConfiguration +import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.model.CaptureStatus import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartSet @@ -178,29 +179,54 @@ inline fun scopeSessionKey(): ScopeSes val USE_SITE = scopeSessionKey, FirTypeScope>() /* TODO REMOVE */ -fun createSubstitution( +fun createSubstitutionForScope( typeParameters: List, // TODO: or really declared? type: ConeClassLikeType, session: FirSession ): Map { val capturedOrType = session.typeContext.captureFromArguments(type, CaptureStatus.FROM_EXPRESSION) ?: type - val typeArguments = (capturedOrType as ConeClassLikeType).typeArguments - return typeParameters.zip(typeArguments) { typeParameter, typeArgument -> - val typeParameterSymbol = typeParameter.symbol - typeParameterSymbol to when (typeArgument) { - is ConeKotlinTypeProjection -> { - typeArgument.type - } - else /* StarProjection */ -> { - ConeTypeIntersector.intersectTypes( - session.typeContext, - typeParameterSymbol.resolvedBounds.map { it.coneType } - ) - } + val capturedTypeArguments = (capturedOrType as ConeClassLikeType).typeArguments + + return typeParameters.withIndex().mapNotNull { (index, typeParameter) -> + val capturedTypeArgument = capturedTypeArguments.getOrNull(index) ?: return@mapNotNull null + require(capturedTypeArgument is ConeKotlinType) { + "There should left no projections after capture conversion, but $capturedTypeArgument found at $index" } + val originalTypeArgument = type.typeArguments.getOrNull(index) ?: return@mapNotNull null + + val typeParameterSymbol = typeParameter.symbol + val resultingArgument = + computeNonTrivialTypeArgumentForScopeSubstitutor(typeParameterSymbol, originalTypeArgument, session, capturedTypeArgument) + ?: capturedTypeArgument + + typeParameterSymbol to resultingArgument }.toMap() } +/** + * Returns null if `capturedTypeArgument` should be used + */ +private fun computeNonTrivialTypeArgumentForScopeSubstitutor( + typeParameterSymbol: FirTypeParameterSymbol, + originalTypeArgument: ConeTypeProjection, + session: FirSession, + capturedTypeArgument: ConeKotlinType +): ConeKotlinType? { + // We don't do anything for contravariant parameters (IN), because their UnsafeVariance usages are mostly return type. + // And if we continue using captured types for them, they will just be approximated (as return types) as they've been before. + if (typeParameterSymbol.variance != Variance.OUT_VARIANCE) return null + + return when (originalTypeArgument.kind) { + // Out is the same as Out + ProjectionKind.OUT -> originalTypeArgument.type!! + // Out<*> is the same as Out (i.e. Out) + ProjectionKind.STAR -> session.typeApproximator.approximateToSuperType( + capturedTypeArgument, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference + ) + else -> null + } +} + private fun ConeClassLikeType.computePartialExpansion( useSiteSession: FirSession, supertypeSupplier: SupertypeSupplier diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt index 54b9c67037f..a86b23bf840 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt @@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.name.StandardClassIds -import org.jetbrains.kotlin.types.TypeApproximatorConfiguration import org.jetbrains.kotlin.types.model.TypeConstructorMarker import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker import org.jetbrains.kotlin.types.model.TypeVariableMarker @@ -204,16 +203,9 @@ class ConeSubstitutorByMap( override fun substituteType(type: ConeKotlinType): ConeKotlinType? { if (type !is ConeTypeParameterType) return null - val result = - substitution[type.lookupTag.symbol].updateNullabilityIfNeeded(type) - ?.withCombinedAttributesFrom(type) - ?: return null - if (type.isUnsafeVarianceType(useSiteSession)) { - return useSiteSession.typeApproximator.approximateToSuperType( - result, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference - ) ?: result - } - return result + return substitution[type.lookupTag.symbol].updateNullabilityIfNeeded(type) + ?.withCombinedAttributesFrom(type) + ?: return null } override fun equals(other: Any?): Boolean { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirKotlinScopeProvider.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirKotlinScopeProvider.kt index 34a1bd7cf05..dd32065dd2d 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirKotlinScopeProvider.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirKotlinScopeProvider.kt @@ -159,7 +159,7 @@ fun ConeKotlinType.scopeForSupertype( private fun substitutor(symbol: FirRegularClassSymbol, type: ConeClassLikeType, useSiteSession: FirSession): ConeSubstitutor { if (type.typeArguments.isEmpty()) return ConeSubstitutor.Empty - val originalSubstitution = createSubstitution(symbol.fir.typeParameters, type, useSiteSession) + val originalSubstitution = createSubstitutionForScope(symbol.fir.typeParameters, type, useSiteSession) return substitutorByMap(originalSubstitution, useSiteSession) } 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 4710d95d69a..7b86f774b07 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 @@ -241,11 +241,6 @@ fun FirTypeRef.isExtensionFunctionType(session: FirSession): Boolean { return coneTypeSafe()?.isExtensionFunctionType(session) == true } -fun ConeKotlinType.isUnsafeVarianceType(session: FirSession): Boolean { - val type = this.coneLowerBoundIfFlexible().fullyExpandedType(session) - return type.attributes.unsafeVarianceType != null -} - fun ConeKotlinType.toSymbol(session: FirSession): FirClassifierSymbol<*>? { return (this as? ConeLookupTagBasedType)?.lookupTag?.toSymbol(session) } diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.fir.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.fir.kt deleted file mode 100644 index ca0d9acc14c..00000000000 --- a/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.fir.kt +++ /dev/null @@ -1,11 +0,0 @@ -class Foo(val baz: Baz) - -class Bar { - val foo: Foo<*> = TODO() - - fun bar(): Baz { - return foo.baz - } -} - -typealias Baz = (@UnsafeVariance T) -> Unit diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.kt index 05ad642e149..5bdf285f2ea 100644 --- a/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.kt +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// ISSUE: KT-54894 class Foo(val baz: Baz) class Bar { diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypesSubstitutionIntoAbbreviation.fir.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypesSubstitutionIntoAbbreviation.fir.kt index d7561d83ff1..80876c7b852 100644 --- a/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypesSubstitutionIntoAbbreviation.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypesSubstitutionIntoAbbreviation.fir.kt @@ -25,7 +25,7 @@ fun main() { ")!>getTag3().action ")!>getTag4().action ")!>getTag5().action - ")!>getTag6().action - ")!>getTag7().action - ")!>getTag8().action + ")!>getTag6().action + ")!>getTag7().action + ")!>getTag8().action } diff --git a/compiler/testData/diagnostics/tests/scopes/variantProjections/dataClassCopy.fir.kt b/compiler/testData/diagnostics/tests/scopes/variantProjections/dataClassCopy.fir.kt new file mode 100644 index 00000000000..1c3571725fc --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/variantProjections/dataClassCopy.fir.kt @@ -0,0 +1,13 @@ +// ISSUE: KT-54764 + +data class Out(val prop: T) + +fun foo(b: Out<*>) { + b.copy("") // error in K1, OK in K2 +} + +fun foo(a: Any) { + if (a is Out<*>) { + a.copy("") + } +} diff --git a/compiler/testData/diagnostics/tests/scopes/variantProjections/dataClassCopy.kt b/compiler/testData/diagnostics/tests/scopes/variantProjections/dataClassCopy.kt new file mode 100644 index 00000000000..315b2e2f7b4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/variantProjections/dataClassCopy.kt @@ -0,0 +1,13 @@ +// ISSUE: KT-54764 + +data class Out(val prop: T) + +fun foo(b: Out<*>) { + b.copy("") // error in K1, OK in K2 +} + +fun foo(a: Any) { + if (a is Out<*>) { + a.copy("") + } +} diff --git a/compiler/testData/diagnostics/tests/scopes/variantProjections/interdependentStarProjections.fir.kt b/compiler/testData/diagnostics/tests/scopes/variantProjections/interdependentStarProjections.fir.kt new file mode 100644 index 00000000000..0b49a5bc7cc --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/variantProjections/interdependentStarProjections.fir.kt @@ -0,0 +1,13 @@ +// ISSUE: KT-54764 + +interface A, F, out E : B> { + fun copy(t: @UnsafeVariance T, f: F, e: @UnsafeVariance E): A +} + +interface B + +fun foo(a: A<*, String, B<*, String>>, b1: B<*, String>, b2: B<*, *>, b3: B>) { + >, kotlin.String, B<*, kotlin.String>>")!>a.copy(b2, "", b1) + >, kotlin.String, B<*, kotlin.String>>")!>a.copy(b1, "", b1) + >, kotlin.String, B<*, kotlin.String>>")!>a.copy(b3, "", b1) +} diff --git a/compiler/testData/diagnostics/tests/scopes/variantProjections/interdependentStarProjections.kt b/compiler/testData/diagnostics/tests/scopes/variantProjections/interdependentStarProjections.kt new file mode 100644 index 00000000000..a1f52a6e034 --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/variantProjections/interdependentStarProjections.kt @@ -0,0 +1,13 @@ +// ISSUE: KT-54764 + +interface A, F, out E : B> { + fun copy(t: @UnsafeVariance T, f: F, e: @UnsafeVariance E): A +} + +interface B + +fun foo(a: A<*, String, B<*, String>>, b1: B<*, String>, b2: B<*, *>, b3: B>) { + , kotlin.String, B>")!>a.copy(b2, "", b1) + , kotlin.String, B>")!>a.copy(b1, "", b1) + , kotlin.String, B>")!>a.copy(b3, "", b1) +} diff --git a/compiler/testData/diagnostics/tests/scopes/variantProjections/unsafeVarianceAndCovariantProjection.kt b/compiler/testData/diagnostics/tests/scopes/variantProjections/unsafeVarianceAndCovariantProjection.kt new file mode 100644 index 00000000000..0f96c0b4343 --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/variantProjections/unsafeVarianceAndCovariantProjection.kt @@ -0,0 +1,32 @@ +// FIR_IDENTICAL +// ISSUE: KT-54764 + +interface Out1 { + fun copy(t: @UnsafeVariance T): Out1 +} + +fun foo1(o1: Out1<*>, o2: Out1<out Any?>, o3: Out1) { + ")!>o1.copy("") + ")!>o2.copy("") + ")!>o3.copy("") +} + +interface Out2 { + fun copy(t: @UnsafeVariance T): Out2 +} + +fun foo2(o1: Out2<*>, o2: Out2<out CharSequence>, o3: Out2) { + ")!>o1.copy("") + ")!>o2.copy("") + ")!>o3.copy("") +} + +interface Out3> { + fun copy(t: @UnsafeVariance T): Out3 +} + +fun foo3(o1: Out3<*>, o2: Out3<out Out3<*>>, o3: Out3>) { + >")!>o1.copy(o1) + >")!>o2.copy(o1) + >")!>o3.copy(o1) +} diff --git a/compiler/testData/ir/irText/types/typeAliasWithUnsafeVariance.fir.ir.txt b/compiler/testData/ir/irText/types/typeAliasWithUnsafeVariance.fir.ir.txt index 55c42ca5057..38f6289f35f 100644 --- a/compiler/testData/ir/irText/types/typeAliasWithUnsafeVariance.fir.ir.txt +++ b/compiler/testData/ir/irText/types/typeAliasWithUnsafeVariance.fir.ir.txt @@ -99,5 +99,5 @@ FILE fqName: fileName:/typeAliasWithUnsafeVariance.kt FUN name:doAction visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit - CALL 'public final fun (): kotlin.Function1.Tag, kotlin.Unit> declared in .Tag' type=kotlin.Function1 origin=GET_PROPERTY + CALL 'public final fun (): kotlin.Function1.Tag, kotlin.Unit> declared in .Tag' type=kotlin.Function1 origin=GET_PROPERTY $this: CALL 'public final fun getTag (): .Tag<*> declared in ' type=.Tag<*> origin=null diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 48c59bb8afe..a4555d1ac09 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -28909,6 +28909,34 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/scopes/protectedVisibility/withSmartcast.kt"); } } + + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/scopes/variantProjections") + @TestDataPath("$PROJECT_ROOT") + public class VariantProjections { + @Test + public void testAllFilesPresentInVariantProjections() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/scopes/variantProjections"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true); + } + + @Test + @TestMetadata("dataClassCopy.kt") + public void testDataClassCopy() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/variantProjections/dataClassCopy.kt"); + } + + @Test + @TestMetadata("interdependentStarProjections.kt") + public void testInterdependentStarProjections() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/variantProjections/interdependentStarProjections.kt"); + } + + @Test + @TestMetadata("unsafeVarianceAndCovariantProjection.kt") + public void testUnsafeVarianceAndCovariantProjection() throws Exception { + runTest("compiler/testData/diagnostics/tests/scopes/variantProjections/unsafeVarianceAndCovariantProjection.kt"); + } + } } @Nested diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/9.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/9.fir.kt index ba61554b849..5108945f4a5 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/9.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/9.fir.kt @@ -26,26 +26,26 @@ fun case_2(a: Out<out Out<out if (a != null) { val b = ?>?>?>?>?>? & Out?>?>?>?>?>")!>a.get() if (b != null) { - val c = ?>?>?>?>? & Out?>?>?>?>")!>b.get() + val c = ?>?>?>?>? & Out?>?>?>?>")!>b.get() if (c != null) { - val d = ?>?>?>? & Out?>?>?>")!>c.get() + val d = ?>?>?>? & Out?>?>?>")!>c.get() if (d != null) { - val e = ?>?>? & Out?>?>")!>d.get() + val e = ?>?>? & Out?>?>")!>d.get() if (e != null) { - val f = ?>? & Out?>")!>e.get() + val f = ?>? & Out?>")!>e.get() if (f != null) { - val g = ? & Out")!>f.get() + val g = ? & Out")!>f.get() if (g != null) { - g - g.equals(null) - g.propT - g.propAny - g.propNullableT - g.propNullableAny - g.funT() - g.funAny() - g.funNullableT() - g.funNullableAny() + g + g.equals(null) + g.propT + g.propAny + g.propNullableT + g.propNullableAny + g.funT() + g.funAny() + g.funNullableT() + g.funNullableAny() } } }