noir icon indicating copy to clipboard operation
noir copied to clipboard

feat: Implement turbofish operator

Open jfecher opened this issue 1 year ago • 1 comments

Description

Problem*

Resolves #3413

Summary*

Adds the turbofish operator ::<> to variables and method calls in Noir.

Additional Context

I'm publishing this as a draft because I'm shelving this work for now after implementing the majority of it.

The work that remains to be done is handling the special case of method calls on generic impls. A generic impl will implicitly add the impl generics to each method - which means the generic count on a method itself as seen by the turbofish operator will not match the actual generics on the function internally. We'll likely need to separate out these implicit generics internally. Such that expected_generic_count = function_generics - impl_generics. I've added this as a test case to the generics test to ensure it works when this is merged.

Documentation*

Check one:

  • [ ] No documentation needed.
  • [ ] Documentation included in this PR.
  • [ ] [Exceptional Case] Documentation to be submitted in a separate PR.
  • [x] No documentation is in this PR yet since it is still a draft.

PR Checklist*

  • [x] I have tested the changes locally.
  • [ ] I have formatted the changes with Prettier and/or cargo fmt on default settings.

jfecher avatar Nov 22 '23 20:11 jfecher

Would be nice to revive it

LogvinovLeon avatar Mar 13 '24 10:03 LogvinovLeon

This should be ready again for the original simple test cases. I will have follow-ups to enable the use case issues for turbofish listed in the original post of https://github.com/noir-lang/noir/issues/4710.

To handle implicit generics on an impl I save the number of generics on the object type when converting a method call to a regular call. We then prepend these implicit generics to the supplied turbofish generics on the function for constructing the new function call HirIdent. We need to do this as the Type::Forall we will instantiate against will include these implicit generics along with the function generics. I kept the function generic count and implicit generics count as distinct variables as I found it to be simpler.

vezenovm avatar May 16 '24 22:05 vezenovm

LGTM, lets add some formatter tests for completeness.

It looks like the tests you adding are failing. I will update them but we did have some other strange bugs and am working on follow-ups.

vezenovm avatar May 17 '24 17:05 vezenovm

Odd, they were working locally.

TomAFrench avatar May 17 '24 18:05 TomAFrench

Ah, it's due to the lack of stdlib. ~I can fix these~ Not gonna try and commit at the same time as you but copying the trait impls from the other test should fix it.

TomAFrench avatar May 17 '24 18:05 TomAFrench

Not gonna try and commit at the same time as you but copying the trait impls from the other test should fix it.

Trying to wrap up a separate bug right now, but will get back to this shortly.

One more thing to note is implementing this in the new elaborator as well. I will add that before merging.

vezenovm avatar May 17 '24 19:05 vezenovm

Ah, it's due to the lack of stdlib. ~I can fix these~ Not gonna try and commit at the same time as you but copying the trait impls from the other test should fix it.

Ok noirc_frontend tests are updated and should be passing. Added some basic formatter tests as well

vezenovm avatar May 17 '24 22:05 vezenovm

Looks like the formatter is injecting unwanted spaces before the fish.

TomAFrench avatar May 20 '24 13:05 TomAFrench

Are we planning to add docs for this now or later?

jfecher avatar May 20 '24 17:05 jfecher

Are we planning to add docs for this now or later?

I'll do a follow-up as this is a pretty old PR so let's get this in first

vezenovm avatar May 20 '24 17:05 vezenovm

Looks like the formatter is injecting unwanted spaces before the fish.

Hmm I'll look again I thought I had it working locally

vezenovm avatar May 20 '24 17:05 vezenovm

In light of https://github.com/noir-lang/noir/pull/5049 I'm going to double check how turbofish arguments are stored for the monomorphizer. Please hold off on merging until then. (I can't request changes).

Edit: Looks fine to me. The turbofish args are correctly stored as the instantiation bindings.

jfecher avatar May 20 '24 17:05 jfecher

This should be ready again

vezenovm avatar May 21 '24 13:05 vezenovm

LGTM

Ok going to merge

vezenovm avatar May 21 '24 14:05 vezenovm

Tried using it and got the error on the simplest example:

use dep::std::unsafe::zeroed;

fn main() -> pub Field {
    fun::<2>()
}

fn fun<N>() -> Field {
    0
}
error: expected type Field, found type ()
  ┌─ /Users/leonidlogvinov/Dev/ZK/trait_repro/src/main.nr:3:18
  │
3 │   fn main() -> pub Field {
  │                    ----- expected Field because of return type
  │ ╭────────────────────────'
4 │ │     fun::<2>()
5 │ │ }
  │ ╰─' () returned here
  │

error: Unexpected ::, expected one of binary operator, Ident
  ┌─ /Users/leonidlogvinov/Dev/ZK/trait_repro/src/main.nr:4:8
  │
4 │     fun::<2>()
  │        ---
  │

Aborting due to 2 previous errors

I'm on Noir 0.30.0

LogvinovLeon avatar May 22 '24 15:05 LogvinovLeon

Turbofish isn't in the 0.30.0 release, this code compiles fine on master.

image

TomAFrench avatar May 22 '24 15:05 TomAFrench