44
55#include " toolchain/check/deduce.h"
66
7+ #include " llvm/ADT/SmallBitVector.h"
78#include " toolchain/base/kind_switch.h"
89#include " toolchain/check/context.h"
910#include " toolchain/check/convert.h"
@@ -183,6 +184,8 @@ class DeductionContext {
183184 llvm::SmallVector<SemIR::InstId> result_arg_ids_;
184185 llvm::SmallVector<Substitution> substitutions_;
185186 SemIR::CompileTimeBindIndex first_deduced_index_;
187+ // Non-deduced indexes, indexed by parameter index - first_deduced_index_.
188+ llvm::SmallBitVector non_deduced_indexes_;
186189};
187190
188191} // namespace
@@ -231,12 +234,33 @@ DeductionContext::DeductionContext(Context& context, SemIR::LocId loc_id,
231234 }
232235 first_deduced_index_ = SemIR::CompileTimeBindIndex (args.size ());
233236 }
237+
238+ non_deduced_indexes_.resize (result_arg_ids_.size () -
239+ first_deduced_index_.index );
234240}
235241
236242auto DeductionContext::Deduce () -> bool {
237243 while (!worklist_.Done ()) {
238244 auto [param_id, arg_id, needs_substitution] = worklist_.PopNext ();
239245
246+ auto note_initializing_param = [&](auto & builder) {
247+ if (auto param =
248+ context ().insts ().TryGetAs <SemIR::SymbolicBindingPattern>(
249+ param_id)) {
250+ CARBON_DIAGNOSTIC (InitializingGenericParam, Note,
251+ " initializing generic parameter `{0}` declared here" ,
252+ SemIR::NameId);
253+ builder.Note (
254+ param_id, InitializingGenericParam,
255+ context ().entity_names ().Get (param->entity_name_id ).name_id );
256+ } else {
257+ NoteGenericHere (context (), generic_id_, builder);
258+ }
259+ };
260+
261+ // TODO: Bail out if there's nothing to deduce: if we're not in a pattern
262+ // and the parameter doesn't have a symbolic constant value.
263+
240264 // If the parameter has a symbolic type, deduce against that.
241265 auto param_type_id = context ().insts ().Get (param_id).type_id ();
242266 if (param_type_id.AsConstantId ().is_symbolic ()) {
@@ -246,54 +270,70 @@ auto DeductionContext::Deduce() -> bool {
246270 } else {
247271 // The argument needs to have the same type as the parameter.
248272 // TODO: Suppress diagnostics here if diagnose_ is false.
249- DiagnosticAnnotationScope annotate_diagnostics (
250- &context ().emitter (), [&](auto & builder) {
251- if (auto param =
252- context ().insts ().TryGetAs <SemIR::BindSymbolicName>(
253- param_id)) {
254- CARBON_DIAGNOSTIC (
255- InitializingGenericParam, Note,
256- " initializing generic parameter `{0}` declared here" ,
257- SemIR::NameId);
258- builder.Note (
259- param_id, InitializingGenericParam,
260- context ().entity_names ().Get (param->entity_name_id ).name_id );
261- }
262- });
273+ // TODO: Only do this when deducing against a symbolic pattern.
274+ DiagnosticAnnotationScope annotate_diagnostics (&context ().emitter (),
275+ note_initializing_param);
263276 arg_id = ConvertToValueOfType (context (), loc_id_, arg_id, param_type_id);
264277 if (arg_id == SemIR::InstId::BuiltinError) {
265278 return false ;
266279 }
267280 }
268281
269- // If the parameter is a symbolic constant, deduce against it. Otherwise, we
270- // assume there is nothing to deduce.
271- // TODO: This won't do the right thing in a template deduction.
272- auto param_const_id = context ().constant_values ().Get (param_id);
273- if (!param_const_id.is_valid () || !param_const_id.is_symbolic ()) {
274- continue ;
275- }
276-
277282 // Attempt to match `param_inst` against `arg_id`. If the match succeeds,
278283 // this should `continue` the outer loop. On `break`, we will try to desugar
279284 // the parameter to continue looking for a match.
280- auto param_inst = context ().insts ().Get (
281- context ().constant_values ().GetInstId (param_const_id));
285+ auto param_inst = context ().insts ().Get (param_id);
282286 CARBON_KIND_SWITCH (param_inst) {
283- // Deducing a symbolic binding from an argument with a constant value
284- // deduces the binding as having that constant value.
285- case SemIR::InstKind::SymbolicBindingPattern:
286- case SemIR::InstKind::BindSymbolicName: {
287- auto entity_name_id = SemIR::EntityNameId::Invalid;
288- if (auto bind = param_inst.TryAs <SemIR::SymbolicBindingPattern>()) {
289- entity_name_id = bind->entity_name_id ;
290- } else {
291- entity_name_id =
292- param_inst.As <SemIR::BindSymbolicName>().entity_name_id ;
287+ // Deducing a symbolic binding pattern from an argument deduces the
288+ // binding as having that constant value. For example, deducing
289+ // `(T:! type)` against `(i32)` deduces `T` to be `i32`. This only arises
290+ // when initializing a generic parameter from an explicitly specified
291+ // argument, and in this case, the argument is required to be a
292+ // compile-time constant.
293+ case CARBON_KIND (SemIR::SymbolicBindingPattern bind): {
294+ auto & entity_name = context ().entity_names ().Get (bind.entity_name_id );
295+ auto index = entity_name.bind_index ;
296+ if (!index.is_valid ()) {
297+ break ;
298+ }
299+ CARBON_CHECK (
300+ index >= first_deduced_index_ &&
301+ static_cast <size_t >(index.index ) < result_arg_ids_.size (),
302+ " Unexpected index {0} for symbolic binding pattern; "
303+ " expected to be in range [{1}, {2})" ,
304+ index.index , first_deduced_index_.index , result_arg_ids_.size ());
305+ CARBON_CHECK (!result_arg_ids_[index.index ].is_valid (),
306+ " Deduced a value for parameter prior to its declaration" );
307+
308+ auto arg_const_inst_id =
309+ context ().constant_values ().GetConstantInstId (arg_id);
310+ if (!arg_const_inst_id.is_valid ()) {
311+ if (diagnose_) {
312+ CARBON_DIAGNOSTIC (CompTimeArgumentNotConstant, Error,
313+ " argument for generic parameter is not a "
314+ " compile-time constant" );
315+ auto diag =
316+ context ().emitter ().Build (loc_id_, CompTimeArgumentNotConstant);
317+ note_initializing_param (diag);
318+ diag.Emit ();
319+ }
320+ return false ;
293321 }
294- auto & entity_name = context ().entity_names ().Get (entity_name_id);
322+
323+ result_arg_ids_[index.index ] = arg_const_inst_id;
324+ // This parameter index should not be deduced if it appears later.
325+ non_deduced_indexes_[index.index - first_deduced_index_.index ] = true ;
326+ continue ;
327+ }
328+
329+ // Deducing a symbolic binding appearing within an expression against a
330+ // constant value deduces the binding as having that value. For example,
331+ // deducing `[T:! type](x: T)` against `("foo")` deduces `T` as `String`.
332+ case CARBON_KIND (SemIR::BindSymbolicName bind): {
333+ auto & entity_name = context ().entity_names ().Get (bind.entity_name_id );
295334 auto index = entity_name.bind_index ;
296- if (!index.is_valid () || index < first_deduced_index_) {
335+ if (!index.is_valid () || index < first_deduced_index_ ||
336+ non_deduced_indexes_[index.index - first_deduced_index_.index ]) {
297337 break ;
298338 }
299339
@@ -324,6 +364,11 @@ auto DeductionContext::Deduce() -> bool {
324364 continue ;
325365 }
326366
367+ case CARBON_KIND (SemIR::ParamPattern pattern): {
368+ Add (pattern.subpattern_id , arg_id, needs_substitution);
369+ continue ;
370+ }
371+
327372 // Various kinds of parameter should match an argument of the same form,
328373 // if the operands all match.
329374 case SemIR::ArrayType::Kind:
@@ -358,6 +403,20 @@ auto DeductionContext::Deduce() -> bool {
358403 break ;
359404 }
360405
406+ // We didn't manage to deduce against the syntactic form of the parameter.
407+ // Convert it to a canonical constant value and try deducing against that.
408+ auto param_const_id = context ().constant_values ().Get (param_id);
409+ if (!param_const_id.is_valid () || !param_const_id.is_symbolic ()) {
410+ // It's not a symbolic constant. There's nothing here to deduce.
411+ continue ;
412+ }
413+ auto param_const_inst_id =
414+ context ().constant_values ().GetInstId (param_const_id);
415+ if (param_const_inst_id != param_id) {
416+ Add (param_const_inst_id, arg_id, needs_substitution);
417+ continue ;
418+ }
419+
361420 // If we've not yet substituted into the parameter, do so now and try again.
362421 if (needs_substitution) {
363422 param_const_id = SubstConstant (context (), param_const_id, substitutions_);
0 commit comments