14
14
#include " toolchain/check/eval.h"
15
15
#include " toolchain/check/import_ref.h"
16
16
#include " toolchain/check/inst_block_stack.h"
17
+ #include " toolchain/diagnostics/diagnostic_emitter.h"
17
18
#include " toolchain/lex/tokenized_buffer.h"
18
19
#include " toolchain/parse/node_ids.h"
19
20
#include " toolchain/parse/node_kind.h"
@@ -190,7 +191,7 @@ auto Context::AddNameToLookup(SemIR::NameId name_id, SemIR::InstId target_id)
190
191
}
191
192
}
192
193
193
- auto Context::LookupNameInDecl (Parse::NodeId /* node_id*/ , SemIR::NameId name_id,
194
+ auto Context::LookupNameInDecl (Parse::NodeId node_id, SemIR::NameId name_id,
194
195
SemIR::NameScopeId scope_id) -> SemIR::InstId {
195
196
if (!scope_id.is_valid ()) {
196
197
// 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,
227
228
//
228
229
// // Error, no `F` in `B`.
229
230
// 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));
231
233
}
232
234
}
233
235
@@ -259,13 +261,70 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id,
259
261
return SemIR::InstId::BuiltinError;
260
262
}
261
263
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,
263
319
const SemIR::NameScope& scope)
264
320
-> SemIR::InstId {
265
321
if (auto it = scope.names .find (name_id); it != scope.names .end ()) {
266
322
TryResolveImportRefUnused (*this , it->second );
267
323
return it->second ;
268
324
}
325
+ if (!scope.import_ir_scopes .empty ()) {
326
+ return LookupInImportIRScopes (*this , loc, name_id, scope);
327
+ }
269
328
return SemIR::InstId::Invalid;
270
329
}
271
330
@@ -281,7 +340,7 @@ auto Context::LookupQualifiedName(Parse::NodeId node_id, SemIR::NameId name_id,
281
340
const auto & scope = name_scopes ().Get (scope_ids.pop_back_val ());
282
341
has_error |= scope.has_error ;
283
342
284
- auto scope_result_id = LookupNameInExactScope (name_id, scope);
343
+ auto scope_result_id = LookupNameInExactScope (node_id, name_id, scope);
285
344
if (!scope_result_id.is_valid ()) {
286
345
// Nothing found in this scope: also look in its extended scopes.
287
346
auto extended = llvm::reverse (scope.extended_scopes );
0 commit comments