@@ -317,7 +317,7 @@ auto Context::AddNameToLookup(SemIR::NameId name_id, SemIR::InstId target_id,
317317auto Context::LookupNameInDecl (SemIR::LocId loc_id, SemIR::NameId name_id,
318318 SemIR::NameScopeId scope_id,
319319 ScopeIndex scope_index)
320- -> std::pair< SemIR::InstId, bool> {
320+ -> SemIR::ScopeLookupResult {
321321 if (!scope_id.has_value ()) {
322322 // Look for a name in the specified scope or a scope nested within it only.
323323 // There are two cases where the name would be in an outer scope:
@@ -353,8 +353,9 @@ auto Context::LookupNameInDecl(SemIR::LocId loc_id, SemIR::NameId name_id,
353353 //
354354 // In this case, the class C is not a redeclaration of its parameter, but
355355 // we find the parameter in order to diagnose a redeclaration error.
356- return {scope_stack ().LookupInLexicalScopesWithin (name_id, scope_index),
357- false };
356+ return SemIR::ScopeLookupResult::MakeWrappedLookupResult (
357+ scope_stack ().LookupInLexicalScopesWithin (name_id, scope_index),
358+ SemIR::AccessKind::Public);
358359 } else {
359360 // We do not look into `extend`ed scopes here. A qualified name in a
360361 // declaration must specify the exact scope in which the name was originally
@@ -365,10 +366,9 @@ auto Context::LookupNameInDecl(SemIR::LocId loc_id, SemIR::NameId name_id,
365366 //
366367 // // Error, no `F` in `B`.
367368 // fn B.F() {}
368- auto result = LookupNameInExactScope (loc_id, name_id, scope_id,
369- name_scopes ().Get (scope_id),
370- /* is_being_declared=*/ true );
371- return {result.inst_id , result.is_poisoned };
369+ return LookupNameInExactScope (loc_id, name_id, scope_id,
370+ name_scopes ().Get (scope_id),
371+ /* is_being_declared=*/ true );
372372 }
373373}
374374
@@ -390,7 +390,7 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id,
390390 LookupScope{.name_scope_id = lookup_scope_id,
391391 .specific_id = specific_id},
392392 /* required=*/ false );
393- non_lexical_result.inst_id . has_value ()) {
393+ non_lexical_result.scope_result . is_found ()) {
394394 return non_lexical_result;
395395 }
396396 }
@@ -400,14 +400,16 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id,
400400 " `{0}` used before initialization" , SemIR::NameId);
401401 emitter_->Emit (node_id, UsedBeforeInitialization, name_id);
402402 return {.specific_id = SemIR::SpecificId::None,
403- .inst_id = SemIR::ErrorInst::SingletonInstId };
403+ .scope_result = SemIR::ScopeLookupResult::MakeError () };
404404 }
405405
406406 if (lexical_result.has_value ()) {
407407 // A lexical scope never needs an associated specific. If there's a
408408 // lexically enclosing generic, then it also encloses the point of use of
409409 // the name.
410- return {.specific_id = SemIR::SpecificId::None, .inst_id = lexical_result};
410+ return {.specific_id = SemIR::SpecificId::None,
411+ .scope_result = SemIR::ScopeLookupResult::MakeFound (
412+ lexical_result, SemIR::AccessKind::Public)};
411413 }
412414
413415 // We didn't find anything at all.
@@ -416,32 +418,32 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id,
416418 }
417419
418420 return {.specific_id = SemIR::SpecificId::None,
419- .inst_id = SemIR::ErrorInst::SingletonInstId };
421+ .scope_result = SemIR::ScopeLookupResult::MakeError () };
420422}
421423
422424auto Context::LookupNameInExactScope (SemIRLoc loc, SemIR::NameId name_id,
423425 SemIR::NameScopeId scope_id,
424426 SemIR::NameScope& scope,
425427 bool is_being_declared)
426- -> LookupNameInExactScopeResult {
428+ -> SemIR::ScopeLookupResult {
427429 if (auto entry_id = is_being_declared ? scope.Lookup (name_id)
428430 : scope.LookupOrPoison (name_id)) {
429- auto entry = scope.GetEntry (*entry_id);
430- if (!entry.is_poisoned ) {
431- LoadImportRef (*this , entry.inst_id );
432- } else if (is_being_declared) {
433- entry.inst_id = SemIR::InstId::None;
431+ auto lookup_result = scope.GetEntry (*entry_id).result ;
432+ if (!lookup_result.is_poisoned ()) {
433+ LoadImportRef (*this , lookup_result.target_inst_id ());
434+ return lookup_result;
434435 }
435- return {entry. inst_id , entry. access_kind , entry. is_poisoned } ;
436+ return SemIR::ScopeLookupResult::MakePoisoned () ;
436437 }
437438
438439 if (!scope.import_ir_scopes ().empty ()) {
439440 // TODO: Enforce other access modifiers for imports.
440- return {ImportNameFromOtherPackage (*this , loc, scope_id,
441- scope.import_ir_scopes (), name_id),
442- SemIR::AccessKind::Public};
441+ return SemIR::ScopeLookupResult::MakeWrappedLookupResult (
442+ ImportNameFromOtherPackage (*this , loc, scope_id,
443+ scope.import_ir_scopes (), name_id),
444+ SemIR::AccessKind::Public);
443445 }
444- return { SemIR::InstId::None, SemIR::AccessKind::Public} ;
446+ return SemIR::ScopeLookupResult::MakeNotFound () ;
445447}
446448
447449// Prints diagnostics on invalid qualified name access.
@@ -583,8 +585,9 @@ auto Context::LookupQualifiedName(SemIR::LocId loc_id, SemIR::NameId name_id,
583585 // TODO: Support reporting of multiple prohibited access.
584586 llvm::SmallVector<ProhibitedAccessInfo> prohibited_accesses;
585587
586- LookupResult result = {.specific_id = SemIR::SpecificId::None,
587- .inst_id = SemIR::InstId::None};
588+ LookupResult result = {
589+ .specific_id = SemIR::SpecificId::None,
590+ .scope_result = SemIR::ScopeLookupResult::MakeNotFound ()};
588591 bool has_error = false ;
589592 bool is_parent_access = false ;
590593
@@ -598,8 +601,9 @@ auto Context::LookupQualifiedName(SemIR::LocId loc_id, SemIR::NameId name_id,
598601 auto & name_scope = name_scopes ().Get (scope_id);
599602 has_error |= name_scope.has_error ();
600603
601- auto [scope_result_id, access_kind, is_poisoned] =
604+ const SemIR::ScopeLookupResult scope_result =
602605 LookupNameInExactScope (loc_id, name_id, scope_id, name_scope);
606+ SemIR::AccessKind access_kind = scope_result.access_kind ();
603607
604608 auto is_access_prohibited =
605609 IsAccessProhibited (access_info, access_kind, is_parent_access);
@@ -608,13 +612,13 @@ auto Context::LookupQualifiedName(SemIR::LocId loc_id, SemIR::NameId name_id,
608612 // multiple prohibited accesses if we can't find a suitable lookup.
609613 if (is_access_prohibited) {
610614 prohibited_accesses.push_back ({
611- .scope_result_id = scope_result_id ,
615+ .scope_result_id = scope_result. target_inst_id () ,
612616 .access_kind = access_kind,
613617 .is_parent_access = is_parent_access,
614618 });
615619 }
616620
617- if (!scope_result_id. has_value () || is_access_prohibited) {
621+ if (!scope_result. is_found () || is_access_prohibited) {
618622 // If nothing is found in this scope or if we encountered an invalid
619623 // access, look in its extended scopes.
620624 const auto & extended = name_scope.extended_scopes ();
@@ -643,23 +647,22 @@ auto Context::LookupQualifiedName(SemIR::LocId loc_id, SemIR::NameId name_id,
643647 }
644648
645649 // If this is our second lookup result, diagnose an ambiguity.
646- if (result.inst_id . has_value ()) {
650+ if (result.scope_result . is_found ()) {
647651 CARBON_DIAGNOSTIC (
648652 NameAmbiguousDueToExtend, Error,
649653 " ambiguous use of name `{0}` found in multiple extended scopes" ,
650654 SemIR::NameId);
651655 emitter_->Emit (loc_id, NameAmbiguousDueToExtend, name_id);
652656 // TODO: Add notes pointing to the scopes.
653657 return {.specific_id = SemIR::SpecificId::None,
654- .inst_id = SemIR::ErrorInst::SingletonInstId };
658+ .scope_result = SemIR::ScopeLookupResult::MakeError () };
655659 }
656660
657- result.inst_id = scope_result_id ;
661+ result.scope_result = scope_result ;
658662 result.specific_id = specific_id;
659- result.is_poisoned = is_poisoned;
660663 }
661664
662- if (required && !result.inst_id . has_value ()) {
665+ if (required && !result.scope_result . is_found ()) {
663666 if (!has_error) {
664667 if (prohibited_accesses.empty ()) {
665668 DiagnoseMemberNameNotFound (loc_id, name_id, lookup_scopes);
@@ -677,9 +680,9 @@ auto Context::LookupQualifiedName(SemIR::LocId loc_id, SemIR::NameId name_id,
677680 }
678681 }
679682
683+ CARBON_CHECK (!result.scope_result .is_poisoned ());
680684 return {.specific_id = SemIR::SpecificId::None,
681- .inst_id = SemIR::ErrorInst::SingletonInstId,
682- .is_poisoned = result.is_poisoned };
685+ .scope_result = SemIR::ScopeLookupResult::MakeError ()};
683686 }
684687
685688 return result;
@@ -699,13 +702,13 @@ static auto GetCorePackage(Context& context, SemIRLoc loc, llvm::StringRef name)
699702 auto core_name_id = SemIR::NameId::ForIdentifier (core_ident_id);
700703
701704 // Look up `package.Core`.
702- auto [core_inst_id, _, is_poisoned] = context.LookupNameInExactScope (
705+ auto core_scope_result = context.LookupNameInExactScope (
703706 loc, core_name_id, SemIR::NameScopeId::Package,
704707 context.name_scopes ().Get (SemIR::NameScopeId::Package));
705- if (core_inst_id. has_value ()) {
708+ if (core_scope_result. is_found ()) {
706709 // We expect it to be a namespace.
707- if (auto namespace_inst =
708- context. insts (). TryGetAs <SemIR::Namespace>(core_inst_id )) {
710+ if (auto namespace_inst = context. insts (). TryGetAs <SemIR::Namespace>(
711+ core_scope_result. target_inst_id () )) {
709712 // TODO: Decide whether to allow the case where `Core` is not a package.
710713 return namespace_inst->name_scope_id ;
711714 }
@@ -727,9 +730,9 @@ auto Context::LookupNameInCore(SemIRLoc loc, llvm::StringRef name)
727730 }
728731
729732 auto name_id = SemIR::NameId::ForIdentifier (identifiers ().Add (name));
730- auto [inst_id, _, is_poisoned] = LookupNameInExactScope (
733+ auto scope_result = LookupNameInExactScope (
731734 loc, name_id, core_package_id, name_scopes ().Get (core_package_id));
732- if (!inst_id. has_value ()) {
735+ if (!scope_result. is_found ()) {
733736 CARBON_DIAGNOSTIC (
734737 CoreNameNotFound, Error,
735738 " name `Core.{0}` implicitly referenced here, but not found" ,
@@ -739,7 +742,7 @@ auto Context::LookupNameInCore(SemIRLoc loc, llvm::StringRef name)
739742 }
740743
741744 // Look through import_refs and aliases.
742- return constant_values ().GetConstantInstId (inst_id );
745+ return constant_values ().GetConstantInstId (scope_result. target_inst_id () );
743746}
744747
745748template <typename BranchNode, typename ... Args>
0 commit comments