Better error recovery
This commit is contained in:
@@ -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);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.*
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user