-
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
Find impl witnesses in facets #5060
base: trunk
Are you sure you want to change the base?
Conversation
toolchain/check/impl_lookup.cpp
Outdated
-> SemIR::InstId { | ||
SemIR::InstId facet_inst_id = | ||
context.constant_values().GetInstId(facet_const_id); | ||
// FIXME: Should we convert from a FacetAccessType to its facet here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this become a TODO, or are you intending to resolve it before landing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made a TODO. This PR is useful even without adding this change, so we can discover later if handling FacetAccessType is useful.
toolchain/check/impl_lookup.cpp
Outdated
SemIR::InstId facet_inst_id = | ||
context.constant_values().GetInstId(facet_const_id); | ||
// FIXME: Should we convert from a FacetAccessType to its facet here? | ||
SemIR::Inst facet_inst = context.insts().Get(facet_inst_id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: i'd maybe consider calling .type_id() on this immediate and skip the facet_inst
local variable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
const auto& complete_facet_type = | ||
context.complete_facet_types().Get(complete_facet_type_id); | ||
for (auto interface : complete_facet_type.required_interfaces) { | ||
if (interface == specific_interface) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect we should only do this if other_requirements
is false for them both? Otherwise we would return an incorrect witness sometimes (which is noted by the TODO you've added at the end). I think it's a better incremental state to reject code incorrectly than to accept things that shouldn't typecheck and cause further errors later?
If there is an other_requirements
we can also fall back to the constant values of the facet type and the query, if you'd like (which is ultimately type_const_id == interface_const_id
in this case), as we're doing in #5047. Then where
conditions that match can also return a correct witness, as long as there's only a single interface in both facet types. Otherwise it will (incorrectly) reject them, which is okay for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think other_requirements are relevant here. As long as the interface id and specific id match, we can use the resulting witness. There is a question of whether that witness satisfies the requirements of the query facet type, but that is necessarily a distinct check and will happen in LookupImplWitness
, not here. In general, we won't expect requirements to match -- for example, a witness for an interface may not have any other requirements, but still the values of the associated constants in that witness can satisfy the requirements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, it sounds like your vision for how to test other conditions is different than what I was expecting, which is fine.
Do you think we could add some tests in this PR for impl lookup on a facet type with where .. impls
, where .. .X == Y
and where .. .X = Y
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify, we could have tests that should pass and that should fail (won't match) for each of these cases? I think we only have the should-pass for where .. impls
at the moment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What cases are you thinking about? I was having trouble finding a test that would cause RequireCompleteFacetType
to fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I think we're now on the same page and where clauses are not working as much as I thought. That said if you can write tests hitting the different features of where
I think it would be helpful. I was not thinking about making RequireCompleteFacetType
fail but rather cases where the comparison/matching of the impl with the query should either pass or fail while considering those different features of where
: rewrite constraint, conditional constraint, or impls contraint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR doesn't do anything about where constraints. I did add some tests to toolchain/check/testdata/builtin_conversions/no_prelude/convert_facet_value_to_narrowed_facet_type.carbon that cover some more cases. Note that one of them fails, but it appears to be due to code that wasn't from this PR:
// in impl_lookup.cpp, GetWitnessIdForImpl():
auto deduced_self_const_id = SemIR::GetConstantValueInSpecific(
context.sem_ir(), specific_id, impl.self_id);
if (type_const_id != deduced_self_const_id) {
Co-authored-by: Dana Jansens <danakj@orodu.net>
|
toolchain/check/testdata/impl/lookup/no_prelude/impl_forall.carbon
Outdated
Show resolved
Hide resolved
const auto& complete_facet_type = | ||
context.complete_facet_types().Get(complete_facet_type_id); | ||
for (auto interface : complete_facet_type.required_interfaces) { | ||
if (interface == specific_interface) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify, we could have tests that should pass and that should fail (won't match) for each of these cases? I think we only have the should-pass for where .. impls
at the moment.
…g impl witnesses in facets (#5054) Here are some test changes so the diffs that come from my upcoming functionality changes are easier to see. Upcoming functionality includes: * Compound member access with non-instance associated constants will change to comply with the design https://docs.carbon-lang.dev/docs/design/expressions/member_access.html#impl-lookup-for-compound-member-access in #5059 . * Impl lookup will add support for finding impl witnesses in facets #5060 I'm also making the toolchain/check/testdata/impl/compound.carbon test into a no_prelude version, and adding a version that tests with importing. --------- Co-authored-by: Josh L <josh11b@users.noreply.github.com>
if (complete_facet_type_id.has_value()) { | ||
const auto& complete_facet_type = | ||
context.complete_facet_types().Get(complete_facet_type_id); | ||
for (auto interface : complete_facet_type.required_interfaces) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to note from our offline convo, if the query specific_interface
has other_requirements
then we don't want to match anything with it, so we return none. And if the facet type's interface has other_requirements
then we want to skip trying to match it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, I haven't made those changes yet. I might end up merging your PR first and then make those changes. since this involves stuff you are touching.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've merged your changes and it should now handle other_requirements
as we discussed.
…cet_type.carbon Now that BitAnd for tpes exists, we should get an error about type conversion, not about BitAnd not existing. Add `type.and` to the Core package in the test in order to improve the error message. This test will likely be made to pass by carbon-language#5060.
…cet_type.carbon Now that BitAnd for types exists, we should get an error about type conversion, not about BitAnd not existing. Add `type.and` to the Core package in the test in order to improve the error message. This test will likely be made to pass by carbon-language#5060.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I synced your changes and this PR is now more capable. I added some tests of this new capability, but one of them fails. That failure isn't due to this PR though, so I think this is ready for re-review.
if (complete_facet_type_id.has_value()) { | ||
const auto& complete_facet_type = | ||
context.complete_facet_types().Get(complete_facet_type_id); | ||
for (auto interface : complete_facet_type.required_interfaces) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've merged your changes and it should now handle other_requirements
as we discussed.
const auto& complete_facet_type = | ||
context.complete_facet_types().Get(complete_facet_type_id); | ||
for (auto interface : complete_facet_type.required_interfaces) { | ||
if (interface == specific_interface) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR doesn't do anything about where constraints. I did add some tests to toolchain/check/testdata/builtin_conversions/no_prelude/convert_facet_value_to_narrowed_facet_type.carbon that cover some more cases. Note that one of them fails, but it appears to be due to code that wasn't from this PR:
// in impl_lookup.cpp, GetWitnessIdForImpl():
auto deduced_self_const_id = SemIR::GetConstantValueInSpecific(
context.sem_ir(), specific_id, impl.self_id);
if (type_const_id != deduced_self_const_id) {
Impl lookup for an interface
I
for a facet with facet type requiring an interfaceI
will now succeed, getting the witness from the facet.