Sorting out how bindings are added to name lookup. (#2869)

This shifts logic so that bindings are added to name lookup only after the scope is complete, removing logic around adding/removing/re-adding names in certain scopes.

This does mean that things like a function's forward declaration will need to go through an extra hoop for name conflict checks, because under this approach a function definition does conflict checking when it adds names for the body's use. But, that seems easy to address, and better than the current hoops.
This commit is contained in:
Jon Ross-Perkins
2023-06-01 16:50:34 -07:00
committed by GitHub
parent a1a7251716
commit 39f7aae98d
76 changed files with 484 additions and 620 deletions
+5 -46
View File
@@ -75,7 +75,9 @@ auto SemanticsContext::AddNodeAndPush(ParseTree::Node parse_node,
auto SemanticsContext::AddNameToLookup(ParseTree::Node name_node,
SemanticsStringId name_id,
SemanticsNodeId target_id) -> void {
if (!AddNameToLookupImpl(name_id, target_id)) {
if (current_scope().names.insert(name_id).second) {
name_lookup_[name_id].push_back(target_id);
} else {
CARBON_DIAGNOSTIC(NameRedefined, Error, "Redefining {0} in the same scope.",
llvm::StringRef);
CARBON_DIAGNOSTIC(PreviousDefinition, Note, "Previous definition is here.");
@@ -88,49 +90,6 @@ auto SemanticsContext::AddNameToLookup(ParseTree::Node name_node,
}
}
auto SemanticsContext::AddNameToLookupImpl(SemanticsStringId name_id,
SemanticsNodeId target_id) -> bool {
if (current_scope().names.insert(name_id).second) {
name_lookup_[name_id].push_back(target_id);
return true;
} else {
return false;
}
}
auto SemanticsContext::BindName(ParseTree::Node name_node,
SemanticsTypeId type_id,
SemanticsNodeId target_id)
-> SemanticsStringId {
CARBON_CHECK(parse_tree_->node_kind(name_node) == ParseNodeKind::DeclaredName)
<< parse_tree_->node_kind(name_node);
auto name_str = parse_tree_->GetNodeText(name_node);
auto name_id = semantics_ir_->AddString(name_str);
AddNode(
SemanticsNode::BindName::Make(name_node, type_id, name_id, target_id));
AddNameToLookup(name_node, name_id, target_id);
return name_id;
}
auto SemanticsContext::TempRemoveLatestNameFromLookup() -> SemanticsNodeId {
// Save the storage ID.
auto it = name_lookup_.find(
node_stack_.Peek<SemanticsStringId>(ParseNodeKind::PatternBinding));
CARBON_CHECK(it != name_lookup_.end());
CARBON_CHECK(!it->second.empty());
auto storage_id = it->second.back();
// Pop the name from lookup.
if (it->second.size() == 1) {
// Erase names that no longer resolve.
name_lookup_.erase(it);
} else {
it->second.pop_back();
}
return storage_id;
}
auto SemanticsContext::LookupName(ParseTree::Node parse_node,
llvm::StringRef name) -> SemanticsNodeId {
CARBON_DIAGNOSTIC(NameNotFound, Error, "Name {0} not found", llvm::StringRef);
@@ -185,7 +144,7 @@ auto SemanticsContext::ImplicitAsForArgs(
if (arg_refs.size() != param_refs.size()) {
CARBON_CHECK(diagnostic != nullptr) << "Should have validated first";
CARBON_DIAGNOSTIC(CallArgCountMismatch, Note,
"Callable cannot be used: Received {0} argument(s), but "
"Function cannot be used: Received {0} argument(s), but "
"require {1} argument(s).",
int, int);
diagnostic->Note(param_parse_node, CallArgCountMismatch, arg_refs.size(),
@@ -204,7 +163,7 @@ auto SemanticsContext::ImplicitAsForArgs(
ImplicitAsKind::Incompatible) {
CARBON_CHECK(diagnostic != nullptr) << "Should have validated first";
CARBON_DIAGNOSTIC(CallArgTypeMismatch, Note,
"Callable cannot be used: Cannot implicityly convert "
"Function cannot be used: Cannot implicityly convert "
"argument {0} from `{1}` to `{2}`.",
size_t, std::string, std::string);
diagnostic->Note(param_parse_node, CallArgTypeMismatch, i,