diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java index 9e4d7a67e9b..d004c5f8d9e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.calls.CallResolver; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults; +import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; import org.jetbrains.kotlin.resolve.calls.util.CallMaker; import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; import org.jetbrains.kotlin.resolve.scopes.*; @@ -151,16 +152,16 @@ public class BodyResolver { resolveFunctionBody(c, trace, constructor, descriptor, bodyDeclaringScope, classDescriptor.getScopeForSecondaryConstructorHeaderResolution(), - new Function1() { + new Function1() { @Override - public Void invoke(@NotNull JetScope headerInnerScope) { - resolveSecondaryConstructorDelegationCall(c, trace, headerInnerScope, constructor, descriptor); - return null; + public DataFlowInfo invoke(@NotNull JetScope headerInnerScope) { + return resolveSecondaryConstructorDelegationCall(c, trace, headerInnerScope, constructor, descriptor); } }); } - private void resolveSecondaryConstructorDelegationCall( + @Nullable + private DataFlowInfo resolveSecondaryConstructorDelegationCall( @NotNull BodiesResolveContext c, @NotNull BindingTrace trace, @NotNull JetScope scope, @@ -168,11 +169,11 @@ public class BodyResolver { @NotNull ConstructorDescriptor descriptor ) { JetConstructorDelegationCall call = constructor.getDelegationCall(); - if (call == null || call.getCalleeExpression() == null) return; + if (call == null || call.getCalleeExpression() == null) return null; JetType superClassType = DescriptorUtils.getSuperClassType(descriptor.getContainingDeclaration()); if (descriptor.getContainingDeclaration().getKind() == ClassKind.ENUM_CLASS && call.getCalleeExpression().isEmpty()) { - return; + return null; } OverloadResolutionResults results = callResolver.resolveFunctionCall( @@ -181,9 +182,12 @@ public class BodyResolver { superClassType != null ? superClassType : NO_EXPECTED_TYPE, c.getOuterDataFlowInfo(), false); - if (results.isSuccess()) { - recordConstructorDelegationCall(trace, descriptor, results.getResultingCall()); + if (results.isSingleResult()) { + ResolvedCall resolvedCall = results.getResultingCall(); + recordConstructorDelegationCall(trace, descriptor, resolvedCall); + return resolvedCall.getDataFlowInfoForArguments().getResultInfo(); } + return null; } private void checkCyclicConstructorDelegationCall( @@ -716,7 +720,7 @@ public class BodyResolver { @NotNull FunctionDescriptor functionDescriptor, @NotNull JetScope bodyDeclaringScope, @Nullable JetScope headerDeclaringScope, - @Nullable Function1 beforeBlockBody + @Nullable Function1 beforeBlockBody ) { JetScope headerInnerScope = FunctionDescriptorUtil.getFunctionInnerScope( headerDeclaringScope == null ? bodyDeclaringScope : headerDeclaringScope, functionDescriptor, trace); @@ -726,15 +730,18 @@ public class BodyResolver { expressionTypingServices.resolveValueParameters(valueParameters, valueParameterDescriptors, headerInnerScope, c.getOuterDataFlowInfo(), trace); + DataFlowInfo dataFlowInfo = null; + if (beforeBlockBody != null) { - beforeBlockBody.invoke(headerInnerScope); + dataFlowInfo = beforeBlockBody.invoke(headerInnerScope); } JetScope bodyInnerScope = headerDeclaringScope == null ? headerInnerScope : FunctionDescriptorUtil.getFunctionInnerScope(bodyDeclaringScope, functionDescriptor, trace); if (function.hasBody()) { - expressionTypingServices.checkFunctionReturnType(bodyInnerScope, function, functionDescriptor, c.getOuterDataFlowInfo(), null, trace); + expressionTypingServices.checkFunctionReturnType( + bodyInnerScope, function, functionDescriptor, dataFlowInfo != null ? dataFlowInfo : c.getOuterDataFlowInfo(), null, trace); } assert functionDescriptor.getReturnType() != null; diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/dataFlowInDelegationCall.kt b/compiler/testData/diagnostics/tests/secondaryConstructors/dataFlowInDelegationCall.kt new file mode 100644 index 00000000000..ecd4baf8f3b --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/dataFlowInDelegationCall.kt @@ -0,0 +1,7 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +class A { + constructor(x: Any, y: Any, z: Any) {} + constructor(x: String?, y: String?): this(x!!, x.length().toString() + y!!, "") { + x.length() + y.length() + } +} diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/dataFlowInDelegationCall.txt b/compiler/testData/diagnostics/tests/secondaryConstructors/dataFlowInDelegationCall.txt new file mode 100644 index 00000000000..017a662d08e --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/dataFlowInDelegationCall.txt @@ -0,0 +1,9 @@ +package + +internal final class A { + public constructor A(/*0*/ x: kotlin.Any, /*1*/ y: kotlin.Any, /*2*/ z: kotlin.Any) + public constructor A(/*0*/ x: kotlin.String?, /*1*/ y: kotlin.String?) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index c53e2361df4..88844c86967 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -10475,6 +10475,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("dataFlowInDelegationCall.kt") + public void testDataFlowInDelegationCall() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/dataFlowInDelegationCall.kt"); + doTest(fileName); + } + @TestMetadata("enums.kt") public void testEnums() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/enums.kt");