diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java index def4b1835e0..6ab150f4aac 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java @@ -263,6 +263,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly controlFlowAnalyzer.setTrace(bindingTrace); + declarationsChecker.setDescriptorResolver(descriptorResolver); declarationsChecker.setTrace(bindingTrace); functionAnalyzerExtension.setTrace(bindingTrace); diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java index 0f9b56c3eb9..6e655a12b3e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java @@ -169,6 +169,7 @@ public class InjectorForBodyResolve { controlFlowAnalyzer.setTrace(bindingTrace); + declarationsChecker.setDescriptorResolver(descriptorResolver); declarationsChecker.setTrace(bindingTrace); functionAnalyzerExtension.setTrace(bindingTrace); diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java index e729f0aa995..c607c450d65 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java @@ -209,6 +209,7 @@ public class InjectorForTopDownAnalyzerBasic { controlFlowAnalyzer.setTrace(bindingTrace); + declarationsChecker.setDescriptorResolver(descriptorResolver); declarationsChecker.setTrace(bindingTrace); functionAnalyzerExtension.setTrace(bindingTrace); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java index 1722104781a..6a2a02e195b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java @@ -41,6 +41,8 @@ public class DeclarationsChecker { private BindingTrace trace; @NotNull private ModifiersChecker modifiersChecker; + @NotNull + private DescriptorResolver descriptorResolver; @Inject public void setTrace(@NotNull BindingTrace trace) { @@ -48,6 +50,11 @@ public class DeclarationsChecker { this.modifiersChecker = new ModifiersChecker(trace); } + @Inject + public void setDescriptorResolver(@NotNull DescriptorResolver descriptorResolver) { + this.descriptorResolver = descriptorResolver; + } + public void process(@NotNull BodiesResolveContext bodiesResolveContext) { for (JetFile file : bodiesResolveContext.getFiles()) { checkModifiersAndAnnotationsInPackageDirective(file); @@ -59,16 +66,19 @@ public class DeclarationsChecker { ClassDescriptorWithResolutionScopes classDescriptor = entry.getValue(); if (!bodiesResolveContext.completeAnalysisNeeded(classOrObject)) continue; + checkSupertypesForConsistency(classDescriptor); + checkTypesInClassHeader(classOrObject); + if (classOrObject instanceof JetClass) { - checkClass((JetClass) classOrObject, classDescriptor); + JetClass jetClass = (JetClass) classOrObject; + checkClass(jetClass, classDescriptor); + descriptorResolver.checkNamesInConstraints( + jetClass, classDescriptor, classDescriptor.getScopeForClassHeaderResolution(), trace); } else if (classOrObject instanceof JetObjectDeclaration) { checkObject((JetObjectDeclaration) classOrObject); } - checkSupertypesForConsistency(classDescriptor); - checkTypesInClassHeader(classOrObject); - modifiersChecker.checkModifiersForDeclaration(classOrObject, classDescriptor); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index 55e4a02dd78..22771dcc45a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -306,7 +306,7 @@ public class DescriptorResolver { List typeParameterDescriptors = resolveTypeParametersForCallableDescriptor(functionDescriptor, innerScope, function.getTypeParameters(), trace); innerScope.changeLockLevel(WritableScope.LockLevel.BOTH); - resolveGenericBounds(function, innerScope, typeParameterDescriptors, trace); + resolveGenericBounds(function, functionDescriptor, innerScope, typeParameterDescriptors, trace); JetType receiverType = null; JetTypeReference receiverTypeRef = function.getReceiverTypeRef(); @@ -627,6 +627,7 @@ public class DescriptorResolver { public void resolveGenericBounds( @NotNull JetTypeParameterListOwner declaration, + @NotNull DeclarationDescriptor descriptor, JetScope scope, List parameters, BindingTrace trace @@ -665,18 +666,7 @@ public class DescriptorResolver { .add(new UpperBoundCheckerTask(boundTypeReference, bound, constraint.isClassObjectConstraint())); } - if (typeParameterDescriptor == null) { - // To tell the user that we look only for locally defined type parameters - ClassifierDescriptor classifier = scope.getClassifier(referencedName); - if (classifier != null) { - trace.report(NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER.on(subjectTypeParameterName, constraint, declaration)); - trace.record(BindingContext.REFERENCE_TARGET, subjectTypeParameterName, classifier); - } - else { - trace.report(UNRESOLVED_REFERENCE.on(subjectTypeParameterName, subjectTypeParameterName)); - } - } - else { + if (typeParameterDescriptor != null) { trace.record(BindingContext.REFERENCE_TARGET, subjectTypeParameterName, typeParameterDescriptor); if (bound != null) { if (constraint.isClassObjectConstraint()) { @@ -713,6 +703,41 @@ public class DescriptorResolver { for (UpperBoundCheckerTask checkerTask : deferredUpperBoundCheckerTasks) { checkUpperBoundType(checkerTask.upperBound, checkerTask.upperBoundType, checkerTask.isClassObjectConstraint, trace); } + + if (!(declaration instanceof JetClass)) { + checkNamesInConstraints(declaration, descriptor, scope, trace); + } + } + + public void checkNamesInConstraints( + @NotNull JetTypeParameterListOwner declaration, + @NotNull DeclarationDescriptor descriptor, + @NotNull JetScope scope, + @NotNull BindingTrace trace + ) { + for (JetTypeConstraint constraint : declaration.getTypeConstraints()) { + JetSimpleNameExpression nameExpression = constraint.getSubjectTypeParameterName(); + if (nameExpression == null) continue; + + Name name = nameExpression.getReferencedNameAsName(); + + ClassifierDescriptor classifier = scope.getClassifier(name); + if (classifier instanceof TypeParameterDescriptor && classifier.getContainingDeclaration() == descriptor) continue; + + if (classifier != null) { + // To tell the user that we look only for locally defined type parameters + trace.report(NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER.on(nameExpression, constraint, declaration)); + trace.record(BindingContext.REFERENCE_TARGET, nameExpression, classifier); + } + else { + trace.report(UNRESOLVED_REFERENCE.on(nameExpression, nameExpression)); + } + + JetTypeReference boundTypeReference = constraint.getBoundTypeReference(); + if (boundTypeReference != null) { + typeResolver.resolveType(scope, boundTypeReference, trace, true); + } + } } public static void reportUnsupportedClassObjectConstraint(BindingTrace trace, JetTypeConstraint constraint) { @@ -877,7 +902,7 @@ public class DescriptorResolver { typeParameterDescriptors = resolveTypeParametersForCallableDescriptor(containingDeclaration, writableScope, typeParameters, trace); writableScope.changeLockLevel(WritableScope.LockLevel.READING); - resolveGenericBounds(property, writableScope, typeParameterDescriptors, trace); + resolveGenericBounds(property, propertyDescriptor, writableScope, typeParameterDescriptors, trace); scopeWithTypeParameters = writableScope; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java index e2983211e08..9efd01dbfd7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -208,7 +208,7 @@ public class TypeHierarchyResolver { if (classOrObject instanceof JetClass) { ClassDescriptorWithResolutionScopes descriptor = entry.getValue(); //noinspection unchecked - descriptorResolver.resolveGenericBounds((JetClass) classOrObject, descriptor.getScopeForClassHeaderResolution(), + descriptorResolver.resolveGenericBounds((JetClass) classOrObject, descriptor, descriptor.getScopeForClassHeaderResolution(), (List) descriptor.getTypeConstructor().getParameters(), trace); } } diff --git a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java index 16d8fc7b982..6763a5ae249 100644 --- a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java +++ b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java @@ -209,6 +209,7 @@ public class InjectorForTopDownAnalyzerForJs { controlFlowAnalyzer.setTrace(bindingTrace); + declarationsChecker.setDescriptorResolver(descriptorResolver); declarationsChecker.setTrace(bindingTrace); functionAnalyzerExtension.setTrace(bindingTrace);