Split stub types into stub type for subtyping and for builder inference and use them in the proper way

This commit is contained in:
Victor Petukhov
2021-05-11 17:14:05 +03:00
parent 703a353d2e
commit 5a11450d77
18 changed files with 97 additions and 101 deletions
@@ -251,13 +251,14 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
) )
} }
override fun createStubType(typeVariable: TypeVariableMarker): StubTypeMarker { override fun createStubTypeForBuilderInference(typeVariable: TypeVariableMarker): StubTypeMarker {
require(typeVariable is ConeTypeVariable) { "$typeVariable should subtype of ${ConeTypeVariable::class.qualifiedName}" } require(typeVariable is ConeTypeVariable) { "$typeVariable should subtype of ${ConeTypeVariable::class.qualifiedName}" }
return ConeStubType(typeVariable, ConeNullability.create(typeVariable.defaultType().isMarkedNullable())) return ConeStubType(typeVariable, ConeNullability.create(typeVariable.defaultType().isMarkedNullable()))
} }
// TODO // TODO
override fun createStubTypeForTypeVariablesInSubtyping(typeVariable: TypeVariableMarker) = createStubType(typeVariable) override fun createStubTypeForTypeVariablesInSubtyping(typeVariable: TypeVariableMarker) =
createStubTypeForBuilderInference(typeVariable)
override fun KotlinTypeMarker.removeAnnotations(): KotlinTypeMarker { override fun KotlinTypeMarker.removeAnnotations(): KotlinTypeMarker {
require(this is ConeKotlinType) require(this is ConeKotlinType)
@@ -103,7 +103,7 @@ object RuntimeAssertionsTypeChecker : AdditionalTypeChecker {
expressionTypeWithSmartCast: KotlinType, expressionTypeWithSmartCast: KotlinType,
c: ResolutionContext<*> c: ResolutionContext<*>
) { ) {
if (TypeUtils.noExpectedType(c.expectedType) || c.expectedType is StubType) return if (TypeUtils.noExpectedType(c.expectedType) || c.expectedType is StubTypeForBuilderInference) return
val assertionInfo = RuntimeAssertionInfo.create( val assertionInfo = RuntimeAssertionInfo.create(
c.expectedType, c.expectedType,
@@ -45,7 +45,7 @@ class BuilderInferenceSession(
callComponents: KotlinCallComponents, callComponents: KotlinCallComponents,
builtIns: KotlinBuiltIns, builtIns: KotlinBuiltIns,
private val topLevelCallContext: BasicCallResolutionContext, private val topLevelCallContext: BasicCallResolutionContext,
private val stubsForPostponedVariables: Map<NewTypeVariable, StubType>, private val stubsForPostponedVariables: Map<NewTypeVariable, StubTypeForBuilderInference>,
private val trace: BindingTrace, private val trace: BindingTrace,
private val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer, private val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer,
private val expressionTypingServices: ExpressionTypingServices, private val expressionTypingServices: ExpressionTypingServices,
@@ -117,7 +117,7 @@ class BuilderInferenceSession(
private fun KotlinType.containsStubType(): Boolean { private fun KotlinType.containsStubType(): Boolean {
return this.contains { return this.contains {
it is StubType it is StubTypeForBuilderInference
} }
} }
@@ -134,8 +134,8 @@ class BuilderInferenceSession(
} }
private fun anyReceiverContainStubType(descriptor: CallableDescriptor): Boolean { private fun anyReceiverContainStubType(descriptor: CallableDescriptor): Boolean {
return descriptor.dispatchReceiverParameter?.type?.contains { it is StubType } == true || return descriptor.dispatchReceiverParameter?.type?.contains { it is StubTypeForBuilderInference } == true ||
descriptor.extensionReceiverParameter?.type?.contains { it is StubType } == true descriptor.extensionReceiverParameter?.type?.contains { it is StubTypeForBuilderInference } == true
} }
private fun isTopLevelBuilderInferenceCall() = findParentBuildInferenceSession() == null private fun isTopLevelBuilderInferenceCall() = findParentBuildInferenceSession() == null
@@ -296,7 +296,7 @@ class CoroutineInferenceSupport(
} }
} }
private fun KotlinType.containsTypeTemplate() = contains { it is TypeTemplate || it is StubType } private fun KotlinType.containsTypeTemplate() = contains { it is TypeTemplate || it is StubTypeForBuilderInference }
fun isApplicableCallForBuilderInference(descriptor: CallableDescriptor, languageVersionSettings: LanguageVersionSettings): Boolean { fun isApplicableCallForBuilderInference(descriptor: CallableDescriptor, languageVersionSettings: LanguageVersionSettings): Boolean {
if (!languageVersionSettings.supportsFeature(LanguageFeature.ExperimentalBuilderInference)) { if (!languageVersionSettings.supportsFeature(LanguageFeature.ExperimentalBuilderInference)) {
@@ -90,7 +90,7 @@ class KotlinResolutionCallbacksImpl(
parameters: List<UnwrappedType>, parameters: List<UnwrappedType>,
expectedReturnType: UnwrappedType?, expectedReturnType: UnwrappedType?,
annotations: Annotations, annotations: Annotations,
stubsForPostponedVariables: Map<NewTypeVariable, StubType>, stubsForPostponedVariables: Map<NewTypeVariable, StubTypeForBuilderInference>,
): ReturnArgumentsAnalysisResult { ): ReturnArgumentsAnalysisResult {
val psiCallArgument = lambdaArgument.psiCallArgument as PSIFunctionKotlinCallArgument val psiCallArgument = lambdaArgument.psiCallArgument as PSIFunctionKotlinCallArgument
val outerCallContext = psiCallArgument.outerCallContext val outerCallContext = psiCallArgument.outerCallContext
@@ -989,7 +989,7 @@ private fun CallableMemberDescriptor.isNotSimpleCall(): Boolean =
it is NewCapturedType || it is NewCapturedType ||
it.constructor is IntegerLiteralTypeConstructor || it.constructor is IntegerLiteralTypeConstructor ||
it is DefinitelyNotNullType || it is DefinitelyNotNullType ||
it is StubType it is StubTypeForBuilderInference
} }
} ?: false) } ?: false)
@@ -415,7 +415,7 @@ class ResolvedAtomCompleter(
val rawExtensionReceiver = callableCandidate.extensionReceiver val rawExtensionReceiver = callableCandidate.extensionReceiver
if (rawExtensionReceiver != null && rawExtensionReceiver.receiver.receiverValue.type.contains { it is StubType }) { if (rawExtensionReceiver != null && rawExtensionReceiver.receiver.receiverValue.type.contains { it is StubTypeForBuilderInference }) {
topLevelTrace.reportDiagnosticOnce(Errors.TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE.on(callableReferenceExpression)) topLevelTrace.reportDiagnosticOnce(Errors.TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE.on(callableReferenceExpression))
return return
} }
@@ -286,7 +286,7 @@ public class DataFlowAnalyzer {
@NotNull Ref<Boolean> hasError, @NotNull Ref<Boolean> hasError,
boolean reportErrorForTypeMismatch boolean reportErrorForTypeMismatch
) { ) {
if (!noExpectedType(c.expectedType) && TypeUtilsKt.contains(expressionType, (type) -> type instanceof StubType)) { if (!noExpectedType(c.expectedType) && TypeUtilsKt.contains(expressionType, (type) -> type instanceof StubTypeForBuilderInference)) {
if (c.inferenceSession instanceof BuilderInferenceSession) { if (c.inferenceSession instanceof BuilderInferenceSession) {
((BuilderInferenceSession) c.inferenceSession).addExpectedTypeConstraint(expression, expressionType, c.expectedType); ((BuilderInferenceSession) c.inferenceSession).addExpectedTypeConstraint(expression, expressionType, c.expectedType);
} }
@@ -114,7 +114,7 @@ class DoubleColonExpressionResolver(
} else { } else {
val result = resolveDoubleColonLHS(expression, c) val result = resolveDoubleColonLHS(expression, c)
if (c.inferenceSession is BuilderInferenceSession && result?.type?.contains { it is StubType } == true) { if (c.inferenceSession is BuilderInferenceSession && result?.type?.contains { it is StubTypeForBuilderInference } == true) {
c.inferenceSession.addOldCallableReferenceCalls(expression) c.inferenceSession.addOldCallableReferenceCalls(expression)
} }
@@ -548,7 +548,7 @@ class DoubleColonExpressionResolver(
val result = getCallableReferenceType(expression, lhs, resolutionResults, c) val result = getCallableReferenceType(expression, lhs, resolutionResults, c)
val doesSomeExtensionReceiverContainsStubType = val doesSomeExtensionReceiverContainsStubType =
resolutionResults != null && resolutionResults.resultingCalls.any { resolvedCall -> resolutionResults != null && resolutionResults.resultingCalls.any { resolvedCall ->
resolvedCall.extensionReceiver?.type?.contains { it is StubType } == true resolvedCall.extensionReceiver?.type?.contains { it is StubTypeForBuilderInference } == true
} }
if (doesSomeExtensionReceiverContainsStubType) { if (doesSomeExtensionReceiverContainsStubType) {
@@ -558,7 +558,7 @@ class DoubleColonExpressionResolver(
val dataFlowInfo = (lhs as? DoubleColonLHS.Expression)?.dataFlowInfo ?: c.dataFlowInfo val dataFlowInfo = (lhs as? DoubleColonLHS.Expression)?.dataFlowInfo ?: c.dataFlowInfo
if (c.inferenceSession is BuilderInferenceSession && result?.contains { it is StubType } == true) { if (c.inferenceSession is BuilderInferenceSession && result?.contains { it is StubTypeForBuilderInference } == true) {
c.inferenceSession.addOldCallableReferenceCalls(expression) c.inferenceSession.addOldCallableReferenceCalls(expression)
} }
@@ -497,7 +497,7 @@ class NewConstraintSystemImpl(
override fun bindingStubsForPostponedVariables(): Map<TypeVariableMarker, StubTypeMarker> { override fun bindingStubsForPostponedVariables(): Map<TypeVariableMarker, StubTypeMarker> {
checkState(State.BUILDING, State.COMPLETION) checkState(State.BUILDING, State.COMPLETION)
// TODO: SUB // TODO: SUB
return storage.postponedTypeVariables.associateWith { createStubType(it) } return storage.postponedTypeVariables.associateWith { createStubTypeForBuilderInference(it) }
} }
override fun currentStorage(): ConstraintStorage { override fun currentStorage(): ConstraintStorage {
@@ -73,8 +73,11 @@ class ClassicTypeSystemContextForCS(override val builtIns: KotlinBuiltIns) : Typ
} }
} }
override fun createStubType(typeVariable: TypeVariableMarker): StubTypeMarker { override fun createStubTypeForBuilderInference(typeVariable: TypeVariableMarker): StubTypeMarker {
return StubType(typeVariable.freshTypeConstructor() as TypeConstructor, typeVariable.defaultType().isMarkedNullable()) return StubTypeForBuilderInference(
typeVariable.freshTypeConstructor() as TypeConstructor,
typeVariable.defaultType().isMarkedNullable()
)
} }
override fun createStubTypeForTypeVariablesInSubtyping(typeVariable: TypeVariableMarker): StubTypeMarker { override fun createStubTypeForTypeVariablesInSubtyping(typeVariable: TypeVariableMarker): StubTypeMarker {
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.StubType import org.jetbrains.kotlin.types.StubTypeForBuilderInference
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
// stateless component // stateless component
@@ -73,7 +73,7 @@ interface KotlinResolutionCallbacks {
parameters: List<UnwrappedType>, parameters: List<UnwrappedType>,
expectedReturnType: UnwrappedType?, // null means, that return type is not proper i.e. it depends on some type variables expectedReturnType: UnwrappedType?, // null means, that return type is not proper i.e. it depends on some type variables
annotations: Annotations, annotations: Annotations,
stubsForPostponedVariables: Map<NewTypeVariable, StubType>, stubsForPostponedVariables: Map<NewTypeVariable, StubTypeForBuilderInference>,
): ReturnArgumentsAnalysisResult ): ReturnArgumentsAnalysisResult
fun bindStubResolvedCallForCandidate(candidate: ResolvedCallAtom) fun bindStubResolvedCallForCandidate(candidate: ResolvedCallAtom)
@@ -168,7 +168,7 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
captureStatus: CaptureStatus captureStatus: CaptureStatus
): CapturedTypeMarker ): CapturedTypeMarker
fun createStubType(typeVariable: TypeVariableMarker): StubTypeMarker fun createStubTypeForBuilderInference(typeVariable: TypeVariableMarker): StubTypeMarker
fun createStubTypeForTypeVariablesInSubtyping(typeVariable: TypeVariableMarker): StubTypeMarker fun createStubTypeForTypeVariablesInSubtyping(typeVariable: TypeVariableMarker): StubTypeMarker
fun KotlinTypeMarker.removeAnnotations(): KotlinTypeMarker fun KotlinTypeMarker.removeAnnotations(): KotlinTypeMarker
@@ -249,7 +249,7 @@ internal class DescriptorRendererImpl(
} }
append(renderTypeArguments(type.arguments)) append(renderTypeArguments(type.arguments))
} }
type is StubType -> append(type.originalTypeVariable.toString()) type is StubTypeForBuilderInference -> append(type.originalTypeVariable.toString())
else -> renderTypeConstructorAndArguments(type) else -> renderTypeConstructorAndArguments(type)
} }
@@ -290,7 +290,7 @@ internal class DescriptorRendererImpl(
is TypeParameterDescriptor, is ClassDescriptor, is TypeAliasDescriptor -> renderClassifierName(cd) is TypeParameterDescriptor, is ClassDescriptor, is TypeAliasDescriptor -> renderClassifierName(cd)
null -> { null -> {
if (typeConstructor is IntersectionTypeConstructor) { if (typeConstructor is IntersectionTypeConstructor) {
typeConstructor.makeDebugNameForIntersectionType { if (it is StubType) it.originalTypeVariable else it } typeConstructor.makeDebugNameForIntersectionType { if (it is StubTypeForBuilderInference) it.originalTypeVariable else it }
} else typeConstructor.toString() } else typeConstructor.toString()
} }
else -> error("Unexpected classifier: " + cd::class.java) else -> error("Unexpected classifier: " + cd::class.java)
@@ -1,75 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.types
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
import org.jetbrains.kotlin.types.model.StubTypeMarker
import org.jetbrains.kotlin.types.refinement.TypeRefinement
// This type is used as a stub for postponed type variables, which are important for coroutine inference
class StubType(
originalTypeVariable: TypeConstructor,
isMarkedNullable: Boolean,
constructor: TypeConstructor = ErrorUtils.createErrorTypeConstructor("Constructor for non fixed type: $originalTypeVariable"),
memberScope: MemberScope = ErrorUtils.createErrorScope("Scope for non fixed type: $originalTypeVariable")
) : AbstractStubType(originalTypeVariable, isMarkedNullable, constructor, memberScope), StubTypeMarker {
override fun materialize(newNullability: Boolean): AbstractStubType {
return StubType(originalTypeVariable, newNullability, constructor, memberScope)
}
}
class StubTypeForTypeVariablesInSubtyping(
originalTypeVariable: TypeConstructor,
isMarkedNullable: Boolean,
constructor: TypeConstructor = ErrorUtils.createErrorTypeConstructor("Constructor for non fixed type: $originalTypeVariable"),
memberScope: MemberScope = ErrorUtils.createErrorScope("Scope for non fixed type: $originalTypeVariable")
) : AbstractStubType(originalTypeVariable, isMarkedNullable, constructor, memberScope), StubTypeMarker {
override fun materialize(newNullability: Boolean): AbstractStubType {
return StubTypeForTypeVariablesInSubtyping(originalTypeVariable, newNullability, constructor, memberScope)
}
}
// This type is used as a replacement of type variables for provideDelegate resolve
class StubTypeForProvideDelegateReceiver(
originalTypeVariable: TypeConstructor,
isMarkedNullable: Boolean,
constructor: TypeConstructor = ErrorUtils.createErrorTypeConstructor("Constructor for non fixed type: $originalTypeVariable"),
memberScope: MemberScope = ErrorUtils.createErrorScope("Scope for non fixed type: $originalTypeVariable")
) : AbstractStubType(originalTypeVariable, isMarkedNullable, constructor, memberScope) {
override fun materialize(newNullability: Boolean): StubTypeForProvideDelegateReceiver {
return StubTypeForProvideDelegateReceiver(originalTypeVariable, newNullability, constructor, memberScope)
}
}
abstract class AbstractStubType(
val originalTypeVariable: TypeConstructor,
override val isMarkedNullable: Boolean,
override val constructor: TypeConstructor,
override val memberScope: MemberScope
) : SimpleType() {
override val arguments: List<TypeProjection>
get() = emptyList()
override val annotations: Annotations
get() = Annotations.EMPTY
override fun replaceAnnotations(newAnnotations: Annotations): SimpleType = this
override fun makeNullableAsSpecified(newNullability: Boolean): SimpleType {
return if (newNullability == isMarkedNullable) this else materialize(newNullability)
}
override fun toString(): String {
return "NonFixed: $originalTypeVariable${if (isMarkedNullable) "?" else ""}"
}
@TypeRefinement
override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = this
abstract fun materialize(newNullability: Boolean): AbstractStubType
}
@@ -0,0 +1,67 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.types
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
import org.jetbrains.kotlin.types.model.StubTypeMarker
import org.jetbrains.kotlin.types.refinement.TypeRefinement
class StubTypeForBuilderInference(
originalTypeVariable: TypeConstructor,
isMarkedNullable: Boolean,
) : AbstractStubType(originalTypeVariable, isMarkedNullable), StubTypeMarker {
override fun materialize(newNullability: Boolean): AbstractStubType =
StubTypeForBuilderInference(originalTypeVariable, newNullability)
override fun toString(): String {
// BI means builder inference
return "Stub (BI): $originalTypeVariable${if (isMarkedNullable) "?" else ""}"
}
}
class StubTypeForTypeVariablesInSubtyping(originalTypeVariable: TypeConstructor, isMarkedNullable: Boolean) :
AbstractStubType(originalTypeVariable, isMarkedNullable), StubTypeMarker {
override fun materialize(newNullability: Boolean): AbstractStubType =
StubTypeForTypeVariablesInSubtyping(originalTypeVariable, newNullability)
override fun toString(): String {
return "Stub (subtyping): $originalTypeVariable${if (isMarkedNullable) "?" else ""}"
}
}
// This type is used as a replacement of type variables for provideDelegate resolve
class StubTypeForProvideDelegateReceiver(originalTypeVariable: TypeConstructor, isMarkedNullable: Boolean) :
AbstractStubType(originalTypeVariable, isMarkedNullable) {
override fun materialize(newNullability: Boolean): StubTypeForProvideDelegateReceiver =
StubTypeForProvideDelegateReceiver(originalTypeVariable, newNullability)
override fun toString(): String {
return "Stub (delegation): $originalTypeVariable${if (isMarkedNullable) "?" else ""}"
}
}
abstract class AbstractStubType(val originalTypeVariable: TypeConstructor, override val isMarkedNullable: Boolean) : SimpleType() {
override val memberScope = ErrorUtils.createErrorScope("Scope for stub type: $originalTypeVariable")
override val constructor = ErrorUtils.createErrorTypeConstructor("Constructor for stub type: $originalTypeVariable")
override val arguments: List<TypeProjection>
get() = emptyList()
override val annotations: Annotations
get() = Annotations.EMPTY
override fun replaceAnnotations(newAnnotations: Annotations): SimpleType = this
override fun makeNullableAsSpecified(newNullability: Boolean): SimpleType {
return if (newNullability == isMarkedNullable) this else materialize(newNullability)
}
@TypeRefinement
override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = this
abstract fun materialize(newNullability: Boolean): AbstractStubType
}
@@ -375,4 +375,4 @@ private fun NewCapturedType.unCaptureTopLevelType(): UnwrappedType {
return constructor.projection.type.unwrap() return constructor.projection.type.unwrap()
} }
fun KotlinType.shouldBeUpdated() = contains { it is StubType || it.constructor is TypeVariableTypeConstructorMarker || it.isError } fun KotlinType.shouldBeUpdated() = contains { it is StubTypeForBuilderInference || it.constructor is TypeVariableTypeConstructorMarker || it.isError }
@@ -81,7 +81,7 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
override fun SimpleTypeMarker.isStubType(): Boolean { override fun SimpleTypeMarker.isStubType(): Boolean {
require(this is SimpleType, this::errorMessage) require(this is SimpleType, this::errorMessage)
return this is StubType || this is StubTypeForProvideDelegateReceiver return this is StubTypeForBuilderInference || this is StubTypeForProvideDelegateReceiver
} }
override fun SimpleTypeMarker.isStubTypeForVariableInSubtyping(): Boolean { override fun SimpleTypeMarker.isStubTypeForVariableInSubtyping(): Boolean {
@@ -544,7 +544,7 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
errorSupportedOnlyInTypeInference() errorSupportedOnlyInTypeInference()
} }
override fun createStubType(typeVariable: TypeVariableMarker): StubTypeMarker { override fun createStubTypeForBuilderInference(typeVariable: TypeVariableMarker): StubTypeMarker {
errorSupportedOnlyInTypeInference() errorSupportedOnlyInTypeInference()
} }