mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-06 10:54:49 +01:00
Deduce facet values for arguments to generic fns receiving a facet type (#4865)
The fn receiving a facet type needs to deduce a type from a FacetAccessType, which is the SemIR type representing the parameter type that is a generic parameter. For example: ``` fn F[T: Interface](val: T); ``` Here T is a generic parameter that is a facet value, but the `val` parameter's type is the facet value converted from a FacetType to a TypeType, with `as type`. The result of that conversion is a FacetAccessType. So the deduction code sees a FacetAccessType for the type of `val`. We make deduction undo the `as type` conversion to move back to the `T` parameter declaration, which has type FacetType in order to deduce the required facet value (which is itself a type constrained by the FacetType). And when we have a facet value (of type FacetType) to be deduced, we will also convert the argument if it is of an appropriate type to a FacetValue that matches the FacetType using the changes from PR #4863. Tests with `impl forall` can cause impl deduction to recurse forever and crash, so those tests are omitted in this PR and they will come in follow-up work that address the infinite recursion. Rebased on top of PR #4885
This commit is contained in:
@@ -335,6 +335,9 @@ auto DeductionContext::Deduce() -> bool {
|
||||
DiagnosticAnnotationScope annotate_diagnostics(
|
||||
&context().emitter(),
|
||||
[&](auto& builder) { NoteInitializingParam(param_id, builder); });
|
||||
// TODO: The call logic should reuse the conversion here (if any) instead
|
||||
// of doing the same conversion again. At the moment we throw away the
|
||||
// converted arg_id.
|
||||
arg_id = ConvertToValueOfType(context(), loc_id_, arg_id, param_type_id);
|
||||
if (arg_id == SemIR::ErrorInst::SingletonInstId) {
|
||||
return false;
|
||||
@@ -435,6 +438,20 @@ auto DeductionContext::Deduce() -> bool {
|
||||
// TODO: Match field name order between param and arg.
|
||||
break;
|
||||
|
||||
case SemIR::FacetAccessType::Kind:
|
||||
// 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(param_inst.As<SemIR::FacetAccessType>().facet_value_inst_id, arg_id,
|
||||
needs_substitution);
|
||||
continue;
|
||||
|
||||
// TODO: Handle more cases.
|
||||
|
||||
default:
|
||||
@@ -534,7 +551,6 @@ auto DeductionContext::CheckDeductionIsComplete() -> bool {
|
||||
auto param_type_const_id = SubstConstant(
|
||||
context(), binding_type_id.AsConstantId(), substitutions_);
|
||||
CARBON_CHECK(param_type_const_id.has_value());
|
||||
CARBON_CHECK(!param_type_const_id.is_symbolic());
|
||||
binding_type_id = context().GetTypeIdForTypeConstant(param_type_const_id);
|
||||
|
||||
// TODO: Suppress diagnostics here if `diagnose_` is false.
|
||||
|
||||
Reference in New Issue
Block a user