[NI] Disable capturing/approximation type in TypeSubstitutor with enabled NI

This commit is contained in:
Dmitriy Novozhilov
2019-05-29 10:35:46 +03:00
parent dad334ffcd
commit 7c4101e21c
80 changed files with 890 additions and 201 deletions
@@ -81,8 +81,7 @@ public class LocalVariableDescriptor extends VariableDescriptorWithInitializerIm
@NotNull
@Override
public LocalVariableDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
if (substitutor.isEmpty()) return this;
throw new UnsupportedOperationException(); // TODO
return this;
}
@Override
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitutio
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SubstitutingScopeProvider
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
@@ -77,7 +78,9 @@ fun ResolutionContext<*>.reportTypeMismatchDueToTypeProjection(
TypeConstructorSubstitution
.create(receiverType)
.wrapWithCapturingSubstitution(needApproximation = false)
.buildSubstitutor().let { callableDescriptor.substitute(it) } ?: return false
.buildSubstitutor().apply {
setSubstitutingScopeProvider(SubstitutingScopeProvider.DEFAULT)
}.let { callableDescriptor.substitute(it) } ?: return false
val nonApproximatedExpectedType = correspondingNotApproximatedTypeByDescriptor(substitutedDescriptor) ?: return false
if (!TypeUtils.contains(nonApproximatedExpectedType) { it.isCaptured() }) return false
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.KotlinResolutionStatelessCallbac
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
import org.jetbrains.kotlin.resolve.lazy.*
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
import org.jetbrains.kotlin.types.SubstitutingScopeProviderImpl
import org.jetbrains.kotlin.types.expressions.DeclarationScopeProviderForLocalClassifierAnalyzer
import org.jetbrains.kotlin.types.expressions.LocalClassDescriptorHolder
import org.jetbrains.kotlin.types.expressions.LocalLazyDeclarationResolver
@@ -117,6 +118,7 @@ fun createContainerForBodyResolve(
useImpl<AnnotationResolverImpl>()
useImpl<BodyResolver>()
useImpl<SubstitutingScopeProviderImpl>()
}
fun createContainerForLazyBodyResolve(
@@ -136,6 +138,7 @@ fun createContainerForLazyBodyResolve(
useImpl<AnnotationResolverImpl>()
useImpl<LazyTopDownAnalyzer>()
useImpl<BasicAbsentDescriptorHandler>()
useImpl<SubstitutingScopeProviderImpl>()
}
fun createContainerForLazyLocalClassifierAnalyzer(
@@ -166,6 +169,7 @@ fun createContainerForLazyLocalClassifierAnalyzer(
useImpl<DeclarationScopeProviderForLocalClassifierAnalyzer>()
useImpl<LocalLazyDeclarationResolver>()
useImpl<SubstitutingScopeProviderImpl>()
useInstance(statementFilter)
}
@@ -183,6 +187,7 @@ fun createContainerForLazyResolve(
configureStandardResolveComponents()
useInstance(declarationProviderFactory)
useImpl<SubstitutingScopeProviderImpl>()
targetEnvironment.configure(this)
@@ -911,7 +911,8 @@ public class DescriptorResolver {
container instanceof ClassDescriptor && ((ClassDescriptor) container).isExpect(),
modifierList != null && PsiUtilsKt.hasActualModifier(modifierList),
modifierList != null && modifierList.hasModifier(KtTokens.EXTERNAL_KEYWORD),
propertyInfo.getHasDelegate()
propertyInfo.getHasDelegate(),
new SubstitutingScopeProviderImpl(languageVersionSettings)
);
List<TypeParameterDescriptorImpl> typeParameterDescriptors;
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.*
@@ -23,12 +25,13 @@ import org.jetbrains.kotlin.resolve.calls.components.AdditionalDiagnosticReporte
import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.CallPosition
import org.jetbrains.kotlin.resolve.calls.inference.approximateCapturedTypes
import org.jetbrains.kotlin.resolve.calls.inference.buildResultingSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.inference.substitute
import org.jetbrains.kotlin.resolve.calls.inference.substituteAndApproximateCapturedTypes
import org.jetbrains.kotlin.resolve.calls.inference.substituteAndApproximateIntegerLiteralTypes
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.makeNullableTypeIfSafeReceiver
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
@@ -38,14 +41,13 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer
import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
@@ -293,15 +295,14 @@ class KotlinToResolvedCallTransformer(
// todo external argument
val argumentExpression = valueArgument.getArgumentExpression() ?: continue
updateRecordedType(argumentExpression, parameter, newContext, resolvedCall.isReallySuccess())
updateRecordedType(argumentExpression, parameter, newContext)
}
}
fun updateRecordedType(
expression: KtExpression,
parameter: ValueParameterDescriptor?,
context: BasicCallResolutionContext,
reportErrorForTypeMismatch: Boolean
context: BasicCallResolutionContext
): KotlinType? {
val deparenthesized = expression.let {
KtPsiUtil.getLastElementDeparenthesized(it, context.statementFilter)
@@ -318,9 +319,6 @@ class KotlinToResolvedCallTransformer(
updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, deparenthesized) ?: updatedType
}
var reportErrorDuringTypeCheck = reportErrorForTypeMismatch
if (parameter != null && ImplicitIntegerCoercion.isEnabledForParameter(parameter)) {
val argumentCompileTimeValue = context.trace[BindingContext.COMPILE_TIME_VALUE, deparenthesized]
if (argumentCompileTimeValue != null && argumentCompileTimeValue.parameters.isConvertableConstVal) {
@@ -329,7 +327,6 @@ class KotlinToResolvedCallTransformer(
updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(
context.trace, context.statementFilter, context.expectedType, generalNumberType, expression
)
reportErrorDuringTypeCheck = true
}
}
@@ -337,7 +334,7 @@ class KotlinToResolvedCallTransformer(
updatedType = updateRecordedTypeForArgument(updatedType, recordedType, expression, context)
dataFlowAnalyzer.checkType(updatedType, deparenthesized, context, reportErrorDuringTypeCheck)
dataFlowAnalyzer.checkType(updatedType, deparenthesized, context, false)
return updatedType
}
@@ -690,32 +687,44 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
@Suppress("UNCHECKED_CAST")
resultingDescriptor = run {
val candidateDescriptor = resolvedCallAtom.candidateDescriptor
val containsCapturedTypes = resolvedCallAtom.candidateDescriptor.returnType?.contains { it is NewCapturedType } ?: false
val containsIntegerLiteralTypes = resolvedCallAtom.candidateDescriptor.returnType?.contains { it.constructor is IntegerLiteralTypeConstructor } ?: false
val containsIntegerLiteralTypes = resolvedCallAtom.candidateDescriptor.returnType?.contains {
it.constructor is IntegerLiteralTypeConstructor
} ?: false
when {
candidateDescriptor is FunctionDescriptor ||
(candidateDescriptor is PropertyDescriptor && (candidateDescriptor.typeParameters.isNotEmpty() || containsCapturedTypes || containsIntegerLiteralTypes)) ->
(candidateDescriptor is PropertyDescriptor && candidateDescriptor.typeParameters.isNotEmpty() || containsIntegerLiteralTypes) ->
// this code is very suspicious. Now it is very useful for BE, because they cannot do nothing with captured types,
// but it seems like temporary solution.
candidateDescriptor.substitute(resolvedCallAtom.substitutor).substituteAndApproximateCapturedTypes(
substitutor ?: FreshVariableNewTypeSubstitutor.Empty
)
candidateDescriptor.substituteAndApproximateIntegerLiteralTypes(resolvedCallAtom.substitutor).let {
if (substitutor != null) {
it.substitute(substitutor)
} else {
it
}
}
else ->
candidateDescriptor
}
} as D
typeArguments = resolvedCallAtom.substitutor.freshVariables.map {
val substituted = (substitutor ?: FreshVariableNewTypeSubstitutor.Empty).safeSubstitute(it.defaultType)
TypeApproximator(substituted.constructor.builtIns)
.approximateToSuperType(substituted, TypeApproximatorConfiguration.IntegerLiteralsTypesApproximation)
?: substituted
(substitutor ?: FreshVariableNewTypeSubstitutor.Empty).safeSubstitute(it.defaultType)
}
calculateExpectedTypeForSamConvertedArgumentMap(substitutor)
}
fun approximateCapturedTypesAndHackSetters() {
val approximator = TypeApproximator(resultingDescriptor.builtIns)
resultingDescriptor = resultingDescriptor.hackSettersAccordingToCapturedOutTypes()
resultingDescriptor = resultingDescriptor.approximateCapturedTypes()
typeArguments = typeArguments.map {
approximator.approximateToSuperType(it, TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation) ?: it
}
}
fun getExpectedTypeForSamConvertedArgument(valueArgument: ValueArgument): UnwrappedType? =
expedtedTypeForSamConvertedArgumentMap?.get(valueArgument)
@@ -808,3 +817,41 @@ fun NewResolvedCallImpl<*>.hasInferredReturnType(): Boolean {
val returnType = this.resultingDescriptor.returnType ?: return false
return !returnType.contains { ErrorUtils.isUninferredParameter(it) }
}
fun ResolvedCall<*>.approximateCapturedTypesAndHackSetters() {
when (this) {
is NewResolvedCallImpl<*> -> approximateCapturedTypesAndHackSetters()
is NewVariableAsFunctionResolvedCallImpl -> {
functionCall.approximateCapturedTypesAndHackSetters()
variableCall.approximateCapturedTypesAndHackSetters()
}
else -> throw UnsupportedOperationException("Illegal resolved call: $this")
}
}
fun <D : CallableDescriptor> D.hackSettersAccordingToCapturedOutTypes(): D {
return when (this) {
is PropertyDescriptorImpl -> hackSettersAccordingToCapturedOutTypes() as D
else -> this
}
}
private fun PropertyDescriptorImpl.hackSettersAccordingToCapturedOutTypes(): PropertyDescriptor {
val setter = setter ?: return this
val valueParameter = setter.valueParameters.first()
val inputType = valueParameter.type
val approximatedType = TypeApproximator(builtIns).approximateToSubType(
inputType.unwrap(),
TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation
) ?: return this
val newProperty = newCopyBuilder().build() as PropertyDescriptorImpl
val newSetter = with(setter) {
PropertySetterDescriptorImpl(newProperty, annotations, modality, visibility, isDefault, isExternal, isInline, kind, original, source)
}
newSetter.initialize(PropertySetterDescriptorImpl.createSetterParameter(newSetter, approximatedType, setter.annotations))
newProperty.initialize(getter, newSetter, backingField, delegateField)
newProperty.isSetterProjectedOut = true
return newProperty
}
@@ -382,6 +382,7 @@ class PSICallResolver(
return cache.getOrPut(implicitReceiver) {
context.transformToReceiverWithSmartCastInfo(implicitReceiver.value)
.prepareReceiverRegardingCaptureTypes()
}
}
}
@@ -110,6 +110,7 @@ class ResolvedAtomCompleter(
kotlinToResolvedCallTransformer.reportDiagnostics(topLevelCallContext, topLevelTrace, resolvedCall, diagnostics)
resolvedCall.approximateCapturedTypesAndHackSetters()
return resolvedCall
}
@@ -155,9 +156,7 @@ class ResolvedAtomCompleter(
.replaceBindingTrace(topLevelTrace)
val argumentExpression = resultValueArgument.valueArgument.getArgumentExpression() ?: continue
kotlinToResolvedCallTransformer.updateRecordedType(
argumentExpression, parameter = null, context = newContext, reportErrorForTypeMismatch = true
)
kotlinToResolvedCallTransformer.updateRecordedType(argumentExpression, parameter = null, context = newContext)
}
}
@@ -24,10 +24,12 @@ import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.SubstitutingScopeProvider
import org.jetbrains.kotlin.types.WrappedTypeFactory
interface LazyClassContext {
val declarationScopeProvider: DeclarationScopeProvider
val substitutingScopeProvider: SubstitutingScopeProvider
val storageManager: StorageManager
val trace: BindingTrace
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import org.jetbrains.kotlin.storage.*;
import org.jetbrains.kotlin.types.SubstitutingScopeProvider;
import org.jetbrains.kotlin.types.WrappedTypeFactory;
import org.jetbrains.kotlin.utils.SmartList;
@@ -81,6 +82,7 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
private DelegationFilter delegationFilter;
private WrappedTypeFactory wrappedTypeFactory;
private PlatformDiagnosticSuppressor platformDiagnosticSuppressor;
private SubstitutingScopeProvider substitutingScopeProvider;
private final SyntheticResolveExtension syntheticResolveExtension;
@@ -146,6 +148,17 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
this.platformDiagnosticSuppressor = platformDiagnosticSuppressor;
}
@NotNull
@Override
public SubstitutingScopeProvider getSubstitutingScopeProvider() {
return substitutingScopeProvider;
}
@Inject
public void setSubstitutingScopeProvider(SubstitutingScopeProvider substitutingScopeProvider) {
this.substitutingScopeProvider = substitutingScopeProvider;
}
// Only calls from injectors expected
@Deprecated
public ResolveSession(
@@ -113,7 +113,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
) {
super(c.getStorageManager(), containingDeclaration, name,
KotlinSourceElementKt.toSourceElement(classLikeInfo.getCorrespondingClassOrObject()),
isExternal
isExternal, c.getSubstitutingScopeProvider()
);
this.c = c;
@@ -0,0 +1,49 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. 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.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.resolve.calls.inference.OldCapturedTypeCreator
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.SubstitutingScope
import org.jetbrains.kotlin.types.typesApproximation.OldCaptureTypeApproximator
class SubstitutingScopeProviderImpl(private val languageVersionSettings: LanguageVersionSettings) : SubstitutingScopeProvider {
override val isNewInferenceEnabled: Boolean get() = languageVersionSettings.supportsFeature(LanguageFeature.NewInference)
override fun createSubstitutingScope(workerScope: MemberScope, givenSubstitutor: TypeSubstitutor): SubstitutingScope {
return SubstitutingScope(workerScope, givenSubstitutor, this)
}
override fun provideApproximator(): CapturedTypeApproximator {
return if (isNewInferenceEnabled) {
NoCapturedTypeApproximator
} else {
OldCaptureTypeApproximator()
}
}
override fun provideCapturedTypeCreator(): CapturedTypeCreator {
return if (isNewInferenceEnabled) {
NoCapturedTypeCreator
} else {
OldCapturedTypeCreator
}
}
}
object NoCapturedTypeCreator : CapturedTypeCreator {
override fun createCapturedType(typeProjection: TypeProjection): TypeProjection {
return typeProjection
}
}
object NoCapturedTypeApproximator : CapturedTypeApproximator {
override fun approximateCapturedTypes(typeProjection: TypeProjection?, approximateContravariant: Boolean): TypeProjection? {
return typeProjection
}
}
@@ -958,6 +958,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
boolean result = true;
KtExpression reportOn = expression != null ? expression : expressionWithParenthesis;
KtExpression originalReportOn = reportOn;
if (reportOn instanceof KtQualifiedExpression) {
KtExpression selector = ((KtQualifiedExpression) reportOn).getSelectorExpression();
if (selector != null)
@@ -968,14 +969,19 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable;
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
if (propertyDescriptor.isSetterProjectedOut()) {
trace.report(SETTER_PROJECTED_OUT.on(reportOn, propertyDescriptor));
trace.report(SETTER_PROJECTED_OUT.on(originalReportOn, propertyDescriptor));
result = false;
}
else if (setter != null) {
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expressionWithParenthesis, context.trace.getBindingContext());
assert resolvedCall != null
: "Call is not resolved for property setter: " + PsiUtilsKt.getElementTextWithContext(expressionWithParenthesis);
checkPropertySetterCall(context.replaceBindingTrace(trace), setter, resolvedCall, reportOn);
if (((PropertyDescriptor)resolvedCall.getResultingDescriptor()).isSetterProjectedOut()) {
trace.report(SETTER_PROJECTED_OUT.on(originalReportOn, propertyDescriptor));
result = false;
} else {
checkPropertySetterCall(context.replaceBindingTrace(trace), setter, resolvedCall, reportOn);
}
}
}
@@ -50,6 +50,7 @@ import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.SubstitutingScopeProvider
import org.jetbrains.kotlin.types.WrappedTypeFactory
class LocalClassifierAnalyzer(
@@ -65,7 +66,8 @@ class LocalClassifierAnalyzer(
private val supertypeLoopChecker: SupertypeLoopChecker,
private val languageVersionSettings: LanguageVersionSettings,
private val delegationFilter: DelegationFilter,
private val wrappedTypeFactory: WrappedTypeFactory
private val wrappedTypeFactory: WrappedTypeFactory,
private val substitutingScopeProvider: SubstitutingScopeProvider
) {
fun processClassOrObject(
scope: LexicalWritableScope?,
@@ -98,7 +100,8 @@ class LocalClassifierAnalyzer(
languageVersionSettings,
SyntheticResolveExtension.getInstance(project),
delegationFilter,
wrappedTypeFactory
wrappedTypeFactory,
substitutingScopeProvider
),
analyzerServices
)
@@ -126,7 +129,8 @@ class LocalClassDescriptorHolder(
val languageVersionSettings: LanguageVersionSettings,
val syntheticResolveExtension: SyntheticResolveExtension,
val delegationFilter: DelegationFilter,
val wrappedTypeFactory: WrappedTypeFactory
val wrappedTypeFactory: WrappedTypeFactory,
val substitutingScopeProvider: SubstitutingScopeProvider
) {
// We do not need to synchronize here, because this code is used strictly from one thread
private var classDescriptor: ClassDescriptor? = null
@@ -166,6 +170,7 @@ class LocalClassDescriptorHolder(
override val syntheticResolveExtension = this@LocalClassDescriptorHolder.syntheticResolveExtension
override val delegationFilter: DelegationFilter = this@LocalClassDescriptorHolder.delegationFilter
override val wrappedTypeFactory: WrappedTypeFactory = this@LocalClassDescriptorHolder.wrappedTypeFactory
override val substitutingScopeProvider: SubstitutingScopeProvider = this@LocalClassDescriptorHolder.substitutingScopeProvider
},
containingDeclaration,
classOrObject.nameAsSafeName,