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

Associated types on traits #3470

Closed
jfecher opened this issue Nov 10, 2023 · 0 comments · Fixed by #5739
Closed

Associated types on traits #3470

jfecher opened this issue Nov 10, 2023 · 0 comments · Fixed by #5739
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@jfecher
Copy link
Contributor

jfecher commented Nov 10, 2023

Problem

We should have associated types on traits. These are partially implemented currently but are untested and require type checking changes, among others.

Happy Case

Associated types such as the following work:

trait Foo {
    type Bar;
}

impl Foo for u32 {
    type Bar = u64;
}

Alternatives Considered

No response

Additional Context

No response

Would you like to submit a PR for this Issue?

No

Support Needs

No response

@jfecher jfecher added the enhancement New feature or request label Nov 10, 2023
@github-project-automation github-project-automation bot moved this to 📋 Backlog in Noir Nov 10, 2023
@kevaundray kevaundray added this to the 1.0 milestone Jan 15, 2024
github-merge-queue bot pushed a commit that referenced this issue Aug 22, 2024
# Description

## Problem\*

Resolves #3470

(does not fix #5544)

## Summary\*

Implements a basic form of associated types in Noir. 
- The main limitation of this work is that all associated types must be
explicitly specified in trait constraints (e.g. `Foo: Iterator<Elem =
i32>`) Instead of `Foo: Iterator`
- Eliding these requires inserting additional implicit generics anywhere
these constraints are used which I considered for this PR but opted to
limit the size instead and leave it for later work.

## Additional Context

This is a large PR which has quite a few non-trivial changes so I'll try
to summarize as best I can to help with reviews:
- Made the `Span` on `UnresolvedType` non-optional for better error
messages.
- Added `GenericTypeArgs` struct to hold both "ordered" and "named"
generics. Ordered generics are the ones we are used to where they are
specified in order. Named generics are associated types where they are
prefixed with `Name =` and may be given in any order in a generics list.
- Added a `Generic` trait to abstract over something that can be generic
(struct, type alias, trait, etc) so that we can share the same method
for resolving all generic things. This saved some code since we were
duplicating checks on these before, and have much more now that we have
to check named args as well.
- Added `TraitGenerics` as the resolved version of `GenericTypeArgs`.
This is used in a couple places including the `impl Trait` type in the
type system.
- Added associated types to the `lookup_trait_implementation` functions
in the NodeInterner. These are just treated as normal generics more or
less. When we allow these to be omitted in the future we should probably
fill these with fresh type variables so that they are still present but
always succeed unification.
- Stored associated types in trait impls in a separate map in the
NodeInterner since they are needed to be referenced within the type
signature of methods in the impl, which is before the impl as a whole
finishes resolution.
- Resolved `Self::AssociatedType` paths. Not that
#5544 is not fixed,
`Trait::AssociatedType` is still a panic.
- Added `current_trait` and `current_trait_impl` fields to the
elaborator to resolve these. Otherwise we don't know what `Self` refers
to.
- Resolved `<Type as Trait>::Type` paths. These are called
`AsTraitPath`s. Caveat: these are not allowed/resolved in arithmetic
generics still. This prevents e.g. `let Size = <T as Serialize>::Size +
<U as Serialize>::Size;`. This is more of an issue for when we allow
implicit associated types. For now since they must be explicit, `<T as
Serialize>::Size` must already be a named generic in scope so the
example would look more like `let Size = TSize + USize;`, see the
`serialize` test as an example.
- Additionally I had to make a couple more updates to arithmetic
generics to get the `serialize` test working:
- The existing rules were mostly good until monomorphization when we'd
have to re-do the same trait constraints but now we'd know the actual
end sizes (constants) for the constraints. This turned out to make it
more difficult as we had to solve `4 = a + b` when serializing a pair
where `a` and `b` are the serialized sizes of each item. In this case
`1` and `3` were the correct answers, and since these refer to specific
items in the pair, even an answer of `3` and `1` would be incorrect. I
ended up solving `<constant> = a + b` to `<constant> - b = a` so that
when we recur on the trait constraints for each item in the pair we'd
get `T: Serialize<Size = 4 - b>` and `U: Serialize<Size = a>`. ~~I have
a feeling the ordering could be wrong here. It type checks but requires
type annotations on the result of `serialize`.~~. We could add more
cases besides just subtraction but since this issue isn't directly
related to associated generics though I'm considering this future work.

## Documentation\*

Check one:
- [ ] No documentation needed.
- [x] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.

# PR Checklist\*

- [ ] I have tested the changes locally.
- [ ] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.

---------

Co-authored-by: Ary Borenszweig <[email protected]>
Co-authored-by: Tom <[email protected]>
@github-project-automation github-project-automation bot moved this from 📋 Backlog to ✅ Done in Noir Aug 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: ✅ Done
Development

Successfully merging a pull request may close this issue.

2 participants