Better error recovery

This commit is contained in:
Andrey Breslav
2011-09-05 20:41:52 +04:00
parent 8801cf37fe
commit abfbe52a5a
4 changed files with 60 additions and 52 deletions
@@ -325,6 +325,8 @@ public class ClassDescriptorResolver {
continue; continue;
} }
TypeParameterDescriptor typeParameterDescriptor = parameterByName.get(referencedName); TypeParameterDescriptor typeParameterDescriptor = parameterByName.get(referencedName);
JetTypeReference boundTypeReference = constraint.getBoundTypeReference();
JetType bound = boundTypeReference != null ? resolveAndCheckUpperBoundType(boundTypeReference, scope, constraint.isClassObjectContraint()) : null;
if (typeParameterDescriptor == null) { if (typeParameterDescriptor == null) {
// To tell the user that we look only for locally defined type parameters // To tell the user that we look only for locally defined type parameters
ClassifierDescriptor classifier = scope.getClassifier(referencedName); ClassifierDescriptor classifier = scope.getClassifier(referencedName);
@@ -338,9 +340,7 @@ public class ClassDescriptorResolver {
} }
else { else {
trace.record(BindingContext.REFERENCE_TARGET, subjectTypeParameterName, typeParameterDescriptor); trace.record(BindingContext.REFERENCE_TARGET, subjectTypeParameterName, typeParameterDescriptor);
JetTypeReference boundTypeReference = constraint.getBoundTypeReference(); if (bound != null) {
if (boundTypeReference != null) {
JetType bound = resolveAndCheckUpperBoundType(boundTypeReference, scope, constraint.isClassObjectContraint());
if (constraint.isClassObjectContraint()) { if (constraint.isClassObjectContraint()) {
typeParameterDescriptor.addClassObjectBound(bound); typeParameterDescriptor.addClassObjectBound(bound);
} }
@@ -56,64 +56,68 @@ public class TypeResolver {
} }
ClassifierDescriptor classifierDescriptor = resolveClass(scope, type); ClassifierDescriptor classifierDescriptor = resolveClass(scope, type);
if (classifierDescriptor != null) { if (classifierDescriptor == null) {
if (classifierDescriptor instanceof TypeParameterDescriptor) { resolveTypeProjections(scope, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments());
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) classifierDescriptor; return;
}
if (classifierDescriptor instanceof TypeParameterDescriptor) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) classifierDescriptor;
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, typeParameterDescriptor); trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, typeParameterDescriptor);
result[0] = new JetTypeImpl(
annotations,
typeParameterDescriptor.getTypeConstructor(),
nullable || TypeUtils.hasNullableBound(typeParameterDescriptor),
Collections.<TypeProjection>emptyList(),
getScopeForTypeParameter(typeParameterDescriptor)
);
resolveTypeProjections(scope, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments());
}
else if (classifierDescriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) classifierDescriptor;
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor);
TypeConstructor typeConstructor = classifierDescriptor.getTypeConstructor();
List<TypeProjection> arguments = resolveTypeProjections(scope, typeConstructor, type.getTypeArguments());
List<TypeParameterDescriptor> parameters = typeConstructor.getParameters();
int expectedArgumentCount = parameters.size();
int actualArgumentCount = arguments.size();
if (ErrorUtils.isError(typeConstructor)) {
result[0] = new JetTypeImpl( result[0] = new JetTypeImpl(
annotations, annotations,
typeParameterDescriptor.getTypeConstructor(), typeConstructor,
nullable || TypeUtils.hasNullableBound(typeParameterDescriptor), nullable,
Collections.<TypeProjection>emptyList(), arguments, // TODO : review
getScopeForTypeParameter(typeParameterDescriptor) classDescriptor.getMemberScope(Collections.<TypeProjection>emptyList())
); );
} }
else if (classifierDescriptor instanceof ClassDescriptor) { else {
ClassDescriptor classDescriptor = (ClassDescriptor) classifierDescriptor; if (actualArgumentCount != expectedArgumentCount) {
String errorMessage = (expectedArgumentCount == 0 ? "No" : expectedArgumentCount) + " type arguments expected";
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor); if (actualArgumentCount == 0) {
TypeConstructor typeConstructor = classifierDescriptor.getTypeConstructor(); trace.getErrorHandler().genericError(type.getNode(), errorMessage);
List<TypeProjection> arguments = resolveTypeProjections(scope, typeConstructor, type.getTypeArguments()); } else {
List<TypeParameterDescriptor> parameters = typeConstructor.getParameters(); trace.getErrorHandler().genericError(type.getTypeArgumentList().getNode(), errorMessage);
int expectedArgumentCount = parameters.size(); }
int actualArgumentCount = arguments.size(); } else {
if (ErrorUtils.isError(typeConstructor)) {
result[0] = new JetTypeImpl( result[0] = new JetTypeImpl(
annotations, annotations,
typeConstructor, typeConstructor,
nullable, nullable,
arguments, // TODO : review arguments,
classDescriptor.getMemberScope(Collections.<TypeProjection>emptyList()) classDescriptor.getMemberScope(arguments)
); );
} if (checkBounds) {
else { TypeSubstitutor substitutor = TypeSubstitutor.create(result[0]);
if (actualArgumentCount != expectedArgumentCount) { for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
String errorMessage = (expectedArgumentCount == 0 ? "No" : expectedArgumentCount) + " type arguments expected"; TypeParameterDescriptor parameter = parameters.get(i);
if (actualArgumentCount == 0) { JetType argument = arguments.get(i).getType();
trace.getErrorHandler().genericError(type.getNode(), errorMessage); JetTypeReference typeReference = type.getTypeArguments().get(i).getTypeReference();
} else {
trace.getErrorHandler().genericError(type.getTypeArgumentList().getNode(), errorMessage);
}
} else {
result[0] = new JetTypeImpl(
annotations,
typeConstructor,
nullable,
arguments,
classDescriptor.getMemberScope(arguments)
);
if (checkBounds) {
TypeSubstitutor substitutor = TypeSubstitutor.create(result[0]);
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
TypeParameterDescriptor parameter = parameters.get(i);
JetType argument = arguments.get(i).getType();
JetTypeReference typeReference = type.getTypeArguments().get(i).getTypeReference();
if (typeReference != null) { if (typeReference != null) {
semanticServices.getClassDescriptorResolver(trace).checkBounds(typeReference, argument, parameter, substitutor); semanticServices.getClassDescriptorResolver(trace).checkBounds(typeReference, argument, parameter, substitutor);
}
} }
} }
} }
+3 -3
View File
@@ -60,9 +60,9 @@ fun <T : A> test2(t : T)
t.bar() t.bar()
} }
val test1 = test2<<error>A</error>>(A()) val t1 = test2<<error>A</error>>(A())
val test2 = test2<<error>B</error>>(B()) val t2 = test2<<error>B</error>>(B())
val test3 = test2<C>(C()) val t3 = test2<C>(C())
class Test<<error>T</error>> class Test<<error>T</error>>
where where
@@ -8,6 +8,10 @@ namespace a {
} }
class Foo<T>() {
val x : T<Int>
}
namespace a { namespace a {
import java.util.* import java.util.*