Improved error reporting for candidates with wrong parameter count

This commit is contained in:
Stanislav Erokhin
2015-08-31 20:32:59 +03:00
parent 8ea6f36903
commit 5ded315cbb
23 changed files with 82 additions and 52 deletions
@@ -160,7 +160,7 @@ public class CandidateResolver(
val argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(
call, tracing, candidateCall, Sets.newLinkedHashSet<ValueArgument>())
if (!argumentMappingStatus.isSuccess()) {
candidateCall.addStatus(OTHER_ERROR)
candidateCall.addStatus(ARGUMENTS_MAPPING_ERROR)
}
}
@@ -136,33 +136,36 @@ public class ResolutionResultsHandler {
}
}
if (!thisLevel.isEmpty()) {
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(thisLevel, false);
if (results.isSingleResult()) {
results.getResultingCall().getTrace().moveAllMyDataTo(task.trace);
return OverloadResolutionResultsImpl.singleFailedCandidate(results.getResultingCall());
if (severityLevel.contains(ARGUMENTS_MAPPING_ERROR)) {
return recordFailedInfo(task, thisLevel);
}
task.tracing.noneApplicable(task.trace, results.getResultingCalls());
task.tracing.recordAmbiguity(task.trace, results.getResultingCalls());
return OverloadResolutionResultsImpl.manyFailedCandidates(results.getResultingCalls());
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(thisLevel, false);
return recordFailedInfo(task, results.getResultingCalls());
}
}
assert false : "Should not be reachable, cause every status must belong to some level";
Set<MutableResolvedCall<D>> noOverrides = OverrideResolver.filterOutOverridden(failedCandidates, MAP_TO_CANDIDATE);
if (noOverrides.size() != 1) {
task.tracing.noneApplicable(task.trace, noOverrides);
task.tracing.recordAmbiguity(task.trace, noOverrides);
return OverloadResolutionResultsImpl.manyFailedCandidates(noOverrides);
}
failedCandidates = noOverrides;
return recordFailedInfo(task, noOverrides);
}
MutableResolvedCall<D> failed = failedCandidates.iterator().next();
failed.getTrace().moveAllMyDataTo(task.trace);
return OverloadResolutionResultsImpl.singleFailedCandidate(failed);
return recordFailedInfo(task, failedCandidates);
}
@NotNull
private static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> recordFailedInfo(
@NotNull ResolutionTask task,
@NotNull Collection<MutableResolvedCall<D>> candidates
) {
if (candidates.size() == 1) {
MutableResolvedCall<D> failed = candidates.iterator().next();
failed.getTrace().moveAllMyDataTo(task.trace);
return OverloadResolutionResultsImpl.singleFailedCandidate(failed);
}
task.tracing.noneApplicable(task.trace, candidates);
task.tracing.recordAmbiguity(task.trace, candidates);
return OverloadResolutionResultsImpl.manyFailedCandidates(candidates);
}
private static <D extends CallableDescriptor> boolean allIncomplete(@NotNull Collection<MutableResolvedCall<D>> results) {
@@ -31,6 +31,7 @@ public enum ResolutionStatus {
// 'a.foo()' shouldn't be resolved to package level non-extension 'fun foo()'
// candidates with such error are thrown away completely
RECEIVER_PRESENCE_ERROR,
ARGUMENTS_MAPPING_ERROR,
INCOMPLETE_TYPE_INFERENCE,
SUCCESS(true);
@@ -38,6 +39,7 @@ public enum ResolutionStatus {
public static final EnumSet<ResolutionStatus>[] SEVERITY_LEVELS = new EnumSet[] {
EnumSet.of(UNSAFE_CALL_ERROR), // weakest
EnumSet.of(OTHER_ERROR),
EnumSet.of(ARGUMENTS_MAPPING_ERROR),
EnumSet.of(RECEIVER_TYPE_ERROR),
EnumSet.of(RECEIVER_PRESENCE_ERROR), // most severe
};
@@ -0,0 +1,16 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
fun foo() {}
fun foo(s: Int) {}
fun bar(a: Any) {}
fun bar(a: Int) {}
fun test() {
<!NONE_APPLICABLE!>foo<!>(1, 2)
foo(<!TYPE_MISMATCH!>""<!>)
<!NONE_APPLICABLE!>bar<!>(1, 2)
<!NONE_APPLICABLE!>bar<!>()
}
@@ -0,0 +1,7 @@
package
internal fun bar(/*0*/ a: kotlin.Any): kotlin.Unit
internal fun bar(/*0*/ a: kotlin.Int): kotlin.Unit
internal fun foo(): kotlin.Unit
internal fun foo(/*0*/ s: kotlin.Int): kotlin.Unit
internal fun test(): kotlin.Unit
@@ -6,12 +6,11 @@ fun <T: Any> joinT(<!UNUSED_PARAMETER!>x<!>: Int, vararg <!UNUSED_PARAMETER!>a<!
return null
}
fun <T: Any> joinT(<!UNUSED_PARAMETER!>x<!>: Any, <!UNUSED_PARAMETER!>y<!>: T): T? {
fun <T: Any> joinT(<!UNUSED_PARAMETER!>x<!>: Comparable<*>, <!UNUSED_PARAMETER!>y<!>: T): T? {
return null
}
fun test() {
val x2 = joinT(<!NON_VARARG_SPREAD!>*<!>1, "2")
val x2 = <!TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR!>joinT<!>(<!TYPE_MISMATCH!>Unit<!>, "2")
checkSubtype<String?>(x2)
}
}
@@ -1,7 +1,7 @@
package
package d {
internal fun </*0*/ T : kotlin.Any> joinT(/*0*/ x: kotlin.Any, /*1*/ y: T): T?
internal fun </*0*/ T : kotlin.Any> joinT(/*0*/ x: kotlin.Comparable<*>, /*1*/ y: T): T?
internal fun </*0*/ T : kotlin.Any> joinT(/*0*/ x: kotlin.Int, /*1*/ vararg a: T /*kotlin.Array<out T>*/): T?
internal fun test(): kotlin.Unit
}
@@ -83,7 +83,7 @@ fun test(n: J?, nn: J) {
J(nn, nn, nn)
J(platformNN, platformNN, platformNN)
<!NONE_APPLICABLE!>J<!>(n, n, n)
<!NONE_APPLICABLE!>J<!>(platformN, platformN, platformN)
J(<!TYPE_MISMATCH!>n<!>, n, n)
J(<!TYPE_MISMATCH!>platformN<!>, platformN, platformN)
J(platformJ, platformJ, platformJ)
}
@@ -11,7 +11,6 @@ public class ResolutionTaskHolder<F, G : F> {
//todo the problem is the type of ResolutionTask is inferred as ResolutionTask<F, F> too early
tasks.<!TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS!>bar<!>(ResolutionTask(candidate))
tasks.<!NONE_APPLICABLE!>add<!>(ResolutionTask(candidate))
tasks.add(ResolutionTask(candidate))
}
}
}
@@ -1,4 +1,4 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class X<T>(val t: T) {
constructor(t: T, i: Int) : <!NONE_APPLICABLE!>this<!>(i)
}
constructor(t: T, i: Int) : this(<!TYPE_MISMATCH!>i<!>)
}
@@ -5,8 +5,8 @@ fun bar(): String? = null
fun foo() {
var x = ArrayList<String>()
x.<!NONE_APPLICABLE!>add<!>(null)
x.<!NONE_APPLICABLE!>add<!>(bar())
x.add(<!NULL_FOR_NONNULL_TYPE!>null<!>)
x.add(<!TYPE_MISMATCH!>bar()<!>)
x.add("")
x[0] = <!NULL_FOR_NONNULL_TYPE!>null<!>
@@ -19,4 +19,4 @@ fun foo() {
val b4: Collection<String?> = x
val b6: MutableCollection<String?> = <!TYPE_MISMATCH!>x<!>
}
}
@@ -22,8 +22,8 @@ fun bar(): String? = null
fun foo() {
var x = A<String>()
x.<!NONE_APPLICABLE!>add<!>(null)
x.<!NONE_APPLICABLE!>add<!>(bar())
x.add(<!NULL_FOR_NONNULL_TYPE!>null<!>)
x.add(<!TYPE_MISMATCH!>bar()<!>)
x.add("")
x[0] = <!NULL_FOR_NONNULL_TYPE!>null<!>
@@ -36,4 +36,4 @@ fun foo() {
val b4: Collection<String?> = x
val b6: MutableCollection<String?> = <!TYPE_MISMATCH!>x<!>
}
}
@@ -60,7 +60,7 @@ fun <T> tt(t : T) : T {
val x : ArrayList<Int> = 0
x`java::java.util.ArrayList.get()`[1]
val foo = `Bar`Bar()
foo`!!`[null, 1]
foo`get2`[null, 1]
foo`get2`[1, 1]
foo`get1`[1]
foo`set1`[1] = ""
@@ -2370,6 +2370,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("overloadedFunction.kt")
public void testOverloadedFunction() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/checkArguments/overloadedFunction.kt");
doTest(fileName);
}
@TestMetadata("SpreadVarargs.kt")
public void testSpreadVarargs() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/checkArguments/SpreadVarargs.kt");