When merging functions, detect uses of imports prior to a redecl. (#3836)

LookupNameInDecl is only called from DeclNameStack, but I'm adding
mark_imports_used there because it feels more consistent. Not sure if we
want a better API boundary. I admit I'm also suspicious of its call to
LookupInCurrentScope but maybe it's okay due to how imports work.

I was choosing to print multiple diagnostics when a declaration is
previously used _and_ doesn't match because I think the "previously
used" is more important, but the "doesn't match" may give an additional
hint about why it didn't work.

The merge.h utility function is because I think we can follow a similar
model for identifying errors with other declarations: classes,
interfaces, etc.
This commit is contained in:
Jon Ross-Perkins
2024-04-02 17:44:55 +00:00
committed by GitHub
parent f8c8861e5f
commit dffe4a36de
14 changed files with 471 additions and 96 deletions
+16 -10
View File
@@ -227,7 +227,8 @@ auto Context::AddNameToLookup(SemIR::NameId name_id, SemIR::InstId target_id)
}
auto Context::LookupNameInDecl(SemIR::LocId loc_id, SemIR::NameId name_id,
SemIR::NameScopeId scope_id) -> SemIR::InstId {
SemIR::NameScopeId scope_id,
bool mark_imports_used) -> SemIR::InstId {
if (!scope_id.is_valid()) {
// Look for a name in the current scope only. There are two cases where the
// name would be in an outer scope:
@@ -263,7 +264,8 @@ auto Context::LookupNameInDecl(SemIR::LocId loc_id, SemIR::NameId name_id,
//
// // Error, no `F` in `B`.
// fn B.F() {}
return LookupNameInExactScope(loc_id, name_id, name_scopes().Get(scope_id));
return LookupNameInExactScope(loc_id, name_id, name_scopes().Get(scope_id),
mark_imports_used);
}
}
@@ -298,8 +300,8 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id,
// Handles lookup through the import_ir_scopes for LookupNameInExactScope.
static auto LookupInImportIRScopes(Context& context, SemIRLoc loc,
SemIR::NameId name_id,
const SemIR::NameScope& scope)
-> SemIR::InstId {
const SemIR::NameScope& scope,
bool mark_imports_used) -> SemIR::InstId {
auto identifier_id = name_id.AsIdentifierId();
llvm::StringRef identifier;
if (identifier_id.is_valid()) {
@@ -342,7 +344,8 @@ static auto LookupInImportIRScopes(Context& context, SemIRLoc loc,
if (result_id.is_valid()) {
MergeImportRef(context, import_inst_id, result_id);
} else {
LoadImportRef(context, import_inst_id, loc);
LoadImportRef(context, import_inst_id,
mark_imports_used ? loc : SemIR::LocId::Invalid);
result_id = import_inst_id;
}
}
@@ -351,14 +354,16 @@ static auto LookupInImportIRScopes(Context& context, SemIRLoc loc,
}
auto Context::LookupNameInExactScope(SemIRLoc loc, SemIR::NameId name_id,
const SemIR::NameScope& scope)
-> SemIR::InstId {
const SemIR::NameScope& scope,
bool mark_imports_used) -> SemIR::InstId {
if (auto it = scope.names.find(name_id); it != scope.names.end()) {
LoadImportRef(*this, it->second, loc);
LoadImportRef(*this, it->second,
mark_imports_used ? loc : SemIR::LocId::Invalid);
return it->second;
}
if (!scope.import_ir_scopes.empty()) {
return LookupInImportIRScopes(*this, loc, name_id, scope);
return LookupInImportIRScopes(*this, loc, name_id, scope,
mark_imports_used);
}
return SemIR::InstId::Invalid;
}
@@ -375,7 +380,8 @@ auto Context::LookupQualifiedName(Parse::NodeId node_id, SemIR::NameId name_id,
const auto& scope = name_scopes().Get(scope_ids.pop_back_val());
has_error |= scope.has_error;
auto scope_result_id = LookupNameInExactScope(node_id, name_id, scope);
auto scope_result_id = LookupNameInExactScope(node_id, name_id, scope,
/*mark_imports_used=*/true);
if (!scope_result_id.is_valid()) {
// Nothing found in this scope: also look in its extended scopes.
auto extended = llvm::reverse(scope.extended_scopes);