FIR substitution: use intersection of bounds for * projection
This commit is contained in:
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.inferenceContext
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
@@ -113,8 +114,19 @@ fun ConeClassLikeType.wrapSubstitutionScopeIfNeed(
|
||||
val typeParameters = (declaration as? FirTypeParametersOwner)?.typeParameters.orEmpty()
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val substitution = typeParameters.zip(this.typeArguments) { typeParameter, typeArgument ->
|
||||
typeParameter.symbol to (typeArgument as? ConeTypedProjection)?.type
|
||||
}.filter { (_, type) -> type != null }.toMap() as Map<FirTypeParameterSymbol, ConeKotlinType>
|
||||
val typeParameterSymbol = typeParameter.symbol
|
||||
typeParameterSymbol to when (typeArgument) {
|
||||
is ConeTypedProjection -> {
|
||||
typeArgument.type
|
||||
}
|
||||
else /* StarProjection */ -> {
|
||||
ConeTypeIntersector.intersectTypes(
|
||||
session.inferenceContext(),
|
||||
typeParameterSymbol.fir.bounds.map { it.coneTypeUnsafe() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}.toMap()
|
||||
|
||||
FirClassSubstitutionScope(session, useSiteMemberScope, builder, substitution)
|
||||
}
|
||||
|
||||
+1
-2
@@ -93,7 +93,7 @@ abstract class AbstractConeSubstitutor : ConeSubstitutor() {
|
||||
}
|
||||
|
||||
private fun ConeDefinitelyNotNullType.substituteOriginal(): ConeDefinitelyNotNullType? {
|
||||
return ConeDefinitelyNotNullType.create(substituteType(original) ?: original)
|
||||
return ConeDefinitelyNotNullType.create(substituteType(original)?.withNullability(ConeNullability.NOT_NULL) ?: original)
|
||||
}
|
||||
|
||||
private fun ConeFlexibleType.substituteBounds(): ConeFlexibleType? {
|
||||
@@ -145,7 +145,6 @@ abstract class AbstractConeSubstitutor : ConeSubstitutor() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun substitutorByMap(substitution: Map<FirTypeParameterSymbol, ConeKotlinType>): ConeSubstitutor {
|
||||
if (substitution.isEmpty()) return ConeSubstitutor.Empty
|
||||
return ConeSubstitutorByMap(substitution)
|
||||
|
||||
+17
-3
@@ -37,8 +37,12 @@ internal inline var FirExpression.resultType: FirTypeRef
|
||||
replaceTypeRef(type)
|
||||
}
|
||||
|
||||
internal fun inferenceComponents(session: FirSession, returnTypeCalculator: ReturnTypeCalculator, scopeSession: ScopeSession) =
|
||||
InferenceComponents(object : ConeInferenceContext, TypeSystemInferenceExtensionContextDelegate, DataFlowInferenceContext {
|
||||
internal interface UniversalConeInferenceContext :
|
||||
ConeInferenceContext, TypeSystemInferenceExtensionContextDelegate, DataFlowInferenceContext
|
||||
|
||||
internal fun FirSession.inferenceContext(): UniversalConeInferenceContext {
|
||||
val session = this
|
||||
return object : UniversalConeInferenceContext {
|
||||
override fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List<SimpleTypeMarker>): SimpleTypeMarker? {
|
||||
// TODO: implement
|
||||
return null
|
||||
@@ -59,4 +63,14 @@ internal fun inferenceComponents(session: FirSession, returnTypeCalculator: Retu
|
||||
require(this is ErrorTypeConstructor)
|
||||
return ConeClassErrorType(reason)
|
||||
}
|
||||
}, session, returnTypeCalculator, scopeSession)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun inferenceComponents(
|
||||
session: FirSession,
|
||||
returnTypeCalculator: ReturnTypeCalculator,
|
||||
scopeSession: ScopeSession
|
||||
): InferenceComponents {
|
||||
val inferenceContext = session.inferenceContext()
|
||||
return InferenceComponents(inferenceContext, session, returnTypeCalculator, scopeSession)
|
||||
}
|
||||
+4
-4
@@ -325,8 +325,8 @@ digraph complex_kt {
|
||||
110 [label="Access variable this@R|/firstIsInstanceOrNull|"];
|
||||
111 [label="Variable declaration: lval <range>: R|kotlin/sequences/Sequence<*>|"];
|
||||
112 [label="Access variable R|<local>/<range>|"];
|
||||
113 [label="Function call: R|<local>/<range>|.R|kotlin/sequences/Sequence.iterator|()"];
|
||||
114 [label="Variable declaration: lval <iterator>: R|kotlin/collections/Iterator<T>|"];
|
||||
113 [label="Function call: R|<local>/<range>|.R|FakeOverride<kotlin/sequences/Sequence.iterator: R|kotlin/collections/Iterator<kotlin/Any?>|>|()"];
|
||||
114 [label="Variable declaration: lval <iterator>: R|kotlin/collections/Iterator<kotlin/Any?>|"];
|
||||
subgraph cluster_25 {
|
||||
color=blue
|
||||
115 [label="Enter while loop"];
|
||||
@@ -344,8 +344,8 @@ digraph complex_kt {
|
||||
color=blue
|
||||
121 [label="Enter block"];
|
||||
122 [label="Access variable R|<local>/<iterator>|"];
|
||||
123 [label="Function call: R|<local>/<iterator>|.R|FakeOverride<kotlin/collections/Iterator.next: R|T|>|()"];
|
||||
124 [label="Variable declaration: lval element: R|T|"];
|
||||
123 [label="Function call: R|<local>/<iterator>|.R|FakeOverride<kotlin/collections/Iterator.next: R|kotlin/Any?|>|()"];
|
||||
124 [label="Variable declaration: lval element: R|kotlin/Any?|"];
|
||||
subgraph cluster_29 {
|
||||
color=blue
|
||||
125 [label="Enter when"];
|
||||
|
||||
+2
-2
@@ -40,9 +40,9 @@ FILE: complex.kt
|
||||
}
|
||||
public final inline fun <reified T : R|kotlin/Any|> R|kotlin/sequences/Sequence<*>|.firstIsInstanceOrNull(): R|T?| {
|
||||
lval <range>: R|kotlin/sequences/Sequence<*>| = this@R|/firstIsInstanceOrNull|
|
||||
lval <iterator>: R|kotlin/collections/Iterator<T>| = R|<local>/<range>|.R|kotlin/sequences/Sequence.iterator|()
|
||||
lval <iterator>: R|kotlin/collections/Iterator<kotlin/Any?>| = R|<local>/<range>|.R|FakeOverride<kotlin/sequences/Sequence.iterator: R|kotlin/collections/Iterator<kotlin/Any?>|>|()
|
||||
while(R|<local>/<iterator>|.R|kotlin/collections/Iterator.hasNext|()) {
|
||||
lval element: R|T| = R|<local>/<iterator>|.R|FakeOverride<kotlin/collections/Iterator.next: R|T|>|()
|
||||
lval element: R|kotlin/Any?| = R|<local>/<iterator>|.R|FakeOverride<kotlin/collections/Iterator.next: R|kotlin/Any?|>|()
|
||||
when () {
|
||||
(R|<local>/element| is R|T|) -> {
|
||||
^firstIsInstanceOrNull R|<local>/element|
|
||||
|
||||
@@ -11,6 +11,6 @@ FILE: test.kt
|
||||
R|<local>/resolvedCall|.R|/ResolvedCall.resultingDescriptor|.R|/name|
|
||||
}
|
||||
public final fun otherTest(call: R|Call<*>|, resolvedCall: R|ResolvedCall<*>|): R|kotlin/Unit| {
|
||||
R|<local>/call|.R|/Call.resultingDescriptor|.R|/name|
|
||||
R|<local>/call|.R|FakeOverride</Call.resultingDescriptor: R|Descriptor|>|.R|/name|
|
||||
R|<local>/resolvedCall|.R|/ResolvedCall.resultingDescriptor|.R|/name|
|
||||
}
|
||||
|
||||
@@ -17,6 +17,6 @@ FILE: test.kt
|
||||
private get(): R|DiagnosticFactory0<DerivedElement>|
|
||||
public final fun createViaFactory(d: R|EmptyDiagnostic|): R|kotlin/Unit| {
|
||||
lval casted: R|Diagnostic<*>!| = R|/DERIVED_FACTORY|.R|FakeOverride</DiagnosticFactory.cast: R|Diagnostic<*>!|>|(R|<local>/d|)
|
||||
lval element: R|E!| = R|<local>/casted|.R|/Diagnostic.element|
|
||||
lval element: R|Element!| = R|<local>/casted|.R|/Diagnostic.element|
|
||||
<Inapplicable(INAPPLICABLE): [/Fix.Fix]>#(R|<local>/element|)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
public open class Some : R|kotlin/Any|, R|Strange<*>| {
|
||||
public open operator fun foo(): R|kotlin/Any|
|
||||
public open operator fun foo(): R|kotlin/Any?|
|
||||
|
||||
public constructor(): R|Some|
|
||||
|
||||
|
||||
Reference in New Issue
Block a user