KT-3461 Nullable argument allowed where shouldn't be
#KT-3461 Fixed
This commit is contained in:
+1
-8
@@ -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")
|
||||||
|
|||||||
Reference in New Issue
Block a user