KT-3461 Nullable argument allowed where shouldn't be

#KT-3461 Fixed
This commit is contained in:
Svetlana Isakova
2013-04-01 19:07:04 +04:00
parent dd0acf6013
commit 12c0a2cb77
5 changed files with 47 additions and 16 deletions
@@ -26,10 +26,8 @@ import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.context.*; import org.jetbrains.jet.lang.resolve.calls.context.*;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl; import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
@@ -183,12 +181,7 @@ public class CallExpressionResolver {
checkSuper(receiver, results, context.trace, callExpression); checkSuper(receiver, results, context.trace, callExpression);
result[0] = true; result[0] = true;
if (results.isSingleResult() && resolveMode == ResolveMode.TOP_LEVEL_CALL) { if (results.isSingleResult() && resolveMode == ResolveMode.TOP_LEVEL_CALL) {
ResolvedCallImpl<FunctionDescriptor> callToComplete = results.getResultingCall().getCallToCompleteTypeArgumentInference(); if (!CallResolverUtil.hasInferredReturnType(results.getResultingCall())) return null;
if (CallResolverUtil.hasReturnTypeDependentOnNotInferredParams(callToComplete)) return null;
// Expected type mismatch was reported before as 'TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH'
ConstraintSystem constraintSystem = callToComplete.getConstraintSystem();
if (constraintSystem != null && constraintSystem.hasOnlyExpectedTypeMismatch()) return null;
} }
return results.isSingleResult() ? results.getResultingCall() : null; return results.isSingleResult() ? results.getResultingCall() : null;
@@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.Call; import org.jetbrains.jet.lang.psi.Call;
@@ -33,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.calls.context.CallResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintsUtil; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintsUtil;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate; import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
@@ -113,9 +115,7 @@ public class CallResolverUtil {
return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), type.isNullable(), newArguments, type.getMemberScope()); return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), type.isNullable(), newArguments, type.getMemberScope());
} }
public static <D extends CallableDescriptor> boolean hasReturnTypeDependentOnNotInferredParams( private static boolean hasReturnTypeDependentOnNotInferredParams(@NotNull ResolvedCallImpl<?> callToComplete) {
@NotNull ResolvedCallImpl<D> callToComplete
) {
ConstraintSystem constraintSystem = callToComplete.getConstraintSystem(); ConstraintSystem constraintSystem = callToComplete.getConstraintSystem();
if (constraintSystem == null) return false; if (constraintSystem == null) return false;
@@ -134,6 +134,17 @@ public class CallResolverUtil {
return false; return false;
} }
public static boolean hasInferredReturnType(ResolvedCallWithTrace<?> call) {
boolean isKnownReturnType = true;
ResolvedCallImpl<?> callToComplete = call.getCallToCompleteTypeArgumentInference();
if (hasReturnTypeDependentOnNotInferredParams(callToComplete)) { isKnownReturnType = false; }
// Expected type mismatch was reported before as 'TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH'
ConstraintSystem constraintSystem = callToComplete.getConstraintSystem();
if (constraintSystem != null && constraintSystem.hasOnlyExpectedTypeMismatch()) { isKnownReturnType = false; }
return isKnownReturnType;
}
@Nullable @Nullable
public static CallKey createCallKey(@NotNull BasicCallResolutionContext context) { public static CallKey createCallKey(@NotNull BasicCallResolutionContext context) {
if (context.call.getCallType() == Call.CallType.INVOKE) { if (context.call.getCallType() == Call.CallType.INVOKE) {
@@ -216,7 +216,7 @@ public class CandidateResolver {
resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor()); resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
} }
public <D extends CallableDescriptor> void completeTypeInferenceDependentOnExpectedTypeForCall( public <D extends CallableDescriptor> JetType completeTypeInferenceDependentOnExpectedTypeForCall(
@NotNull CallCandidateResolutionContext<D> context, @NotNull CallCandidateResolutionContext<D> context,
boolean isInnerCall boolean isInnerCall
) { ) {
@@ -239,7 +239,8 @@ public class CandidateResolver {
context.tracing.typeInferenceFailed(context.trace, errorData); context.tracing.typeInferenceFailed(context.trace, errorData);
resolvedCall.addStatus(ResolutionStatus.OTHER_ERROR); resolvedCall.addStatus(ResolutionStatus.OTHER_ERROR);
return; if (!CallResolverUtil.hasInferredReturnType(resolvedCall)) return null;
return resolvedCall.getResultingDescriptor().getReturnType();
} }
boolean boundsAreSatisfied = ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, /*substituteOtherTypeParametersInBounds=*/true); boolean boundsAreSatisfied = ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, /*substituteOtherTypeParametersInBounds=*/true);
@@ -271,9 +272,11 @@ public class CandidateResolver {
DataFlowUtils.checkType(resolvedCall.getResultingDescriptor().getReturnType(), (JetCallExpression) callElement, context, context.dataFlowInfo); DataFlowUtils.checkType(resolvedCall.getResultingDescriptor().getReturnType(), (JetCallExpression) callElement, context, context.dataFlowInfo);
} }
} }
return resolvedCall.getResultingDescriptor().getReturnType();
} }
public <D extends CallableDescriptor> void completeNestedCallsInference( @Nullable
public <D extends CallableDescriptor> JetType completeNestedCallsInference(
@NotNull CallCandidateResolutionContext<D> context @NotNull CallCandidateResolutionContext<D> context
) { ) {
ResolvedCallImpl<D> resolvedCall = context.candidateCall; ResolvedCallImpl<D> resolvedCall = context.candidateCall;
@@ -318,16 +321,20 @@ public class CandidateResolver {
CallCandidateResolutionContext<FunctionDescriptor> contextForArgument = CallCandidateResolutionContext<FunctionDescriptor> contextForArgument =
storedContextForArgument.replaceResolveMode(ResolveMode.TOP_LEVEL_CALL).replaceBindingTrace(context.trace).replaceExpectedType(expectedType); storedContextForArgument.replaceResolveMode(ResolveMode.TOP_LEVEL_CALL).replaceBindingTrace(context.trace).replaceExpectedType(expectedType);
JetType type;
if (contextForArgument.candidateCall.hasIncompleteTypeParameters()) { if (contextForArgument.candidateCall.hasIncompleteTypeParameters()) {
completeTypeInferenceDependentOnExpectedTypeForCall(contextForArgument, true); type = completeTypeInferenceDependentOnExpectedTypeForCall(contextForArgument, true);
} }
else { else {
completeNestedCallsInference(contextForArgument); type = completeNestedCallsInference(contextForArgument);
checkValueArgumentTypes(contextForArgument); checkValueArgumentTypes(contextForArgument);
} }
DataFlowUtils.checkType(type, expression, contextForArgument);
} }
} }
recordReferenceForInvokeFunction(context); recordReferenceForInvokeFunction(context);
return resolvedCall.getResultingDescriptor().getReturnType();
} }
private static <D extends CallableDescriptor> void recordReferenceForInvokeFunction(CallCandidateResolutionContext<D> context) { private static <D extends CallableDescriptor> void recordReferenceForInvokeFunction(CallCandidateResolutionContext<D> context) {
@@ -0,0 +1,15 @@
//KT-3461 Nullable argument allowed where shouldn't be
package a
class F {
fun p(): String? = null
}
fun foo(<!UNUSED_PARAMETER!>s<!>: String) {}
fun r(): Int? = null
fun test() {
foo(<!TYPE_MISMATCH!>F().p()<!>)
foo(<!TYPE_MISMATCH!>r()<!>)
}
@@ -2195,6 +2195,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/inference/nestedCalls/kt3395.kt"); doTest("compiler/testData/diagnostics/tests/inference/nestedCalls/kt3395.kt");
} }
@TestMetadata("kt3461checkTypes.kt")
public void testKt3461checkTypes() throws Exception {
doTest("compiler/testData/diagnostics/tests/inference/nestedCalls/kt3461checkTypes.kt");
}
} }
@TestMetadata("compiler/testData/diagnostics/tests/inference/regressions") @TestMetadata("compiler/testData/diagnostics/tests/inference/regressions")