diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FunctionDescriptorUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FunctionDescriptorUtil.java index 2b00103cd5e..1f5af68ce05 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FunctionDescriptorUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FunctionDescriptorUtil.java @@ -53,15 +53,18 @@ public class FunctionDescriptorUtil { private FunctionDescriptorUtil() { } - public static Map createSubstitutionContext(@NotNull FunctionDescriptor functionDescriptor, List typeArguments) { + public static Map createSubstitutionContext( + @NotNull FunctionDescriptor functionDescriptor, + @NotNull List typeArguments + ) { if (functionDescriptor.getTypeParameters().isEmpty()) return Collections.emptyMap(); Map result = new HashMap(); - int typeArgumentsSize = typeArguments.size(); List typeParameters = functionDescriptor.getTypeParameters(); - assert typeArgumentsSize == typeParameters.size(); - for (int i = 0; i < typeArgumentsSize; i++) { + assert typeArguments.size() >= typeParameters.size() : + "Insufficient number of type arguments.\nType arguments: " + typeArguments + "\nType parameters: " + typeParameters; + for (int i = 0; i < typeParameters.size(); i++) { TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i); JetType typeArgument = typeArguments.get(i); result.put(typeParameterDescriptor.getTypeConstructor(), new TypeProjectionImpl(typeArgument)); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java index 829daade765..c08194d4244 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java @@ -142,22 +142,25 @@ public class CandidateResolver { projection.getTypeReference(), context.scope, context.trace, ErrorUtils.createErrorType("Star projection in a call"))); } int expectedTypeArgumentCount = candidate.getTypeParameters().size(); - if (expectedTypeArgumentCount == jetTypeArguments.size()) { - - checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, context.trace); - - Map - substitutionContext = FunctionDescriptorUtil - .createSubstitutionContext((FunctionDescriptor) candidate, typeArguments); - TypeSubstitutor substitutor = TypeSubstitutor.create(substitutionContext); - candidateCall.setResultingSubstitutor(substitutor); - - candidateCall.addStatus(checkAllValueArguments(context, SHAPE_FUNCTION_ARGUMENTS).status); + for (int index = jetTypeArguments.size(); index < expectedTypeArgumentCount; index++) { + typeArguments.add(ErrorUtils.createErrorType( + "Explicit type argument expected for " + candidate.getTypeParameters().get(index).getName())); } - else { + Map substitutionContext = + FunctionDescriptorUtil.createSubstitutionContext((FunctionDescriptor) candidate, typeArguments); + TypeSubstitutor substitutor = TypeSubstitutor.create(substitutionContext); + + if (expectedTypeArgumentCount != jetTypeArguments.size()) { candidateCall.addStatus(OTHER_ERROR); context.tracing.wrongNumberOfTypeArguments(context.trace, expectedTypeArgumentCount); } + else { + checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, substitutor, context.trace); + } + + candidateCall.setResultingSubstitutor(substitutor); + + candidateCall.addStatus(checkAllValueArguments(context, SHAPE_FUNCTION_ARGUMENTS).status); } task.performAdvancedChecks(candidate, context.trace, context.tracing); @@ -648,17 +651,11 @@ public class CandidateResolver { @NotNull List jetTypeArguments, @NotNull List typeArguments, @NotNull CallableDescriptor functionDescriptor, - @NotNull BindingTrace trace) { - Map context = Maps.newHashMap(); - - List typeParameters = functionDescriptor.getOriginal().getTypeParameters(); - for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) { - TypeParameterDescriptor typeParameter = typeParameters.get(i); - JetType typeArgument = typeArguments.get(i); - context.put(typeParameter.getTypeConstructor(), new TypeProjectionImpl(typeArgument)); - } - TypeSubstitutor substitutor = TypeSubstitutor.create(context); - for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) { + @NotNull TypeSubstitutor substitutor, + @NotNull BindingTrace trace + ) { + List typeParameters = functionDescriptor.getTypeParameters(); + for (int i = 0; i < typeParameters.size(); i++) { TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i); JetType typeArgument = typeArguments.get(i); JetTypeReference typeReference = jetTypeArguments.get(i).getTypeReference(); diff --git a/compiler/testData/diagnostics/tests/resolve/wrongNumberOfTypeArguments.kt b/compiler/testData/diagnostics/tests/resolve/wrongNumberOfTypeArguments.kt new file mode 100644 index 00000000000..b41383e9f25 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/wrongNumberOfTypeArguments.kt @@ -0,0 +1,14 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun foo(t: T) = t + +fun test1() { + foo("") +} + + +fun bar(t: T, r: R) {} + +fun test2() { + bar("", "") +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index efaf773507c..d9a5dd82151 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -7048,6 +7048,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest("compiler/testData/diagnostics/tests/resolve/resolveWithoutGenerics.kt"); } + @TestMetadata("wrongNumberOfTypeArguments.kt") + public void testWrongNumberOfTypeArguments() throws Exception { + doTest("compiler/testData/diagnostics/tests/resolve/wrongNumberOfTypeArguments.kt"); + } + @TestMetadata("compiler/testData/diagnostics/tests/resolve/invoke") @InnerTestClasses({Invoke.Errors.class}) public static class Invoke extends AbstractJetDiagnosticsTest { diff --git a/idea/testData/completion/smart/WrongNumberOfTypeArguments.kt b/idea/testData/completion/smart/WrongNumberOfTypeArguments.kt new file mode 100644 index 00000000000..3676d1ab913 --- /dev/null +++ b/idea/testData/completion/smart/WrongNumberOfTypeArguments.kt @@ -0,0 +1,9 @@ +package aaaa + +fun foo(s: String, t: T) {} + +fun test(s: String) { + foo() +} + +// EXIST: s \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java index bd0f9f02c0d..f51b640401c 100644 --- a/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java @@ -578,4 +578,9 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT doTest("idea/testData/completion/smart/WithQualifier.kt"); } + @TestMetadata("WrongNumberOfTypeArguments.kt") + public void testWrongNumberOfTypeArguments() throws Exception { + doTest("idea/testData/completion/smart/WrongNumberOfTypeArguments.kt"); + } + }