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

chore!: removing implicit numeric generics #5837

Merged
merged 64 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
19cf0c3
chore: wip removing implicit numeric generics
michaeljklein Aug 27, 2024
136ef8d
wip removing support for implicit generics, updating tests
michaeljklein Aug 28, 2024
2fb72f0
updated tests to use explicit numeric generics, added tests to preven…
michaeljklein Aug 28, 2024
0ec783c
removing TODO's and wip comments, removing implicit numeric generics …
michaeljklein Aug 28, 2024
bdb7729
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Aug 28, 2024
776d194
debug noirc_frontend tests
michaeljklein Aug 28, 2024
d35baf1
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Aug 28, 2024
b331952
Update compiler/noirc_frontend/src/elaborator/mod.rs
michaeljklein Aug 29, 2024
484694e
Update compiler/noirc_frontend/src/elaborator/mod.rs
michaeljklein Aug 29, 2024
f339e56
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Aug 29, 2024
8d9ae0b
Update compiler/noirc_frontend/src/elaborator/types.rs
michaeljklein Aug 29, 2024
a1538e5
remove generic_is_numeric methods
michaeljklein Aug 29, 2024
7011bca
move generic kind check to convert_expression_type, update test for a…
michaeljklein Aug 29, 2024
197f037
update array/slice/generics docs with explicit numeric generics, move…
michaeljklein Aug 29, 2024
93e33b8
use TypeKindMismatch instead of UseExplicitNumericGeneric
michaeljklein Aug 29, 2024
007610d
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Aug 29, 2024
686360d
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Aug 29, 2024
a75631b
cargo clippy/fmt
michaeljklein Aug 29, 2024
6ee01d2
./test_programs/format.sh
michaeljklein Aug 29, 2024
8db0ee7
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Sep 3, 2024
f1a9b95
add test for #5447
michaeljklein Sep 3, 2024
ea8a61b
use explicit numeric generics in noir_codegen test
michaeljklein Sep 3, 2024
89ea894
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Sep 3, 2024
5b546bc
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Sep 4, 2024
6ec95cc
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Sep 9, 2024
543c713
move type_kind_mismatch and implicit_numeric_generics_type compile_fa…
michaeljklein Sep 9, 2024
dae8ce7
Update compiler/noirc_frontend/src/tests.rs
michaeljklein Sep 9, 2024
b8690f9
Update compiler/noirc_frontend/src/tests.rs
michaeljklein Sep 9, 2024
be8f235
Update compiler/noirc_frontend/src/tests.rs
michaeljklein Sep 9, 2024
3d28fed
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Sep 10, 2024
84c6e38
remove redundant test, restore regression unit test, clarify error in…
michaeljklein Sep 11, 2024
164beb4
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Sep 11, 2024
ff7eb1c
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Sep 11, 2024
ee458aa
deduplicating docs
michaeljklein Sep 11, 2024
43ee2cc
remove redundant test
michaeljklein Sep 11, 2024
4726267
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
TomAFrench Sep 11, 2024
626fe19
wip debugging failing kind errors, remove unused constant_variable fu…
michaeljklein Sep 12, 2024
25be3a0
cargo clippy/fmt
michaeljklein Sep 12, 2024
2ea6063
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Sep 12, 2024
bd4d515
wip debugging kind mismatch errors: Type::Constant needs kind informa…
michaeljklein Sep 12, 2024
dca751c
wip: adding kind info for infix and constant types
michaeljklein Sep 16, 2024
d334fd4
wip debugging tests
michaeljklein Sep 16, 2024
19abd2d
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Sep 16, 2024
6a6a826
updating Type::Constant cases, debugging failing stdlib and test_prog…
michaeljklein Sep 16, 2024
91092e6
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Sep 16, 2024
6c41e48
cleanup, add kind checks in infix_kind instead of defaulting, check f…
michaeljklein Sep 16, 2024
618e053
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Sep 16, 2024
b7dce00
add issue to remove TypeVariableKind::Constant and cleanup
michaeljklein Sep 16, 2024
78478ea
fix test kinds
michaeljklein Sep 16, 2024
b5e53e2
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Sep 17, 2024
7160258
Merge branch 'master' into michaeljklein/no-implicit-numeric-generics
michaeljklein Sep 17, 2024
2bf7048
Update compiler/noirc_frontend/src/hir_def/types.rs
michaeljklein Sep 17, 2024
9fb9341
Update compiler/noirc_frontend/src/hir_def/types.rs
michaeljklein Sep 17, 2024
b783767
Update compiler/noirc_frontend/src/hir_def/types.rs
michaeljklein Sep 17, 2024
fec1bcf
Update compiler/noirc_frontend/src/hir_def/types/arithmetic.rs
michaeljklein Sep 17, 2024
ee8ee18
Update compiler/noirc_frontend/src/tests.rs
michaeljklein Sep 17, 2024
f5fde5d
Update compiler/noirc_frontend/src/hir_def/types/arithmetic.rs
michaeljklein Sep 17, 2024
80da93d
Update test_programs/execution_success/global_consts/src/main.nr
michaeljklein Sep 17, 2024
9159ef6
Update test_programs/execution_success/global_consts/src/main.nr
michaeljklein Sep 17, 2024
18f89fe
Update tooling/lsp/src/requests/hover.rs
michaeljklein Sep 17, 2024
155e896
Update compiler/noirc_frontend/src/hir_def/types/arithmetic.rs
michaeljklein Sep 17, 2024
db7d9f6
Update compiler/noirc_frontend/src/hir_def/types/arithmetic.rs
michaeljklein Sep 17, 2024
075af22
support for bound type variables in Type::kind
michaeljklein Sep 17, 2024
7db75aa
fix displaying '(8: numeric u32)' -> '8'
michaeljklein Sep 17, 2024
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
6 changes: 3 additions & 3 deletions aztec_macros/src/utils/hir_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub fn signature_of_type(typ: &Type) -> String {
Type::FieldElement => "Field".to_owned(),
Type::Bool => "bool".to_owned(),
Type::Array(len, typ) => {
if let Type::Constant(len) = **len {
if let Type::Constant(len, _) = **len {
format!("[{};{len}]", signature_of_type(typ))
} else {
unimplemented!("Cannot generate signature for array with length type {:?}", typ)
Expand All @@ -90,7 +90,7 @@ pub fn signature_of_type(typ: &Type) -> String {
format!("({})", fields.join(","))
}
Type::String(len_typ) => {
if let Type::Constant(len) = **len_typ {
if let Type::Constant(len, _) = **len_typ {
format!("str<{len}>")
} else {
unimplemented!(
Expand Down Expand Up @@ -326,7 +326,7 @@ pub fn get_serialized_length(
let serialized_trait_impl = serialized_trait_impl_shared.borrow();

match serialized_trait_impl.trait_generics.first().unwrap() {
Type::Constant(value) => Ok(*value),
Type::Constant(value, _) => Ok(*value),
_ => Err(MacroError {
primary_message: format!("{} length for {} must be a constant", trait_name, typ),
secondary_message: None,
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_driver/src/abi_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType {
}
Type::Error
| Type::Unit
| Type::Constant(_)
| Type::Constant(..)
| Type::InfixExpr(..)
| Type::TraitAsType(..)
| Type::TypeVariable(_, _)
Expand Down
10 changes: 5 additions & 5 deletions compiler/noirc_frontend/src/elaborator/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::{
},
node_interner::{DefinitionKind, ExprId, FuncId, InternedStatementKind, TraitMethodId},
token::Tokens,
QuotedType, Shared, StructType, Type,
Kind, QuotedType, Shared, StructType, Type,
};

use super::{Elaborator, LambdaContext};
Expand Down Expand Up @@ -162,7 +162,7 @@ impl<'context> Elaborator<'context> {
(Lit(int), self.polymorphic_integer_or_field())
}
Literal::Str(str) | Literal::RawStr(str, _) => {
let len = Type::Constant(str.len() as u32);
let len = Type::Constant(str.len() as u32, Kind::u32());
(Lit(HirLiteral::Str(str)), Type::String(Box::new(len)))
}
Literal::FmtStr(str) => self.elaborate_fmt_string(str, span),
Expand Down Expand Up @@ -204,7 +204,7 @@ impl<'context> Elaborator<'context> {
elem_id
});

let length = Type::Constant(elements.len() as u32);
let length = Type::Constant(elements.len() as u32, Kind::u32());
(HirArrayLiteral::Standard(elements), first_elem_type, length)
}
ArrayLiteral::Repeated { repeated_element, length } => {
Expand All @@ -215,7 +215,7 @@ impl<'context> Elaborator<'context> {
UnresolvedTypeExpression::Constant(0, span)
});

let length = self.convert_expression_type(length);
let length = self.convert_expression_type(length, span);
let (repeated_element, elem_type) = self.elaborate_expression(*repeated_element);

let length_clone = length.clone();
Expand Down Expand Up @@ -268,7 +268,7 @@ impl<'context> Elaborator<'context> {
}
}

let len = Type::Constant(str.len() as u32);
let len = Type::Constant(str.len() as u32, Kind::u32());
let typ = Type::FmtString(Box::new(len), Box::new(Type::Tuple(capture_types)));
(HirExpression::Literal(HirLiteral::FmtStr(str, fmt_str_idents)), typ)
}
Expand Down
63 changes: 1 addition & 62 deletions compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
},
hir_def::{
expr::{HirCapturedVar, HirIdent},
function::{FunctionBody, Parameters},
function::FunctionBody,
traits::TraitConstraint,
types::{Generics, Kind, ResolvedGeneric},
},
Expand Down Expand Up @@ -415,7 +415,6 @@ impl<'context> Elaborator<'context> {
self.add_existing_variable_to_scope(name, parameter.clone(), true);
}

self.declare_numeric_generics(&func_meta.parameters, func_meta.return_type());
self.add_trait_constraints_to_scope(&func_meta);

let (hir_func, body_type) = match kind {
Expand Down Expand Up @@ -896,44 +895,6 @@ impl<'context> Elaborator<'context> {
}
}

// TODO(https://github.com/noir-lang/noir/issues/5156): Remove implicit numeric generics
fn declare_numeric_generics(&mut self, params: &Parameters, return_type: &Type) {
if self.generics.is_empty() {
return;
}

for (name_to_find, type_variable) in Self::find_numeric_generics(params, return_type) {
// Declare any generics to let users use numeric generics in scope.
// Don't issue a warning if these are unused
//
// We can fail to find the generic in self.generics if it is an implicit one created
// by the compiler. This can happen when, e.g. eliding array lengths using the slice
// syntax [T].
if let Some(ResolvedGeneric { name, span, kind, .. }) =
self.generics.iter_mut().find(|generic| generic.name.as_ref() == &name_to_find)
{
let scope = self.scopes.get_mut_scope();
let value = scope.find(&name_to_find);
if value.is_some() {
// With the addition of explicit numeric generics we do not want to introduce numeric generics in this manner
// However, this is going to be a big breaking change so for now we simply issue a warning while users have time
// to transition to the new syntax
// e.g. this code would break with a duplicate definition error:
// ```
// fn foo<let N: u8>(arr: [Field; N]) { }
// ```
continue;
}
*kind = Kind::Numeric(Box::new(Type::default_int_type()));
let ident = Ident::new(name.to_string(), *span);
let definition = DefinitionKind::GenericType(type_variable);
self.add_variable_decl_inner(ident.clone(), false, false, false, definition);

self.push_err(ResolverError::UseExplicitNumericGeneric { ident });
}
}
}

fn add_trait_constraints_to_scope(&mut self, func_meta: &FuncMeta) {
for constraint in &func_meta.trait_constraints {
let object = constraint.typ.clone();
Expand Down Expand Up @@ -1187,28 +1148,6 @@ impl<'context> Elaborator<'context> {
let fields_len = fields.len();
self.interner.update_struct(*type_id, |struct_def| {
struct_def.set_fields(fields);

// TODO(https://github.com/noir-lang/noir/issues/5156): Remove this with implicit numeric generics
// This is only necessary for resolving named types when implicit numeric generics are used.
let mut found_names = Vec::new();
struct_def.find_numeric_generics_in_fields(&mut found_names);
for generic in struct_def.generics.iter_mut() {
for found_generic in found_names.iter() {
if found_generic == generic.name.as_str() {
if matches!(generic.kind, Kind::Normal) {
let ident = Ident::new(generic.name.to_string(), generic.span);
self.errors.push((
CompilationError::ResolverError(
ResolverError::UseExplicitNumericGeneric { ident },
),
self.file,
));
generic.kind = Kind::Numeric(Box::new(Type::default_int_type()));
}
break;
}
}
}
});

for field_index in 0..fields_len {
Expand Down
123 changes: 62 additions & 61 deletions compiler/noirc_frontend/src/elaborator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::{
},
hir::{
comptime::{Interpreter, Value},
def_collector::dc_crate::CompilationError,
def_map::ModuleDefId,
resolution::errors::ResolverError,
type_check::{
Expand Down Expand Up @@ -76,45 +77,22 @@ impl<'context> Elaborator<'context> {
FieldElement => Type::FieldElement,
Array(size, elem) => {
let elem = Box::new(self.resolve_type_inner(*elem, kind));
let mut size = self.convert_expression_type(size);
// TODO(https://github.com/noir-lang/noir/issues/5156): Remove this once we only have explicit numeric generics
if let Type::NamedGeneric(type_var, name, _) = size {
size = Type::NamedGeneric(
type_var,
name,
Kind::Numeric(Box::new(Type::default_int_type())),
);
}
let size = self.convert_expression_type(size, span);
Type::Array(Box::new(size), elem)
}
Slice(elem) => {
let elem = Box::new(self.resolve_type_inner(*elem, kind));
Type::Slice(elem)
}
Expression(expr) => self.convert_expression_type(expr),
Expression(expr) => self.convert_expression_type(expr, span),
Integer(sign, bits) => Type::Integer(sign, bits),
Bool => Type::Bool,
String(size) => {
let mut resolved_size = self.convert_expression_type(size);
// TODO(https://github.com/noir-lang/noir/issues/5156): Remove this once we only have explicit numeric generics
if let Type::NamedGeneric(type_var, name, _) = resolved_size {
resolved_size = Type::NamedGeneric(
type_var,
name,
Kind::Numeric(Box::new(Type::default_int_type())),
);
}
let resolved_size = self.convert_expression_type(size, span);
Type::String(Box::new(resolved_size))
}
FormatString(size, fields) => {
let mut resolved_size = self.convert_expression_type(size);
if let Type::NamedGeneric(type_var, name, _) = resolved_size {
resolved_size = Type::NamedGeneric(
type_var,
name,
Kind::Numeric(Box::new(Type::default_int_type())),
);
}
let resolved_size = self.convert_expression_type(size, span);
let fields = self.resolve_type_inner(*fields, kind);
Type::FmtString(Box::new(resolved_size), Box::new(fields))
}
Expand Down Expand Up @@ -191,26 +169,18 @@ impl<'context> Elaborator<'context> {
_ => (),
}

// Check that any types with a type kind match the expected type kind supplied to this function
// TODO(https://github.com/noir-lang/noir/issues/5156): make this named generic check more general with `*resolved_kind != kind`
// as implicit numeric generics still existing makes this check more challenging to enforce
// An example of a more general check that we should switch to:
// if resolved_type.kind() != kind.clone() {
// let expected_typ_err = CompilationError::TypeError(TypeCheckError::TypeKindMismatch {
// expected_kind: kind.to_string(),
// expr_kind: resolved_type.kind().to_string(),
// expr_span: span.expect("Type should have span"),
// });
// self.errors.push((expected_typ_err, self.file));
// return Type::Error;
// }
if let Type::NamedGeneric(_, name, resolved_kind) = &resolved_type {
if matches!(resolved_kind, Kind::Numeric { .. }) && matches!(kind, Kind::Normal) {
let expected_typ_err =
ResolverError::NumericGenericUsedForType { name: name.to_string(), span };
self.push_err(expected_typ_err);
return Type::Error;
}
if !kind.matches_opt(resolved_type.kind()) {
let expected_typ_err = CompilationError::TypeError(TypeCheckError::TypeKindMismatch {
expected_kind: kind.to_string(),
expr_kind: resolved_type
.kind()
.as_ref()
.map(Kind::to_string)
.unwrap_or("unknown".to_string()),
expr_span: span,
});
self.errors.push((expected_typ_err, self.file));
return Type::Error;
}

resolved_type
Expand Down Expand Up @@ -441,30 +411,61 @@ impl<'context> Elaborator<'context> {

let reference_location = Location::new(path.span(), self.file);
self.interner.add_global_reference(id, reference_location);
let kind = self
.interner
.get_global_let_statement(id)
.map(|let_statement| Kind::Numeric(Box::new(let_statement.r#type)))
.unwrap_or(Kind::u32());

Some(Type::Constant(self.eval_global_as_array_length(id, path)))
Some(Type::Constant(self.eval_global_as_array_length(id, path), kind))
}
_ => None,
}
}

pub(super) fn convert_expression_type(&mut self, length: UnresolvedTypeExpression) -> Type {
pub(super) fn convert_expression_type(
&mut self,
length: UnresolvedTypeExpression,
span: Span,
) -> Type {
match length {
UnresolvedTypeExpression::Variable(path) => {
self.lookup_generic_or_global_type(&path).unwrap_or_else(|| {
self.push_err(ResolverError::NoSuchNumericTypeVariable { path });
Type::Constant(0)
})
let resolved_length =
self.lookup_generic_or_global_type(&path).unwrap_or_else(|| {
self.push_err(ResolverError::NoSuchNumericTypeVariable { path });
Type::Constant(0, Kind::u32())
});

if let Type::NamedGeneric(ref _type_var, ref _name, ref kind) = resolved_length {
if !kind.is_numeric() {
self.push_err(TypeCheckError::TypeKindMismatch {
expected_kind: Kind::u32().to_string(),
expr_kind: kind.to_string(),
expr_span: span,
});
return Type::Error;
}
}
resolved_length
}
UnresolvedTypeExpression::Constant(int, _) => Type::Constant(int),
UnresolvedTypeExpression::Constant(int, _span) => Type::Constant(int, Kind::u32()),
UnresolvedTypeExpression::BinaryOperation(lhs, op, rhs, span) => {
let lhs = self.convert_expression_type(*lhs);
let rhs = self.convert_expression_type(*rhs);
let (lhs_span, rhs_span) = (lhs.span(), rhs.span());
let lhs = self.convert_expression_type(*lhs, lhs_span);
let rhs = self.convert_expression_type(*rhs, rhs_span);

match (lhs, rhs) {
(Type::Constant(lhs), Type::Constant(rhs)) => {
(Type::Constant(lhs, lhs_kind), Type::Constant(rhs, rhs_kind)) => {
if lhs_kind != rhs_kind {
self.push_err(TypeCheckError::TypeKindMismatch {
expected_kind: lhs_kind.to_string(),
expr_kind: rhs_kind.to_string(),
expr_span: span,
});
return Type::Error;
}
if let Some(result) = op.function(lhs, rhs) {
Type::Constant(result)
Type::Constant(result, lhs_kind)
} else {
self.push_err(ResolverError::OverflowInType { lhs, op, rhs, span });
Type::Error
Expand Down Expand Up @@ -1686,7 +1687,7 @@ impl<'context> Elaborator<'context> {
| Type::Unit
| Type::Error
| Type::TypeVariable(_, _)
| Type::Constant(_)
| Type::Constant(..)
| Type::NamedGeneric(_, _, _)
| Type::Quoted(_)
| Type::Forall(_, _) => (),
Expand Down Expand Up @@ -1727,7 +1728,7 @@ impl<'context> Elaborator<'context> {
Type::Struct(struct_type, generics) => {
for (i, generic) in generics.iter().enumerate() {
if let Type::NamedGeneric(type_variable, name, _) = generic {
if struct_type.borrow().generic_is_numeric(i) {
if struct_type.borrow().generics[i].is_numeric() {
found.insert(name.to_string(), type_variable.clone());
}
} else {
Expand All @@ -1738,7 +1739,7 @@ impl<'context> Elaborator<'context> {
Type::Alias(alias, generics) => {
for (i, generic) in generics.iter().enumerate() {
if let Type::NamedGeneric(type_variable, name, _) = generic {
if alias.borrow().generic_is_numeric(i) {
if alias.borrow().generics[i].is_numeric() {
found.insert(name.to_string(), type_variable.clone());
}
} else {
Expand Down
Loading
Loading