diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index 8b3c126ded..151633f9e3 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -16,7 +16,9 @@ use noirc_frontend::graph::{CrateId, CrateName}; use noirc_frontend::hir::def_map::{Contract, CrateDefMap}; use noirc_frontend::hir::Context; use noirc_frontend::macros_api::MacroProcessor; -use noirc_frontend::monomorphization::{monomorphize, monomorphize_debug, MonomorphizationError}; +use noirc_frontend::monomorphization::{ + errors::MonomorphizationError, monomorphize, monomorphize_debug, +}; use noirc_frontend::node_interner::FuncId; use noirc_frontend::token::SecondaryAttribute; use std::path::Path; diff --git a/compiler/noirc_frontend/src/ast/statement.rs b/compiler/noirc_frontend/src/ast/statement.rs index b14ead8ad4..dea9fc0f3d 100644 --- a/compiler/noirc_frontend/src/ast/statement.rs +++ b/compiler/noirc_frontend/src/ast/statement.rs @@ -120,7 +120,7 @@ impl StatementKind { // Desugar `a = b` to `a = a b`. This relies on the evaluation of `a` having no side effects, // which is currently enforced by the restricted syntax of LValues. if operator != Token::Assign { - let lvalue_expr = lvalue.as_expression(span); + let lvalue_expr = lvalue.as_expression(); let error_msg = "Token passed to Statement::assign is not a binary operator"; let infix = crate::InfixExpression { @@ -425,9 +425,9 @@ pub struct AssignStatement { #[derive(Debug, PartialEq, Eq, Clone)] pub enum LValue { Ident(Ident), - MemberAccess { object: Box, field_name: Ident }, - Index { array: Box, index: Expression }, - Dereference(Box), + MemberAccess { object: Box, field_name: Ident, span: Span }, + Index { array: Box, index: Expression, span: Span }, + Dereference(Box, Span), } #[derive(Debug, PartialEq, Eq, Clone)] @@ -484,28 +484,40 @@ impl Recoverable for Pattern { } impl LValue { - fn as_expression(&self, span: Span) -> Expression { + fn as_expression(&self) -> Expression { let kind = match self { LValue::Ident(ident) => ExpressionKind::Variable(Path::from_ident(ident.clone())), - LValue::MemberAccess { object, field_name } => { + LValue::MemberAccess { object, field_name, span: _ } => { ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { - lhs: object.as_expression(span), + lhs: object.as_expression(), rhs: field_name.clone(), })) } - LValue::Index { array, index } => ExpressionKind::Index(Box::new(IndexExpression { - collection: array.as_expression(span), - index: index.clone(), - })), - LValue::Dereference(lvalue) => { + LValue::Index { array, index, span: _ } => { + ExpressionKind::Index(Box::new(IndexExpression { + collection: array.as_expression(), + index: index.clone(), + })) + } + LValue::Dereference(lvalue, _span) => { ExpressionKind::Prefix(Box::new(crate::PrefixExpression { operator: crate::UnaryOp::Dereference { implicitly_added: false }, - rhs: lvalue.as_expression(span), + rhs: lvalue.as_expression(), })) } }; + let span = self.span(); Expression::new(kind, span) } + + pub fn span(&self) -> Span { + match self { + LValue::Ident(ident) => ident.span(), + LValue::MemberAccess { span, .. } + | LValue::Index { span, .. } + | LValue::Dereference(_, span) => *span, + } + } } #[derive(Debug, PartialEq, Eq, Clone)] @@ -675,9 +687,11 @@ impl Display for LValue { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { LValue::Ident(ident) => ident.fmt(f), - LValue::MemberAccess { object, field_name } => write!(f, "{object}.{field_name}"), - LValue::Index { array, index } => write!(f, "{array}[{index}]"), - LValue::Dereference(lvalue) => write!(f, "*{lvalue}"), + LValue::MemberAccess { object, field_name, span: _ } => { + write!(f, "{object}.{field_name}") + } + LValue::Index { array, index, span: _ } => write!(f, "{array}[{index}]"), + LValue::Dereference(lvalue, _span) => write!(f, "*{lvalue}"), } } } diff --git a/compiler/noirc_frontend/src/debug/mod.rs b/compiler/noirc_frontend/src/debug/mod.rs index 8e5c174d27..71e0d44b47 100644 --- a/compiler/noirc_frontend/src/debug/mod.rs +++ b/compiler/noirc_frontend/src/debug/mod.rs @@ -282,7 +282,7 @@ impl DebugInstrumenter { .unwrap_or_else(|| panic!("var lookup failed for var_name={}", &id.0.contents)); build_assign_var_stmt(var_id, id_expr(&ident("__debug_expr", id.span()))) } - ast::LValue::Dereference(_lv) => { + ast::LValue::Dereference(_lv, span) => { // TODO: this is a dummy statement for now, but we should // somehow track the derefence and update the pointed to // variable @@ -303,16 +303,16 @@ impl DebugInstrumenter { }); break; } - ast::LValue::MemberAccess { object, field_name } => { + ast::LValue::MemberAccess { object, field_name, span } => { cursor = object; let field_name_id = self.insert_field_name(&field_name.0.contents); - indexes.push(sint_expr(-(field_name_id.0 as i128), expression_span)); + indexes.push(sint_expr(-(field_name_id.0 as i128), *span)); } - ast::LValue::Index { index, array } => { + ast::LValue::Index { index, array, span: _ } => { cursor = array; indexes.push(index.clone()); } - ast::LValue::Dereference(_ref) => { + ast::LValue::Dereference(_ref, _span) => { unimplemented![] } } diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index f8e3c4cab6..a6511a6b0f 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -1303,18 +1303,23 @@ impl<'a> Resolver<'a> { HirLValue::Ident(ident.0, Type::Error) } - LValue::MemberAccess { object, field_name } => { - let object = Box::new(self.resolve_lvalue(*object)); - HirLValue::MemberAccess { object, field_name, field_index: None, typ: Type::Error } - } - LValue::Index { array, index } => { + LValue::MemberAccess { object, field_name, span } => HirLValue::MemberAccess { + object: Box::new(self.resolve_lvalue(*object)), + field_name, + location: Location::new(span, self.file), + field_index: None, + typ: Type::Error, + }, + LValue::Index { array, index, span } => { let array = Box::new(self.resolve_lvalue(*array)); let index = self.resolve_expression(index); - HirLValue::Index { array, index, typ: Type::Error } + let location = Location::new(span, self.file); + HirLValue::Index { array, index, location, typ: Type::Error } } - LValue::Dereference(lvalue) => { + LValue::Dereference(lvalue, span) => { let lvalue = Box::new(self.resolve_lvalue(*lvalue)); - HirLValue::Dereference { lvalue, element_type: Type::Error } + let location = Location::new(span, self.file); + HirLValue::Dereference { lvalue, location, element_type: Type::Error } } } } diff --git a/compiler/noirc_frontend/src/hir/type_check/stmt.rs b/compiler/noirc_frontend/src/hir/type_check/stmt.rs index 69363d5f00..b97a453099 100644 --- a/compiler/noirc_frontend/src/hir/type_check/stmt.rs +++ b/compiler/noirc_frontend/src/hir/type_check/stmt.rs @@ -1,5 +1,5 @@ use iter_extended::vecmap; -use noirc_errors::{Location, Span}; +use noirc_errors::Span; use crate::hir_def::expr::{HirExpression, HirIdent, HirLiteral}; use crate::hir_def::stmt::{ @@ -195,41 +195,43 @@ impl<'interner> TypeChecker<'interner> { (typ.clone(), HirLValue::Ident(ident.clone(), typ), mutable) } - HirLValue::MemberAccess { object, field_name, .. } => { + HirLValue::MemberAccess { object, field_name, location, .. } => { let (lhs_type, object, mut mutable) = self.check_lvalue(object, assign_span); let mut object = Box::new(object); - let span = field_name.span(); let field_name = field_name.clone(); let object_ref = &mut object; let mutable_ref = &mut mutable; + let location = *location; let dereference_lhs = move |_: &mut Self, _, element_type| { // We must create a temporary value first to move out of object_ref before // we eventually reassign to it. let id = DefinitionId::dummy_id(); - let location = Location::new(span, fm::FileId::dummy()); let ident = HirIdent::non_trait_method(id, location); let tmp_value = HirLValue::Ident(ident, Type::Error); let lvalue = std::mem::replace(object_ref, Box::new(tmp_value)); - *object_ref = Box::new(HirLValue::Dereference { lvalue, element_type }); + *object_ref = + Box::new(HirLValue::Dereference { lvalue, element_type, location }); *mutable_ref = true; }; let name = &field_name.0.contents; let (object_type, field_index) = self - .check_field_access(&lhs_type, name, span, Some(dereference_lhs)) + .check_field_access(&lhs_type, name, field_name.span(), Some(dereference_lhs)) .unwrap_or((Type::Error, 0)); let field_index = Some(field_index); let typ = object_type.clone(); - let lvalue = HirLValue::MemberAccess { object, field_name, field_index, typ }; + let lvalue = + HirLValue::MemberAccess { object, field_name, field_index, typ, location }; (object_type, lvalue, mutable) } - HirLValue::Index { array, index, .. } => { + HirLValue::Index { array, index, location, .. } => { let index_type = self.check_expression(index); let expr_span = self.interner.expr_span(index); + let location = *location; index_type.unify( &Type::polymorphic_integer_or_field(self.interner), @@ -248,7 +250,8 @@ impl<'interner> TypeChecker<'interner> { // as needed to unwrap any &mut wrappers. while let Type::MutableReference(element) = lvalue_type.follow_bindings() { let element_type = element.as_ref().clone(); - lvalue = HirLValue::Dereference { lvalue: Box::new(lvalue), element_type }; + lvalue = + HirLValue::Dereference { lvalue: Box::new(lvalue), element_type, location }; lvalue_type = *element; // We know this value to be mutable now since we found an `&mut` mutable = true; @@ -275,11 +278,12 @@ impl<'interner> TypeChecker<'interner> { }; let array = Box::new(lvalue); - (typ.clone(), HirLValue::Index { array, index: *index, typ }, mutable) + (typ.clone(), HirLValue::Index { array, index: *index, typ, location }, mutable) } - HirLValue::Dereference { lvalue, element_type: _ } => { + HirLValue::Dereference { lvalue, element_type: _, location } => { let (reference_type, lvalue, _) = self.check_lvalue(lvalue, assign_span); let lvalue = Box::new(lvalue); + let location = *location; let element_type = Type::type_variable(self.interner.next_type_variable_id()); let expected_type = Type::MutableReference(Box::new(element_type.clone())); @@ -291,7 +295,11 @@ impl<'interner> TypeChecker<'interner> { }); // Dereferences are always mutable since we already type checked against a &mut T - (element_type.clone(), HirLValue::Dereference { lvalue, element_type }, true) + ( + element_type.clone(), + HirLValue::Dereference { lvalue, element_type, location }, + true, + ) } } } diff --git a/compiler/noirc_frontend/src/hir_def/stmt.rs b/compiler/noirc_frontend/src/hir_def/stmt.rs index 4e5f718cf4..c5e287b393 100644 --- a/compiler/noirc_frontend/src/hir_def/stmt.rs +++ b/compiler/noirc_frontend/src/hir_def/stmt.rs @@ -99,6 +99,15 @@ impl HirPattern { | HirPattern::Struct(_, _, location) => location.span, } } + + pub(crate) fn location(&self) -> Location { + match self { + HirPattern::Identifier(ident) => ident.location, + HirPattern::Mutable(_, location) + | HirPattern::Tuple(_, location) + | HirPattern::Struct(_, _, location) => *location, + } + } } /// Represents an Ast form that can be assigned to. These @@ -111,14 +120,17 @@ pub enum HirLValue { field_name: Ident, field_index: Option, typ: Type, + location: Location, }, Index { array: Box, index: ExprId, typ: Type, + location: Location, }, Dereference { lvalue: Box, element_type: Type, + location: Location, }, } diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index a2aee5e471..ec8b54c33b 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -543,11 +543,11 @@ impl TypeBinding { pub struct TypeVariableId(pub usize); impl Type { - pub fn default_int_type() -> Type { + pub fn default_int_or_field_type() -> Type { Type::FieldElement } - pub fn default_range_loop_type() -> Type { + pub fn default_int_type() -> Type { Type::Integer(Signedness::Unsigned, IntegerBitSize::SixtyFour) } @@ -787,7 +787,7 @@ impl std::fmt::Display for Type { Type::TypeVariable(var, TypeVariableKind::Normal) => write!(f, "{}", var.borrow()), Type::TypeVariable(binding, TypeVariableKind::Integer) => { if let TypeBinding::Unbound(_) = &*binding.borrow() { - write!(f, "{}", TypeVariableKind::Integer.default_type()) + write!(f, "{}", Type::default_int_type()) } else { write!(f, "{}", binding.borrow()) } @@ -1706,11 +1706,12 @@ impl BinaryTypeOperator { impl TypeVariableKind { /// Returns the default type this type variable should be bound to if it is still unbound /// during monomorphization. - pub(crate) fn default_type(&self) -> Type { + pub(crate) fn default_type(&self) -> Option { match self { - TypeVariableKind::IntegerOrField | TypeVariableKind::Normal => Type::default_int_type(), - TypeVariableKind::Integer => Type::default_range_loop_type(), - TypeVariableKind::Constant(length) => Type::Constant(*length), + TypeVariableKind::IntegerOrField => Some(Type::default_int_or_field_type()), + TypeVariableKind::Integer => Some(Type::default_int_type()), + TypeVariableKind::Constant(length) => Some(Type::Constant(*length)), + TypeVariableKind::Normal => None, } } } @@ -1744,12 +1745,12 @@ impl From<&Type> for PrintableType { }, Type::TypeVariable(binding, TypeVariableKind::Integer) => match &*binding.borrow() { TypeBinding::Bound(typ) => typ.into(), - TypeBinding::Unbound(_) => Type::default_range_loop_type().into(), + TypeBinding::Unbound(_) => Type::default_int_type().into(), }, Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) => { match &*binding.borrow() { TypeBinding::Bound(typ) => typ.into(), - TypeBinding::Unbound(_) => Type::default_int_type().into(), + TypeBinding::Unbound(_) => Type::default_int_or_field_type().into(), } } Type::Bool => PrintableType::Boolean, diff --git a/compiler/noirc_frontend/src/monomorphization/errors.rs b/compiler/noirc_frontend/src/monomorphization/errors.rs new file mode 100644 index 0000000000..3011c26cff --- /dev/null +++ b/compiler/noirc_frontend/src/monomorphization/errors.rs @@ -0,0 +1,39 @@ +use thiserror::Error; + +use noirc_errors::{CustomDiagnostic, FileDiagnostic, Location}; + +#[derive(Debug, Error)] +pub enum MonomorphizationError { + #[error("Length of generic array could not be determined.")] + UnknownArrayLength { location: Location }, + + #[error("Type annotations needed")] + TypeAnnotationsNeeded { location: Location }, +} + +impl MonomorphizationError { + fn location(&self) -> Location { + match self { + MonomorphizationError::UnknownArrayLength { location } + | MonomorphizationError::TypeAnnotationsNeeded { location } => *location, + } + } +} + +impl From for FileDiagnostic { + fn from(error: MonomorphizationError) -> FileDiagnostic { + let location = error.location(); + let call_stack = vec![location]; + let diagnostic = error.into_diagnostic(); + diagnostic.in_file(location.file).with_call_stack(call_stack) + } +} + +impl MonomorphizationError { + fn into_diagnostic(self) -> CustomDiagnostic { + let message = self.to_string(); + let location = self.location(); + + CustomDiagnostic::simple_error(message, String::new(), location.span) + } +} diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index 618eba8f19..2223773948 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -8,16 +8,6 @@ //! //! The entry point to this pass is the `monomorphize` function which, starting from a given //! function, will monomorphize the entire reachable program. -use acvm::FieldElement; -use iter_extended::{btree_map, try_vecmap, vecmap}; -use noirc_errors::{CustomDiagnostic, FileDiagnostic, Location}; -use noirc_printable_type::PrintableType; -use std::{ - collections::{BTreeMap, HashMap, VecDeque}, - unreachable, -}; -use thiserror::Error; - use crate::{ debug::DebugInstrumenter, hir_def::{ @@ -31,13 +21,25 @@ use crate::{ FunctionKind, IntegerBitSize, Signedness, Type, TypeBinding, TypeBindings, TypeVariable, TypeVariableKind, UnaryOp, Visibility, }; +use acvm::FieldElement; +use iter_extended::{btree_map, try_vecmap, vecmap}; +use noirc_errors::Location; +use noirc_printable_type::PrintableType; +use std::{ + collections::{BTreeMap, HashMap, VecDeque}, + unreachable, +}; -use self::ast::{Definition, FuncId, Function, LocalId, Program}; use self::debug_types::DebugTypeTracker; +use self::{ + ast::{Definition, FuncId, Function, LocalId, Program}, + errors::MonomorphizationError, +}; pub mod ast; mod debug; pub mod debug_types; +pub mod errors; pub mod printer; struct LambdaContext { @@ -88,40 +90,6 @@ struct Monomorphizer<'interner> { type HirType = crate::Type; -#[derive(Debug, Error)] -pub enum MonomorphizationError { - #[error("Length of generic array could not be determined.")] - UnknownArrayLength { location: Location }, -} - -impl MonomorphizationError { - fn call_stack(&self) -> Vec { - match self { - MonomorphizationError::UnknownArrayLength { location } => vec![*location], - } - } -} - -impl From for FileDiagnostic { - fn from(error: MonomorphizationError) -> FileDiagnostic { - let call_stack = error.call_stack(); - let file_id = call_stack.last().map(|location| location.file).unwrap_or_default(); - let diagnostic = error.into_diagnostic(); - diagnostic.in_file(file_id).with_call_stack(call_stack) - } -} - -impl MonomorphizationError { - fn into_diagnostic(self) -> CustomDiagnostic { - CustomDiagnostic::simple_error( - "Internal Consistency Evaluators Errors: \n - This is likely a bug. Consider opening an issue at https://github.com/noir-lang/noir/issues".to_owned(), - self.to_string(), - noirc_errors::Span::inclusive(0, 0) - ) - } -} - /// Starting from the given `main` function, monomorphize the entire program, /// replacing all references to type variables and NamedGenerics with concrete /// types, duplicating definitions as necessary to do so. @@ -308,13 +276,15 @@ impl<'interner> Monomorphizer<'interner> { let body_expr_id = *self.interner.function(&f).as_expr(); let body_return_type = self.interner.id_type(body_expr_id); - let return_type = self.convert_type(match meta.return_type() { + let return_type = match meta.return_type() { Type::TraitAsType(..) => &body_return_type, - _ => meta.return_type(), - }); + other => other, + }; + + let return_type = Self::convert_type(return_type, meta.location)?; let unconstrained = modifiers.is_unconstrained; - let parameters = self.parameters(&meta.parameters); + let parameters = self.parameters(&meta.parameters)?; let body = self.expr(body_expr_id)?; let function = ast::Function { id, name, parameters, body, return_type, unconstrained }; @@ -329,12 +299,15 @@ impl<'interner> Monomorphizer<'interner> { /// Monomorphize each parameter, expanding tuple/struct patterns into multiple parameters /// and binding any generic types found. - fn parameters(&mut self, params: &Parameters) -> Vec<(ast::LocalId, bool, String, ast::Type)> { + fn parameters( + &mut self, + params: &Parameters, + ) -> Result, MonomorphizationError> { let mut new_params = Vec::with_capacity(params.len()); for (parameter, typ, _) in ¶ms.0 { - self.parameter(parameter, typ, &mut new_params); + self.parameter(parameter, typ, &mut new_params)?; } - new_params + Ok(new_params) } fn parameter( @@ -342,21 +315,22 @@ impl<'interner> Monomorphizer<'interner> { param: &HirPattern, typ: &HirType, new_params: &mut Vec<(ast::LocalId, bool, String, ast::Type)>, - ) { + ) -> Result<(), MonomorphizationError> { match param { HirPattern::Identifier(ident) => { let new_id = self.next_local_id(); let definition = self.interner.definition(ident.id); let name = definition.name.clone(); - new_params.push((new_id, definition.mutable, name, self.convert_type(typ))); + let typ = Self::convert_type(typ, ident.location)?; + new_params.push((new_id, definition.mutable, name, typ)); self.define_local(ident.id, new_id); } - HirPattern::Mutable(pattern, _) => self.parameter(pattern, typ, new_params), + HirPattern::Mutable(pattern, _) => self.parameter(pattern, typ, new_params)?, HirPattern::Tuple(fields, _) => { let tuple_field_types = unwrap_tuple_type(typ); for (field, typ) in fields.iter().zip(tuple_field_types) { - self.parameter(field, &typ, new_params); + self.parameter(field, &typ, new_params)?; } } HirPattern::Struct(_, fields, _) => { @@ -373,10 +347,11 @@ impl<'interner> Monomorphizer<'interner> { unreachable!("Expected a field named '{field_name}' in the struct pattern") }); - self.parameter(field, &field_type, new_params); + self.parameter(field, &field_type, new_params)?; } } } + Ok(()) } fn expr( @@ -399,9 +374,10 @@ impl<'interner> Monomorphizer<'interner> { } HirExpression::Literal(HirLiteral::Bool(value)) => Literal(Bool(value)), HirExpression::Literal(HirLiteral::Integer(value, sign)) => { + let location = self.interner.id_location(expr); + let typ = Self::convert_type(&self.interner.id_type(expr), location)?; + if sign { - let typ = self.convert_type(&self.interner.id_type(expr)); - let location = self.interner.id_location(expr); match typ { ast::Type::Field => Literal(Integer(-value, typ, location)), ast::Type::Integer(_, bit_size) => { @@ -412,8 +388,6 @@ impl<'interner> Monomorphizer<'interner> { _ => unreachable!("Integer literal must be numeric"), } } else { - let typ = self.convert_type(&self.interner.id_type(expr)); - let location = self.interner.id_location(expr); Literal(Integer(value, typ, location)) } } @@ -437,7 +411,7 @@ impl<'interner> Monomorphizer<'interner> { ast::Expression::Unary(ast::Unary { operator: prefix.operator, rhs: Box::new(self.expr(prefix.rhs)?), - result_type: self.convert_type(&self.interner.id_type(expr)), + result_type: Self::convert_type(&self.interner.id_type(expr), location)?, location, }) } @@ -466,8 +440,8 @@ impl<'interner> Monomorphizer<'interner> { let function_type = Type::Function(args, Box::new(ret.clone()), env); let method = infix.trait_method_id; - let func = self.resolve_trait_method_reference(expr, function_type, method); - self.create_operator_impl_call(func, lhs, infix.operator, rhs, ret, location) + let func = self.resolve_trait_method_reference(expr, function_type, method)?; + self.create_operator_impl_call(func, lhs, infix.operator, rhs, ret, location)? } else { let lhs = Box::new(lhs); let rhs = Box::new(rhs); @@ -485,23 +459,22 @@ impl<'interner> Monomorphizer<'interner> { HirExpression::Call(call) => self.function_call(call, expr)?, - HirExpression::Cast(cast) => ast::Expression::Cast(ast::Cast { - lhs: Box::new(self.expr(cast.lhs)?), - r#type: self.convert_type(&cast.r#type), - location: self.interner.expr_location(&expr), - }), + HirExpression::Cast(cast) => { + let location = self.interner.expr_location(&expr); + let typ = Self::convert_type(&cast.r#type, location)?; + let lhs = Box::new(self.expr(cast.lhs)?); + ast::Expression::Cast(ast::Cast { lhs, r#type: typ, location }) + } HirExpression::If(if_expr) => { - let cond = self.expr(if_expr.condition)?; - let then = self.expr(if_expr.consequence)?; + let condition = Box::new(self.expr(if_expr.condition)?); + let consequence = Box::new(self.expr(if_expr.consequence)?); let else_ = if_expr.alternative.map(|alt| self.expr(alt)).transpose()?.map(Box::new); - ast::Expression::If(ast::If { - condition: Box::new(cond), - consequence: Box::new(then), - alternative: else_, - typ: self.convert_type(&self.interner.id_type(expr)), - }) + + let location = self.interner.expr_location(&expr); + let typ = Self::convert_type(&self.interner.id_type(expr), location)?; + ast::Expression::If(ast::If { condition, consequence, alternative: else_, typ }) } HirExpression::Tuple(fields) => { @@ -528,7 +501,8 @@ impl<'interner> Monomorphizer<'interner> { array_elements: Vec, is_slice: bool, ) -> Result { - let typ = self.convert_type(&self.interner.id_type(array)); + let location = self.interner.expr_location(&array); + let typ = Self::convert_type(&self.interner.id_type(array), location)?; let contents = try_vecmap(array_elements, |id| self.expr(id))?; if is_slice { Ok(ast::Expression::Literal(ast::Literal::Slice(ast::ArrayLiteral { contents, typ }))) @@ -544,7 +518,8 @@ impl<'interner> Monomorphizer<'interner> { length: HirType, is_slice: bool, ) -> Result { - let typ = self.convert_type(&self.interner.id_type(array)); + let location = self.interner.expr_location(&array); + let typ = Self::convert_type(&self.interner.id_type(array), location)?; let length = length.evaluate_to_u64().ok_or_else(|| { let location = self.interner.expr_location(&array); @@ -564,7 +539,8 @@ impl<'interner> Monomorphizer<'interner> { id: node_interner::ExprId, index: HirIndexExpression, ) -> Result { - let element_type = self.convert_type(&self.interner.id_type(id)); + let location = self.interner.expr_location(&id); + let element_type = Self::convert_type(&self.interner.id_type(id), location)?; let collection = Box::new(self.expr(index.collection)?); let index = Box::new(self.expr(index.index)?); @@ -595,11 +571,14 @@ impl<'interner> Monomorphizer<'interner> { self.define_local(for_loop.identifier.id, index_variable); let block = Box::new(self.expr(for_loop.block)?); + let index_location = for_loop.identifier.location; + let index_type = self.interner.id_type(for_loop.start_range); + let index_type = Self::convert_type(&index_type, index_location)?; Ok(ast::Expression::For(ast::For { index_variable, index_name: self.interner.definition_name(for_loop.identifier.id).to_owned(), - index_type: self.convert_type(&self.interner.id_type(for_loop.start_range)), + index_type, start_range: Box::new(start), end_range: Box::new(end), start_range_location: self.interner.expr_location(&for_loop.start_range), @@ -623,7 +602,7 @@ impl<'interner> Monomorphizer<'interner> { ) -> Result { let expr = self.expr(let_statement.expression)?; let expected_type = self.interner.id_type(let_statement.expression); - Ok(self.unpack_pattern(let_statement.pattern, expr, &expected_type)) + self.unpack_pattern(let_statement.pattern, expr, &expected_type) } fn constructor( @@ -644,7 +623,8 @@ impl<'interner> Monomorphizer<'interner> { for (field_name, expr_id) in constructor.fields { let new_id = self.next_local_id(); let field_type = field_type_map.get(&field_name.0.contents).unwrap(); - let typ = self.convert_type(field_type); + let location = self.interner.expr_location(&expr_id); + let typ = Self::convert_type(field_type, location)?; field_vars.insert(field_name.0.contents.clone(), (new_id, typ)); let expression = Box::new(self.expr(expr_id)?); @@ -688,19 +668,19 @@ impl<'interner> Monomorphizer<'interner> { pattern: HirPattern, value: ast::Expression, typ: &HirType, - ) -> ast::Expression { + ) -> Result { match pattern { HirPattern::Identifier(ident) => { let new_id = self.next_local_id(); self.define_local(ident.id, new_id); let definition = self.interner.definition(ident.id); - ast::Expression::Let(ast::Let { + Ok(ast::Expression::Let(ast::Let { id: new_id, mutable: definition.mutable, name: definition.name.clone(), expression: Box::new(value), - }) + })) } HirPattern::Mutable(pattern, _) => self.unpack_pattern(*pattern, value, typ), HirPattern::Tuple(patterns, _) => { @@ -729,7 +709,7 @@ impl<'interner> Monomorphizer<'interner> { &mut self, value: ast::Expression, fields: impl Iterator, - ) -> ast::Expression { + ) -> Result { let fresh_id = self.next_local_id(); let mut definitions = vec![ast::Expression::Let(ast::Let { @@ -740,21 +720,22 @@ impl<'interner> Monomorphizer<'interner> { })]; for (i, (field_pattern, field_type)) in fields.into_iter().enumerate() { - let location = None; + let location = field_pattern.location(); let mutable = false; let definition = Definition::Local(fresh_id); let name = i.to_string(); - let typ = self.convert_type(&field_type); + let typ = Self::convert_type(&field_type, location)?; + let location = Some(location); let new_rhs = ast::Expression::Ident(ast::Ident { location, mutable, definition, name, typ }); let new_rhs = ast::Expression::ExtractTupleField(Box::new(new_rhs), i); - let new_expr = self.unpack_pattern(field_pattern, new_rhs, &field_type); + let new_expr = self.unpack_pattern(field_pattern, new_rhs, &field_type)?; definitions.push(new_expr); } - ast::Expression::Block(definitions) + Ok(ast::Expression::Block(definitions)) } /// Find a captured variable in the innermost closure, and construct an expression @@ -780,15 +761,20 @@ impl<'interner> Monomorphizer<'interner> { } /// A local (ie non-global) ident only - fn local_ident(&mut self, ident: &HirIdent) -> Option { + fn local_ident( + &mut self, + ident: &HirIdent, + ) -> Result, MonomorphizationError> { let definition = self.interner.definition(ident.id); let name = definition.name.clone(); let mutable = definition.mutable; - let definition = self.lookup_local(ident.id)?; - let typ = self.convert_type(&self.interner.definition_type(ident.id)); + let Some(definition) = self.lookup_local(ident.id) else { + return Ok(None); + }; - Some(ast::Ident { location: Some(ident.location), mutable, definition, name, typ }) + let typ = Self::convert_type(&self.interner.definition_type(ident.id), ident.location)?; + Ok(Some(ast::Ident { location: Some(ident.location), mutable, definition, name, typ })) } fn ident( @@ -799,7 +785,7 @@ impl<'interner> Monomorphizer<'interner> { let typ = self.interner.id_type(expr_id); if let ImplKind::TraitMethod(method, _, _) = ident.impl_kind { - return Ok(self.resolve_trait_method_reference(expr_id, typ, method)); + return self.resolve_trait_method_reference(expr_id, typ, method); } let definition = self.interner.definition(ident.id); @@ -809,7 +795,7 @@ impl<'interner> Monomorphizer<'interner> { let location = Some(ident.location); let name = definition.name.clone(); let definition = self.lookup_function(*func_id, expr_id, &typ, None); - let typ = self.convert_type(&typ); + let typ = Self::convert_type(&typ, ident.location)?; let ident = ast::Ident { location, mutable, definition, name, typ: typ.clone() }; let ident_expression = ast::Expression::Ident(ident); if self.is_function_closure_type(&typ) { @@ -832,10 +818,13 @@ impl<'interner> Monomorphizer<'interner> { }; self.expr(let_.expression)? } - DefinitionKind::Local(_) => self.lookup_captured_expr(ident.id).unwrap_or_else(|| { - let ident = self.local_ident(&ident).unwrap(); - ast::Expression::Ident(ident) - }), + DefinitionKind::Local(_) => match self.lookup_captured_expr(ident.id) { + Some(expr) => expr, + None => { + let ident = self.local_ident(&ident)?.unwrap(); + ast::Expression::Ident(ident) + } + }, DefinitionKind::GenericType(type_variable) => { let value = match &*type_variable.borrow() { TypeBinding::Unbound(_) => { @@ -848,7 +837,7 @@ impl<'interner> Monomorphizer<'interner> { let value = FieldElement::from(value as u128); let location = self.interner.id_location(expr_id); - let typ = self.convert_type(&typ); + let typ = Self::convert_type(&typ, ident.location)?; ast::Expression::Literal(ast::Literal::Integer(value, typ, location)) } }; @@ -857,26 +846,28 @@ impl<'interner> Monomorphizer<'interner> { } /// Convert a non-tuple/struct type to a monomorphized type - fn convert_type(&self, typ: &HirType) -> ast::Type { - match typ { + fn convert_type(typ: &HirType, location: Location) -> Result { + Ok(match typ { HirType::FieldElement => ast::Type::Field, HirType::Integer(sign, bits) => ast::Type::Integer(*sign, *bits), HirType::Bool => ast::Type::Bool, HirType::String(size) => ast::Type::String(size.evaluate_to_u64().unwrap_or(0)), HirType::FmtString(size, fields) => { let size = size.evaluate_to_u64().unwrap_or(0); - let fields = Box::new(self.convert_type(fields.as_ref())); + let fields = Box::new(Self::convert_type(fields.as_ref(), location)?); ast::Type::FmtString(size, fields) } HirType::Unit => ast::Type::Unit, HirType::Array(length, element) => { - let element = Box::new(self.convert_type(element.as_ref())); - // TODO: convert to MonomorphizationError - let length = length.evaluate_to_u64().unwrap_or(0); + let element = Box::new(Self::convert_type(element.as_ref(), location)?); + let length = match length.evaluate_to_u64() { + Some(length) => length, + None => return Err(MonomorphizationError::TypeAnnotationsNeeded { location }), + }; ast::Type::Array(length, element) } HirType::Slice(element) => { - let element = Box::new(self.convert_type(element.as_ref())); + let element = Box::new(Self::convert_type(element.as_ref(), location)?); ast::Type::Slice(element) } HirType::TraitAsType(..) => { @@ -884,55 +875,53 @@ impl<'interner> Monomorphizer<'interner> { } HirType::NamedGeneric(binding, _) => { if let TypeBinding::Bound(binding) = &*binding.borrow() { - return self.convert_type(binding); + return Self::convert_type(binding, location); } // Default any remaining unbound type variables. // This should only happen if the variable in question is unused // and within a larger generic type. - binding.bind(HirType::default_int_type()); + binding.bind(HirType::default_int_or_field_type()); ast::Type::Field } HirType::TypeVariable(binding, kind) => { if let TypeBinding::Bound(binding) = &*binding.borrow() { - return self.convert_type(binding); + return Self::convert_type(binding, location); } // Default any remaining unbound type variables. // This should only happen if the variable in question is unused // and within a larger generic type. - let default = if self.is_range_loop - && (matches!(kind, TypeVariableKind::IntegerOrField) - || matches!(kind, TypeVariableKind::Integer)) - { - Type::default_range_loop_type() - } else { - kind.default_type() + let default = match kind.default_type() { + Some(typ) => typ, + None => return Err(MonomorphizationError::TypeAnnotationsNeeded { location }), }; - let monomorphized_default = self.convert_type(&default); + let monomorphized_default = Self::convert_type(&default, location)?; binding.bind(default); monomorphized_default } HirType::Struct(def, args) => { let fields = def.borrow().get_fields(args); - let fields = vecmap(fields, |(_, field)| self.convert_type(&field)); + let fields = try_vecmap(fields, |(_, field)| Self::convert_type(&field, location))?; ast::Type::Tuple(fields) } - HirType::Alias(def, args) => self.convert_type(&def.borrow().get_type(args)), + HirType::Alias(def, args) => { + Self::convert_type(&def.borrow().get_type(args), location)? + } HirType::Tuple(fields) => { - let fields = vecmap(fields, |x| self.convert_type(x)); + let fields = try_vecmap(fields, |x| Self::convert_type(x, location))?; ast::Type::Tuple(fields) } HirType::Function(args, ret, env) => { - let args = vecmap(args, |x| self.convert_type(x)); - let ret = Box::new(self.convert_type(ret)); - let env = self.convert_type(env); + let args = try_vecmap(args, |x| Self::convert_type(x, location))?; + let ret = Box::new(Self::convert_type(ret, location)?); + let env = Self::convert_type(env, location)?; match &env { ast::Type::Unit => ast::Type::Function(args, ret, Box::new(env)), ast::Type::Tuple(_elements) => ast::Type::Tuple(vec![ @@ -948,7 +937,7 @@ impl<'interner> Monomorphizer<'interner> { } HirType::MutableReference(element) => { - let element = self.convert_type(element); + let element = Self::convert_type(element, location)?; ast::Type::MutableReference(Box::new(element)) } @@ -956,7 +945,7 @@ impl<'interner> Monomorphizer<'interner> { unreachable!("Unexpected type {} found", typ) } HirType::Code => unreachable!("Tried to translate Code type into runtime code"), - } + }) } fn is_function_closure(&self, t: ast::Type) -> bool { @@ -987,7 +976,7 @@ impl<'interner> Monomorphizer<'interner> { expr_id: node_interner::ExprId, function_type: HirType, method: TraitMethodId, - ) -> ast::Expression { + ) -> Result { let trait_impl = self .interner .get_selected_impl_for_expression(expr_id) @@ -1031,13 +1020,15 @@ impl<'interner> Monomorphizer<'interner> { }; let the_trait = self.interner.get_trait(method.trait_id); - ast::Expression::Ident(ast::Ident { + let location = self.interner.expr_location(&expr_id); + + Ok(ast::Expression::Ident(ast::Ident { definition: Definition::Function(func_id), mutable: false, location: None, name: the_trait.methods[method.method_index].name.0.contents.clone(), - typ: self.convert_type(&function_type), - }) + typ: Self::convert_type(&function_type, location)?, + })) } fn function_call( @@ -1052,7 +1043,8 @@ impl<'interner> Monomorphizer<'interner> { self.patch_debug_instrumentation_call(&call, &mut arguments)?; let return_type = self.interner.id_type(id); - let return_type = self.convert_type(&return_type); + let location = self.interner.expr_location(&id); + let return_type = Self::convert_type(&return_type, location)?; let location = call.location; @@ -1072,7 +1064,7 @@ impl<'interner> Monomorphizer<'interner> { let mut block_expressions = vec![]; let func_type = self.interner.id_type(call.func); - let func_type = self.convert_type(&func_type); + let func_type = Self::convert_type(&func_type, location)?; let is_closure = self.is_function_closure(func_type); let func = if is_closure { @@ -1094,7 +1086,7 @@ impl<'interner> Monomorphizer<'interner> { definition: Definition::Local(local_id), mutable: false, name: "tmp".to_string(), - typ: self.convert_type(&self.interner.id_type(call.func)), + typ: Self::convert_type(&self.interner.id_type(call.func), location)?, }); let env_argument = @@ -1293,24 +1285,24 @@ impl<'interner> Monomorphizer<'interner> { fn lvalue(&mut self, lvalue: HirLValue) -> Result { let value = match lvalue { - HirLValue::Ident(ident, _) => self - .lookup_captured_lvalue(ident.id) - .unwrap_or_else(|| ast::LValue::Ident(self.local_ident(&ident).unwrap())), + HirLValue::Ident(ident, _) => match self.lookup_captured_lvalue(ident.id) { + Some(value) => value, + None => ast::LValue::Ident(self.local_ident(&ident)?.unwrap()), + }, HirLValue::MemberAccess { object, field_index, .. } => { let field_index = field_index.unwrap(); let object = Box::new(self.lvalue(*object)?); ast::LValue::MemberAccess { object, field_index } } - HirLValue::Index { array, index, typ } => { - let location = self.interner.expr_location(&index); + HirLValue::Index { array, index, typ, location } => { let array = Box::new(self.lvalue(*array)?); let index = Box::new(self.expr(index)?); - let element_type = self.convert_type(&typ); + let element_type = Self::convert_type(&typ, location)?; ast::LValue::Index { array, index, element_type, location } } - HirLValue::Dereference { lvalue, element_type } => { + HirLValue::Dereference { lvalue, element_type, location } => { let reference = Box::new(self.lvalue(*lvalue)?); - let element_type = self.convert_type(&element_type); + let element_type = Self::convert_type(&element_type, location)?; ast::LValue::Dereference { reference, element_type } } }; @@ -1324,7 +1316,7 @@ impl<'interner> Monomorphizer<'interner> { expr: node_interner::ExprId, ) -> Result { if lambda.captures.is_empty() { - self.lambda_no_capture(lambda) + self.lambda_no_capture(lambda, expr) } else { let (setup, closure_variable) = self.lambda_with_setup(lambda, expr)?; Ok(ast::Expression::Block(vec![setup, closure_variable])) @@ -1334,16 +1326,19 @@ impl<'interner> Monomorphizer<'interner> { fn lambda_no_capture( &mut self, lambda: HirLambda, + expr: node_interner::ExprId, ) -> Result { - let ret_type = self.convert_type(&lambda.return_type); + let location = self.interner.expr_location(&expr); + let ret_type = Self::convert_type(&lambda.return_type, location)?; let lambda_name = "lambda"; - let parameter_types = vecmap(&lambda.parameters, |(_, typ)| self.convert_type(typ)); + let parameter_types = + try_vecmap(&lambda.parameters, |(_, typ)| Self::convert_type(typ, location))?; // Manually convert to Parameters type so we can reuse the self.parameters method let parameters = vecmap(lambda.parameters, |(pattern, typ)| (pattern, typ, Visibility::Private)).into(); - let parameters = self.parameters(¶meters); + let parameters = self.parameters(¶meters)?; let body = self.expr(lambda.body)?; let id = self.next_function_id(); @@ -1386,15 +1381,17 @@ impl<'interner> Monomorphizer<'interner> { // patterns in the resulting tree, // which seems more fragile, we directly reuse the return parameters // of this function in those cases - let ret_type = self.convert_type(&lambda.return_type); + let location = self.interner.expr_location(&expr); + let ret_type = Self::convert_type(&lambda.return_type, location)?; let lambda_name = "lambda"; - let parameter_types = vecmap(&lambda.parameters, |(_, typ)| self.convert_type(typ)); + let parameter_types = + try_vecmap(&lambda.parameters, |(_, typ)| Self::convert_type(typ, location))?; // Manually convert to Parameters type so we can reuse the self.parameters method let parameters = vecmap(lambda.parameters, |(pattern, typ)| (pattern, typ, Visibility::Private)).into(); - let mut converted_parameters = self.parameters(¶meters); + let mut converted_parameters = self.parameters(¶meters)?; let id = self.next_function_id(); let name = lambda_name.to_owned(); @@ -1402,26 +1399,27 @@ impl<'interner> Monomorphizer<'interner> { let env_local_id = self.next_local_id(); let env_name = "env"; - let env_tuple = ast::Expression::Tuple(vecmap(&lambda.captures, |capture| { - match capture.transitive_capture_index { - Some(field_index) => match self.lambda_envs_stack.last() { - Some(lambda_ctx) => ast::Expression::ExtractTupleField( - Box::new(ast::Expression::Ident(lambda_ctx.env_ident.clone())), - field_index, - ), - None => unreachable!( - "Expected to find a parent closure environment, but found none" - ), - }, - None => { - let ident = self.local_ident(&capture.ident).unwrap(); - ast::Expression::Ident(ident) + let env_tuple = + ast::Expression::Tuple(try_vecmap(&lambda.captures, |capture| { + match capture.transitive_capture_index { + Some(field_index) => { + let lambda_ctx = self.lambda_envs_stack.last().expect( + "Expected to find a parent closure environment, but found none", + ); + + let ident = Box::new(ast::Expression::Ident(lambda_ctx.env_ident.clone())); + Ok(ast::Expression::ExtractTupleField(ident, field_index)) + } + None => { + let ident = self.local_ident(&capture.ident)?.unwrap(); + Ok(ast::Expression::Ident(ident)) + } } - } - })); + })?); + let expr_type = self.interner.id_type(expr); let env_typ = if let types::Type::Function(_, _, function_env_type) = expr_type { - self.convert_type(&function_env_type) + Self::convert_type(&function_env_type, location)? } else { unreachable!("expected a Function type for a Lambda node") }; @@ -1612,10 +1610,10 @@ impl<'interner> Monomorphizer<'interner> { rhs: ast::Expression, ret: Type, location: Location, - ) -> ast::Expression { + ) -> Result { let arguments = vec![lhs, rhs]; let func = Box::new(func); - let return_type = self.convert_type(&ret); + let return_type = Self::convert_type(&ret, location)?; let mut result = ast::Expression::Call(ast::Call { func, arguments, return_type, location }); @@ -1660,7 +1658,7 @@ impl<'interner> Monomorphizer<'interner> { _ => (), } - result + Ok(result) } /// Call sites are instantiated against the trait method, but when an impl is later selected, diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index a40355be8a..7ecff12163 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -526,8 +526,8 @@ fn assign_operator() -> impl NoirParser { } enum LValueRhs { - MemberAccess(Ident), - Index(Expression), + MemberAccess(Ident, Span), + Index(Expression, Span), } fn lvalue<'a, P>(expr_parser: P) -> impl NoirParser + 'a @@ -539,23 +539,28 @@ where let dereferences = just(Token::Star) .ignore_then(lvalue.clone()) - .map(|lvalue| LValue::Dereference(Box::new(lvalue))); + .map_with_span(|lvalue, span| LValue::Dereference(Box::new(lvalue), span)); let parenthesized = lvalue.delimited_by(just(Token::LeftParen), just(Token::RightParen)); let term = choice((parenthesized, dereferences, l_ident)); - let l_member_rhs = just(Token::Dot).ignore_then(field_name()).map(LValueRhs::MemberAccess); + let l_member_rhs = + just(Token::Dot).ignore_then(field_name()).map_with_span(LValueRhs::MemberAccess); let l_index = expr_parser .delimited_by(just(Token::LeftBracket), just(Token::RightBracket)) - .map(LValueRhs::Index); + .map_with_span(LValueRhs::Index); term.then(l_member_rhs.or(l_index).repeated()).foldl(|lvalue, rhs| match rhs { - LValueRhs::MemberAccess(field_name) => { - LValue::MemberAccess { object: Box::new(lvalue), field_name } + LValueRhs::MemberAccess(field_name, span) => { + let span = lvalue.span().merge(span); + LValue::MemberAccess { object: Box::new(lvalue), field_name, span } + } + LValueRhs::Index(index, span) => { + let span = lvalue.span().merge(span); + LValue::Index { array: Box::new(lvalue), index, span } } - LValueRhs::Index(index) => LValue::Index { array: Box::new(lvalue), index }, }) }) } diff --git a/test_programs/compile_failure/array_length_defaulting/Nargo.toml b/test_programs/compile_failure/array_length_defaulting/Nargo.toml new file mode 100644 index 0000000000..fa376596ee --- /dev/null +++ b/test_programs/compile_failure/array_length_defaulting/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "array_length_defaulting" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] diff --git a/test_programs/compile_failure/array_length_defaulting/src/main.nr b/test_programs/compile_failure/array_length_defaulting/src/main.nr new file mode 100644 index 0000000000..216a9ae3f0 --- /dev/null +++ b/test_programs/compile_failure/array_length_defaulting/src/main.nr @@ -0,0 +1,10 @@ +fn main() { + let x = dep::std::unsafe::zeroed(); + foo(x); +} + +fn foo(array: [Field; N]) { + for elem in array { + println(elem); + } +} diff --git a/test_programs/compile_failure/typevar_default/Nargo.toml b/test_programs/compile_failure/typevar_default/Nargo.toml new file mode 100644 index 0000000000..b3cd08bb8f --- /dev/null +++ b/test_programs/compile_failure/typevar_default/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "typevar_default" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/typevar_default/src/main.nr b/test_programs/compile_failure/typevar_default/src/main.nr new file mode 100644 index 0000000000..1eb9cf63de --- /dev/null +++ b/test_programs/compile_failure/typevar_default/src/main.nr @@ -0,0 +1,12 @@ +fn main() { + // Expecting error: type annotations needed (N not known) + let _ = slice_to_array(&[1, 2, 3]); +} + +fn slice_to_array(slice: [Field]) -> [Field; N] { + let mut array = [0; N]; + for i in 0 .. N { + array[i] = slice[i]; + } + array +} diff --git a/test_programs/compile_success_empty/option/src/main.nr b/test_programs/compile_success_empty/option/src/main.nr index 989c8f65bf..c5f321256b 100644 --- a/test_programs/compile_success_empty/option/src/main.nr +++ b/test_programs/compile_success_empty/option/src/main.nr @@ -39,9 +39,9 @@ fn main() { let add1_u64 = |value: Field| Option::some(value as u64 + 1); - assert(none.and_then(|_value| Option::none()).is_none()); + assert(none.and_then(|_value| none).is_none()); assert(none.and_then(add1_u64).is_none()); - assert(some.and_then(|_value| Option::none()).is_none()); + assert(some.and_then(|_value| none).is_none()); assert(some.and_then(add1_u64).unwrap() == 4); assert(some.and_then(|x| Option::some(x + ten)).unwrap() == 13); diff --git a/test_programs/execution_success/prelude/src/main.nr b/test_programs/execution_success/prelude/src/main.nr index c9ae448c48..226341f1e7 100644 --- a/test_programs/execution_success/prelude/src/main.nr +++ b/test_programs/execution_success/prelude/src/main.nr @@ -1,6 +1,6 @@ fn main() { - let _xs = Vec::new(); - let _option = Option::none(); + let _xs: Vec = Vec::new(); + let _option: Option = Option::none(); print("42\n"); println("42"); diff --git a/tooling/noirc_abi/src/lib.rs b/tooling/noirc_abi/src/lib.rs index cffb0c20cd..d0dcb37396 100644 --- a/tooling/noirc_abi/src/lib.rs +++ b/tooling/noirc_abi/src/lib.rs @@ -147,7 +147,9 @@ impl AbiType { Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) | Type::TypeVariable(binding, TypeVariableKind::Integer) => match &*binding.borrow() { TypeBinding::Bound(typ) => Self::from_type(context, typ), - TypeBinding::Unbound(_) => Self::from_type(context, &Type::default_int_type()), + TypeBinding::Unbound(_) => { + Self::from_type(context, &Type::default_int_or_field_type()) + } }, Type::Bool => Self::Boolean, Type::String(size) => {