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

Usage of Trait::method syntax on globals results in monomorphisation ICE. #5029

Closed
Pasifaee opened this issue May 14, 2024 · 4 comments · Fixed by #5602
Closed

Usage of Trait::method syntax on globals results in monomorphisation ICE. #5029

Pasifaee opened this issue May 14, 2024 · 4 comments · Fixed by #5602
Labels
bug Something isn't working

Comments

@Pasifaee
Copy link

Aim

I wanted to have a structure with multiple trait From implementations and use From::from(...) syntax to create a global variable.

Expected Behavior

This code compiles:

struct Struct {
    field: Field
}

impl From<Field> for Struct {
    fn from(field: Field) -> Self {
        Struct { field }
    }
}

impl From<u64> for Struct {
    fn from(num: u64) -> Self {
        Struct { field: num as Field }
    }
}

global s: Struct = From::from(0);

fn main() {
    println(s);
}

Bug

The code above causes compilation panic. I also can't use Struct::from(...) syntax because it causes compiler error: 'Could not resolve 'from' in path'.

To Reproduce

  1. Try to compile the code above.

Project Impact

Nice-to-have

Impact Context

No response

Workaround

None

Workaround Description

No response

Additional Context

No response

Installation Method

Binary (noirup default)

Nargo Version

nargo version = 0.29.0 noirc version = 0.29.0+2da28997dbedce4a00d2162eddb57564bdb23546

NoirJS Version

No response

Would you like to submit a PR for this Issue?

None

Support Needs

No response

@Pasifaee Pasifaee added the bug Something isn't working label May 14, 2024
@github-project-automation github-project-automation bot moved this to 📋 Backlog in Noir May 14, 2024
@TomAFrench
Copy link
Member

This is unrelated to multiple implementations of the same trait as I get the same ICE when commenting out either of the trait impls.

Struct::from issue is due to #4943 (comment)

@TomAFrench
Copy link
Member

Can reproduce this with

global s: BoundedVec<Field, 2> = From::from([0]);

fn main() {
    println(s);
}

so it looks like the issue is specific to usage of Trait::method syntax in globals.

@TomAFrench TomAFrench changed the title Multiple implementations of trait From used globally cause compiler panic Usage of Trait::method syntax on globals results in monomorphisation ICE. May 14, 2024
@TomAFrench
Copy link
Member

For completeness the error is

% nargo compile                                                                                                        ~/aztec-packages/noir/noir-repo/temp tf/native-recursion tom-box
The application panicked (crashed).
Message:  ICE: missing trait impl - should be caught during type checking
Location: compiler/noirc_frontend/src/monomorphization/mod.rs:1027

@asterite
Copy link
Collaborator

This program:

global s: BoundedVec<Field, 2> = From::from([0]);

fn main() {
    println(s);
}

now gives this error:

error: No impl found due to prior type error
  ┌─ src/main.nr:1:34
  │
1 │ global s: BoundedVec<Field, 2> = From::from([0]);
  │                                  ----------
  │
  = Call stack:
    1. src/main.nr:1:34

So at least no panic, but I think it should compile so I'll take a look at this.

github-merge-queue bot pushed a commit that referenced this issue Jul 25, 2024
# Description

## Problem

Resolves #5029

## Summary

Trait constraints weren't checked after elaborating a global.

## Additional Context

I couldn't just call `check_and_pop_function_context()` because that
also defaults type variables... and if we do that the usage of a global
will not have an effect on its type. I guess this is one scenario:

```rust
global x = 1; // What's the type of x?
```

We don't know. I guess it ends up being `Field` later on (where?) But if
we have this:

```rust
global x = 1;

fn main() {
  let y: i32 = 0;
  assert_eq(x, y);
}
```

now x's type will be `i32` because of that comparison. So if we eagerly
bind `1` to its default type, this will break.

All of this to say: in Rust a global's type (well, for a `const`) must
be explicitly specified. I guess that if we also did that in Noir then
this wouldn't be a problem. And given that globals are, well, global, it
might be strange to have `global x = 1` expecting that to be a Field,
used as a Field in many places, but you accidentally compare it to an
`i32` and the type changes under the hood. But that's a bigger
discussion, so maybe the fix in this PR is good for now?

## Documentation\*

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

# PR Checklist\*

- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
@github-project-automation github-project-automation bot moved this from 📋 Backlog to ✅ Done in Noir Jul 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

3 participants