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

fix: error on incorrect generic count for impl and type alias #5623

Merged
merged 2 commits into from
Jul 29, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions compiler/noirc_frontend/src/elaborator/types.rs
Original file line number Diff line number Diff line change
@@ -239,6 +239,7 @@ impl<'context> Elaborator<'context> {

if let Some(type_alias) = self.lookup_type_alias(path.clone()) {
let type_alias = type_alias.borrow();
let actual_generic_count = args.len();
let expected_generic_count = type_alias.generics.len();
let type_alias_string = type_alias.to_string();
let id = type_alias.id;
@@ -247,9 +248,13 @@ impl<'context> Elaborator<'context> {
self.resolve_type_inner(arg, &generic.kind)
});

self.verify_generics_count(expected_generic_count, &mut args, span, || {
type_alias_string
});
self.verify_generics_count(
expected_generic_count,
actual_generic_count,
&mut args,
span,
|| type_alias_string,
);

if let Some(item) = self.current_item {
self.interner.add_type_alias_dependency(item, id);
@@ -279,6 +284,8 @@ impl<'context> Elaborator<'context> {
}

let expected_generic_count = struct_type.borrow().generics.len();
let actual_generic_count = args.len();

if !self.in_contract()
&& self
.interner
@@ -296,9 +303,13 @@ impl<'context> Elaborator<'context> {
self.resolve_type_inner(arg, &generic.kind)
});

self.verify_generics_count(expected_generic_count, &mut args, span, || {
struct_type.borrow().to_string()
});
self.verify_generics_count(
expected_generic_count,
actual_generic_count,
&mut args,
span,
|| struct_type.borrow().to_string(),
);

if let Some(current_item) = self.current_item {
let dependency_id = struct_type.borrow().id;
@@ -333,15 +344,16 @@ impl<'context> Elaborator<'context> {
fn verify_generics_count(
&mut self,
expected_count: usize,
actual_count: usize,
args: &mut Vec<Type>,
span: Span,
type_name: impl FnOnce() -> String,
) {
if args.len() != expected_count {
if actual_count != expected_count {
self.push_err(ResolverError::IncorrectGenericCount {
span,
item_name: type_name(),
actual: args.len(),
actual: actual_count,
expected: expected_count,
});

48 changes: 48 additions & 0 deletions compiler/noirc_frontend/src/tests.rs
Original file line number Diff line number Diff line change
@@ -2309,7 +2309,7 @@
}

#[test]
fn underflowing_u8() {

Check warning on line 2312 in compiler/noirc_frontend/src/tests.rs

GitHub Actions / Code

Unknown word (underflowing)
let src = r#"
fn main() {
let _: u8 = -1;
@@ -2347,7 +2347,7 @@
}

#[test]
fn underflowing_i8() {

Check warning on line 2350 in compiler/noirc_frontend/src/tests.rs

GitHub Actions / Code

Unknown word (underflowing)
let src = r#"
fn main() {
let _: i8 = -129;
@@ -2681,3 +2681,51 @@
assert_eq!(*expected, 1);
assert_eq!(*found, 2);
}

#[test]
fn incorrect_generic_count_on_struct_impl() {
let src = r#"
struct Foo {}
impl <T> Foo<T> {}
fn main() {}
"#;

let errors = get_program_errors(src);
assert_eq!(errors.len(), 1);

let CompilationError::ResolverError(ResolverError::IncorrectGenericCount {
actual,
expected,
..
}) = errors[0].0
else {
panic!("Expected an incorrect generic count mismatch error, got {:?}", errors[0].0);
};

assert_eq!(actual, 1);
assert_eq!(expected, 0);
}

#[test]
fn incorrect_generic_count_on_type_alias() {
let src = r#"
struct Foo {}
type Bar = Foo<i32>;
fn main() {}
"#;

let errors = get_program_errors(src);
assert_eq!(errors.len(), 1);

let CompilationError::ResolverError(ResolverError::IncorrectGenericCount {
actual,
expected,
..
}) = errors[0].0
else {
panic!("Expected an incorrect generic count mismatch error, got {:?}", errors[0].0);
};

assert_eq!(actual, 1);
assert_eq!(expected, 0);
}

Unchanged files with check annotations Beta

use chumsky::prelude::*;
use iter_extended::vecmap;
use lalrpop_util::lalrpop_mod;

Check warning on line 53 in compiler/noirc_frontend/src/parser/parser.rs

GitHub Actions / Code

Unknown word (lalrpop)

Check warning on line 53 in compiler/noirc_frontend/src/parser/parser.rs

GitHub Actions / Code

Unknown word (lalrpop)
use noirc_errors::{Span, Spanned};
mod assertion;
mod traits;
mod types;
// synthesized by LALRPOP

Check warning on line 67 in compiler/noirc_frontend/src/parser/parser.rs

GitHub Actions / Code

Unknown word (LALRPOP)
lalrpop_mod!(pub noir_parser);

Check warning on line 68 in compiler/noirc_frontend/src/parser/parser.rs

GitHub Actions / Code

Unknown word (lalrpop)
#[cfg(test)]
mod test_helpers;
if cfg!(feature = "experimental_parser") {
for parsed_item in &parsed_module.items {
if lalrpop_parser_supports_kind(&parsed_item.kind) {

Check warning on line 93 in compiler/noirc_frontend/src/parser/parser.rs

GitHub Actions / Code

Unknown word (lalrpop)
match &parsed_item.kind {
ItemKind::Import(parsed_use_tree) => {
prototype_parse_use_tree(Some(parsed_use_tree), source_program);
}
// other kinds prevented by lalrpop_parser_supports_kind

Check warning on line 98 in compiler/noirc_frontend/src/parser/parser.rs

GitHub Actions / Code

Unknown word (lalrpop)
_ => unreachable!(),
}
}
}
let mut lexer = Lexer::new(input);
lexer = lexer.skip_whitespaces(false);

Check warning on line 115 in compiler/noirc_frontend/src/parser/parser.rs

GitHub Actions / Code

Unknown word (whitespaces)
let mut errors = Vec::new();
// NOTE: this is a hack to get the references working