Просмотр исходного кода

Improve diagnostic for unknown name in name qualifier. (#2579)

As requested in #2572.
Richard Smith 3 лет назад
Родитель
Сommit
1a8a41a5a6

+ 10 - 3
explorer/ast/static_scope.cpp

@@ -52,14 +52,21 @@ auto StaticScope::Resolve(std::string_view name,
   return *result;
 }
 
-auto StaticScope::ResolveHere(std::string_view name, SourceLocation source_loc,
+auto StaticScope::ResolveHere(std::optional<ValueNodeView> this_scope,
+                              std::string_view name, SourceLocation source_loc,
                               bool allow_undeclared) const
     -> ErrorOr<ValueNodeView> {
   CARBON_ASSIGN_OR_RETURN(std::optional<ValueNodeView> result,
                           TryResolveHere(name, source_loc, allow_undeclared));
   if (!result) {
-    return ProgramError(source_loc)
-           << "could not resolve '" << name << "' in this scope";
+    if (this_scope) {
+      return ProgramError(source_loc)
+             << "name '" << name << "' has not been declared in "
+             << PrintAsID(this_scope->base());
+    } else {
+      return ProgramError(source_loc)
+             << "name '" << name << "' has not been declared in this scope";
+    }
   }
   return *result;
 }

+ 2 - 1
explorer/ast/static_scope.h

@@ -65,7 +65,8 @@ class StaticScope {
   // error at `source_loc` if the name is not declared in this scope. If
   // `allow_undeclared` is `true`, names that have been added but not yet marked
   // declared or usable do not result in an error.
-  auto ResolveHere(std::string_view name, SourceLocation source_loc,
+  auto ResolveHere(std::optional<ValueNodeView> this_scope,
+                   std::string_view name, SourceLocation source_loc,
                    bool allow_undeclared) const -> ErrorOr<ValueNodeView>;
 
   // Returns the value node of the BindingPattern of the returned var definition

+ 5 - 2
explorer/interpreter/resolve_names.cpp

@@ -113,14 +113,16 @@ auto NameResolver::ResolveQualifier(DeclaredName name,
                                     bool allow_undeclared)
     -> ErrorOr<Nonnull<StaticScope*>> {
   Nonnull<StaticScope*> scope = &enclosing_scope;
+  std::optional<ValueNodeView> scope_node;
   for (const auto& [loc, qualifier] : name.qualifiers()) {
     // TODO: If we permit qualified names anywhere other than the top level, we
     // will need to decide whether the first name in the qualifier is looked up
     // only in the innermost enclosing scope or in all enclosing scopes.
     CARBON_ASSIGN_OR_RETURN(
         ValueNodeView node,
-        scope->ResolveHere(qualifier, loc, allow_undeclared));
+        scope->ResolveHere(scope_node, qualifier, loc, allow_undeclared));
 
+    scope_node = node;
     if (const auto* namespace_decl =
             dyn_cast<NamespaceDeclaration>(&node.base())) {
       scope = &namespace_scopes_[namespace_decl];
@@ -282,7 +284,8 @@ auto NameResolver::ResolveNames(Expression& expression,
             << "name resolved to undeclared namespace";
         CARBON_ASSIGN_OR_RETURN(
             const auto value_node,
-            ns_it->second.ResolveHere(access.member_name(), access.source_loc(),
+            ns_it->second.ResolveHere(scope, access.member_name(),
+                                      access.source_loc(),
                                       /*allow_undeclared=*/false));
         access.set_value_node(value_node);
         return {value_node};

+ 1 - 1
explorer/testdata/namespace/fail_unknown_member.carbon

@@ -11,6 +11,6 @@ package ExplorerTest api;
 namespace N;
 
 fn Main() -> i32 {
-  // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/namespace/fail_unknown_member.carbon:[[@LINE+1]]: could not resolve 'value' in this scope
+  // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/namespace/fail_unknown_member.carbon:[[@LINE+1]]: name 'value' has not been declared in namespace N
   return N.value;
 }

+ 1 - 1
explorer/testdata/namespace/fail_unknown_namespace.carbon

@@ -8,7 +8,7 @@
 
 package ExplorerTest api;
 
-// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/namespace/fail_unknown_namespace.carbon:[[@LINE+1]]: could not resolve 'N' in this scope
+// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/namespace/fail_unknown_namespace.carbon:[[@LINE+1]]: name 'N' has not been declared in this scope
 fn N.F() {}
 
 fn Main() -> i32 {