Deduce arguments against the canonical facet value (#6158)

When deducing an argument against a type that is `<facet value> as type`
we don't care about the `as type` part of that expression. We want to
find an argument that can convert to the `FacetType` of the facet value
for the generic binding that is the `<facet value>`.

This was done after-the-fact in the Deduce switch, but we move this
canonicalization step to be more explicit and done up front at the start
of the Deduce loop. This:
- Avoids a trip through the Deduce loop for a `FacetAccessType`
parameter, just to deduce through it in the switch, which avoids convert
and creation of extraneous constant values.
- Uses the `GetCanonicalFacetOrTypeValue()` function so that when we add
`SymbolicBindingType` handling to that function it will apply to Deduce
as well correctly, instead of needing to handle both in the switch.
This commit is contained in:
Dana Jansens
2025-10-03 17:05:19 +00:00
committed by GitHub
parent e3b4482893
commit b99bc00632
7 changed files with 33 additions and 60 deletions
+8 -14
View File
@@ -10,6 +10,7 @@
#include "toolchain/check/convert.h"
#include "toolchain/check/generic.h"
#include "toolchain/check/subst.h"
#include "toolchain/check/type.h"
#include "toolchain/diagnostics/diagnostic.h"
#include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/impl.h"
@@ -289,7 +290,14 @@ auto DeductionContext::Deduce() -> bool {
if (context().types().Is<SemIR::PatternType>(param_type_id)) {
param_type_id =
SemIR::ExtractScrutineeType(context().sem_ir(), param_type_id);
} else if (context().types().IsFacetType(param_type_id)) {
// Given `fn F[G:! Interface](g: G)`, the type of `g` is `G as type`. For
// deduction, we want to ignore the `as type`, and check that the argument
// can convert to the FacetType of the canonical facet value.
param_id = GetCanonicalFacetOrTypeValue(context(), param_id);
param_type_id = context().insts().Get(param_id).type_id();
}
// If the parameter has a symbolic type, deduce against that.
if (param_type_id.is_symbolic()) {
Add(context().types().GetInstId(param_type_id),
@@ -411,20 +419,6 @@ auto DeductionContext::Deduce() -> bool {
// TODO: Match field name order between param and arg.
break;
case CARBON_KIND(SemIR::FacetAccessType access): {
// Given `fn F[G:! Interface](g: G)`, the type of `g` is `G as type`.
// `G` is a symbolic binding, whose type is a facet type, but `G as
// type` converts into a `FacetAccessType`.
//
// When we see a `FacetAccessType` parameter here, we want to deduce the
// facet type of `G`, not `G as type`, for the argument (so that the
// argument would be a facet value, whose type is the same facet type of
// `G`. So here we "undo" the `as type` operation that's built into the
// `g` parameter's type.
Add(access.facet_value_inst_id, arg_id);
continue;
}
// TODO: Handle more cases.
default: