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

As requested in #2572.
This commit is contained in:
Richard Smith
2023-02-03 16:05:08 -08:00
committed by GitHub
parent 6d4920148b
commit 1a8a41a5a6
5 changed files with 19 additions and 8 deletions
+10 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 {