Propagate inference session into declaration analyzers

It prevents missing inference session for local declaration (local functions, local classes or objects)

^KT-44801 Fixed
This commit is contained in:
Victor Petukhov
2021-02-12 13:58:27 +03:00
parent dae1f4c05d
commit 6f64fd2fec
19 changed files with 150 additions and 42 deletions
@@ -16723,6 +16723,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inference/builderInference/lackOfNullCheckOnNullableInsideBuild.kt");
}
@Test
@TestMetadata("propagateInferenceSessionIntoDeclarationAnalyzers.kt")
public void testPropagateInferenceSessionIntoDeclarationAnalyzers() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/propagateInferenceSessionIntoDeclarationAnalyzers.kt");
}
@Test
@TestMetadata("specialCallsWithCallableReferences.kt")
public void testSpecialCallsWithCallableReferences() throws Exception {
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
import java.util.Collection;
import java.util.Map;
@@ -58,4 +59,7 @@ public interface BodiesResolveContext {
@NotNull
TopDownAnalysisMode getTopDownAnalysisMode();
@Nullable
ExpressionTypingContext getLocalContext();
}
@@ -47,6 +47,7 @@ import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver;
import org.jetbrains.kotlin.resolve.scopes.*;
import org.jetbrains.kotlin.types.*;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor;
import org.jetbrains.kotlin.types.expressions.ValueParameterResolver;
@@ -134,7 +135,7 @@ public class BodyResolver {
for (Map.Entry<KtSecondaryConstructor, ClassConstructorDescriptor> entry : c.getSecondaryConstructors().entrySet()) {
LexicalScope declaringScope = c.getDeclaringScope(entry.getKey());
assert declaringScope != null : "Declaring scope should be registered before body resolve";
resolveSecondaryConstructorBody(c.getOuterDataFlowInfo(), trace, entry.getKey(), entry.getValue(), declaringScope);
resolveSecondaryConstructorBody(c.getOuterDataFlowInfo(), trace, entry.getKey(), entry.getValue(), declaringScope, c.getLocalContext());
}
if (c.getSecondaryConstructors().isEmpty()) return;
Set<ConstructorDescriptor> visitedConstructors = new HashSet<>();
@@ -148,18 +149,22 @@ public class BodyResolver {
@NotNull BindingTrace trace,
@NotNull KtSecondaryConstructor constructor,
@NotNull ClassConstructorDescriptor descriptor,
@NotNull LexicalScope declaringScope
@NotNull LexicalScope declaringScope,
@Nullable ExpressionTypingContext localContext
) {
ForceResolveUtil.forceResolveAllContents(descriptor.getAnnotations());
resolveFunctionBody(outerDataFlowInfo, trace, constructor, descriptor, declaringScope,
headerInnerScope -> resolveSecondaryConstructorDelegationCall(
outerDataFlowInfo, trace, headerInnerScope, constructor, descriptor
),
scope -> new LexicalScopeImpl(
scope, descriptor, scope.isOwnerDescriptorAccessibleByLabel(), scope.getImplicitReceiver(),
LexicalScopeKind.CONSTRUCTOR_HEADER
));
resolveFunctionBody(
outerDataFlowInfo, trace, constructor, descriptor, declaringScope,
headerInnerScope -> resolveSecondaryConstructorDelegationCall(
outerDataFlowInfo, trace, headerInnerScope, constructor, descriptor
),
scope -> new LexicalScopeImpl(
scope, descriptor, scope.isOwnerDescriptorAccessibleByLabel(), scope.getImplicitReceiver(),
LexicalScopeKind.CONSTRUCTOR_HEADER
),
localContext
);
}
@Nullable
@@ -835,7 +840,7 @@ public class BodyResolver {
if (getterDescriptor != null) {
if (getter != null) {
LexicalScope accessorScope = makeScopeForPropertyAccessor(c, getter, propertyDescriptor);
resolveFunctionBody(c.getOuterDataFlowInfo(), fieldAccessTrackingTrace, getter, getterDescriptor, accessorScope);
resolveFunctionBody(c.getOuterDataFlowInfo(), fieldAccessTrackingTrace, getter, getterDescriptor, accessorScope, c.getLocalContext());
}
if (getter != null || forceResolveAnnotations) {
@@ -849,7 +854,7 @@ public class BodyResolver {
if (setterDescriptor != null) {
if (setter != null) {
LexicalScope accessorScope = makeScopeForPropertyAccessor(c, setter, propertyDescriptor);
resolveFunctionBody(c.getOuterDataFlowInfo(), fieldAccessTrackingTrace, setter, setterDescriptor, accessorScope);
resolveFunctionBody(c.getOuterDataFlowInfo(), fieldAccessTrackingTrace, setter, setterDescriptor, accessorScope, c.getLocalContext());
}
if (setter != null || forceResolveAnnotations) {
@@ -921,7 +926,7 @@ public class BodyResolver {
bodyResolveCache.resolveFunctionBody(declaration).addOwnDataTo(trace, true);
}
else {
resolveFunctionBody(c.getOuterDataFlowInfo(), trace, declaration, entry.getValue(), scope);
resolveFunctionBody(c.getOuterDataFlowInfo(), trace, declaration, entry.getValue(), scope, c.getLocalContext());
}
}
}
@@ -931,11 +936,12 @@ public class BodyResolver {
@NotNull BindingTrace trace,
@NotNull KtDeclarationWithBody function,
@NotNull FunctionDescriptor functionDescriptor,
@NotNull LexicalScope declaringScope
@NotNull LexicalScope declaringScope,
@Nullable ExpressionTypingContext localContext
) {
computeDeferredType(functionDescriptor.getReturnType());
resolveFunctionBody(outerDataFlowInfo, trace, function, functionDescriptor, declaringScope, null, null);
resolveFunctionBody(outerDataFlowInfo, trace, function, functionDescriptor, declaringScope, null, null, localContext);
assert functionDescriptor.getReturnType() != null;
}
@@ -948,7 +954,8 @@ public class BodyResolver {
@NotNull LexicalScope scope,
@Nullable Function1<LexicalScope, DataFlowInfo> beforeBlockBody,
// Creates wrapper scope for header resolution if necessary (see resolveSecondaryConstructorBody)
@Nullable Function1<LexicalScope, LexicalScope> headerScopeFactory
@Nullable Function1<LexicalScope, LexicalScope> headerScopeFactory,
@Nullable ExpressionTypingContext localContext
) {
ProgressManager.checkCanceled();
@@ -989,7 +996,8 @@ public class BodyResolver {
if (function.hasBody()) {
expressionTypingServices.checkFunctionReturnType(
innerScope, function, functionDescriptor, dataFlowInfo != null ? dataFlowInfo : outerDataFlowInfo, null, trace);
innerScope, function, functionDescriptor, dataFlowInfo != null ? dataFlowInfo : outerDataFlowInfo, null, trace, localContext
);
}
assert functionDescriptor.getReturnType() != null;
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.resolve.checkers.checkClassifierUsages
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.lazy.*
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
import java.util.*
class LazyTopDownAnalyzer(
@@ -57,9 +58,10 @@ class LazyTopDownAnalyzer(
fun analyzeDeclarations(
topDownAnalysisMode: TopDownAnalysisMode,
declarations: Collection<PsiElement>,
outerDataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY
outerDataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY,
localContext: ExpressionTypingContext? = null
): TopDownAnalysisContext {
val c = TopDownAnalysisContext(topDownAnalysisMode, outerDataFlowInfo, declarationScopeProvider)
val c = TopDownAnalysisContext(topDownAnalysisMode, outerDataFlowInfo, declarationScopeProvider, localContext)
val topLevelFqNames = HashMultimap.create<FqName, KtElement>()
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProvider;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
import java.io.PrintStream;
import java.util.*;
@@ -49,6 +50,7 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
private final TopDownAnalysisMode topDownAnalysisMode;
private final DeclarationScopeProvider declarationScopeProvider;
private final ExpressionTypingContext localContext;
private StringBuilder debugOutput;
@@ -60,6 +62,25 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
this.topDownAnalysisMode = topDownAnalysisMode;
this.outerDataFlowInfo = outerDataFlowInfo;
this.declarationScopeProvider = declarationScopeProvider;
this.localContext = null;
}
public TopDownAnalysisContext(
@NotNull TopDownAnalysisMode topDownAnalysisMode,
@NotNull DataFlowInfo outerDataFlowInfo,
@NotNull DeclarationScopeProvider declarationScopeProvider,
@Nullable ExpressionTypingContext localContext
) {
this.topDownAnalysisMode = topDownAnalysisMode;
this.outerDataFlowInfo = outerDataFlowInfo;
this.declarationScopeProvider = declarationScopeProvider;
this.localContext = localContext;
}
@Override
@Nullable
public ExpressionTypingContext getLocalContext() {
return localContext;
}
@Override
@@ -145,7 +145,8 @@ public class ExpressionTypingServices {
@NotNull FunctionDescriptor functionDescriptor,
@NotNull DataFlowInfo dataFlowInfo,
@Nullable KotlinType expectedReturnType,
BindingTrace trace
BindingTrace trace,
@Nullable ExpressionTypingContext localContext
) {
if (expectedReturnType == null) {
expectedReturnType = functionDescriptor.getReturnType();
@@ -153,11 +154,15 @@ public class ExpressionTypingServices {
expectedReturnType = NO_EXPECTED_TYPE;
}
}
checkFunctionReturnType(function, ExpressionTypingContext.newContext(
ExpressionTypingContext context = ExpressionTypingContext.newContext(
trace,
functionInnerScope, dataFlowInfo, expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE, getLanguageVersionSettings(),
expressionTypingComponents.dataFlowValueFactory
));
functionInnerScope, dataFlowInfo, expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE,
getLanguageVersionSettings(), expressionTypingComponents.dataFlowValueFactory,
localContext == null ? InferenceSession.Companion.getDefault() : localContext.inferenceSession
);
checkFunctionReturnType(function, context);
}
/*package*/ void checkFunctionReturnType(KtDeclarationWithBody function, ExpressionTypingContext context) {
@@ -100,7 +100,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
ForceResolveUtil.forceResolveAllContents(functionDescriptor.returnType)
} else {
components.expressionTypingServices.checkFunctionReturnType(
functionInnerScope, function, functionDescriptor, context.dataFlowInfo, null, context.trace
functionInnerScope, function, functionDescriptor, context.dataFlowInfo, null, context.trace, context
)
}
@@ -116,7 +116,8 @@ class LocalClassifierAnalyzer(
container.get<LazyTopDownAnalyzer>().analyzeDeclarations(
TopDownAnalysisMode.LocalDeclarations,
listOf(classOrObject),
context.dataFlowInfo
context.dataFlowInfo,
localContext = context
)
}
}
@@ -0,0 +1,34 @@
// WITH_RUNTIME
import kotlin.experimental.ExperimentalTypeInference
interface Callback {
fun onSuccess()
}
public interface SendChannelX<in E> {
public fun close(cause: Throwable? = null): Boolean
}
public interface ProducerScopeX<in E> {
public val channel: SendChannelX<E>
fun foo(x: E)
}
public class FlowX<out T> {}
@OptIn(ExperimentalTypeInference::class)
public fun <T> callbackFlowX(@BuilderInference block: ProducerScopeX<T>.() -> Unit): FlowX<T> = FlowX()
fun foo(): FlowX<String> = callbackFlowX {
object : Callback {
override fun onSuccess() {
channel.close()
}
}
}
fun box(): String {
foo()
return "OK"
}
@@ -1,14 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNREACHABLE_CODE
interface Some {
fun method(): Unit
}
fun <S> elvis(nullable: S?, notNullable: S): S = TODO()
fun <R : Some> Some.doWithPredicate(predicate: (R) -> Unit): R? = TODO()
fun test(derived: Some) {
val expected: Some = derived.doWithPredicate { it.method() } ?: TODO()
val expected2: Some = elvis(derived.doWithPredicate { it.<!UNRESOLVED_REFERENCE!>method<!>() }, TODO())
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNREACHABLE_CODE
interface Some {
@@ -16723,6 +16723,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inference/builderInference/lackOfNullCheckOnNullableInsideBuild.kt");
}
@Test
@TestMetadata("propagateInferenceSessionIntoDeclarationAnalyzers.kt")
public void testPropagateInferenceSessionIntoDeclarationAnalyzers() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/propagateInferenceSessionIntoDeclarationAnalyzers.kt");
}
@Test
@TestMetadata("specialCallsWithCallableReferences.kt")
public void testSpecialCallsWithCallableReferences() throws Exception {
@@ -16723,6 +16723,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inference/builderInference/lackOfNullCheckOnNullableInsideBuild.kt");
}
@Test
@TestMetadata("propagateInferenceSessionIntoDeclarationAnalyzers.kt")
public void testPropagateInferenceSessionIntoDeclarationAnalyzers() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/propagateInferenceSessionIntoDeclarationAnalyzers.kt");
}
@Test
@TestMetadata("specialCallsWithCallableReferences.kt")
public void testSpecialCallsWithCallableReferences() throws Exception {
@@ -13907,6 +13907,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inference/builderInference/lackOfNullCheckOnNullableInsideBuild.kt");
}
@TestMetadata("propagateInferenceSessionIntoDeclarationAnalyzers.kt")
public void testPropagateInferenceSessionIntoDeclarationAnalyzers() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/propagateInferenceSessionIntoDeclarationAnalyzers.kt");
}
@TestMetadata("specialCallsWithCallableReferences.kt")
public void testSpecialCallsWithCallableReferences() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferences.kt");
@@ -43,6 +43,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.lazy.*
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
import java.util.*
import java.util.concurrent.ConcurrentMap
@@ -677,7 +678,7 @@ class ResolveElementCache(
ForceResolveUtil.forceResolveAllContents(functionDescriptor)
val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter)
bodyResolver.resolveFunctionBody(DataFlowInfo.EMPTY, trace, namedFunction, functionDescriptor, scope)
bodyResolver.resolveFunctionBody(DataFlowInfo.EMPTY, trace, namedFunction, functionDescriptor, scope, null)
forceResolveAnnotationsInside(namedFunction)
@@ -696,7 +697,7 @@ class ResolveElementCache(
ForceResolveUtil.forceResolveAllContents(constructorDescriptor)
val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter)
bodyResolver.resolveSecondaryConstructorBody(DataFlowInfo.EMPTY, trace, constructor, constructorDescriptor, scope)
bodyResolver.resolveSecondaryConstructorBody(DataFlowInfo.EMPTY, trace, constructor, constructorDescriptor, scope, null)
forceResolveAnnotationsInside(constructor)
@@ -835,6 +836,8 @@ class ResolveElementCache(
override fun getOuterDataFlowInfo(): DataFlowInfo = DataFlowInfo.EMPTY
override fun getTopDownAnalysisMode() = topDownAnalysisMode
override fun getLocalContext(): ExpressionTypingContext? = null
}
companion object {
@@ -12187,6 +12187,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/inference/builderInference/lackOfNullCheckOnNullableInsideBuild.kt");
}
@TestMetadata("propagateInferenceSessionIntoDeclarationAnalyzers.kt")
public void testPropagateInferenceSessionIntoDeclarationAnalyzers() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/propagateInferenceSessionIntoDeclarationAnalyzers.kt");
}
@TestMetadata("specialCallsWithCallableReferences.kt")
public void testSpecialCallsWithCallableReferences() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferences.kt");
@@ -11672,6 +11672,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inference/builderInference/lackOfNullCheckOnNullableInsideBuild.kt");
}
@TestMetadata("propagateInferenceSessionIntoDeclarationAnalyzers.kt")
public void testPropagateInferenceSessionIntoDeclarationAnalyzers() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/propagateInferenceSessionIntoDeclarationAnalyzers.kt");
}
@TestMetadata("specialCallsWithCallableReferences.kt")
public void testSpecialCallsWithCallableReferences() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferences.kt");
@@ -11737,6 +11737,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inference/builderInference/lackOfNullCheckOnNullableInsideBuild.kt");
}
@TestMetadata("propagateInferenceSessionIntoDeclarationAnalyzers.kt")
public void testPropagateInferenceSessionIntoDeclarationAnalyzers() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/propagateInferenceSessionIntoDeclarationAnalyzers.kt");
}
@TestMetadata("specialCallsWithCallableReferences.kt")
public void testSpecialCallsWithCallableReferences() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferences.kt");
@@ -6208,6 +6208,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/inference/builderInference/lackOfNullCheckOnNullableInsideBuild.kt");
}
@TestMetadata("propagateInferenceSessionIntoDeclarationAnalyzers.kt")
public void testPropagateInferenceSessionIntoDeclarationAnalyzers() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/propagateInferenceSessionIntoDeclarationAnalyzers.kt");
}
@TestMetadata("substituteStubTypeIntolambdaParameterDescriptor.kt")
public void testSubstituteStubTypeIntolambdaParameterDescriptor() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt");