Skip to content
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

Open
wants to merge 13 commits into
base: trunk
Choose a base branch
from

Conversation

josh11b
Copy link
Contributor

@josh11b josh11b commented Mar 3, 2025

Impl lookup for an interface I for a facet with facet type requiring an interface I will now succeed, getting the witness from the facet.

-> 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?
Copy link
Contributor

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?

Copy link
Contributor Author

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.

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);
Copy link
Contributor

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

Copy link
Contributor Author

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) {
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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) {

josh11b and others added 2 commits March 3, 2025 14:08
Co-authored-by: Dana Jansens <danakj@orodu.net>
@josh11b josh11b added the dependent Depends on another issue/PR label Mar 4, 2025
@josh11b
Copy link
Contributor Author

josh11b commented Mar 4, 2025

I think #5054 will make the test diffs clearer, once it is submitted and merged into this branch.

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) {
Copy link
Contributor

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.

github-merge-queue bot pushed a commit that referenced this pull request Mar 4, 2025
…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) {
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

@josh11b josh11b removed the dependent Depends on another issue/PR label Mar 4, 2025
danakj added a commit to danakj/carbon-lang that referenced this pull request Mar 5, 2025
…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.
danakj added a commit to danakj/carbon-lang that referenced this pull request Mar 5, 2025
…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.
github-merge-queue bot pushed a commit that referenced this pull request Mar 5, 2025
…cet_type.carbon (#5077)

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 #5060.
Copy link
Contributor Author

@josh11b josh11b left a 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) {
Copy link
Contributor Author

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) {
Copy link
Contributor Author

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) {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants