Skip to content

Commit 957f115

Browse files
authored
Start pulling in names from cross-package imports. (#3789)
Note, I'm annotating the lookup partly so that the reason the conflict comes up is clear, partly so that there's actually a diagnostic line associated with the root cause as more tests get packed into a single file.
1 parent 8cb932b commit 957f115

File tree

8 files changed

+498
-29
lines changed

8 files changed

+498
-29
lines changed

toolchain/base/value_store.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,14 @@ class ValueStore<StringId> : public Yaml::Printable<ValueStore<StringId>> {
200200
return values_[id.index];
201201
}
202202

203+
// Returns an ID for the value, or Invalid if not found.
204+
auto Lookup(llvm::StringRef value) const -> StringId {
205+
if (auto it = map_.find(value); it != map_.end()) {
206+
return it->second;
207+
}
208+
return StringId::Invalid;
209+
}
210+
203211
auto OutputYaml() const -> Yaml::OutputMapping {
204212
return Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) {
205213
for (auto [i, val] : llvm::enumerate(values_)) {
@@ -233,6 +241,10 @@ class StringStoreWrapper : public Printable<StringStoreWrapper<IdT>> {
233241
return values_->Get(StringId(id.index));
234242
}
235243

244+
auto Lookup(llvm::StringRef value) const -> IdT {
245+
return IdT(values_->Lookup(value).index);
246+
}
247+
236248
auto Print(llvm::raw_ostream& out) const -> void { out << *values_; }
237249

238250
auto size() const -> size_t { return values_->size(); }

toolchain/check/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ cc_library(
7878
"//common:vlog",
7979
"//toolchain/base:index_base",
8080
"//toolchain/check:scope_stack",
81+
"//toolchain/diagnostics:diagnostic_emitter",
8182
"//toolchain/lex:tokenized_buffer",
8283
"//toolchain/parse:node_kind",
8384
"//toolchain/parse:tree",

toolchain/check/context.cpp

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "toolchain/check/eval.h"
1515
#include "toolchain/check/import_ref.h"
1616
#include "toolchain/check/inst_block_stack.h"
17+
#include "toolchain/diagnostics/diagnostic_emitter.h"
1718
#include "toolchain/lex/tokenized_buffer.h"
1819
#include "toolchain/parse/node_ids.h"
1920
#include "toolchain/parse/node_kind.h"
@@ -190,7 +191,7 @@ auto Context::AddNameToLookup(SemIR::NameId name_id, SemIR::InstId target_id)
190191
}
191192
}
192193

193-
auto Context::LookupNameInDecl(Parse::NodeId /*node_id*/, SemIR::NameId name_id,
194+
auto Context::LookupNameInDecl(Parse::NodeId node_id, SemIR::NameId name_id,
194195
SemIR::NameScopeId scope_id) -> SemIR::InstId {
195196
if (!scope_id.is_valid()) {
196197
// Look for a name in the current scope only. There are two cases where the
@@ -227,7 +228,8 @@ auto Context::LookupNameInDecl(Parse::NodeId /*node_id*/, SemIR::NameId name_id,
227228
//
228229
// // Error, no `F` in `B`.
229230
// fn B.F() {}
230-
return LookupNameInExactScope(name_id, name_scopes().Get(scope_id));
231+
return LookupNameInExactScope(node_id, name_id,
232+
name_scopes().Get(scope_id));
231233
}
232234
}
233235

@@ -259,13 +261,70 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id,
259261
return SemIR::InstId::BuiltinError;
260262
}
261263

262-
auto Context::LookupNameInExactScope(SemIR::NameId name_id,
264+
// Handles lookup through the import_ir_scopes for LookupNameInExactScope.
265+
static auto LookupInImportIRScopes(Context& context, SemIRLocation loc,
266+
SemIR::NameId name_id,
267+
const SemIR::NameScope& scope)
268+
-> SemIR::InstId {
269+
auto identifier_id = name_id.AsIdentifierId();
270+
llvm::StringRef identifier;
271+
if (identifier_id.is_valid()) {
272+
identifier = context.identifiers().Get(identifier_id);
273+
}
274+
275+
DiagnosticAnnotationScope annotate_diagnostics(
276+
&context.emitter(), [&](auto& builder) {
277+
CARBON_DIAGNOSTIC(InNameLookup, Note, "In name lookup for `{0}`.",
278+
SemIR::NameId);
279+
builder.Note(loc, InNameLookup, name_id);
280+
});
281+
282+
auto result_id = SemIR::InstId::Invalid;
283+
for (auto [import_ir_id, import_scope_id] : scope.import_ir_scopes) {
284+
auto& import_ir = context.import_irs().Get(import_ir_id);
285+
286+
// Determine the NameId in the import IR.
287+
SemIR::NameId import_name_id = name_id;
288+
if (identifier_id.is_valid()) {
289+
auto import_identifier_id = import_ir->identifiers().Lookup(identifier);
290+
if (!import_identifier_id.is_valid()) {
291+
// Name doesn't exist in the import IR.
292+
continue;
293+
}
294+
import_name_id = SemIR::NameId::ForIdentifier(import_identifier_id);
295+
}
296+
297+
// Look up the name in the import scope.
298+
const auto& import_scope = import_ir->name_scopes().Get(import_scope_id);
299+
auto it = import_scope.names.find(import_name_id);
300+
if (it == import_scope.names.end()) {
301+
// Name doesn't exist in the import scope.
302+
continue;
303+
}
304+
auto import_inst_id = context.AddPlaceholderInst(
305+
{SemIR::ImportRefUnused{import_ir_id, it->second}});
306+
TryResolveImportRefUnused(context, import_inst_id);
307+
if (result_id.is_valid()) {
308+
// TODO: Add generalized merge functionality (merge_decls.h?).
309+
context.DiagnoseDuplicateName(import_inst_id, result_id);
310+
} else {
311+
result_id = import_inst_id;
312+
}
313+
}
314+
315+
return result_id;
316+
}
317+
318+
auto Context::LookupNameInExactScope(SemIRLocation loc, SemIR::NameId name_id,
263319
const SemIR::NameScope& scope)
264320
-> SemIR::InstId {
265321
if (auto it = scope.names.find(name_id); it != scope.names.end()) {
266322
TryResolveImportRefUnused(*this, it->second);
267323
return it->second;
268324
}
325+
if (!scope.import_ir_scopes.empty()) {
326+
return LookupInImportIRScopes(*this, loc, name_id, scope);
327+
}
269328
return SemIR::InstId::Invalid;
270329
}
271330

@@ -281,7 +340,7 @@ auto Context::LookupQualifiedName(Parse::NodeId node_id, SemIR::NameId name_id,
281340
const auto& scope = name_scopes().Get(scope_ids.pop_back_val());
282341
has_error |= scope.has_error;
283342

284-
auto scope_result_id = LookupNameInExactScope(name_id, scope);
343+
auto scope_result_id = LookupNameInExactScope(node_id, name_id, scope);
285344
if (!scope_result_id.is_valid()) {
286345
// Nothing found in this scope: also look in its extended scopes.
287346
auto extended = llvm::reverse(scope.extended_scopes);

toolchain/check/context.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ class Context {
122122
// Performs a name lookup in a specified scope, returning the referenced
123123
// instruction. Does not look into extended scopes. Returns an invalid
124124
// instruction if the name is not found.
125-
auto LookupNameInExactScope(SemIR::NameId name_id,
125+
auto LookupNameInExactScope(SemIRLocation loc, SemIR::NameId name_id,
126126
const SemIR::NameScope& scope) -> SemIR::InstId;
127127

128128
// Performs a qualified name lookup in a specified scope and in scopes that

toolchain/check/impl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ static auto BuildInterfaceWitness(
9090
if (auto fn_decl = decl.TryAs<SemIR::FunctionDecl>()) {
9191
auto& fn = context.functions().Get(fn_decl->function_id);
9292
auto impl_decl_id =
93-
context.LookupNameInExactScope(fn.name_id, impl_scope);
93+
context.LookupNameInExactScope(decl_id, fn.name_id, impl_scope);
9494
if (impl_decl_id.is_valid()) {
9595
used_decl_ids.push_back(impl_decl_id);
9696
table.push_back(CheckAssociatedFunctionImplementation(

0 commit comments

Comments
 (0)