@@ -72,45 +72,130 @@ static auto NoteIncompleteNamedConstraint(
7272 }
7373}
7474
75+ // Makes a copy of a Specific from one generic to apply to another given
76+ // `generic_id`, with a given `Self` argument appended to the end.
77+ static auto MakeCopyOfSpecificAndAppendSelf (
78+ Context& context, SemIR::LocId loc_id, SemIR::SpecificId specific_id,
79+ SemIR::GenericId generic_id, SemIR::InstId self_id) -> SemIR::SpecificId {
80+ auto source_specific_args_id =
81+ context.specifics ().GetArgsOrEmpty (specific_id);
82+ auto source_specific_args =
83+ context.inst_blocks ().Get (source_specific_args_id);
84+
85+ llvm::SmallVector<SemIR::InstId> arg_ids;
86+ arg_ids.reserve (source_specific_args.size () + 1 );
87+ // Start with the enclosing arguments from the source Specific.
88+ llvm::append_range (arg_ids, source_specific_args);
89+ // Add the new `Self` argument.
90+ arg_ids.push_back (self_id);
91+
92+ return MakeSpecific (context, loc_id, generic_id, arg_ids);
93+ }
94+
95+ static auto GetRequireImplsSpecificSelf (Context& context,
96+ const SemIR::RequireImpls& require)
97+ -> SemIR::InstId {
98+ const auto & require_generic = context.generics ().Get (require.generic_id );
99+ const auto & require_self_specific =
100+ context.specifics ().Get (require_generic.self_specific_id );
101+ auto require_self_specific_args =
102+ context.inst_blocks ().Get (require_self_specific.args_id );
103+ // The last argument of a `require` generic is always `Self`, as require can
104+ // not have any parameters of its own, only enclosing parameters.
105+ return require_self_specific_args.back ();
106+ }
107+
108+ static auto GetFacetTypeInSpecific (Context& context,
109+ SemIR::SpecificId specific_id,
110+ SemIR::InstId facet_type)
111+ -> SemIR::FacetTypeId {
112+ auto const_facet_type = SemIR::GetConstantValueInSpecific (
113+ context.sem_ir (), specific_id, facet_type);
114+ if (const_facet_type == SemIR::ErrorInst::ConstantId) {
115+ return SemIR::FacetTypeId::None;
116+ }
117+ auto facet_type_in_specific = context.insts ().GetAs <SemIR::FacetType>(
118+ context.constant_values ().GetInstId (const_facet_type));
119+ return facet_type_in_specific.facet_type_id ;
120+ }
121+
75122static auto RequireCompleteFacetType (Context& context, SemIR::LocId loc_id,
76123 const SemIR::FacetType& facet_type,
77124 MakeDiagnosticBuilderFn diagnoser)
78125 -> bool {
79- const auto & facet_type_info =
80- context.facet_types ().Get (facet_type.facet_type_id );
126+ llvm::SmallVector<SemIR::FacetTypeId> work = {facet_type.facet_type_id };
127+ while (!work.empty ()) {
128+ auto next_facet_type_id = work.pop_back_val ();
129+ const auto & facet_type_info = context.facet_types ().Get (next_facet_type_id);
81130
82- for (auto extends : facet_type_info.extend_constraints ) {
83- auto interface_id = extends.interface_id ;
84- const auto & interface = context.interfaces ().Get (interface_id);
85- if (!interface.is_complete ()) {
86- if (diagnoser) {
87- auto builder = diagnoser ();
88- NoteIncompleteInterface (context, interface_id, builder);
89- builder.Emit ();
131+ struct SpecificForRequires {
132+ SemIR::SpecificId specific_id;
133+ SemIR::RequireImplsBlockId requires_block_id;
134+ };
135+ llvm::SmallVector<SpecificForRequires> specifics;
136+
137+ for (auto extends : facet_type_info.extend_constraints ) {
138+ auto interface_id = extends.interface_id ;
139+ const auto & interface = context.interfaces ().Get (interface_id);
140+ if (!interface.is_complete ()) {
141+ if (diagnoser) {
142+ auto builder = diagnoser ();
143+ NoteIncompleteInterface (context, interface_id, builder);
144+ builder.Emit ();
145+ }
146+ return false ;
147+ }
148+ if (interface.generic_id .has_value ()) {
149+ specifics.push_back (
150+ {extends.specific_id , interface.require_impls_block_id });
151+ }
152+ if (extends.specific_id .has_value ()) {
153+ ResolveSpecificDefinition (context, loc_id, extends.specific_id );
90154 }
91- return false ;
92- }
93-
94- if (extends.specific_id .has_value ()) {
95- ResolveSpecificDefinition (context, loc_id, extends.specific_id );
96155 }
97- }
98156
99- for (auto extends : facet_type_info.extend_named_constraints ) {
100- auto named_constraint_id = extends.named_constraint_id ;
101- const auto & constraint =
102- context.named_constraints ().Get (named_constraint_id);
103- if (!constraint.is_complete ()) {
104- if (diagnoser) {
105- auto builder = diagnoser ();
106- NoteIncompleteNamedConstraint (context, named_constraint_id, builder);
107- builder.Emit ();
157+ for (auto extends : facet_type_info.extend_named_constraints ) {
158+ auto named_constraint_id = extends.named_constraint_id ;
159+ const auto & constraint =
160+ context.named_constraints ().Get (named_constraint_id);
161+ if (!constraint.is_complete ()) {
162+ if (diagnoser) {
163+ auto builder = diagnoser ();
164+ NoteIncompleteNamedConstraint (context, named_constraint_id, builder);
165+ builder.Emit ();
166+ }
167+ return false ;
168+ }
169+ if (constraint.generic_id .has_value ()) {
170+ specifics.push_back (
171+ {extends.specific_id , constraint.require_impls_block_id });
172+ }
173+ if (extends.specific_id .has_value ()) {
174+ ResolveSpecificDefinition (context, loc_id, extends.specific_id );
108175 }
109- return false ;
110176 }
111177
112- if (extends.specific_id .has_value ()) {
113- ResolveSpecificDefinition (context, loc_id, extends.specific_id );
178+ // Formulate a specific for each `require` declaration, as the specific may
179+ // introduce errors. Then recurse on those specific facet types to find
180+ // other interfaces/constraints that may contain other require declarations.
181+ for (auto [specific_id, requires_block_id] : specifics) {
182+ for (auto require_impls_id :
183+ context.require_impls_blocks ().Get (requires_block_id)) {
184+ const auto & require = context.require_impls ().Get (require_impls_id);
185+ if (require.extend_self ) {
186+ auto require_specific_id = MakeCopyOfSpecificAndAppendSelf (
187+ context, loc_id, specific_id, require.generic_id ,
188+ GetRequireImplsSpecificSelf (context, require));
189+ // Construct the specific facet type. If None is returned, it means an
190+ // error was diagnosed.
191+ auto facet_type_id = GetFacetTypeInSpecific (
192+ context, require_specific_id, require.facet_type_inst_id );
193+ if (!facet_type_id.has_value ()) {
194+ return false ;
195+ }
196+ work.push_back (facet_type_id);
197+ }
198+ }
114199 }
115200 }
116201
0 commit comments