Add feature support for "smart casts on variables in closures"
So #KT-14486 Fixed
This commit is contained in:
@@ -608,7 +608,7 @@ public class BodyResolver {
|
||||
KtExpression body = anonymousInitializer.getBody();
|
||||
if (body != null) {
|
||||
PreliminaryDeclarationVisitor.Companion.createForDeclaration(
|
||||
(KtDeclaration) anonymousInitializer.getParent().getParent(), trace);
|
||||
(KtDeclaration) anonymousInitializer.getParent().getParent(), trace, languageVersionSettings);
|
||||
expressionTypingServices.getTypeInfo(
|
||||
scopeForInitializers, body, NO_EXPECTED_TYPE, outerDataFlowInfo, trace, /*isStatement = */true
|
||||
);
|
||||
@@ -680,7 +680,7 @@ public class BodyResolver {
|
||||
) {
|
||||
computeDeferredType(propertyDescriptor.getReturnType());
|
||||
|
||||
PreliminaryDeclarationVisitor.Companion.createForDeclaration(property, trace);
|
||||
PreliminaryDeclarationVisitor.Companion.createForDeclaration(property, trace, languageVersionSettings);
|
||||
KtExpression initializer = property.getInitializer();
|
||||
LexicalScope propertyHeaderScope = ScopeUtils.makeScopeForPropertyHeader(getScopeForProperty(c, property), propertyDescriptor);
|
||||
|
||||
@@ -851,7 +851,7 @@ public class BodyResolver {
|
||||
// Creates wrapper scope for header resolution if necessary (see resolveSecondaryConstructorBody)
|
||||
@Nullable Function1<LexicalScope, LexicalScope> headerScopeFactory
|
||||
) {
|
||||
PreliminaryDeclarationVisitor.Companion.createForDeclaration(function, trace);
|
||||
PreliminaryDeclarationVisitor.Companion.createForDeclaration(function, trace, languageVersionSettings);
|
||||
LexicalScope innerScope = FunctionDescriptorUtil.getFunctionInnerScope(scope, functionDescriptor, trace, overloadChecker);
|
||||
List<KtParameter> valueParameters = function.getValueParameters();
|
||||
List<ValueParameterDescriptor> valueParameterDescriptors = functionDescriptor.getValueParameters();
|
||||
|
||||
@@ -1154,7 +1154,7 @@ public class DescriptorResolver {
|
||||
@NotNull FunctionDescriptor functionDescriptor
|
||||
) {
|
||||
return wrappedTypeFactory.createRecursionIntolerantDeferredType(trace, () -> {
|
||||
PreliminaryDeclarationVisitor.Companion.createForDeclaration(function, trace);
|
||||
PreliminaryDeclarationVisitor.Companion.createForDeclaration(function, trace, languageVersionSettings);
|
||||
KotlinType type = expressionTypingServices.getBodyExpressionType(
|
||||
trace, scope, dataFlowInfo, function, functionDescriptor);
|
||||
KotlinType result = transformAnonymousTypeIfNeeded(functionDescriptor, function, type, trace);
|
||||
|
||||
+2
-1
@@ -84,7 +84,8 @@ class VariableTypeAndInitializerResolver(
|
||||
wrappedTypeFactory.createRecursionIntolerantDeferredType(
|
||||
trace
|
||||
) {
|
||||
PreliminaryDeclarationVisitor.createForDeclaration(variable, trace)
|
||||
PreliminaryDeclarationVisitor.createForDeclaration(variable, trace,
|
||||
expressionTypingServices.languageVersionSettings)
|
||||
val initializerType = resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace, local)
|
||||
transformAnonymousTypeIfNeeded(variableDescriptor, variable, initializerType, trace)
|
||||
}
|
||||
|
||||
+3
-1
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.smartcasts
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isNullableNothing
|
||||
import org.jetbrains.kotlin.cfg.ControlFlowInformationProvider
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor
|
||||
@@ -378,7 +379,8 @@ object DataFlowValueFactory {
|
||||
val variableContainingDeclaration = variableDescriptor.containingDeclaration
|
||||
if (isAccessedInsideClosure(variableContainingDeclaration, bindingContext, accessElement)) {
|
||||
// stable iff we have no writers in closures AND this closure is AFTER all writers
|
||||
return if (hasNoWritersInClosures(variableContainingDeclaration, writers, bindingContext) &&
|
||||
return if (preliminaryVisitor.languageVersionSettings.supportsFeature(LanguageFeature.CapturedInClosureSmartCasts) &&
|
||||
hasNoWritersInClosures(variableContainingDeclaration, writers, bindingContext) &&
|
||||
isAccessedInsideClosureAfterAllWriters(writers, accessElement)) {
|
||||
STABLE_VARIABLE
|
||||
}
|
||||
|
||||
+6
-1
@@ -17,10 +17,10 @@
|
||||
package org.jetbrains.kotlin.types.expressions;
|
||||
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
|
||||
@@ -68,6 +68,11 @@ public class ExpressionTypingServices {
|
||||
this.expressionTypingFacade = facade;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public LanguageVersionSettings getLanguageVersionSettings() {
|
||||
return expressionTypingComponents.languageVersionSettings;
|
||||
}
|
||||
|
||||
@NotNull public StatementFilter getStatementFilter() {
|
||||
return statementFilter;
|
||||
}
|
||||
|
||||
+10
-5
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.types.expressions
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
@@ -26,7 +27,10 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
|
||||
class PreliminaryDeclarationVisitor(val declaration: KtDeclaration): AssignedVariablesSearcher() {
|
||||
class PreliminaryDeclarationVisitor(
|
||||
val declaration: KtDeclaration,
|
||||
val languageVersionSettings: LanguageVersionSettings
|
||||
): AssignedVariablesSearcher() {
|
||||
|
||||
override fun writers(variableDescriptor: VariableDescriptor): MutableSet<Writer> {
|
||||
lazyTrigger
|
||||
@@ -39,17 +43,18 @@ class PreliminaryDeclarationVisitor(val declaration: KtDeclaration): AssignedVar
|
||||
|
||||
companion object {
|
||||
|
||||
fun createForExpression(expression: KtExpression, trace: BindingTrace) {
|
||||
expression.getStrictParentOfType<KtDeclaration>()?.let { createForDeclaration(it, trace) }
|
||||
fun createForExpression(expression: KtExpression, trace: BindingTrace, languageVersionSettings: LanguageVersionSettings) {
|
||||
expression.getStrictParentOfType<KtDeclaration>()?.let { createForDeclaration(it, trace, languageVersionSettings) }
|
||||
}
|
||||
|
||||
private fun topMostNonClassDeclaration(declaration: KtDeclaration) =
|
||||
declaration.parentsWithSelf.filterIsInstance<KtDeclaration>().findLast { it !is KtClassOrObject } ?: declaration
|
||||
|
||||
fun createForDeclaration(declaration: KtDeclaration, trace: BindingTrace) {
|
||||
fun createForDeclaration(declaration: KtDeclaration, trace: BindingTrace, languageVersionSettings: LanguageVersionSettings) {
|
||||
val visitorOwner = topMostNonClassDeclaration(declaration)
|
||||
if (trace.get(BindingContext.PRELIMINARY_VISITOR, visitorOwner) != null) return
|
||||
trace.record(BindingContext.PRELIMINARY_VISITOR, visitorOwner, PreliminaryDeclarationVisitor(visitorOwner))
|
||||
trace.record(BindingContext.PRELIMINARY_VISITOR, visitorOwner,
|
||||
PreliminaryDeclarationVisitor(visitorOwner, languageVersionSettings))
|
||||
}
|
||||
|
||||
fun getVisitorByVariable(variableDescriptor: VariableDescriptor, bindingContext: BindingContext): PreliminaryDeclarationVisitor? {
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ fun foo(s: String?) {
|
||||
}
|
||||
if (x != null) {
|
||||
run {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.hashCode()
|
||||
<!SMARTCAST_IMPOSSIBLE!>x<!>.hashCode()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor
|
||||
contextDependency: ContextDependency = ContextDependency.INDEPENDENT,
|
||||
expressionTypingServices: ExpressionTypingServices = contextExpression.getResolutionFacade().frontendService<ExpressionTypingServices>()
|
||||
): KotlinTypeInfo {
|
||||
PreliminaryDeclarationVisitor.createForExpression(this, trace)
|
||||
PreliminaryDeclarationVisitor.createForExpression(this, trace, expressionTypingServices.languageVersionSettings)
|
||||
return expressionTypingServices.getTypeInfo(scope, this, expectedType, dataFlowInfo, trace, isStatement, contextExpression, contextDependency)
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -54,7 +54,8 @@ class CodeFragmentAnalyzer(
|
||||
|
||||
when (codeFragmentElement) {
|
||||
is KtExpression -> {
|
||||
PreliminaryDeclarationVisitor.createForExpression(codeFragmentElement, trace)
|
||||
PreliminaryDeclarationVisitor.createForExpression(codeFragmentElement, trace,
|
||||
expressionTypingServices.languageVersionSettings)
|
||||
expressionTypingServices.getTypeInfo(
|
||||
scopeForContextElement,
|
||||
codeFragmentElement,
|
||||
|
||||
Reference in New Issue
Block a user