~
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 1dc13fb..d185e59 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
@@ -187,7 +187,11 @@
class ConeRawType(
lowerBound: ConeSimpleKotlinType,
upperBound: ConeSimpleKotlinType
-) : ConeFlexibleType(lowerBound, upperBound), RawTypeMarker
+) : ConeFlexibleType(lowerBound, upperBound), RawTypeMarker {
+ init {
+ require(upperBound is ConeClassLikeType)
+ }
+}
/*
* Contract of the intersection type: it is flat. It means that
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 6fae545..b43744f 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
@@ -9,16 +9,17 @@
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
+import org.jetbrains.kotlin.fir.resolve.substitution.ConeRawScopeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.FirUnstableSmartcastTypeScope
import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.scopes.scopeForClass
-import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
+import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
@@ -65,6 +66,7 @@
fir.scopeForClass(substitutorByMap(substitution, useSiteSession), useSiteSession, scopeSession)
}
+
is ConeTypeParameterType -> {
val symbol = lookupTag.symbol
scopeSession.getOrBuild(symbol, TYPE_PARAMETER_SCOPE_KEY) {
@@ -75,7 +77,16 @@
intersectionType.scope(useSiteSession, scopeSession, requiredPhase) ?: FirTypeScope.Empty
}
}
- is ConeRawType -> lowerBound.scope(useSiteSession, scopeSession, requiredPhase)
+
+ is ConeRawType -> {
+ require(lowerBound is ConeClassLikeType) {
+ "Bounds of raw types are expected to be a class type, but $lowerBound found"
+ }
+ val fullyExpandedType = (lowerBound as ConeClassLikeType).fullyExpandedType(useSiteSession)
+ val fir = fullyExpandedType.lookupTag.toSymbol(useSiteSession)?.fir as? FirClass ?: return null
+ fir.scopeForClass(ConeRawScopeSubstitutor(useSiteSession), useSiteSession, scopeSession)
+ }
+
is ConeDynamicType -> useSiteSession.dynamicMembersStorage.getDynamicScopeFor(scopeSession)
is ConeFlexibleType -> lowerBound.scope(useSiteSession, scopeSession, requiredPhase)
is ConeIntersectionType -> FirTypeIntersectionScope.prepareIntersectionScope(
@@ -86,6 +97,7 @@
},
this
)
+
is ConeDefinitelyNotNullType -> original.scope(useSiteSession, scopeSession, requiredPhase)
is ConeIntegerConstantOperatorType -> scopeSession.getOrBuildScopeForIntegerConstantOperatorType(useSiteSession, this)
is ConeIntegerLiteralConstantType -> error("ILT should not be in receiver position")
@@ -93,6 +105,13 @@
}
}
+private fun ConeClassLikeType.obtainFirOfClass(useSiteSession: FirSession, requiredPhase: FirResolvePhase): FirClass? {
+ val fullyExpandedType = fullyExpandedType(useSiteSession)
+ val fir = fullyExpandedType.lookupTag.toSymbol(useSiteSession)?.fir as? FirClass ?: return null
+
+ return fir.also { it.symbol.lazyResolveToPhase(requiredPhase) }
+}
+
fun FirClassSymbol<*>.defaultType(): ConeClassLikeType = fir.defaultType()
fun FirClass.defaultType(): ConeClassLikeType =
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 8666ce3..343c635 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
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.fir.resolve.substitution
import org.jetbrains.kotlin.fir.FirSession
+import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
+import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.resolve.withCombinedAttributesFrom
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
@@ -52,7 +54,7 @@
return (newType ?: type.substituteRecursive())
}
- private fun ConeKotlinType.substituteRecursive(): ConeKotlinType? {
+ protected fun ConeKotlinType.substituteRecursive(): ConeKotlinType? {
return when (this) {
is ConeErrorType -> return null
is ConeClassLikeType -> this.substituteArguments()
@@ -63,6 +65,7 @@
if (it.lowerBound == it.upperBound) it.lowerBound
else it
}
+
is ConeCapturedType -> return substituteCapturedType()
is ConeDefinitelyNotNullType -> this.substituteOriginal()
is ConeIntersectionType -> this.substituteIntersectedTypes()
@@ -152,6 +155,7 @@
nullability.isNullable,
attributes
)
+
else -> error("Unknown class-like type to substitute: $this, ${this::class}")
}
}
@@ -221,6 +225,45 @@
override fun hashCode() = hashCode
}
+class ConeRawScopeSubstitutor(
+ private val useSiteSession: FirSession,
+) : AbstractConeSubstitutor(useSiteSession.typeContext) {
+ override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
+ return when {
+ type is ConeTypeParameterType -> {
+ substituteType(
+ listOf(type.lookupTag.symbol).eraseToUpperBounds(useSiteSession)[0] as ConeKotlinType
+ )
+ }
+
+ type is ConeClassLikeType && type.typeArguments.isNotEmpty() -> {
+ val firClass = type.fullyExpandedType(useSiteSession).lookupTag.toFirRegularClassSymbol(useSiteSession) ?: return null
+ return ConeRawType(
+ type.withArguments(firClass.typeParameterSymbols.eraseToUpperBounds(useSiteSession)),
+ type.replaceArgumentsWithStarProjections()
+ )
+ }
+
+ type is ConeFlexibleType -> {
+ val substitutedLowerBound = substituteOrNull(type.lowerBound)
+ val substitutedUpperBound = substituteOrNull(type.upperBound)
+ if (substitutedLowerBound == null && substitutedUpperBound == null) return null
+
+ val newLowerBound = substitutedLowerBound?.lowerBoundIfFlexible() ?: type.lowerBound
+ val newUpperBound = substitutedLowerBound?.lowerBoundIfFlexible() ?: type.lowerBound
+
+ if (newLowerBound.typeArguments.isNotEmpty() || newUpperBound.typeArguments.isNotEmpty()) {
+ return ConeRawType(newLowerBound, newUpperBound)
+ }
+
+ return ConeFlexibleType(newLowerBound, newUpperBound)
+ }
+
+ else -> null
+ }
+ }
+}
+
fun createTypeSubstitutorByTypeConstructor(
map: Map<TypeConstructorMarker, ConeKotlinType>,
context: ConeTypeContext,
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 9986794..88804c5 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
@@ -10,7 +10,6 @@
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
-import org.jetbrains.kotlin.fir.declarations.utils.classId
import org.jetbrains.kotlin.fir.declarations.utils.delegateFields
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.resolve.*
@@ -20,9 +19,10 @@
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
-import org.jetbrains.kotlin.fir.types.ConeErrorType
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
+import org.jetbrains.kotlin.fir.types.ConeErrorType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
+import org.jetbrains.kotlin.fir.types.lowerBoundIfFlexible
class FirKotlinScopeProvider(
val declaredMemberScopeDecorator: (
@@ -165,7 +165,7 @@
useSiteSession,
basicScope,
key, substitutor,
- substitutor.substituteOrSelf(classFirDispatchReceiver.defaultType()) as ConeClassLikeType,
+ substitutor.substituteOrSelf(classFirDispatchReceiver.defaultType()).lowerBoundIfFlexible() as ConeClassLikeType,
skipPrivateMembers,
makeExpect = isFromExpectClass
)
diff --git a/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningOnSAMAdaption.kt b/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningOnSAMAdaption.kt
index c62cb3e..154d883 100644
--- a/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningOnSAMAdaption.kt
+++ b/compiler/testData/diagnostics/tests/warningsForBreakingChanges/capturedTypes/noWarningOnSAMAdaption.kt
@@ -1,17 +1,5 @@
// FIR_IDENTICAL
// SKIP_TXT
-// FILE: TaskProvider.java
-public interface TaskProvider<T extends CharSequence> {
- void configure(Action<? super T> a);
-}
-
-// FILE: main.kt
-fun interface Action<E> {
- fun E.exec()
-}
-
-fun foo(tp: TaskProvider<out CharSequence>) {
- tp.configure {
- length
- }
+fun MutableList<out CharSequence>.foo() {
+ this.add(this.get(0))
}