-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deduce through FacetValue should not consider witnesses #5178
Comments
I am going to throw up a PR that does the 2nd one for now, but open to any of these or other ideas - or let me know if I am wrong in here somewhere. |
Added a fourth possible option, which hardcodes FacetValue differently - avoiding deduce_through() for it. |
Here's the full example/test:
|
From open discussion 2025-03-25: we like option 4. |
We talked more and determined that the type of Once that change is done, deduce is fine with the different instructions since they have the same types, so no change is needed to accomodate things here. |
This will be done as part of #5169, then, by simply sharing the type. No particular work item for this issue, so I will close it. |
So I understand the failure in deduce from the symbolic witness PR. When we deduce on FacetValue it is now
deduce_through
, which makes it look at its args. There are two args:type_inst_id
This is the instruction "wrapped" by the FacetValue. It's often a FacetAccessType, in generic code. And it's a concrete type implementing the required interfaces in non-generic code.
The deduce look-through is about this instruction.
For example here:
In the second impl decl, we get a deduction parameter of:
Which is itself symbolic due to the BindSymbolicName.
And we have an argument of:
These FacetValues are not the same constant value, since they differ in the specific of the nested
DD
class. So we deduce-through and compare the instructions inside, which are ClassType. The parameter's type is not symbolic so we compare the values as-is. They also don't have the same constant value so we deduce-through them, which makes use deduce on the values in the specific when AddInstArg() is called on the ClassType::arg1 values: BindSymbolicName, and ClassType "EE".Here the parameter type is now the BindSymbolicName from the generic bindings. The argument ClassType "EE" has the same type
type
as the parameter, so it is stored as the deduced argument value for it.witnesses_block_id
This is the found witnesses for the FacetValue. When we deduce through the
FacetValue
we now also compare these for equality.Before specialization and symbolic witnesses, we were counting on these witnesses to always be the same constant values for compatible
FacetValues
.Specialization and Symbolic witnesses break deduction
When
impl
lookup finds a symbolic witness, which is placed in the InstBlock of the FacetValue, the above deduction process breaks. Before we compare thetype_inst_id
, we first compare the witnesses, sinceAddInstArg()
on theFacetValue::witnesses_block_id
will add them all (from both param and arg) to the deduction. Now we get two different kinds of witnesses, with different constant values.The parameter's type is the concrete
WitnessSymbolicType
, so their values are compared for deduction. ImplWitness has a different type,WitnessType
so we try to convert them for which there is no conversion defined. This results in anErrorInst
from conversion and we abort deduction since the arguments can't be substituted into the parameters.What do?
I posit that it was never correct to compare the witnesses of a FacetValue. That deduce should deduce-through the
FacetValue
to thetype_inst_id
only.Why is this correct? The exact value of the witnesses do not matter for deduction. All witnesses share the fact that they prove an
impl
declaration does exist for the query. Symbolic witnesses for a given query are all the same. A concrete witness only adds more information to the symbolic one, so it's always safe to use a concrete witness in the place of a symbolic one. Meaning it's fine to use the argument FacetValue when the parameter is a FacetValue in all cases:What about converting?
We should thus allow argument FacetValue (of any witnesses) to convert to parameter FacetValue (of any witnesses). Convert itself has no problem with this as long as deduce asks for it.
We don't want to convert ImplWitness to ImplSymbolicWitness in deduction. The types are different and converting a concrete witness to a symbolic one loses information. Whereas converting the FacetValue containing a concrete witness to a FacetValue containing a symbolic witness will retain the concrete witnesses after conversion, since it is the FacetValue's type that is changing not the witnesses'.
Deduce through FacetValue (sort-of)
There's a couple ways to approach deducing through FacetValue for its
type_inst_id
but not its witnesses:deduce_through
in typed_inst.h from a bool to an enum:WitnessType
andWitnessSymbolicType
(or instructions that areImplWitness
andImplSymbolicWitness
) in the deduce loop, or when adding insts to the worklist.deduce_through
forFacetValue
and handle it explicitly in the deduce for loop, comparing that the argument is also aFacetValue
and then adding bothtype_inst_id
s.The text was updated successfully, but these errors were encountered: