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

feat: type alias for numeric generics #7583

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Conversation

guipublic
Copy link
Contributor

Description

Problem*

Resolves #7272

Summary*

Allow type alias to reference numeric generic expression.

Additional Context

Changes are minimal, more use cases need to be tested. In particular there is no documentation. It can be added as a subsequent PR (or even in this one).
The PR is done in order to validate the approach taken.

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.

@guipublic guipublic requested a review from a team March 5, 2025 11:23
@guipublic guipublic changed the title type alias for numeric generics feat: type alias for numeric generics Mar 5, 2025
@guipublic
Copy link
Contributor Author

I am not sure why I had to update some unit tests.

// It must be a numeric type
num_typ = Some(self.parse_type_or_error());
}
let location = self.location_since(start_location);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This location should be created right before finishing parsing the type alias (I think this is why you get a difference in the tests). It seems previously this was right before the semicolons.

#[derive(Clone, Debug)]
pub struct NumericTypeAlias {
pub type_alias: NormalTypeAlias,
pub numeric_type: UnresolvedType,
Copy link
Collaborator

Choose a reason for hiding this comment

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

If the only difference between the two aliases is this numeric_type, maybe it could be turned into numeric_type: Option<UnresolvedType> in NoirTypeAlias to avoid an enum. I think parsing will be simplified too, and maybe the elaborator side too. The only downside I can see is that we need to remember to check this field during elaboration, but it's a one-time case and with a test we'll have it covered.

Copy link
Contributor

Choose a reason for hiding this comment

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

I also think the Option<UnresolvedType> approach may be simpler

let generics = vecmap(&self.type_alias.generics, |generic| generic.to_string());
write!(
f,
"numeric ({}) type {}<{}> = {}",
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't know if we use this strings for compilation, but right now that output doesn't match the syntax that we use for parsing it.

let b: [u8; 6] = foo();
assert(b[0] == 0);
}
fn foo<let N:u32>() -> [u8;Double::<N>] {
Copy link
Contributor

@jfecher jfecher Mar 5, 2025

Choose a reason for hiding this comment

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

It's unfortunate we can't parse this as Double<N> without the turbofish. We're parsing an expression here not a type so we run into something like D < N > 2 actually being a valid expression...

May need to keep this for now. Can you add a test that shows we can still use the alias without the turbofish, where a type is expected? E.g. BoundedVec<Field, Double<N>>

Comment on lines +211 to +216
if let Some((span, message)) =
get_error_line_span_and_message(line, '-', byte, last_line_length)
{
custom_spans_with_errors.push((span, message));
continue;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Unsure why we'd need to change this either. @asterite any insights?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think the overall location of the type alias was changed so these tests broke (though I'm not sure why we'd need custom spans here).

code_lines.push(line);

byte += line.len() + 1; // For '\n'
last_line_length = line.len();
}

dbg!(&custom_spans_with_errors);
Copy link
Contributor

Choose a reason for hiding this comment

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

A few leftover dbg in this function

#[derive(Clone, Debug)]
pub struct NumericTypeAlias {
pub type_alias: NormalTypeAlias,
pub numeric_type: UnresolvedType,
Copy link
Contributor

Choose a reason for hiding this comment

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

I also think the Option<UnresolvedType> approach may be simpler

let b: [u8; 6] = foo();
assert(b[0] == 0);
}
fn foo<let N:u32>() -> [u8;Double::<N>] {
Copy link
Contributor

@jfecher jfecher Mar 5, 2025

Choose a reason for hiding this comment

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

It's unfortunate we can't parse this as Double<N> without the turbofish. We're parsing an expression here not a type so we run into something like D < N > 2 actually being a valid expression...

May need to keep this for now. Can you add a test that shows we can still use the alias without the turbofish, where a type is expected? E.g. BoundedVec<Field, Double<N>>

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.

Type aliases for numeric types
3 participants