FIR substitution: use intersection of bounds for * projection

This commit is contained in:
Mikhail Glukhikh
2019-11-14 15:50:36 +03:00
parent 43a8c1282f
commit 1e548e3f21
8 changed files with 41 additions and 16 deletions
@@ -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)
}
@@ -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)
@@ -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
View File
@@ -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
View File
@@ -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|