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

Deduce facet values for arguments to generic fns receiving a facet type #4865

Draft
wants to merge 2 commits into
base: trunk
Choose a base branch
from

Conversation

danakj
Copy link
Contributor

@danakj danakj commented Jan 29, 2025

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.

This PR is written on top of #4863.

If a type satisfies the requirements of a FacetType, then that type
as a value can be converted to a FacetValue, which binds the type value
to the FacetType.

For instance, if the class A implements an interface B, then

  fn F(b:! B) {}

can be called with the type `A`

  F(A);

This does not handle yet receiving non-type values matching a FacetType,
as that requires deducing the required FacetValue for the caller's
argument. Follow-up work will do this step.
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 carbon-language#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.

This PR is written on top of carbon-language#4863.
@danakj
Copy link
Contributor Author

danakj commented Jan 29, 2025

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.

The fuzzer tests are too good, and see this immediately. I will have to either do more here or add some context.TODOs, but then I also hit an eval phase check, so this isn't ready yet I guess.

class Ginger {}
impl Ginger as Goat {}

fn WalkGoat[T:! Goat](g: T) {}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self: add a test with a generic interface, and the generic argument comes in a later parameter:

fn CallGenericMethod[T:! type](U:! Generic(T), t: T) {}

fn G(t: GenericParam) { CallGenericMethod(GenericParam, t); }

From @zygoloid here: https://github.com/carbon-language/carbon-lang/pull/4882/files#r1939902344

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.

1 participant