K2: Rework scopes for types with projection arguments for Out types

The only case when behavior is change is described at
 computeNonTrivialTypeArgumentForScopeSubstitutor

The idea is to avoid depending on the presence of @UnsafeVariance
and instead approximate captured types in covariant argument positions
before building substitution scopes

It's correct because for Captured(*) <: Supertype,
Out<Captured(*)> <: Out<Supertype> and when we've got @UnsafeVariance
value parameters at Out, it's ok to allow passing Supertype there.

^KT-57602 Fixed
^KT-54894 Fixed
This commit is contained in:
Denis.Zharkov
2023-03-24 17:21:03 +01:00
committed by Space Team
parent 1cd040fd6a
commit 55a58e54fe
25 changed files with 300 additions and 79 deletions
@@ -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
@@ -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
@@ -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<kotlin/collections/List.iterator: R|kotlin/collections/Iterator<CapturedType(*)>|>|()" style="filled" fillcolor=yellow];
57 [label="Function call: this@R|/firstIsInstanceOrNull|.R|SubstitutionOverride<kotlin/collections/List.iterator: R|kotlin/collections/Iterator<kotlin/Any?>|>|()" style="filled" fillcolor=yellow];
58 [label="Variable declaration: lval <iterator>: R|kotlin/collections/Iterator<kotlin/Any?>|"];
subgraph cluster_19 {
color=blue
@@ -24,7 +24,7 @@ FILE: complex.kt
}
public final inline fun <reified T : R|kotlin/Any|> R|kotlin/collections/List<*>|.firstIsInstanceOrNull(): R|T?| {
{
lval <iterator>: R|kotlin/collections/Iterator<kotlin/Any?>| = this@R|/firstIsInstanceOrNull|.R|SubstitutionOverride<kotlin/collections/List.iterator: R|kotlin/collections/Iterator<CapturedType(*)>|>|()
lval <iterator>: R|kotlin/collections/Iterator<kotlin/Any?>| = this@R|/firstIsInstanceOrNull|.R|SubstitutionOverride<kotlin/collections/List.iterator: R|kotlin/collections/Iterator<kotlin/Any?>|>|()
while(R|<local>/<iterator>|.R|SubstitutionOverride<kotlin/collections/Iterator.hasNext: R|kotlin/Boolean|>|()) {
lval element: R|kotlin/Any?| = R|<local>/<iterator>|.R|SubstitutionOverride<kotlin/collections/Iterator.next: R|kotlin/Any?|>|()
{
@@ -77,7 +77,7 @@ FILE: typeAliasWithTypeArguments.kt
public final fun test_6(a: R|A|, out1: R|Out1<A>|, out2: R|Out1<in A>|, out3: R|Out1<out A>|): R|kotlin/Unit| {
R|<local>/out1|.R|SubstitutionOverride</Out.value: R|A|>|().R|/A.foo|()
R|<local>/out2|.<Unresolved name: value>#().<Unresolved name: foo>#()
R|<local>/out3|.R|SubstitutionOverride</Out.value: R|CapturedType(out A)|>|().R|/A.foo|()
R|<local>/out3|.R|SubstitutionOverride</Out.value: R|A|>|().R|/A.foo|()
}
public final fun test_7(a: R|A|, inv1: R|Invariant1<A>|, inv2: R|Invariant1<in A>|, inv3: R|Invariant1<out A>|): R|kotlin/Unit| {
R|<local>/inv1|.R|SubstitutionOverride</Invariant.value: R|A|>|().R|/A.foo|()
@@ -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
@@ -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
@@ -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)
}
@@ -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<String, String>,
// 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<FirClassSymbol<*>, FirTypeScope>()
@@ -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,
)
}
@@ -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 <reified ID : Any, reified FS : FirScope> scopeSessionKey(): ScopeSes
val USE_SITE = scopeSessionKey<FirClassSymbol<*>, FirTypeScope>()
/* TODO REMOVE */
fun createSubstitution(
fun createSubstitutionForScope(
typeParameters: List<FirTypeParameterRef>, // TODO: or really declared?
type: ConeClassLikeType,
session: FirSession
): Map<FirTypeParameterSymbol, ConeKotlinType> {
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<out T> is the same as Out<T>
ProjectionKind.OUT -> originalTypeArgument.type!!
// Out<*> is the same as Out<SubstitutedUpperBounds> (i.e. Out<Supertype(CapturedType(*))>)
ProjectionKind.STAR -> session.typeApproximator.approximateToSuperType(
capturedTypeArgument, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
)
else -> null
}
}
private fun ConeClassLikeType.computePartialExpansion(
useSiteSession: FirSession,
supertypeSupplier: SupertypeSupplier
@@ -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 {
@@ -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)
}
@@ -241,11 +241,6 @@ fun FirTypeRef.isExtensionFunctionType(session: FirSession): Boolean {
return coneTypeSafe<ConeKotlinType>()?.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)
}
@@ -1,11 +0,0 @@
class Foo<out T>(val baz: Baz<T>)
class Bar {
val foo: Foo<*> = TODO()
fun <T> bar(): Baz<T> {
return <!RETURN_TYPE_MISMATCH!>foo.baz<!>
}
}
typealias Baz<T> = (@UnsafeVariance T) -> Unit
@@ -1,3 +1,5 @@
// FIR_IDENTICAL
// ISSUE: KT-54894
class Foo<out T>(val baz: Baz<T>)
class Bar {
@@ -25,7 +25,7 @@ fun main() {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Unit>")!>getTag3().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Unit>")!>getTag4().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Any?>")!>getTag5().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Unit>")!>getTag6().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Unit>")!>getTag7().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Any?>")!>getTag8().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action<in kotlin.Any?>")!>getTag6().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action<kotlin.Any?>")!>getTag7().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action2<kotlin.Any?>")!>getTag8().action<!>
}
@@ -0,0 +1,13 @@
// ISSUE: KT-54764
data class Out<out T>(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("")
}
}
@@ -0,0 +1,13 @@
// ISSUE: KT-54764
data class Out<out T>(val prop: T)
fun foo(b: Out<*>) {
b.copy(<!TYPE_MISMATCH!>""<!>) // error in K1, OK in K2
}
fun foo(a: Any) {
if (a is Out<*>) {
<!DEBUG_INFO_SMARTCAST!>a<!>.copy("")
}
}
@@ -0,0 +1,13 @@
// ISSUE: KT-54764
interface A<out T : B<F, E>, F, out E : B<T, F>> {
fun copy(t: @UnsafeVariance T, f: F, e: @UnsafeVariance E): A<T, F, E>
}
interface B<out X, out Y>
fun foo(a: A<*, String, B<*, String>>, b1: B<*, String>, b2: B<*, *>, b3: B<String, B<*, String>>) {
<!DEBUG_INFO_EXPRESSION_TYPE("A<B<kotlin.String, B<*, kotlin.String>>, kotlin.String, B<*, kotlin.String>>")!>a.copy(<!ARGUMENT_TYPE_MISMATCH!>b2<!>, "", b1)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("A<B<kotlin.String, B<*, kotlin.String>>, kotlin.String, B<*, kotlin.String>>")!>a.copy(<!ARGUMENT_TYPE_MISMATCH!>b1<!>, "", b1)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("A<B<kotlin.String, B<*, kotlin.String>>, kotlin.String, B<*, kotlin.String>>")!>a.copy(b3, "", b1)<!>
}
@@ -0,0 +1,13 @@
// ISSUE: KT-54764
interface A<out T : B<F, E>, F, out E : B<T, F>> {
fun copy(t: @UnsafeVariance T, f: F, e: @UnsafeVariance E): A<T, F, E>
}
interface B<out X, out Y>
fun foo(a: A<*, String, B<*, String>>, b1: B<*, String>, b2: B<*, *>, b3: B<String, B<*, String>>) {
<!DEBUG_INFO_EXPRESSION_TYPE("A<B<*, *>, kotlin.String, B<kotlin.Any?, kotlin.String>>")!>a.copy(b2, "", b1)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("A<B<*, *>, kotlin.String, B<kotlin.Any?, kotlin.String>>")!>a.copy(b1, "", b1)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("A<B<*, *>, kotlin.String, B<kotlin.Any?, kotlin.String>>")!>a.copy(b3, "", b1)<!>
}
@@ -0,0 +1,32 @@
// FIR_IDENTICAL
// ISSUE: KT-54764
interface Out1<out T> {
fun copy(t: @UnsafeVariance T): Out1<T>
}
fun foo1(o1: Out1<*>, o2: Out1<<!REDUNDANT_PROJECTION!>out<!> Any?>, o3: Out1<Any?>) {
<!DEBUG_INFO_EXPRESSION_TYPE("Out1<kotlin.Any?>")!>o1.copy("")<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Out1<kotlin.Any?>")!>o2.copy("")<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Out1<kotlin.Any?>")!>o3.copy("")<!>
}
interface Out2<out T : CharSequence> {
fun copy(t: @UnsafeVariance T): Out2<T>
}
fun foo2(o1: Out2<*>, o2: Out2<<!REDUNDANT_PROJECTION!>out<!> CharSequence>, o3: Out2<CharSequence>) {
<!DEBUG_INFO_EXPRESSION_TYPE("Out2<kotlin.CharSequence>")!>o1.copy("")<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Out2<kotlin.CharSequence>")!>o2.copy("")<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Out2<kotlin.CharSequence>")!>o3.copy("")<!>
}
interface Out3<out T : Out3<T>> {
fun copy(t: @UnsafeVariance T): Out3<T>
}
fun foo3(o1: Out3<*>, o2: Out3<<!REDUNDANT_PROJECTION!>out<!> Out3<*>>, o3: Out3<Out3<*>>) {
<!DEBUG_INFO_EXPRESSION_TYPE("Out3<Out3<*>>")!>o1.copy(o1)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Out3<Out3<*>>")!>o2.copy(o1)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Out3<Out3<*>>")!>o3.copy(o1)<!>
}
@@ -99,5 +99,5 @@ FILE fqName:<root> 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 <get-action> (): kotlin.Function1<RenderingT of <root>.Tag, kotlin.Unit> declared in <root>.Tag' type=kotlin.Function1<kotlin.Nothing, kotlin.Unit> origin=GET_PROPERTY
CALL 'public final fun <get-action> (): kotlin.Function1<RenderingT of <root>.Tag, kotlin.Unit> declared in <root>.Tag' type=kotlin.Function1<kotlin.Any?, kotlin.Unit> origin=GET_PROPERTY
$this: CALL 'public final fun getTag (): <root>.Tag<*> declared in <root>' type=<root>.Tag<*> origin=null
@@ -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
@@ -26,26 +26,26 @@ fun case_2(a: Out<<!REDUNDANT_PROJECTION!>out<!> Out<<!REDUNDANT_PROJECTION!>out
if (a != null) {
val b = <!DEBUG_INFO_EXPRESSION_TYPE("Out<out Out<out Out<out Out<out Out<out Out<out kotlin.Int?>?>?>?>?>?>? & Out<out Out<out Out<out Out<out Out<out Out<out kotlin.Int?>?>?>?>?>?>")!>a<!>.get()
if (b != null) {
val c = <!DEBUG_INFO_EXPRESSION_TYPE("Out<Out<Out<Out<Out<kotlin.Any?>?>?>?>?>? & Out<Out<Out<Out<Out<kotlin.Any?>?>?>?>?>")!>b<!>.get()
val c = <!DEBUG_INFO_EXPRESSION_TYPE("Out<out Out<out Out<out Out<out Out<out kotlin.Int?>?>?>?>?>? & Out<out Out<out Out<out Out<out Out<out kotlin.Int?>?>?>?>?>")!>b<!>.get()
if (c != null) {
val d = <!DEBUG_INFO_EXPRESSION_TYPE("Out<Out<Out<Out<kotlin.Any?>?>?>?>? & Out<Out<Out<Out<kotlin.Any?>?>?>?>")!>c<!>.get()
val d = <!DEBUG_INFO_EXPRESSION_TYPE("Out<out Out<out Out<out Out<out kotlin.Int?>?>?>?>? & Out<out Out<out Out<out Out<out kotlin.Int?>?>?>?>")!>c<!>.get()
if (d != null) {
val e = <!DEBUG_INFO_EXPRESSION_TYPE("Out<Out<Out<kotlin.Any?>?>?>? & Out<Out<Out<kotlin.Any?>?>?>")!>d<!>.get()
val e = <!DEBUG_INFO_EXPRESSION_TYPE("Out<out Out<out Out<out kotlin.Int?>?>?>? & Out<out Out<out Out<out kotlin.Int?>?>?>")!>d<!>.get()
if (e != null) {
val f = <!DEBUG_INFO_EXPRESSION_TYPE("Out<Out<kotlin.Any?>?>? & Out<Out<kotlin.Any?>?>")!>e<!>.get()
val f = <!DEBUG_INFO_EXPRESSION_TYPE("Out<out Out<out kotlin.Int?>?>? & Out<out Out<out kotlin.Int?>?>")!>e<!>.get()
if (f != null) {
val g = <!DEBUG_INFO_EXPRESSION_TYPE("Out<kotlin.Any?>? & Out<kotlin.Any?>")!>f<!>.get()
val g = <!DEBUG_INFO_EXPRESSION_TYPE("Out<out kotlin.Int?>? & Out<out kotlin.Int?>")!>f<!>.get()
if (g != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>g<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>g<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>g<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>g<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>g<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>g<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>g<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>g<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>g<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>g<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>g<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>g<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>g<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>g<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>g<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>g<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>g<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>g<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>g<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>g<!>.funNullableAny()
}
}
}