Skip to content

fix: allowing accessing associated constants via Self::...#8403

Merged
asterite merged 17 commits intomasterfrom
ab/access_trait_associated_constants_via_self
May 13, 2025
Merged

fix: allowing accessing associated constants via Self::...#8403
asterite merged 17 commits intomasterfrom
ab/access_trait_associated_constants_via_self

Conversation

@asterite
Copy link
Collaborator

@asterite asterite commented May 7, 2025

Description

Problem

Part of #7812
Part of #8096

Summary

This PR only solves two very specific cases.

Self::N inside a trait

This now compiles fine:

trait Trait {
    let N: u32;

    fn foo() -> u32 {
        Self::N
    }
}

For this, if we find Self::N while being inside a trait, we search for an associated constant. If we find one, that's the type of the expression. The value of the expression doesn't matter (I used zero) because trait methods never produce code, only trait impl methods.

Self::N inside a trait impl

This now compiles fine:

pub trait Trait {
    let N: u32;

    fn foo() -> u32;
}

impl Trait for i32 {
    let N: u32 = 10;

    fn foo() -> u32 {
        Self::N
    }
}

For this, if we find Self::N while being inside a trait impl, we search for an associated constant. If we find one and it has a constant value, we use that value.

What still doesn't work?

The other way to access an associated constant is in code like this:

pub trait Trait {
    let N: u32;
}

fn foo<T>(t: T) where T: Trait -> u32 {
  T::N
}

This case is trickier because even though we can find the associated type, we don't know it's value and I think we have to defer that until monomorphization... but we don't have anything to represent that, yet.

Another thing that doesn't work is the Self::N case inside a trait impl where N is an associated constant without a constant value. For example:

pub trait Trait {
    let N: u32;

    fn foo() -> u32;
}

struct Foo<let M: u32> {}

impl<let M: u32> Trait for Foo<M> {
    let N: u32 = M;

    fn foo() -> u32 {
        Self::N
    }
}

Here, like in the previous case, we can only know the value of N during monomorphization.


I still think this PR might be worth on its own because the logic to solve at least the last case would be around the new code, except that we need something new to represent it. And then, the two cases implemented here cover a lot of use cases, probably the most common ones.

Additional Context

  1. I noticed that Type::Constant holds a FieldElement, but I'm thinking it should probably hold a SignedField.
  2. Together with this PR I included a couple of nargo expand fixes regarding associated constants. I needed those for the new tests, but in the end the new tests fail for a different reason... but some of the existing ignored tests could be unignored.

Documentation

Check one:

  • No documentation needed.
  • 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 and/or cargo fmt on default settings.

@asterite asterite requested a review from a team May 8, 2025 11:14
@asterite
Copy link
Collaborator Author

asterite commented May 8, 2025

I created #8417 as an incomplete follow-up PR to show how this could be implemented for the general case. I think we need a new DefinitionKind for this. Right now that definition is pushed when we need it, but we probably want to push one definition for each trait impl associated constant and store those IDs somewhere, to later retrieve them.

But... given that I'm not too familiar with definition IDs I'd prefer to do that as a follow-up PR, if that approach would be correct.

Copy link
Member

@TomAFrench TomAFrench left a comment

Choose a reason for hiding this comment

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

Forgot to hit approve on this.

@asterite asterite added this pull request to the merge queue May 13, 2025
Merged via the queue into master with commit 8863c6a May 13, 2025
118 checks passed
@asterite asterite deleted the ab/access_trait_associated_constants_via_self branch May 13, 2025 17:28
github-merge-queue bot pushed a commit to AztecProtocol/aztec-packages that referenced this pull request May 14, 2025
Automated pull of nightly from the
[noir](https://github.com/noir-lang/noir) programming language, a
dependency of Aztec.
BEGIN_COMMIT_OVERRIDE
fix: pass Field to ToBits intrinsic in remove_bit_shifts optimization
(noir-lang/noir#8493)
fix: don't produce `index Field` in value merger
(noir-lang/noir#8492)
fix: allowing accessing associated constants via `Self::...`
(noir-lang/noir#8403)
fix: remove unused generic in static_assert
(noir-lang/noir#8488)
fix: disallow generics on entry points
(noir-lang/noir#8490)
chore(test): Replicate comptime stack overflow in a test
(noir-lang/noir#8473)
feat: `#[test(only_fail_with = "...")]`
(noir-lang/noir#8460)
fix: variable used in fmtstr inside lambda wasn't tracked as captured
(noir-lang/noir#8487)
chore(test): Add more tests for defunctionalization
(noir-lang/noir#8481)
END_COMMIT_OVERRIDE

Co-authored-by: AztecBot <tech@aztecprotocol.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants