Skip to content

Commit

Permalink
Merge branch 'master' into michaeljklein/proptest-arithmetic-generics
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeljklein authored Nov 5, 2024
2 parents bab3dec + 35dedb5 commit de5bf43
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 8 deletions.
5 changes: 2 additions & 3 deletions compiler/noirc_frontend/src/ast/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,9 +454,8 @@ impl Path {
self.last_segment().ident
}

pub fn first_name(&self) -> &str {
assert!(!self.segments.is_empty());
&self.segments.first().unwrap().ident.0.contents
pub fn first_name(&self) -> Option<&str> {
self.segments.first().map(|segment| segment.ident.0.contents.as_str())
}

pub fn last_name(&self) -> &str {
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/elaborator/path_resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ impl<'context> Elaborator<'context> {
pub(super) fn resolve_path(&mut self, mut path: Path) -> PathResolutionResult {
let mut module_id = self.module_id();

if path.kind == PathKind::Plain && path.first_name() == SELF_TYPE_NAME {
if path.kind == PathKind::Plain && path.first_name() == Some(SELF_TYPE_NAME) {
if let Some(Type::Struct(struct_type, _)) = &self.self_type {
let struct_type = struct_type.borrow();
if path.segments.len() == 1 {
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/elaborator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ impl<'context> Elaborator<'context> {

// Resolve Self::Foo to an associated type on the current trait or trait impl
fn lookup_associated_type_on_self(&self, path: &Path) -> Option<Type> {
if path.segments.len() == 2 && path.first_name() == SELF_TYPE_NAME {
if path.segments.len() == 2 && path.first_name() == Some(SELF_TYPE_NAME) {
if let Some(trait_id) = self.current_trait {
let the_trait = self.interner.get_trait(trait_id);
if let Some(typ) = the_trait.get_associated_type(path.last_name()) {
Expand Down
5 changes: 4 additions & 1 deletion compiler/noirc_frontend/src/hir_def/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1221,7 +1221,6 @@ impl Type {
| Type::Forall(_, _)
| Type::Quoted(_)
| Type::Slice(_)
| Type::InfixExpr(_, _, _)
| Type::TraitAsType(..) => false,

Type::CheckedCast { to, .. } => to.is_valid_for_program_input(),
Expand All @@ -1241,6 +1240,10 @@ impl Type {
.get_fields(generics)
.into_iter()
.all(|(_, field)| field.is_valid_for_program_input()),

Type::InfixExpr(lhs, _, rhs) => {
lhs.is_valid_for_program_input() && rhs.is_valid_for_program_input()
}
}
}

Expand Down
49 changes: 48 additions & 1 deletion compiler/noirc_frontend/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ pub(crate) fn remove_experimental_warnings(errors: &mut Vec<(CompilationError, F
}

pub(crate) fn get_program(src: &str) -> (ParsedModule, Context, Vec<(CompilationError, FileId)>) {
get_program_with_maybe_parser_errors(
src, false, // allow parser errors
)
}

pub(crate) fn get_program_with_maybe_parser_errors(
src: &str,
allow_parser_errors: bool,
) -> (ParsedModule, Context, Vec<(CompilationError, FileId)>) {
let root = std::path::Path::new("/");
let fm = FileManager::new(root);

Expand All @@ -72,7 +81,7 @@ pub(crate) fn get_program(src: &str) -> (ParsedModule, Context, Vec<(Compilation
let mut errors = vecmap(parser_errors, |e| (e.into(), root_file_id));
remove_experimental_warnings(&mut errors);

if !has_parser_error(&errors) {
if allow_parser_errors || !has_parser_error(&errors) {
let inner_attributes: Vec<SecondaryAttribute> = program
.items
.iter()
Expand Down Expand Up @@ -3645,3 +3654,41 @@ fn use_type_alias_to_generic_concrete_type_in_method_call() {
"#;
assert_no_errors(src);
}

#[test]
fn allows_struct_with_generic_infix_type_as_main_input_1() {
let src = r#"
struct Foo<let N: u32> {
x: [u64; N * 2],
}
fn main(_x: Foo<18>) {}
"#;
assert_no_errors(src);
}

#[test]
fn allows_struct_with_generic_infix_type_as_main_input_2() {
let src = r#"
struct Foo<let N: u32> {
x: [u64; N * 2],
}
fn main(_x: Foo<2 * 9>) {}
"#;
assert_no_errors(src);
}

#[test]
fn allows_struct_with_generic_infix_type_as_main_input_3() {
let src = r#"
struct Foo<let N: u32> {
x: [u64; N * 2],
}
global N = 9;
fn main(_x: Foo<N * 2>) {}
"#;
assert_no_errors(src);
}
18 changes: 17 additions & 1 deletion compiler/noirc_frontend/src/tests/traits.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::hir::def_collector::dc_crate::CompilationError;
use crate::hir::resolution::errors::ResolverError;
use crate::tests::get_program_errors;
use crate::tests::{get_program_errors, get_program_with_maybe_parser_errors};

use super::assert_no_errors;

Expand Down Expand Up @@ -390,3 +390,19 @@ fn trait_bounds_which_are_dependent_on_generic_types_are_resolved_correctly() {
"#;
assert_no_errors(src);
}

#[test]
fn does_not_crash_on_as_trait_path_with_empty_path() {
let src = r#"
struct Foo {
x: <N>,
}
fn main() {}
"#;

let (_, _, errors) = get_program_with_maybe_parser_errors(
src, true, // allow parser errors
);
assert!(!errors.is_empty());
}

0 comments on commit de5bf43

Please sign in to comment.