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.calls.autocasts.DataFlowInfo;
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.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.OverloadResolutionResultsImpl;
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
@@ -183,12 +181,7 @@ public class CallExpressionResolver {
checkSuper(receiver, results, context.trace, callExpression);
result[0] = true;
if (results.isSingleResult() && resolveMode == ResolveMode.TOP_LEVEL_CALL) {
ResolvedCallImpl<FunctionDescriptor> callToComplete = results.getResultingCall().getCallToCompleteTypeArgumentInference();
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;
if (!CallResolverUtil.hasInferredReturnType(results.getResultingCall())) return 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.Nullable;
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.ValueParameterDescriptor;
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.ConstraintsUtil;
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.tasks.ResolutionCandidate;
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());
}
public static <D extends CallableDescriptor> boolean hasReturnTypeDependentOnNotInferredParams(
@NotNull ResolvedCallImpl<D> callToComplete
) {
private static boolean hasReturnTypeDependentOnNotInferredParams(@NotNull ResolvedCallImpl<?> callToComplete) {
ConstraintSystem constraintSystem = callToComplete.getConstraintSystem();
if (constraintSystem == null) return false;
@@ -134,6 +134,17 @@ public class CallResolverUtil {
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
public static CallKey createCallKey(@NotNull BasicCallResolutionContext context) {
if (context.call.getCallType() == Call.CallType.INVOKE) {
@@ -216,7 +216,7 @@ public class CandidateResolver {
resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
}
public <D extends CallableDescriptor> void completeTypeInferenceDependentOnExpectedTypeForCall(
public <D extends CallableDescriptor> JetType completeTypeInferenceDependentOnExpectedTypeForCall(
@NotNull CallCandidateResolutionContext<D> context,
boolean isInnerCall
) {
@@ -239,7 +239,8 @@ public class CandidateResolver {
context.tracing.typeInferenceFailed(context.trace, errorData);
resolvedCall.addStatus(ResolutionStatus.OTHER_ERROR);
return;
if (!CallResolverUtil.hasInferredReturnType(resolvedCall)) return null;
return resolvedCall.getResultingDescriptor().getReturnType();
}
boolean boundsAreSatisfied = ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, /*substituteOtherTypeParametersInBounds=*/true);
@@ -271,9 +272,11 @@ public class CandidateResolver {
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
) {
ResolvedCallImpl<D> resolvedCall = context.candidateCall;
@@ -318,16 +321,20 @@ public class CandidateResolver {
CallCandidateResolutionContext<FunctionDescriptor> contextForArgument =
storedContextForArgument.replaceResolveMode(ResolveMode.TOP_LEVEL_CALL).replaceBindingTrace(context.trace).replaceExpectedType(expectedType);
JetType type;
if (contextForArgument.candidateCall.hasIncompleteTypeParameters()) {
completeTypeInferenceDependentOnExpectedTypeForCall(contextForArgument, true);
type = completeTypeInferenceDependentOnExpectedTypeForCall(contextForArgument, true);
}
else {
completeNestedCallsInference(contextForArgument);
type = completeNestedCallsInference(contextForArgument);
checkValueArgumentTypes(contextForArgument);
}
DataFlowUtils.checkType(type, expression, contextForArgument);
}
}
recordReferenceForInvokeFunction(context);
return resolvedCall.getResultingDescriptor().getReturnType();
}
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");
}
@TestMetadata("kt3461checkTypes.kt")
public void testKt3461checkTypes() throws Exception {
doTest("compiler/testData/diagnostics/tests/inference/nestedCalls/kt3461checkTypes.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/tests/inference/regressions")