@@ -434,15 +434,13 @@ class ImportRefResolver : public ImportContext {
434434
435435 // Performs resolution for one instruction and then performs all work we
436436 // deferred.
437- // NOLINTNEXTLINE(misc-no-recursion)
438437 auto Resolve (SemIR::InstId inst_id) -> SemIR::ConstantId {
439438 auto const_id = ResolveOneInst (inst_id);
440439 PerformPendingWork ();
441440 return const_id;
442441 }
443442
444443 // Wraps constant evaluation with logic to handle constants.
445- // NOLINTNEXTLINE(misc-no-recursion)
446444 auto ResolveConstant (SemIR::ConstantId import_const_id) -> SemIR::ConstantId {
447445 return Resolve (GetInstWithConstantValue (import_ir (), import_const_id));
448446 }
@@ -511,6 +509,18 @@ static auto AddImportRef(ImportContext& context, SemIR::InstId inst_id,
511509 entity_name_id);
512510}
513511
512+ // Handles setting a constant on instructions related to an import.
513+ static auto SetIndirectConstantValues (
514+ Context& context, llvm::ArrayRef<SemIR::ImportIRInst> indirect_insts,
515+ SemIR::ConstantId constant_id) -> void {
516+ for (const auto & import_ir_inst : indirect_insts) {
517+ auto ir_index =
518+ context.sem_ir ().import_irs ().GetRawIndex (import_ir_inst.ir_id ());
519+ context.import_ir_constant_values ()[ir_index].Set (import_ir_inst.inst_id (),
520+ constant_id);
521+ }
522+ }
523+
514524// Adds an import_ref instruction for an instruction that we have already loaded
515525// from an imported IR, with a known constant value. This is useful when the
516526// instruction has a symbolic constant value, in order to produce an instruction
@@ -622,7 +632,7 @@ static auto GetLocalTypeInstId(ImportRefResolver& resolver,
622632 // The input instruction is a TypeInstId, and import does not change the type
623633 // of instructions, so the result is also a valid TypeInstId.
624634 return SemIR::TypeInstId::UnsafeMake (
625- GetLocalConstantInstId (resolver, static_cast <SemIR::InstId>( inst_id) ));
635+ GetLocalConstantInstId (resolver, inst_id));
626636}
627637
628638// Returns the ConstantId for a TypeId. Adds unresolved constants to
@@ -777,31 +787,65 @@ static auto MakeIncompleteGeneric(ImportContext& context, SemIR::InstId decl_id,
777787namespace {
778788// Local information associated with an imported generic.
779789struct GenericData {
780- // TODO: Delete `GenericData` if we still don't use it once generic import is
781- // more stable.
790+ struct Binding {
791+ // The attached type's constant, which may differ from the type on the
792+ // constant. This needs to be preserved for the ImportRef.
793+ SemIR::ConstantId type_constant_id;
794+ SemIR::ConstantId inst_constant_id;
795+ };
796+ llvm::SmallVector<Binding> bindings;
782797};
783798} // namespace
784799
785800// Gets a local version of the data associated with a generic.
786- static auto GetLocalGenericData (ImportRefResolver& /* resolver*/ ,
787- SemIR::GenericId /* generic_id */ )
801+ static auto GetLocalGenericData (ImportRefResolver& resolver,
802+ SemIR::GenericId import_generic_id )
788803 -> GenericData {
789- return {};
804+ GenericData generic_data;
805+ if (import_generic_id.has_value ()) {
806+ const auto & import_generic =
807+ resolver.import_generics ().Get (import_generic_id);
808+
809+ if (import_generic.bindings_id .has_value ()) {
810+ auto import_bindings =
811+ resolver.import_inst_blocks ().Get (import_generic.bindings_id );
812+ generic_data.bindings .reserve (import_bindings.size ());
813+ for (auto import_inst_id : import_bindings) {
814+ generic_data.bindings .push_back (
815+ {.type_constant_id = GetLocalConstantId (
816+ resolver,
817+ resolver.import_insts ().GetAttachedType (import_inst_id)),
818+ .inst_constant_id = GetLocalConstantId (resolver, import_inst_id)});
819+ }
820+ }
821+ }
822+ return generic_data;
790823}
791824
792825// Adds the given local generic data to the given generic.
793826static auto SetGenericData (ImportContext& context,
794827 SemIR::GenericId import_generic_id,
795828 SemIR::GenericId new_generic_id,
796- const GenericData& /* generic_data*/ ) -> void {
829+ const GenericData& generic_data) -> void {
797830 if (!import_generic_id.has_value ()) {
798831 return ;
799832 }
800833
801834 const auto & import_generic = context.import_generics ().Get (import_generic_id);
802835 auto & new_generic = context.local_generics ().Get (new_generic_id);
803- new_generic.bindings_id =
804- GetLocalImportRefInstBlock (context, import_generic.bindings_id );
836+
837+ auto import_bindings =
838+ context.import_inst_blocks ().Get (import_generic.bindings_id );
839+ llvm::SmallVector<SemIR::InstId> new_bindings;
840+ new_bindings.reserve (import_bindings.size ());
841+ for (auto [import_binding_id, binding] :
842+ llvm::zip_equal (import_bindings, generic_data.bindings )) {
843+ auto local_type_id = context.local_types ().GetTypeIdForTypeConstantId (
844+ binding.type_constant_id );
845+ new_bindings.push_back (AddLoadedImportRef (
846+ context, local_type_id, import_binding_id, binding.inst_constant_id ));
847+ }
848+ new_generic.bindings_id = context.local_inst_blocks ().Add (new_bindings);
805849
806850 // Track that we need to fill in the remaining information in
807851 // FinishPendingGeneric.
@@ -3388,10 +3432,6 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
33883432// `None` if more has been added to the stack. This is the same as
33893433// TryResolveInst, except that it may resolve symbolic constants as canonical
33903434// constants instead of as constants associated with a particular generic.
3391- //
3392- // TODO: Consider refactoring the body to a helper in order to eliminate
3393- // recursion.
3394- // NOLINTNEXTLINE(misc-no-recursion)
33953435static auto TryResolveInstCanonical (ImportRefResolver& resolver,
33963436 SemIR::InstId inst_id,
33973437 SemIR::ConstantId const_id)
@@ -3767,7 +3807,6 @@ auto ImportRefResolver::ResolveOneInst(SemIR::InstId inst_id)
37673807 return constant_id;
37683808}
37693809
3770- // NOLINTNEXTLINE(misc-no-recursion)
37713810auto ImportRefResolver::ResolveType (SemIR::TypeId import_type_id)
37723811 -> SemIR::TypeId {
37733812 if (!import_type_id.has_value ()) {
@@ -3865,13 +3904,7 @@ auto ImportRefResolver::SetResolvedConstId(
38653904 SemIR::InstId inst_id, llvm::ArrayRef<SemIR::ImportIRInst> indirect_insts,
38663905 SemIR::ConstantId const_id) -> void {
38673906 local_constant_values_for_import_insts ().Set (inst_id, const_id);
3868- for (auto indirect_inst : indirect_insts) {
3869- local_context ()
3870- .import_ir_constant_values ()
3871- [local_context ().sem_ir ().import_irs ().GetRawIndex (
3872- indirect_inst.ir_id ())]
3873- .Set (indirect_inst.inst_id (), const_id);
3874- }
3907+ SetIndirectConstantValues (local_context (), indirect_insts, const_id);
38753908}
38763909
38773910// Resolves and returns the local contents for an imported instruction block
@@ -3918,22 +3951,13 @@ static auto ResolveLocalEvalBlock(ImportRefResolver& resolver,
39183951}
39193952
39203953// Fills in the remaining information in a partially-imported generic.
3921- // NOLINTNEXTLINE(misc-no-recursion)
39223954static auto FinishPendingGeneric (ImportRefResolver& resolver,
39233955 ImportContext::PendingGeneric pending)
39243956 -> void {
39253957 const auto & import_generic =
39263958 resolver.import_generics ().Get (pending.import_id );
39273959 auto & local_generic = resolver.local_generics ().Get (pending.local_id );
39283960
3929- // Load the bindings for the generic eagerly; they're used to form the self
3930- // specific.
3931- // TODO: Avoid recursion.
3932- for (auto binding_id :
3933- resolver.local_inst_blocks ().Get (local_generic.bindings_id )) {
3934- LoadImportRef (resolver.local_context (), binding_id);
3935- }
3936-
39373961 local_generic.decl_block_id =
39383962 ResolveLocalEvalBlock (resolver, import_generic, pending.local_id ,
39393963 SemIR::GenericInstIndex::Region::Declaration);
@@ -3983,7 +4007,6 @@ static auto FinishPendingSpecific(ImportRefResolver& resolver,
39834007}
39844008
39854009// Perform any work that we deferred until the end of the main Resolve loop.
3986- // NOLINTNEXTLINE(misc-no-recursion)
39874010auto ImportRefResolver::PerformPendingWork () -> void {
39884011 // Note that the individual Finish steps can add new pending work, so keep
39894012 // going until we have no more work to do.
@@ -4047,7 +4070,6 @@ static auto GetInstForLoad(Context& context,
40474070 }
40484071}
40494072
4050- // NOLINTNEXTLINE(misc-no-recursion)
40514073auto LoadImportRef (Context& context, SemIR::InstId inst_id) -> void {
40524074 auto inst = context.insts ().TryGetAs <SemIR::ImportRefUnloaded>(inst_id);
40534075 if (!inst) {
@@ -4092,12 +4114,7 @@ auto LoadImportRef(Context& context, SemIR::InstId inst_id) -> void {
40924114
40934115 // Store the constant for both the ImportRefLoaded and indirect instructions.
40944116 context.constant_values ().Set (inst_id, constant_id);
4095- for (const auto & import_ir_inst : indirect_insts) {
4096- context
4097- .import_ir_constant_values ()[context.sem_ir ().import_irs ().GetRawIndex (
4098- import_ir_inst.ir_id ())]
4099- .Set (import_ir_inst.inst_id (), constant_id);
4100- }
4117+ SetIndirectConstantValues (context, indirect_insts, constant_id);
41014118}
41024119
41034120auto ImportImplsFromApiFile (Context& context) -> void {
0 commit comments