diff --git a/compiler/noirc_frontend/src/ast/mod.rs b/compiler/noirc_frontend/src/ast/mod.rs index 38e9c224d1f..21cc8307151 100644 --- a/compiler/noirc_frontend/src/ast/mod.rs +++ b/compiler/noirc_frontend/src/ast/mod.rs @@ -14,6 +14,7 @@ mod traits; mod type_alias; mod visitor; +use noirc_errors::Located; use noirc_errors::Location; pub use visitor::AttributeTarget; pub use visitor::Visitor; @@ -491,6 +492,24 @@ impl UnresolvedTypeData { | UnresolvedTypeData::Error => false, } } + + pub(crate) fn try_into_expression(&self) -> Option { + match self { + UnresolvedTypeData::Expression(expr) => Some(expr.clone()), + UnresolvedTypeData::Parenthesized(unresolved_type) => { + unresolved_type.typ.try_into_expression() + } + UnresolvedTypeData::Named(path, generics, _) + if path.is_ident() && generics.is_empty() => + { + Some(UnresolvedTypeExpression::Variable(path.clone())) + } + UnresolvedTypeData::AsTraitPath(as_trait_path) => { + Some(UnresolvedTypeExpression::AsTraitPath(as_trait_path.clone())) + } + _ => None, + } + } } impl UnresolvedTypeExpression { @@ -569,6 +588,25 @@ impl UnresolvedTypeExpression { } } + pub fn to_expression_kind(&self) -> ExpressionKind { + match self { + UnresolvedTypeExpression::Variable(path) => ExpressionKind::Variable(path.clone()), + UnresolvedTypeExpression::Constant(int, suffix, _) => { + ExpressionKind::Literal(Literal::Integer(*int, *suffix)) + } + UnresolvedTypeExpression::BinaryOperation(lhs, op, rhs, location) => { + ExpressionKind::Infix(Box::new(InfixExpression { + lhs: Expression { kind: lhs.to_expression_kind(), location: *location }, + operator: Located::from(*location, op.operator_to_binary_op_kind_helper()), + rhs: Expression { kind: rhs.to_expression_kind(), location: *location }, + })) + } + UnresolvedTypeExpression::AsTraitPath(path) => { + ExpressionKind::AsTraitPath(Box::new(*path.clone())) + } + } + } + fn operator_allowed(op: BinaryOpKind) -> bool { matches!( op, @@ -592,6 +630,17 @@ impl UnresolvedTypeExpression { } } } + + pub(crate) fn is_valid_expression(&self) -> bool { + match self { + UnresolvedTypeExpression::Variable(path) => path.no_generic(), + UnresolvedTypeExpression::Constant(_, _, _) => true, + UnresolvedTypeExpression::BinaryOperation(lhs, _, rhs, _) => { + lhs.is_valid_expression() && rhs.is_valid_expression() + } + UnresolvedTypeExpression::AsTraitPath(_) => true, + } + } } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] diff --git a/compiler/noirc_frontend/src/ast/statement.rs b/compiler/noirc_frontend/src/ast/statement.rs index 0f059a6e6e5..eb0180e017b 100644 --- a/compiler/noirc_frontend/src/ast/statement.rs +++ b/compiler/noirc_frontend/src/ast/statement.rs @@ -478,6 +478,16 @@ impl Path { && self.segments.first().unwrap().generics.is_none() } + pub fn no_generic(&self) -> bool { + for segment in &self.segments { + if segment.generics.is_some() { + return false; + } + } + + true + } + pub fn as_ident(&self) -> Option<&Ident> { if !self.is_ident() { return None; diff --git a/compiler/noirc_frontend/src/ast/type_alias.rs b/compiler/noirc_frontend/src/ast/type_alias.rs index 532593fad0b..5380137a3ba 100644 --- a/compiler/noirc_frontend/src/ast/type_alias.rs +++ b/compiler/noirc_frontend/src/ast/type_alias.rs @@ -4,16 +4,19 @@ use noirc_errors::Location; use std::fmt::Display; /// Ast node for type aliases +/// Depending on 'numeric_type', a Type Alias can be an alias to a normal type, or to a numeric generic type #[derive(Clone, Debug)] -pub struct NoirTypeAlias { +pub struct TypeAlias { pub name: Ident, pub generics: UnresolvedGenerics, pub typ: UnresolvedType, pub visibility: ItemVisibility, pub location: Location, + pub numeric_type: Option, + pub numeric_location: Location, } -impl Display for NoirTypeAlias { +impl Display for TypeAlias { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let generics = vecmap(&self.generics, |generic| generic.to_string()); write!(f, "type {}<{}> = {}", self.name, generics.join(", "), self.typ) diff --git a/compiler/noirc_frontend/src/ast/visitor.rs b/compiler/noirc_frontend/src/ast/visitor.rs index 2d69c4c118f..6602d145968 100644 --- a/compiler/noirc_frontend/src/ast/visitor.rs +++ b/compiler/noirc_frontend/src/ast/visitor.rs @@ -7,9 +7,9 @@ use crate::{ CastExpression, ConstrainExpression, ConstructorExpression, Expression, ExpressionKind, ForLoopStatement, ForRange, Ident, IfExpression, IndexExpression, InfixExpression, LValue, Lambda, LetStatement, Literal, MemberAccessExpression, MethodCallExpression, - ModuleDeclaration, NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, Path, - PrefixExpression, Statement, StatementKind, TraitImplItem, TraitItem, TypeImpl, UseTree, - UseTreeKind, + ModuleDeclaration, NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, Path, + PrefixExpression, Statement, StatementKind, TraitImplItem, TraitItem, TypeImpl, + UnresolvedGeneric, UseTree, UseTreeKind, }, node_interner::{ ExprId, InternedExpressionKind, InternedPattern, InternedStatementKind, @@ -25,7 +25,7 @@ use crate::{ use super::{ ForBounds, FunctionReturnType, GenericTypeArgs, ItemVisibility, MatchExpression, - NoirEnumeration, Pattern, TraitBound, TraitImplItemKind, TypePath, UnresolvedGeneric, + NoirEnumeration, Pattern, TraitBound, TraitImplItemKind, TypeAlias, TypePath, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, UnsafeExpression, }; @@ -148,7 +148,7 @@ pub trait Visitor { true } - fn visit_noir_type_alias(&mut self, _: &NoirTypeAlias, _: Span) -> bool { + fn visit_noir_type_alias(&mut self, _: &TypeAlias, _: Span) -> bool { true } @@ -864,7 +864,7 @@ impl NoirEnumeration { } } -impl NoirTypeAlias { +impl TypeAlias { pub fn accept(&self, span: Span, visitor: &mut impl Visitor) { if visitor.visit_noir_type_alias(self, span) { self.accept_children(visitor); diff --git a/compiler/noirc_frontend/src/elaborator/mod.rs b/compiler/noirc_frontend/src/elaborator/mod.rs index 1d1dc954070..957208249a7 100644 --- a/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/compiler/noirc_frontend/src/elaborator/mod.rs @@ -1815,18 +1815,52 @@ impl<'context> Elaborator<'context> { let name = &alias.type_alias_def.name; let visibility = alias.type_alias_def.visibility; - let location = alias.type_alias_def.typ.location; + let location = alias.type_alias_def.location; let generics = self.add_generics(&alias.type_alias_def.generics); self.current_item = Some(DependencyId::Alias(alias_id)); let wildcard_allowed = false; - let typ = self.use_type(alias.type_alias_def.typ, wildcard_allowed); + let (typ, num_expr) = if let Some(num_type) = alias.type_alias_def.numeric_type { + let num_type = self.resolve_type(num_type, wildcard_allowed); + let kind = Kind::numeric(num_type); + let num_expr = alias.type_alias_def.typ.typ.try_into_expression(); + + if let Some(num_expr) = num_expr { + // Checks that the expression only references generics and constants + if !num_expr.is_valid_expression() { + self.errors.push(CompilationError::ResolverError( + ResolverError::RecursiveTypeAlias { + location: alias.type_alias_def.numeric_location, + }, + )); + (Type::Error, None) + } else { + ( + self.resolve_type_with_kind( + alias.type_alias_def.typ, + &kind, + wildcard_allowed, + ), + Some(num_expr), + ) + } + } else { + self.errors.push(CompilationError::ResolverError( + ResolverError::ExpectedNumericExpression { + typ: alias.type_alias_def.typ.typ.to_string(), + location, + }, + )); + (Type::Error, None) + } + } else { + (self.use_type(alias.type_alias_def.typ, wildcard_allowed), None) + }; if visibility != ItemVisibility::Private { self.check_type_is_not_more_private_then_item(name, visibility, &typ, location); } - - self.interner.set_type_alias(alias_id, typ, generics); + self.interner.set_type_alias(alias_id, typ, generics, num_expr); self.generics.clear(); } diff --git a/compiler/noirc_frontend/src/elaborator/patterns.rs b/compiler/noirc_frontend/src/elaborator/patterns.rs index be542ecf759..7d25ba065ec 100644 --- a/compiler/noirc_frontend/src/elaborator/patterns.rs +++ b/compiler/noirc_frontend/src/elaborator/patterns.rs @@ -6,7 +6,7 @@ use crate::{ DataType, Kind, Shared, Type, TypeAlias, TypeBindings, ast::{ ERROR_IDENT, Expression, ExpressionKind, GenericTypeArgs, Ident, ItemVisibility, Path, - PathSegment, Pattern, TypePath, + PathSegment, Pattern, TypePath, UnresolvedTypeExpression, }, elaborator::{ Turbofish, @@ -581,6 +581,18 @@ impl Elaborator<'_> { let (expr, item) = self.resolve_variable(variable); let definition_id = expr.id; + if let Some(PathResolutionItem::TypeAlias(alias)) = item { + // A type alias to a numeric generics is considered like a variable + // but it is not a real variable so it does not resolve to a valid Identifier + // In order to handle this, we retrieve the numeric generics expression that the type aliases to + let type_alias = self.interner.get_type_alias(alias); + if let Some(expr) = &type_alias.borrow().numeric_expr { + let expr = UnresolvedTypeExpression::to_expression_kind(expr); + let expr = Expression::new(expr, type_alias.borrow().location); + return self.elaborate_expression(expr); + } + } + let (type_generics, self_generic) = if let Some(item) = item { self.resolve_item_turbofish_and_self_type(item) } else { @@ -1155,6 +1167,15 @@ impl Elaborator<'_> { Err(_) => error, }, None => match self.lookup_global(path) { + Ok((dummy_id, PathResolutionItem::TypeAlias(type_alias_id))) + if dummy_id == DefinitionId::dummy_id() => + { + // Allow path which resolves to a type alias + return Ok(( + (HirIdent::non_trait_method(dummy_id, location), 4), + Some(PathResolutionItem::TypeAlias(type_alias_id)), + )); + } Ok((id, item)) => { return Ok(((HirIdent::non_trait_method(id, location), 0), Some(item))); } diff --git a/compiler/noirc_frontend/src/elaborator/scope.rs b/compiler/noirc_frontend/src/elaborator/scope.rs index 96f16bfcfdc..ea9a66e421a 100644 --- a/compiler/noirc_frontend/src/elaborator/scope.rs +++ b/compiler/noirc_frontend/src/elaborator/scope.rs @@ -88,14 +88,31 @@ impl Elaborator<'_> { return Ok((self.interner.function_definition_id(function), item)); } - if let PathResolutionItem::Global(global) = item { - let global = self.interner.get_global(global); - return Ok((global.definition_id, item)); - } - let expected = "global variable"; let got = "local variable"; - Err(ResolverError::Expected { location, expected, got }) + match item { + PathResolutionItem::Global(global) => { + let global = self.interner.get_global(global); + Ok((global.definition_id, item)) + } + PathResolutionItem::TypeAlias(type_alias_id) => { + let type_alias = self.interner.get_type_alias(type_alias_id); + + if type_alias.borrow().numeric_expr.is_some() { + // Type alias to numeric generics are aliases to some global value + // Therefore we allow this case although we cannot provide the value yet + return Ok((DefinitionId::dummy_id(), item)); + } + if matches!(type_alias.borrow().typ, Type::Alias(_, _)) + || matches!(type_alias.borrow().typ, Type::Error) + { + // Type alias to a type alias is not supported, but the error is handled in define_type_alias() + return Ok((DefinitionId::dummy_id(), item)); + } + Err(ResolverError::Expected { location, expected, got }) + } + _ => Err(ResolverError::Expected { location, expected, got }), + } } pub fn push_scope(&mut self) { diff --git a/compiler/noirc_frontend/src/elaborator/types.rs b/compiler/noirc_frontend/src/elaborator/types.rs index 68286210182..3fc7b27df57 100644 --- a/compiler/noirc_frontend/src/elaborator/types.rs +++ b/compiler/noirc_frontend/src/elaborator/types.rs @@ -104,12 +104,7 @@ impl Elaborator<'_> { kind: &Kind, wildcard_allowed: bool, ) -> Type { - self.resolve_type_with_kind_inner( - typ, - kind, - PathResolutionMode::MarkAsReferenced, - wildcard_allowed, - ) + self.resolve_type_inner(typ, kind, PathResolutionMode::MarkAsReferenced, wildcard_allowed) } /// Translates an UnresolvedType into a Type and appends any @@ -705,14 +700,19 @@ impl Elaborator<'_> { ) -> Type { match length { UnresolvedTypeExpression::Variable(path) => { + let mut ab = GenericTypeArgs::default(); + // Use generics from path, if they exist + if let Some(last_segment) = path.segments.last() { + if let Some(generics) = &last_segment.generics { + ab.ordered_args = generics.clone(); + } + } let path = self.validate_path(path); let mode = PathResolutionMode::MarkAsReferenced; - let typ = self.resolve_named_type( - path, - GenericTypeArgs::default(), - mode, - wildcard_allowed, - ); + let mut typ = self.resolve_named_type(path, ab, mode, wildcard_allowed); + if let Type::Alias(alias, vec) = typ { + typ = alias.borrow().get_type(&vec); + } self.check_kind(typ, expected_kind, location) } UnresolvedTypeExpression::Constant(int, suffix, _span) => { diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index bc3b94ea79a..5ed00a45e29 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -14,7 +14,7 @@ use crate::{Generics, Type}; use crate::hir::Context; use crate::hir::resolution::import::{ImportDirective, resolve_import}; -use crate::ast::{Expression, NoirEnumeration}; +use crate::ast::{Expression, NoirEnumeration, TypeAlias}; use crate::node_interner::{ FuncId, GlobalId, ModuleAttributes, NodeInterner, ReferenceId, TraitId, TraitImplId, TypeAliasId, TypeId, @@ -22,8 +22,8 @@ use crate::node_interner::{ use crate::ast::{ ExpressionKind, Ident, ItemVisibility, LetStatement, Literal, NoirFunction, NoirStruct, - NoirTrait, NoirTypeAlias, Path, PathSegment, UnresolvedGenerics, UnresolvedTraitConstraint, - UnresolvedType, UnsupportedNumericGenericType, + NoirTrait, Path, PathSegment, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, + UnsupportedNumericGenericType, }; use crate::elaborator::FrontendOptions; @@ -111,7 +111,7 @@ pub struct UnresolvedTypeAlias { pub file_id: FileId, pub crate_id: CrateId, pub module_id: LocalModuleId, - pub type_alias_def: NoirTypeAlias, + pub type_alias_def: TypeAlias, } #[derive(Debug, Clone)] diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index d6b2d1afb87..a0e99dafeb6 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -13,8 +13,8 @@ use rustc_hash::FxHashMap as HashMap; use crate::ast::{ Documented, Expression, FunctionDefinition, Ident, ItemVisibility, LetStatement, ModuleDeclaration, NoirEnumeration, NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, - NoirTypeAlias, Pattern, TraitImplItemKind, TraitItem, TypeImpl, UnresolvedType, - UnresolvedTypeData, desugar_generic_trait_bounds_and_reorder_where_clause, + Pattern, TraitImplItemKind, TraitItem, TypeAlias, TypeImpl, UnresolvedType, UnresolvedTypeData, + desugar_generic_trait_bounds_and_reorder_where_clause, }; use crate::elaborator::PrimitiveType; use crate::hir::resolution::errors::ResolverError; @@ -371,7 +371,7 @@ impl ModCollector<'_> { fn collect_type_aliases( &mut self, context: &mut Context, - type_aliases: Vec>, + type_aliases: Vec>, krate: CrateId, ) -> Vec { let mut errors: Vec = vec![]; diff --git a/compiler/noirc_frontend/src/hir/resolution/errors.rs b/compiler/noirc_frontend/src/hir/resolution/errors.rs index b05271d0cba..fe3d5cf9cc4 100644 --- a/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -168,6 +168,10 @@ pub enum ResolverError { UnexpectedItemInPattern { location: Location, item: &'static str }, #[error("Trait `{trait_name}` doesn't have a method named `{method_name}`")] NoSuchMethodInTrait { trait_name: String, method_name: String, location: Location }, + #[error("Cannot use a type alias inside a type alias")] + RecursiveTypeAlias { location: Location }, + #[error("expected numeric expressions, got {typ}")] + ExpectedNumericExpression { typ: String, location: Location }, #[error( "Indexing an array or slice with a type other than `u32` is deprecated and will soon be an error" )] @@ -238,7 +242,9 @@ impl ResolverError { | ResolverError::UnexpectedItemInPattern { location, .. } | ResolverError::NoSuchMethodInTrait { location, .. } | ResolverError::VariableAlreadyDefinedInPattern { new_location: location, .. } - | ResolverError::NonU32Index { location } + | ResolverError::ExpectedNumericExpression { location, .. } + | ResolverError::RecursiveTypeAlias { location } => *location, + ResolverError::NonU32Index { location } | ResolverError::NoPredicatesAttributeOnUnconstrained { location, .. } | ResolverError::FoldAttributeOnUnconstrained { location, .. } | ResolverError::OracleMarkedAsConstrained { location, .. } @@ -273,133 +279,133 @@ impl<'a> From<&'a ResolverError> for Diagnostic { fn from(error: &'a ResolverError) -> Diagnostic { match error { ResolverError::DuplicateDefinition { name, first_location, second_location} => { - let mut diag = Diagnostic::simple_error( - format!("duplicate definitions of {name} found"), - "second definition found here".to_string(), - *second_location, - ); - diag.add_secondary("first definition found here".to_string(), *first_location); - diag - } + let mut diag = Diagnostic::simple_error( + format!("duplicate definitions of {name} found"), + "second definition found here".to_string(), + *second_location, + ); + diag.add_secondary("first definition found here".to_string(), *first_location); + diag + } ResolverError::UnusedVariable { ident } => { - let mut diagnostic = Diagnostic::simple_warning( - format!("unused variable {ident}"), - "unused variable".to_string(), - ident.location(), - ); - diagnostic.unnecessary = true; - diagnostic - } + let mut diagnostic = Diagnostic::simple_warning( + format!("unused variable {ident}"), + "unused variable".to_string(), + ident.location(), + ); + diagnostic.unnecessary = true; + diagnostic + } ResolverError::UnusedItem { ident, item} => { - let item_type = item.item_type(); + let item_type = item.item_type(); - let mut diagnostic = - if let UnusedItem::Struct(..) = item { - Diagnostic::simple_warning( - format!("{item_type} `{ident}` is never constructed"), - format!("{item_type} is never constructed"), - ident.location(), - ) - } else { - Diagnostic::simple_warning( - format!("unused {item_type} {ident}"), - format!("unused {item_type}"), - ident.location(), - ) - }; - diagnostic.unnecessary = true; - diagnostic - } + let mut diagnostic = + if let UnusedItem::Struct(..) = item { + Diagnostic::simple_warning( + format!("{item_type} `{ident}` is never constructed"), + format!("{item_type} is never constructed"), + ident.location(), + ) + } else { + Diagnostic::simple_warning( + format!("unused {item_type} {ident}"), + format!("unused {item_type}"), + ident.location(), + ) + }; + diagnostic.unnecessary = true; + diagnostic + } ResolverError::UnconditionalRecursion { name, location} => { - Diagnostic::simple_warning( - format!("function `{name}` cannot return without recursing"), - "function cannot return without recursing".to_string(), - *location, - ) - } + Diagnostic::simple_warning( + format!("function `{name}` cannot return without recursing"), + "function cannot return without recursing".to_string(), + *location, + ) + } ResolverError::VariableNotDeclared { name, location } => { - if name == "_" { - Diagnostic::simple_error( - "in expressions, `_` can only be used on the left-hand side of an assignment".to_string(), - "`_` not allowed here".to_string(), - *location, - ) - } else { - Diagnostic::simple_error( - format!("cannot find `{name}` in this scope"), - "not found in this scope".to_string(), - *location, - ) - } - }, + if name == "_" { + Diagnostic::simple_error( + "in expressions, `_` can only be used on the left-hand side of an assignment".to_string(), + "`_` not allowed here".to_string(), + *location, + ) + } else { + Diagnostic::simple_error( + format!("cannot find `{name}` in this scope"), + "not found in this scope".to_string(), + *location, + ) + } + }, ResolverError::PathResolutionError(error) => error.into(), ResolverError::Expected { location, expected, got } => Diagnostic::simple_error( - format!("expected {expected} got {got}"), - String::new(), - *location, - ), + format!("expected {expected} got {got}"), + String::new(), + *location, + ), ResolverError::DuplicateField { field } => Diagnostic::simple_error( - format!("duplicate field {field}"), - String::new(), - field.location(), - ), + format!("duplicate field {field}"), + String::new(), + field.location(), + ), ResolverError::NoSuchField { field, struct_definition } => { - Diagnostic::simple_error( - format!("no such field {field} defined in struct {struct_definition}"), - String::new(), - field.location(), - ) - } + Diagnostic::simple_error( + format!("no such field {field} defined in struct {struct_definition}"), + String::new(), + field.location(), + ) + } ResolverError::MissingFields { location, missing_fields, struct_definition } => { - let plural = if missing_fields.len() != 1 { "s" } else { "" }; - let remaining_fields_names = match &missing_fields[..] { - [field1] => field1.clone(), - [field1, field2] => format!("{field1} and {field2}"), - [field1, field2, field3] => format!("{field1}, {field2} and {field3}"), - _ => { - let len = missing_fields.len() - 3; - let len_plural = if len != 1 {"s"} else {""}; + let plural = if missing_fields.len() != 1 { "s" } else { "" }; + let remaining_fields_names = match &missing_fields[..] { + [field1] => field1.clone(), + [field1, field2] => format!("{field1} and {field2}"), + [field1, field2, field3] => format!("{field1}, {field2} and {field3}"), + _ => { + let len = missing_fields.len() - 3; + let len_plural = if len != 1 {"s"} else {""}; - let truncated_fields = format!(" and {len} other field{len_plural}"); - let missing_fields = &missing_fields[0..3]; - format!("{}{truncated_fields}", missing_fields.join(", ")) - } - }; + let truncated_fields = format!(" and {len} other field{len_plural}"); + let missing_fields = &missing_fields[0..3]; + format!("{}{truncated_fields}", missing_fields.join(", ")) + } + }; - Diagnostic::simple_error( - format!("missing field{plural} {remaining_fields_names} in struct {struct_definition}"), - String::new(), - *location, - ) - } + Diagnostic::simple_error( + format!("missing field{plural} {remaining_fields_names} in struct {struct_definition}"), + String::new(), + *location, + ) + } ResolverError::UnnecessaryMut { first_mut, second_mut } => { - let mut error = Diagnostic::simple_error( - "'mut' here is not necessary".to_owned(), - "".to_owned(), - *second_mut, - ); - error.add_secondary( - "Pattern was already made mutable from this 'mut'".to_owned(), - *first_mut, - ); - error - } + let mut error = Diagnostic::simple_error( + "'mut' here is not necessary".to_owned(), + "".to_owned(), + *second_mut, + ); + error.add_secondary( + "Pattern was already made mutable from this 'mut'".to_owned(), + *first_mut, + ); + error + } ResolverError::UnnecessaryPub { ident, position } => { - let mut diag = Diagnostic::simple_error( - format!("unnecessary pub keyword on {position} for function {ident}"), - format!("unnecessary pub {position}"), - ident.location(), - ); + let mut diag = Diagnostic::simple_error( + format!("unnecessary pub keyword on {position} for function {ident}"), + format!("unnecessary pub {position}"), + ident.location(), + ); - diag.add_note("The `pub` keyword only has effects on arguments to the entry-point function of a program. Thus, adding it to other function parameters can be deceiving and should be removed".to_owned()); - diag - } + diag.add_note("The `pub` keyword only has effects on arguments to the entry-point function of a program. Thus, adding it to other function parameters can be deceiving and should be removed".to_owned()); + diag + } ResolverError::NecessaryPub { ident } => { - let mut diag = Diagnostic::simple_error( - format!("missing pub keyword on return type of function {ident}"), - "missing pub on return type".to_string(), - ident.location(), - ); + let mut diag = Diagnostic::simple_error( + format!("missing pub keyword on return type of function {ident}"), + "missing pub on return type".to_string(), + ident.location(), + ); diag.add_note("The `pub` keyword is mandatory for the entry-point function return type because the verifier cannot retrieve private witness and thus the function will not be able to return a 'priv' value".to_owned()); diag @@ -415,24 +421,24 @@ impl<'a> From<&'a ResolverError> for Diagnostic { *location, ), ResolverError::GenericsOnSelfType { location } => Diagnostic::simple_error( - "Cannot apply generics to Self type".into(), - "Use an explicit type name or apply the generics at the start of the impl instead".into(), - *location, - ), + "Cannot apply generics to Self type".into(), + "Use an explicit type name or apply the generics at the start of the impl instead".into(), + *location, + ), ResolverError::GenericsOnAssociatedType { location } => Diagnostic::simple_error( - "Generic Associated Types (GATs) are currently unsupported in Noir".into(), - "Cannot apply generics to an associated type".into(), - *location, - ), + "Generic Associated Types (GATs) are currently unsupported in Noir".into(), + "Cannot apply generics to an associated type".into(), + *location, + ), ResolverError::ParserError(error) => error.as_ref().into(), ResolverError::InvalidClosureEnvironment { location, typ } => Diagnostic::simple_error( - format!("{typ} is not a valid closure environment type"), - "Closure environment must be a tuple or unit type".to_string(), *location), + format!("{typ} is not a valid closure environment type"), + "Closure environment must be a tuple or unit type".to_string(), *location), ResolverError::NestedSlices { location } => Diagnostic::simple_error( - "Nested slices, i.e. slices within an array or slice, are not supported".into(), - "Try to use a constant sized array or BoundedVec instead".into(), - *location, - ), + "Nested slices, i.e. slices within an array or slice, are not supported".into(), + "Try to use a constant sized array or BoundedVec instead".into(), + *location, + ), ResolverError::AbiAttributeOutsideContract { location } => { Diagnostic::simple_error( "#[abi(tag)] attributes can only be used in contracts".to_string(), @@ -455,84 +461,84 @@ impl<'a> From<&'a ResolverError> for Diagnostic { diagnostic }, ResolverError::UnconstrainedOracleReturnToConstrained { location } => Diagnostic::simple_error( - error.to_string(), - "This oracle call must be wrapped in a call to another unconstrained function before being returned to a constrained runtime".into(), - *location, - ), + error.to_string(), + "This oracle call must be wrapped in a call to another unconstrained function before being returned to a constrained runtime".into(), + *location, + ), ResolverError::DependencyCycle { location, item, cycle } => { - Diagnostic::simple_error( - "Dependency cycle found".into(), - format!("'{item}' recursively depends on itself: {cycle}"), - *location, - ) - }, + Diagnostic::simple_error( + "Dependency cycle found".into(), + format!("'{item}' recursively depends on itself: {cycle}"), + *location, + ) + }, ResolverError::JumpInConstrainedFn { is_break, location } => { - let item = if *is_break { "break" } else { "continue" }; - Diagnostic::simple_error( - format!("{item} is only allowed in unconstrained functions"), - "Constrained code must always have a known number of loop iterations".into(), - *location, - ) - }, + let item = if *is_break { "break" } else { "continue" }; + Diagnostic::simple_error( + format!("{item} is only allowed in unconstrained functions"), + "Constrained code must always have a known number of loop iterations".into(), + *location, + ) + }, ResolverError::LoopInConstrainedFn { location } => { - Diagnostic::simple_error( - "`loop` is only allowed in unconstrained functions".into(), - "Constrained code must always have a known number of loop iterations".into(), - *location, - ) - }, + Diagnostic::simple_error( + "`loop` is only allowed in unconstrained functions".into(), + "Constrained code must always have a known number of loop iterations".into(), + *location, + ) + }, ResolverError::LoopWithoutBreak { location } => { - Diagnostic::simple_error( - "`loop` must have at least one `break` in it".into(), - "Infinite loops are disallowed".into(), - *location, - ) - }, + Diagnostic::simple_error( + "`loop` must have at least one `break` in it".into(), + "Infinite loops are disallowed".into(), + *location, + ) + }, ResolverError::WhileInConstrainedFn { location } => { - Diagnostic::simple_error( - "`while` is only allowed in unconstrained functions".into(), - "Constrained code must always have a known number of loop iterations".into(), - *location, - ) - }, + Diagnostic::simple_error( + "`while` is only allowed in unconstrained functions".into(), + "Constrained code must always have a known number of loop iterations".into(), + *location, + ) + }, ResolverError::JumpOutsideLoop { is_break, location } => { - let item = if *is_break { "break" } else { "continue" }; - Diagnostic::simple_error( - format!("{item} is only allowed within loops"), - "".into(), - *location, - ) - }, + let item = if *is_break { "break" } else { "continue" }; + Diagnostic::simple_error( + format!("{item} is only allowed within loops"), + "".into(), + *location, + ) + }, ResolverError::MutableGlobal { location } => { - Diagnostic::simple_error( - "Only `comptime` globals may be mutable".into(), - String::new(), - *location, - ) - }, + Diagnostic::simple_error( + "Only `comptime` globals may be mutable".into(), + String::new(), + *location, + ) + }, ResolverError::UnspecifiedGlobalType { pattern_location, expr_location, expected_type } => { - let mut diagnostic = Diagnostic::simple_error( - "Globals must have a specified type".to_string(), - String::new(), - *pattern_location, - ); - diagnostic.add_secondary(format!("Inferred type is `{expected_type}`"), *expr_location); - diagnostic - }, + let mut diagnostic = Diagnostic::simple_error( + "Globals must have a specified type".to_string(), + String::new(), + *pattern_location, + ); + diagnostic.add_secondary(format!("Inferred type is `{expected_type}`"), *expr_location); + diagnostic + }, ResolverError::UnevaluatedGlobalType { location } => { - Diagnostic::simple_error( - "Global failed to evaluate".to_string(), - String::new(), - *location, - ) - } + Diagnostic::simple_error( + "Global failed to evaluate".to_string(), + String::new(), + *location, + ) + } ResolverError::NegativeGlobalType { location, global_value } => { - Diagnostic::simple_error( - "Globals used in a type position must be non-negative".to_string(), - format!("But found value `{global_value:?}`"), - *location, - ) - } + Diagnostic::simple_error( + "Globals used in a type position must be non-negative".to_string(), + format!("But found value `{global_value:?}`"), + *location, + ) + } ResolverError::NonIntegralGlobalType { location, global_value } => { Diagnostic::simple_error( "Globals used in a type position must be integers".to_string(), @@ -575,89 +581,89 @@ impl<'a> From<&'a ResolverError> for Diagnostic { diag } ResolverError::UnquoteUsedOutsideQuote { location } => { - Diagnostic::simple_error( - "The unquote operator '$' can only be used within a quote expression".into(), - "".into(), - *location, - ) - }, + Diagnostic::simple_error( + "The unquote operator '$' can only be used within a quote expression".into(), + "".into(), + *location, + ) + }, ResolverError::InvalidSyntaxInMacroCall { location } => { - Diagnostic::simple_error( - "Invalid syntax in macro call".into(), - "Macro calls must call a comptime function directly, they cannot use higher-order functions".into(), - *location, - ) - }, + Diagnostic::simple_error( + "Invalid syntax in macro call".into(), + "Macro calls must call a comptime function directly, they cannot use higher-order functions".into(), + *location, + ) + }, ResolverError::MacroIsNotComptime { location } => { - Diagnostic::simple_error( - "This macro call is to a non-comptime function".into(), - "Macro calls must be to comptime functions".into(), - *location, - ) - }, + Diagnostic::simple_error( + "This macro call is to a non-comptime function".into(), + "Macro calls must be to comptime functions".into(), + *location, + ) + }, ResolverError::NonFunctionInAnnotation { location } => { - Diagnostic::simple_error( - "Unknown annotation".into(), - "The name of an annotation must refer to a comptime function".into(), - *location, - ) - }, + Diagnostic::simple_error( + "Unknown annotation".into(), + "The name of an annotation must refer to a comptime function".into(), + *location, + ) + }, ResolverError::MacroResultInGenericsListNotAGeneric { location, typ } => { - Diagnostic::simple_error( - format!("Type `{typ}` was inserted into a generics list from a macro, but it is not a generic"), - format!("Type `{typ}` is not a generic"), - *location, - ) - } + Diagnostic::simple_error( + format!("Type `{typ}` was inserted into a generics list from a macro, but it is not a generic"), + format!("Type `{typ}` is not a generic"), + *location, + ) + } ResolverError::NamedTypeArgs { location, item_kind } => { - Diagnostic::simple_error( - format!("Named type arguments aren't allowed on a {item_kind}"), - "Named type arguments are only allowed for associated types on traits".to_string(), - *location, - ) - } + Diagnostic::simple_error( + format!("Named type arguments aren't allowed on a {item_kind}"), + "Named type arguments are only allowed for associated types on traits".to_string(), + *location, + ) + } ResolverError::AssociatedConstantsMustBeNumeric { location } => { - Diagnostic::simple_error( - "Associated constants may only be a field or integer type".to_string(), - "Only numeric constants are allowed".to_string(), - *location, - ) - } + Diagnostic::simple_error( + "Associated constants may only be a field or integer type".to_string(), + "Only numeric constants are allowed".to_string(), + *location, + ) + } ResolverError::BinaryOpError { lhs, op, rhs, err, location } => { - Diagnostic::simple_error( - format!("Computing `{lhs} {op} {rhs}` failed with error {err}"), - String::new(), - *location, - ) - } + Diagnostic::simple_error( + format!("Computing `{lhs} {op} {rhs}` failed with error {err}"), + String::new(), + *location, + ) + } ResolverError::QuoteInRuntimeCode { location } => { - Diagnostic::simple_error( - "`quote` cannot be used in runtime code".to_string(), - "Wrap this in a `comptime` block or function to use it".to_string(), - *location, - ) - }, + Diagnostic::simple_error( + "`quote` cannot be used in runtime code".to_string(), + "Wrap this in a `comptime` block or function to use it".to_string(), + *location, + ) + }, ResolverError::ComptimeTypeInRuntimeCode { typ, location } => { - Diagnostic::simple_error( - format!("Comptime-only type `{typ}` cannot be used in runtime code"), - "Comptime-only type used here".to_string(), - *location, - ) - }, + Diagnostic::simple_error( + format!("Comptime-only type `{typ}` cannot be used in runtime code"), + "Comptime-only type used here".to_string(), + *location, + ) + }, ResolverError::MutatingComptimeInNonComptimeContext { name, location } => { - Diagnostic::simple_error( - format!("Comptime variable `{name}` cannot be mutated in a non-comptime context"), - format!("`{name}` mutated here"), - *location, - ) - }, + Diagnostic::simple_error( + format!("Comptime variable `{name}` cannot be mutated in a non-comptime context"), + format!("`{name}` mutated here"), + *location, + ) + }, ResolverError::InvalidInternedStatementInExpr { statement, location } => { - Diagnostic::simple_error( - format!("Failed to parse `{statement}` as an expression"), - "The statement was used from a macro here".to_string(), - *location, - ) - }, + Diagnostic::simple_error( + format!("Failed to parse `{statement}` as an expression"), + "The statement was used from a macro here".to_string(), + *location, + ) + }, ResolverError::UnsupportedNumericGenericType(err) => err.into(), ResolverError::TypeIsMorePrivateThenItem { typ, item, location } => { Diagnostic::simple_error( @@ -667,19 +673,19 @@ impl<'a> From<&'a ResolverError> for Diagnostic { ) }, ResolverError::AttributeFunctionIsNotAPath { function, location } => { - Diagnostic::simple_error( - format!("Attribute function `{function}` is not a path"), - "An attribute's function should be a single identifier or a path".into(), - *location, - ) - }, + Diagnostic::simple_error( + format!("Attribute function `{function}` is not a path"), + "An attribute's function should be a single identifier or a path".into(), + *location, + ) + }, ResolverError::AttributeFunctionNotInScope { name, location } => { - Diagnostic::simple_error( - format!("Attribute function `{name}` is not in scope"), - String::new(), - *location, - ) - }, + Diagnostic::simple_error( + format!("Attribute function `{name}` is not in scope"), + String::new(), + *location, + ) + }, ResolverError::TraitNotImplemented { impl_trait, missing_trait: the_trait, type_missing_trait: typ, location, missing_trait_location} => { let mut diagnostic = Diagnostic::simple_error( format!("The trait bound `{typ}: {the_trait}` is not satisfied"), @@ -689,47 +695,61 @@ impl<'a> From<&'a ResolverError> for Diagnostic { diagnostic }, ResolverError::ExpectedTrait { found, location } => { - Diagnostic::simple_error( - format!("Expected a trait, found {found}"), - String::new(), - *location) + Diagnostic::simple_error( + format!("Expected a trait, found {found}"), + String::new(), + *location) - } + } ResolverError::InvalidSyntaxInPattern { location } => { - Diagnostic::simple_error( - "Invalid syntax in match pattern".into(), - "Only literal, constructor, and variable patterns are allowed".into(), - *location) - }, + Diagnostic::simple_error( + "Invalid syntax in match pattern".into(), + "Only literal, constructor, and variable patterns are allowed".into(), + *location) + }, ResolverError::VariableAlreadyDefinedInPattern { existing, new_location } => { - let message = format!("Variable `{existing}` was already defined in the same match pattern"); - let secondary = format!("`{existing}` redefined here"); - let mut error = Diagnostic::simple_error(message, secondary, *new_location); - error.add_secondary(format!("`{existing}` was previously defined here"), existing.location()); - error - }, + let message = format!("Variable `{existing}` was already defined in the same match pattern"); + let secondary = format!("`{existing}` redefined here"); + let mut error = Diagnostic::simple_error(message, secondary, *new_location); + error.add_secondary(format!("`{existing}` was previously defined here"), existing.location()); + error + }, ResolverError::NonIntegerGlobalUsedInPattern { location } => { - let message = "Only integer or boolean globals can be used in match patterns".to_string(); - let secondary = "This global is not an integer or boolean".to_string(); - Diagnostic::simple_error(message, secondary, *location) - }, + let message = "Only integer or boolean globals can be used in match patterns".to_string(); + let secondary = "This global is not an integer or boolean".to_string(); + Diagnostic::simple_error(message, secondary, *location) + }, ResolverError::TypeUnsupportedInMatch { typ, location } => { - Diagnostic::simple_error( - format!("Cannot match on values of type `{typ}`"), - String::new(), - *location, - ) - }, + Diagnostic::simple_error( + format!("Cannot match on values of type `{typ}`"), + String::new(), + *location, + ) + }, ResolverError::UnexpectedItemInPattern { item, location } => { - Diagnostic::simple_error( - format!("Expected a struct, enum, or literal pattern, but found a {item}"), - String::new(), - *location, - ) - }, + Diagnostic::simple_error( + format!("Expected a struct, enum, or literal pattern, but found a {item}"), + String::new(), + *location, + ) + }, ResolverError::NoSuchMethodInTrait { trait_name, method_name, location } => { + Diagnostic::simple_error( + format!("Trait `{trait_name}` has no method named `{method_name}`"), + String::new(), + *location, + ) + }, + ResolverError::RecursiveTypeAlias { location } => { + Diagnostic::simple_error( + "Cannot use a type alias inside a type alias".to_string(), + String::new(), + *location, + ) + }, + ResolverError::ExpectedNumericExpression { typ, location } => { Diagnostic::simple_error( - format!("Trait `{trait_name}` has no method named `{method_name}`"), + format!("Expected a numeric expression, but got `{typ}`"), String::new(), *location, ) diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 8e0dbdc7fda..5e598e4d700 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -9,7 +9,7 @@ use proptest_derive::Arbitrary; use acvm::{AcirField, FieldElement}; use crate::{ - ast::{IntegerBitSize, ItemVisibility}, + ast::{BinaryOpKind, IntegerBitSize, ItemVisibility, UnresolvedTypeExpression}, hir::{ def_map::ModuleId, type_check::{TypeCheckError, generics::TraitGenerics}, @@ -713,6 +713,8 @@ pub struct TypeAlias { pub generics: Generics, pub visibility: ItemVisibility, pub location: Location, + /// Optional expression, used by type aliases to numeric generics + pub numeric_expr: Option, pub module_id: ModuleId, } @@ -756,13 +758,19 @@ impl TypeAlias { visibility: ItemVisibility, module_id: ModuleId, ) -> TypeAlias { - TypeAlias { id, typ, name, location, generics, visibility, module_id } + TypeAlias { id, typ, name, location, generics, visibility, module_id, numeric_expr: None } } - pub fn set_type_and_generics(&mut self, new_typ: Type, new_generics: Generics) { + pub fn set_type_and_generics( + &mut self, + new_typ: Type, + new_generics: Generics, + num_expr: Option, + ) { assert_eq!(self.typ, Type::Error); self.typ = new_typ; self.generics = new_generics; + self.numeric_expr = num_expr; } pub fn get_type(&self, generic_args: &[Type]) -> Type { @@ -860,6 +868,18 @@ pub enum BinaryTypeOperator { Modulo, } +impl BinaryTypeOperator { + pub fn operator_to_binary_op_kind_helper(&self) -> BinaryOpKind { + match self { + BinaryTypeOperator::Addition => BinaryOpKind::Add, + BinaryTypeOperator::Subtraction => BinaryOpKind::Subtract, + BinaryTypeOperator::Multiplication => BinaryOpKind::Multiply, + BinaryTypeOperator::Division => BinaryOpKind::Divide, + BinaryTypeOperator::Modulo => BinaryOpKind::Modulo, + } + } +} + /// A TypeVariable is a mutable reference that is either /// bound to some type, or unbound with a given TypeVariableId. #[derive(PartialEq, Eq, Clone, Hash, PartialOrd, Ord)] diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 75f14731ea8..c3bac23881b 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -16,6 +16,7 @@ use rustc_hash::FxHashMap as HashMap; use crate::QuotedType; use crate::ast::{ ExpressionKind, Ident, LValue, Pattern, StatementKind, UnaryOp, UnresolvedTypeData, + UnresolvedTypeExpression, }; use crate::graph::CrateId; use crate::hir::comptime; @@ -870,9 +871,15 @@ impl NodeInterner { f(value); } - pub fn set_type_alias(&mut self, type_id: TypeAliasId, typ: Type, generics: Generics) { + pub fn set_type_alias( + &mut self, + type_id: TypeAliasId, + typ: Type, + generics: Generics, + num_expr: Option, + ) { let type_alias_type = &mut self.type_aliases[type_id.0]; - type_alias_type.borrow_mut().set_type_and_generics(typ, generics); + type_alias_type.borrow_mut().set_type_and_generics(typ, generics, num_expr); } /// Returns the interned statement corresponding to `stmt_id` diff --git a/compiler/noirc_frontend/src/parser/mod.rs b/compiler/noirc_frontend/src/parser/mod.rs index e44c46188d6..72a9d30c302 100644 --- a/compiler/noirc_frontend/src/parser/mod.rs +++ b/compiler/noirc_frontend/src/parser/mod.rs @@ -13,7 +13,7 @@ mod parser; use crate::ast::{ Documented, Ident, ImportStatement, ItemVisibility, LetStatement, ModuleDeclaration, - NoirEnumeration, NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, TypeImpl, + NoirEnumeration, NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, TypeAlias, TypeImpl, UseTree, }; use crate::token::SecondaryAttribute; @@ -34,7 +34,7 @@ pub struct SortedModule { pub traits: Vec>, pub trait_impls: Vec, pub impls: Vec, - pub type_aliases: Vec>, + pub type_aliases: Vec>, pub globals: Vec<(Documented, ItemVisibility)>, /// Module declarations like `mod foo;` @@ -158,7 +158,7 @@ pub enum ItemKind { Trait(NoirTrait), TraitImpl(NoirTraitImpl), Impl(TypeImpl), - TypeAlias(NoirTypeAlias), + TypeAlias(TypeAlias), Global(LetStatement, ItemVisibility), ModuleDecl(ModuleDeclaration), Submodules(ParsedSubModule), @@ -264,7 +264,7 @@ impl SortedModule { self.impls.push(r#impl); } - fn push_type_alias(&mut self, type_alias: NoirTypeAlias, doc_comments: Vec) { + fn push_type_alias(&mut self, type_alias: TypeAlias, doc_comments: Vec) { self.type_aliases.push(Documented::new(type_alias, doc_comments)); } diff --git a/compiler/noirc_frontend/src/parser/parser/type_alias.rs b/compiler/noirc_frontend/src/parser/parser/type_alias.rs index 809651ede62..861c4c1f73d 100644 --- a/compiler/noirc_frontend/src/parser/parser/type_alias.rs +++ b/compiler/noirc_frontend/src/parser/parser/type_alias.rs @@ -1,7 +1,7 @@ use noirc_errors::Location; use crate::{ - ast::{ItemVisibility, NoirTypeAlias, UnresolvedType, UnresolvedTypeData}, + ast::{ItemVisibility, TypeAlias, UnresolvedType, UnresolvedTypeData}, token::Token, }; @@ -13,56 +13,68 @@ impl Parser<'_> { &mut self, visibility: ItemVisibility, start_location: Location, - ) -> NoirTypeAlias { + ) -> TypeAlias { + let location = self.location_at_previous_token_end(); let Some(name) = self.eat_ident() else { self.expected_identifier(); - let location = self.location_at_previous_token_end(); - return NoirTypeAlias { + return TypeAlias { visibility, name: self.unknown_ident_at_previous_token_end(), generics: Vec::new(), typ: UnresolvedType { typ: UnresolvedTypeData::Error, location }, location: start_location, + numeric_type: None, + numeric_location: Location::dummy(), }; }; - + // Optional numeric type for alias over numeric generics + let mut num_typ = None; let generics = self.parse_generics_disallowing_trait_bounds(); - - if !self.eat_assign() { + if self.eat_colon() { + // To specify a type alias on a numeric generic expression, we need to specify the type of the expression + // It must be a numeric type + num_typ = Some(self.parse_type_or_error()); + } + let mut expr_location = self.current_token_location; + let location; + let typ = if !self.eat_assign() { self.expected_token(Token::Assign); - - let location = self.location_since(start_location); + location = self.location_since(start_location); self.eat_semicolons(); + UnresolvedType { + typ: UnresolvedTypeData::Error, + location: self.location_at_previous_token_end(), + } + } else { + expr_location = self.current_token_location; + let typ = self.parse_type_or_type_expression().unwrap(); + location = self.location_since(start_location); + self.eat_semicolon_or_error(); + typ + }; + let numeric_location = self.location_since(expr_location); - return NoirTypeAlias { - visibility, - name, - generics, - typ: UnresolvedType { - typ: UnresolvedTypeData::Error, - location: self.location_at_previous_token_end(), - }, - location, - }; + TypeAlias { + visibility, + name, + generics, + typ, + location, + numeric_type: num_typ, + numeric_location, } - - let typ = self.parse_type_or_error(); - let location = self.location_since(start_location); - self.eat_semicolon_or_error(); - - NoirTypeAlias { visibility, name, generics, typ, location } } } #[cfg(test)] mod tests { use crate::{ - ast::NoirTypeAlias, + ast::TypeAlias, parse_program_with_dummy_file, parser::{ItemKind, parser::tests::expect_no_errors}, }; - fn parse_type_alias_no_errors(src: &str) -> NoirTypeAlias { + fn parse_type_alias_no_errors(src: &str) -> TypeAlias { let (mut module, errors) = parse_program_with_dummy_file(src); expect_no_errors(&errors); assert_eq!(module.items.len(), 1); @@ -89,4 +101,12 @@ mod tests { assert_eq!("Foo", alias.name.to_string()); assert_eq!(alias.generics.len(), 1); } + + #[test] + fn parse_numeric_generic_type_alias() { + let src = "type Double: u32 = N * 2;"; + let alias = parse_type_alias_no_errors(src); + assert_eq!("Double", alias.name.to_string()); + assert_eq!(alias.generics.len(), 1); + } } diff --git a/compiler/noirc_frontend/src/test_utils.rs b/compiler/noirc_frontend/src/test_utils.rs index a58a5088d64..edfbdd2a435 100644 --- a/compiler/noirc_frontend/src/test_utils.rs +++ b/compiler/noirc_frontend/src/test_utils.rs @@ -199,7 +199,13 @@ fn emit_compile_test(test_path: &str, src: &str, mut expect: Expect) { } } - let error_to_bug_cases = ["cast_negative_one_to_u8_size_checks"]; + let error_to_bug_cases = [ + "cast_negative_one_to_u8_size_checks", + "disallows_composing_numeric_type_aliases", + "disallows_numeric_type_aliases_to_expression_with_alias", + "disallows_numeric_type_aliases_to_expression_with_alias_2", + "disallows_numeric_type_aliases_to_type", + ]; if let Expect::Success = expect { if error_to_bug_cases .iter() diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index 203401f7726..e2412c3269a 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -134,6 +134,7 @@ fn check_errors_with_options( // // ~~~ error message let mut secondary_spans_with_errors: Vec<(Span, String)> = Vec::new(); + // The byte at the start of this line let mut byte = 0; // The length of the last line, needed to go back to the byte at the beginning of the last line @@ -158,7 +159,6 @@ fn check_errors_with_options( byte += line.len() + 1; // For '\n' last_line_length = line.len(); } - let mut primary_spans_with_errors: HashMap = primary_spans_with_errors.into_iter().collect(); @@ -206,7 +206,6 @@ fn check_errors_with_options( .unwrap_or_else(|| panic!("Expected {error:?} to have a secondary label")); let span = secondary.location.span; let message = &error.message; - let Some(expected_message) = primary_spans_with_errors.remove(&span) else { if let Some(message) = secondary_spans_with_errors.get(&span) { report_all(context.file_manager.as_file_map(), &errors, false, false); diff --git a/compiler/noirc_frontend/src/tests/aliases.rs b/compiler/noirc_frontend/src/tests/aliases.rs index 49fcfc38d98..d60b683b3cb 100644 --- a/compiler/noirc_frontend/src/tests/aliases.rs +++ b/compiler/noirc_frontend/src/tests/aliases.rs @@ -1,4 +1,4 @@ -use crate::assert_no_errors; +use crate::{assert_no_errors, check_errors}; #[named] #[test] @@ -95,6 +95,17 @@ fn double_generic_alias_in_path() { assert_no_errors!(src); } +#[named] +#[test] +fn identity_numeric_type_alias_works() { + let src = r#" + pub type Identity: u32 = N; + + fn main() {} + "#; + assert_no_errors!(src); +} + #[named] #[test] #[should_panic] @@ -105,6 +116,141 @@ fn self_referring_type_alias_is_not_allowed() { fn main() { let x: X = 1; } + "#; + assert_no_errors!(src); +} + +#[named] +#[test] +fn type_alias_to_numeric_generic() { + let src = r#" + type Double: u32 = N * 2; + fn main() { + let b: [u32; 6] = foo(); + assert(b[0] == 0); + } + fn foo() -> [u32;Double::] { + let mut a = [0;Double::]; + for i in 0..Double:: { + a[i] = i; + } + a + } + "#; + assert_no_errors!(src); +} + +#[named] +#[test] +fn disallows_composing_numeric_type_aliases() { + let src = r#" + type Double: u32 = N * 2; + type Quadruple: u32 = Double>; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Expected a numeric expression, but got `Double>` + fn main() { + let b: [u32; 12] = foo(); + ^^^ Type annotation needed + ~~~ Could not determine the value of the generic argument `N` declared on the function `foo` + assert(b[0] == 0); + } + fn foo() -> [u32;Quadruple::] { + let n = Double::; // To avoid the unused 'Double' error + let mut a = [0;Quadruple::]; + for i in 0..Quadruple:: { + a[i] = i + n; + } + a + } + "#; + check_errors!(src); +} + +#[named] +#[test] +fn disallows_numeric_type_aliases_to_expression_with_alias() { + let src = r#" + type Double: u32 = N * 2; + type Quadruple: u32 = Double::+Double::; + ^^^^^^^^^^^^^^^^^^^^^^^^ Cannot use a type alias inside a type alias + fn main() { + let b: [u32; 12] = foo(); + ^^^ Type annotation needed + ~~~ Could not determine the value of the generic argument `N` declared on the function `foo` + assert(b[0] == 0); + } + fn foo() -> [u32;Quadruple::] { + let n = Double::; // To avoid the unused 'Double' error + let mut a = [0;Quadruple::]; + for i in 0..Quadruple:: { + a[i] = i + n; + } + a + } + "#; + check_errors!(src); +} + +#[named] +#[test] +fn disallows_numeric_type_aliases_to_expression_with_alias_2() { + let src = r#" + type Double: u32 = N * 2; + type Quadruple: u32 = N*(Double::+3); + ^^^^^^^^^^^^^^^^^^ Cannot use a type alias inside a type alias + + fn main() { + let b: [u32; 12] = foo(); + ^^^ Type annotation needed + ~~~ Could not determine the value of the generic argument `N` declared on the function `foo` + assert(b[0] == 0); + } + fn foo() -> [u32;Quadruple::] { + let n = Double::; // To avoid the unused 'Double' error + let mut a = [0;Quadruple::]; + for i in 0..Quadruple:: { + a[i] = i + n; + } + a + } + "#; + check_errors!(src); +} + +#[named] +#[test] +fn disallows_numeric_type_aliases_to_type() { + let src = r#" + type Foo: u32 = u32; + ^^^ Type provided when a numeric generic was expected + ~~~ the numeric generic is not of type `u32` + + fn main(a: Foo) -> pub Foo { + a + } + "#; + check_errors!(src); +} + +#[named] +#[test] +fn type_alias_to_numeric_as_generic() { + let src = r#" + type Double: u32 = N * 2; + + pub struct Foo { + a: T, + b: [Field; N], + } + fn main(x: Field) { + let a = foo::<4>(x); + assert(a.a == x); + } + fn foo(x: Field) -> Foo> { + Foo { + a: x, + b: [1; Double::] + } + } "#; assert_no_errors!(src); } diff --git a/compiler/noirc_frontend/src/tests/visibility.rs b/compiler/noirc_frontend/src/tests/visibility.rs index e53c80c59e4..26bf54a7d7c 100644 --- a/compiler/noirc_frontend/src/tests/visibility.rs +++ b/compiler/noirc_frontend/src/tests/visibility.rs @@ -24,7 +24,7 @@ fn errors_if_type_alias_aliases_more_private_type() { let src = r#" struct Foo {} pub type Bar = Foo; - ^^^ Type `Foo` is more private than item `Bar` + ^^^^^^^^^^^^^^^^^^ Type `Foo` is more private than item `Bar` pub fn no_unused_warnings() { let _: Bar = Foo {}; } @@ -40,7 +40,7 @@ fn errors_if_type_alias_aliases_more_private_type_in_generic() { pub struct Generic { value: T } struct Foo {} pub type Bar = Generic; - ^^^^^^^^^^^^ Type `Foo` is more private than item `Bar` + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Type `Foo` is more private than item `Bar` pub fn no_unused_warnings() { let _ = Foo {}; let _: Bar = Generic { value: Foo {} }; @@ -58,7 +58,7 @@ fn errors_if_pub_type_alias_leaks_private_type_in_generic() { struct Bar {} pub struct Foo { pub value: T } pub type FooBar = Foo; - ^^^^^^^^ Type `Bar` is more private than item `FooBar` + ^^^^^^^^^^^^^^^^^^^^^^^^^^ Type `Bar` is more private than item `FooBar` pub fn no_unused_warnings() { let _: FooBar = Foo { value: Bar {} }; diff --git a/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_composing_numeric_type_aliases/Nargo.toml b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_composing_numeric_type_aliases/Nargo.toml new file mode 100644 index 00000000000..ad7a5b0c496 --- /dev/null +++ b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_composing_numeric_type_aliases/Nargo.toml @@ -0,0 +1,7 @@ + + [package] + name = "noirc_frontend_tests_aliases_disallows_composing_numeric_type_aliases" + type = "bin" + authors = [""] + + [dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_composing_numeric_type_aliases/src/main.nr b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_composing_numeric_type_aliases/src/main.nr new file mode 100644 index 00000000000..81a9948735e --- /dev/null +++ b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_composing_numeric_type_aliases/src/main.nr @@ -0,0 +1,16 @@ + + type Double: u32 = N * 2; + type Quadruple: u32 = Double>; + fn main() { + let b: [u32; 12] = foo(); + assert(b[0] == 0); + } + fn foo() -> [u32;Quadruple::] { + let n = Double::; // To avoid the unused 'Double' error + let mut a = [0;Quadruple::]; + for i in 0..Quadruple:: { + a[i] = i + n; + } + a + } + \ No newline at end of file diff --git a/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_composing_numeric_type_aliases/src_hash.txt b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_composing_numeric_type_aliases/src_hash.txt new file mode 100644 index 00000000000..8c0d6dc7e55 --- /dev/null +++ b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_composing_numeric_type_aliases/src_hash.txt @@ -0,0 +1 @@ +9312592120729157351 \ No newline at end of file diff --git a/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias/Nargo.toml b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias/Nargo.toml new file mode 100644 index 00000000000..142668a7b29 --- /dev/null +++ b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias/Nargo.toml @@ -0,0 +1,7 @@ + + [package] + name = "noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias" + type = "bin" + authors = [""] + + [dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias/src/main.nr b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias/src/main.nr new file mode 100644 index 00000000000..912f800af3c --- /dev/null +++ b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias/src/main.nr @@ -0,0 +1,16 @@ + + type Double: u32 = N * 2; + type Quadruple: u32 = Double::+Double::; + fn main() { + let b: [u32; 12] = foo(); + assert(b[0] == 0); + } + fn foo() -> [u32;Quadruple::] { + let n = Double::; // To avoid the unused 'Double' error + let mut a = [0;Quadruple::]; + for i in 0..Quadruple:: { + a[i] = i + n; + } + a + } + \ No newline at end of file diff --git a/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias/src_hash.txt b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias/src_hash.txt new file mode 100644 index 00000000000..14e6e062b34 --- /dev/null +++ b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias/src_hash.txt @@ -0,0 +1 @@ +11505745393982003357 \ No newline at end of file diff --git a/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias_2/Nargo.toml b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias_2/Nargo.toml new file mode 100644 index 00000000000..1528369ae04 --- /dev/null +++ b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias_2/Nargo.toml @@ -0,0 +1,7 @@ + + [package] + name = "noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias_2" + type = "bin" + authors = [""] + + [dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias_2/src/main.nr b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias_2/src/main.nr new file mode 100644 index 00000000000..82bb2f332f8 --- /dev/null +++ b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias_2/src/main.nr @@ -0,0 +1,17 @@ + + type Double: u32 = N * 2; + type Quadruple: u32 = N*(Double::+3); + + fn main() { + let b: [u32; 12] = foo(); + assert(b[0] == 0); + } + fn foo() -> [u32;Quadruple::] { + let n = Double::; // To avoid the unused 'Double' error + let mut a = [0;Quadruple::]; + for i in 0..Quadruple:: { + a[i] = i + n; + } + a + } + \ No newline at end of file diff --git a/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias_2/src_hash.txt b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias_2/src_hash.txt new file mode 100644 index 00000000000..8592e4b0737 --- /dev/null +++ b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias_2/src_hash.txt @@ -0,0 +1 @@ +2259100302281809625 \ No newline at end of file diff --git a/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_type/Nargo.toml b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_type/Nargo.toml new file mode 100644 index 00000000000..f4fe8074c90 --- /dev/null +++ b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_type/Nargo.toml @@ -0,0 +1,7 @@ + + [package] + name = "noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_type" + type = "bin" + authors = [""] + + [dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_type/src/main.nr b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_type/src/main.nr new file mode 100644 index 00000000000..e95c51cc26c --- /dev/null +++ b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_type/src/main.nr @@ -0,0 +1,7 @@ + + type Foo: u32 = u32; + + fn main(a: Foo) -> pub Foo { + a + } + \ No newline at end of file diff --git a/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_type/src_hash.txt b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_type/src_hash.txt new file mode 100644 index 00000000000..4093a978155 --- /dev/null +++ b/test_programs/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_type/src_hash.txt @@ -0,0 +1 @@ +14239910228341176700 \ No newline at end of file diff --git a/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_identity_numeric_type_alias_works/Nargo.toml b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_identity_numeric_type_alias_works/Nargo.toml new file mode 100644 index 00000000000..11f2261c3c8 --- /dev/null +++ b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_identity_numeric_type_alias_works/Nargo.toml @@ -0,0 +1,7 @@ + + [package] + name = "noirc_frontend_tests_aliases_identity_numeric_type_alias_works" + type = "bin" + authors = [""] + + [dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_identity_numeric_type_alias_works/src/main.nr b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_identity_numeric_type_alias_works/src/main.nr new file mode 100644 index 00000000000..ab32e9852a6 --- /dev/null +++ b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_identity_numeric_type_alias_works/src/main.nr @@ -0,0 +1,5 @@ + + pub type Identity: u32 = N; + + fn main() {} + \ No newline at end of file diff --git a/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_identity_numeric_type_alias_works/src_hash.txt b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_identity_numeric_type_alias_works/src_hash.txt new file mode 100644 index 00000000000..0a269cf05a7 --- /dev/null +++ b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_identity_numeric_type_alias_works/src_hash.txt @@ -0,0 +1 @@ +4880584451925734703 \ No newline at end of file diff --git a/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_as_generic/Nargo.toml b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_as_generic/Nargo.toml new file mode 100644 index 00000000000..91634c7ae07 --- /dev/null +++ b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_as_generic/Nargo.toml @@ -0,0 +1,7 @@ + + [package] + name = "noirc_frontend_tests_aliases_type_alias_to_numeric_as_generic" + type = "bin" + authors = [""] + + [dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_as_generic/src/main.nr b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_as_generic/src/main.nr new file mode 100644 index 00000000000..981c2d87830 --- /dev/null +++ b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_as_generic/src/main.nr @@ -0,0 +1,18 @@ + + type Double: u32 = N * 2; + + pub struct Foo { + a: T, + b: [Field; N], + } + fn main(x: Field) { + let a = foo::<4>(x); + assert(a.a == x); + } + fn foo(x: Field) -> Foo> { + Foo { + a: x, + b: [1; Double::] + } + } + \ No newline at end of file diff --git a/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_as_generic/src_hash.txt b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_as_generic/src_hash.txt new file mode 100644 index 00000000000..a91c5c20db7 --- /dev/null +++ b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_as_generic/src_hash.txt @@ -0,0 +1 @@ +9213057798705197017 \ No newline at end of file diff --git a/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_generic/Nargo.toml b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_generic/Nargo.toml new file mode 100644 index 00000000000..63a41ccc56d --- /dev/null +++ b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_generic/Nargo.toml @@ -0,0 +1,7 @@ + + [package] + name = "noirc_frontend_tests_aliases_type_alias_to_numeric_generic" + type = "bin" + authors = [""] + + [dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_generic/src/main.nr b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_generic/src/main.nr new file mode 100644 index 00000000000..969a1456d7b --- /dev/null +++ b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_generic/src/main.nr @@ -0,0 +1,14 @@ + + type Double: u32 = N * 2; + fn main() { + let b: [u32; 6] = foo(); + assert(b[0] == 0); + } + fn foo() -> [u32;Double::] { + let mut a = [0;Double::]; + for i in 0..Double:: { + a[i] = i; + } + a + } + \ No newline at end of file diff --git a/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_generic/src_hash.txt b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_generic/src_hash.txt new file mode 100644 index 00000000000..7adc0ec57e2 --- /dev/null +++ b/test_programs/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_generic/src_hash.txt @@ -0,0 +1 @@ +4319076876570430566 \ No newline at end of file diff --git a/test_programs/execution_success/numeric_type_alias/Nargo.toml b/test_programs/execution_success/numeric_type_alias/Nargo.toml new file mode 100644 index 00000000000..05011152804 --- /dev/null +++ b/test_programs/execution_success/numeric_type_alias/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "numeric_type_alias" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/numeric_type_alias/Prover.toml b/test_programs/execution_success/numeric_type_alias/Prover.toml new file mode 100644 index 00000000000..55cccb955a9 --- /dev/null +++ b/test_programs/execution_success/numeric_type_alias/Prover.toml @@ -0,0 +1,2 @@ +x = "3" + diff --git a/test_programs/execution_success/numeric_type_alias/src/main.nr b/test_programs/execution_success/numeric_type_alias/src/main.nr new file mode 100644 index 00000000000..737d6ab0c18 --- /dev/null +++ b/test_programs/execution_success/numeric_type_alias/src/main.nr @@ -0,0 +1,67 @@ +type Double: u32 = N * 2; + +fn main(x: Field) { + let mut m = new_matrix::<3, 4>(); + m.elements[3 * 2 + 3] = 10; + m.elements[3 * 2 + x as u32] = 5 + x; + assert(equal(m, m)); + let b = transpose(m); + assert(b.elements != m.elements); + assert(trace(b) != trace(m)); + assert(sum(b) == sum(m)); + + let a = test_2::<4>(x); + assert(a.len() == 1); +} + +fn test_2(x: Field) -> BoundedVec> { + let mut a = BoundedVec::new(); + a.push(x); + a +} + +type MSize: u32 = N * M; + +struct Matrix { + elements: [Field; MSize::], +} + +fn new_matrix() -> Matrix { + let mut a = [0; MSize::]; + Matrix { elements: a } +} + +fn trace(A: Matrix) -> Field { + let n = if N > M { M } else { N }; + let mut s = 0; + for i in 0..n { + s += A.elements[i * N + i]; + } + s +} + +fn sum(A: Matrix) -> Field { + let mut s = 0; + for i in 0..MSize:: { + s += A.elements[i]; + } + s +} + +fn equal(A: Matrix, B: Matrix) -> bool { + let mut s = true; + for i in 0..MSize:: { + s = s | (A.elements[i] == B.elements[i]); + } + s +} + +fn transpose(a: Matrix) -> Matrix { + let mut b = new_matrix::(); + for i in 0..N { + for j in 0..M { + b.elements[j * N + i] = a.elements[i * M + j]; + } + } + b +} diff --git a/tooling/lsp/src/requests/workspace_symbol.rs b/tooling/lsp/src/requests/workspace_symbol.rs index 7be8ea41ed0..8ca90944efe 100644 --- a/tooling/lsp/src/requests/workspace_symbol.rs +++ b/tooling/lsp/src/requests/workspace_symbol.rs @@ -16,7 +16,7 @@ use noirc_errors::{Location, Span}; use noirc_frontend::{ ast::{ Ident, LetStatement, NoirEnumeration, NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, - NoirTypeAlias, Pattern, TraitImplItemKind, TraitItem, TypeImpl, Visitor, + Pattern, TraitImplItemKind, TraitItem, TypeAlias, TypeImpl, Visitor, }, parser::ParsedSubModule, }; @@ -174,7 +174,7 @@ impl Visitor for WorkspaceSymbolGatherer<'_> { false } - fn visit_noir_type_alias(&mut self, alias: &NoirTypeAlias, _span: Span) -> bool { + fn visit_noir_type_alias(&mut self, alias: &TypeAlias, _span: Span) -> bool { self.push_symbol(&alias.name, SymbolKind::STRUCT); false } diff --git a/tooling/lsp/src/with_file.rs b/tooling/lsp/src/with_file.rs index 41bcc078566..a080947e529 100644 --- a/tooling/lsp/src/with_file.rs +++ b/tooling/lsp/src/with_file.rs @@ -10,9 +10,9 @@ use noirc_frontend::{ FunctionReturnType, GenericTypeArgs, Ident, IdentOrQuotedType, IfExpression, IndexExpression, InfixExpression, LValue, Lambda, LetStatement, Literal, MatchExpression, MemberAccessExpression, MethodCallExpression, ModuleDeclaration, NoirEnumeration, - NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, Param, Path, - PathSegment, Pattern, PrefixExpression, Statement, StatementKind, StructField, TraitBound, - TraitImplItem, TraitImplItemKind, TraitItem, TypeImpl, TypePath, UnresolvedGeneric, + NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, Param, Path, PathSegment, Pattern, + PrefixExpression, Statement, StatementKind, StructField, TraitBound, TraitImplItem, + TraitImplItemKind, TraitItem, TypeAlias, TypeImpl, TypePath, UnresolvedGeneric, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, UnsafeExpression, UseTree, UseTreeKind, WhileStatement, }, @@ -57,7 +57,7 @@ fn item_kind_with_file(item_kind: ItemKind, file: FileId) -> ItemKind { } ItemKind::Impl(type_impl) => ItemKind::Impl(type_impl_with_file(type_impl, file)), ItemKind::TypeAlias(noir_type_alias) => { - ItemKind::TypeAlias(noir_type_alias_with_file(noir_type_alias, file)) + ItemKind::TypeAlias(type_alias_with_file(noir_type_alias, file)) } ItemKind::Global(let_statement, item_visibility) => { ItemKind::Global(let_statement_with_file(let_statement, file), item_visibility) @@ -136,13 +136,17 @@ fn pattern_with_file(pattern: Pattern, file: FileId) -> Pattern { } } -fn noir_type_alias_with_file(noir_type_alias: NoirTypeAlias, file: FileId) -> NoirTypeAlias { - NoirTypeAlias { - name: ident_with_file(noir_type_alias.name, file), - generics: unresolved_generics_with_file(noir_type_alias.generics, file), - typ: unresolved_type_with_file(noir_type_alias.typ, file), - visibility: noir_type_alias.visibility, - location: location_with_file(noir_type_alias.location, file), +fn type_alias_with_file(type_alias: TypeAlias, file: FileId) -> TypeAlias { + TypeAlias { + name: ident_with_file(type_alias.name, file), + generics: unresolved_generics_with_file(type_alias.generics, file), + typ: unresolved_type_with_file(type_alias.typ, file), + visibility: type_alias.visibility, + location: location_with_file(type_alias.location, file), + numeric_type: type_alias + .numeric_type + .map(|num_type| unresolved_type_with_file(num_type, file)), + numeric_location: location_with_file(type_alias.numeric_location, file), } } diff --git a/tooling/nargo_cli/build.rs b/tooling/nargo_cli/build.rs index 1855b28463c..73a3851074e 100644 --- a/tooling/nargo_cli/build.rs +++ b/tooling/nargo_cli/build.rs @@ -154,19 +154,22 @@ const IGNORED_MINIMAL_EXECUTION_TESTS: [&str; 13] = [ /// might not be worth it. /// Others are ignored because of existing bugs in `nargo expand`. /// As the bugs are fixed these tests should be removed from this list. -const IGNORED_NARGO_EXPAND_EXECUTION_TESTS: [&str; 8] = [ +const IGNORED_NARGO_EXPAND_EXECUTION_TESTS: [&str; 10] = [ // There's nothing special about this program but making it work with a custom entry would involve // having to parse the Nargo.toml file, etc., which is not worth it "custom_entry", // There's no "src/main.nr" here so it's trickier to make this work "diamond_deps_0", // bug + "numeric_type_alias", "negative_associated_constants", // bug "regression_9116", // There's no "src/main.nr" here so it's trickier to make this work "overlapping_dep_and_mod", // bug + "regression_9116", + // bug "trait_associated_constant", // There's no "src/main.nr" here so it's trickier to make this work "workspace", @@ -212,7 +215,7 @@ const IGNORED_NARGO_EXPAND_COMPILE_SUCCESS_EMPTY_TESTS: [&str; 13] = [ /// These tests are ignored because of existing bugs in `nargo expand`. /// As the bugs are fixed these tests should be removed from this list. -const IGNORED_NARGO_EXPAND_COMPILE_SUCCESS_NO_BUG_TESTS: [&str; 15] = [ +const IGNORED_NARGO_EXPAND_COMPILE_SUCCESS_NO_BUG_TESTS: [&str; 18] = [ "noirc_frontend_tests_arithmetic_generics_checked_casts_do_not_prevent_canonicalization", "noirc_frontend_tests_check_trait_as_type_as_fn_parameter", "noirc_frontend_tests_check_trait_as_type_as_two_fn_parameters", @@ -226,6 +229,9 @@ const IGNORED_NARGO_EXPAND_COMPILE_SUCCESS_NO_BUG_TESTS: [&str; 15] = [ "noirc_frontend_tests_u32_globals_as_sizes_in_types", // This creates a struct at comptime which, expanded, gives a visibility error "noirc_frontend_tests_visibility_visibility_bug_inside_comptime", + "noirc_frontend_tests_aliases_identity_numeric_type_alias_works", + "noirc_frontend_tests_aliases_type_alias_to_numeric_as_generic", + "noirc_frontend_tests_aliases_type_alias_to_numeric_generic", // bug "noirc_frontend_tests_traits_associated_constant_sum_of_other_constants_3", "noirc_frontend_tests_traits_trait_where_clause_associated_type_constraint_expected_order", diff --git a/tooling/nargo_cli/tests/snapshots/compile_failure/associated_constants_do_not_accept_turbofish/execute__tests__stderr.snap b/tooling/nargo_cli/tests/snapshots/compile_failure/associated_constants_do_not_accept_turbofish/execute__tests__stderr.snap index e602029ae43..0dfbfd68a2d 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_failure/associated_constants_do_not_accept_turbofish/execute__tests__stderr.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_failure/associated_constants_do_not_accept_turbofish/execute__tests__stderr.snap @@ -2,18 +2,18 @@ source: tooling/nargo_cli/tests/execute.rs expression: stderr --- -error: Generic Associated Types (GATs) are currently unsupported in Noir - ┌─ src/main.nr:4:32 +error: Could not resolve 'Self' in path + ┌─ src/main.nr:4:25 │ 4 │ fn foo() -> [Field; Self::N::] { - │ ------- Cannot apply generics to an associated type + │ ---- │ -error: Generic Associated Types (GATs) are currently unsupported in Noir - ┌─ src/main.nr:5:20 +error: Could not resolve 'Self' in path + ┌─ src/main.nr:5:13 │ 5 │ [0; Self::N::] - │ ------- Cannot apply generics to an associated type + │ ---- │ Aborting due to 2 previous errors diff --git a/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_aliases_disallows_composing_numeric_type_aliases/execute__tests__stderr.snap b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_aliases_disallows_composing_numeric_type_aliases/execute__tests__stderr.snap new file mode 100644 index 00000000000..03d75d8af6c --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_aliases_disallows_composing_numeric_type_aliases/execute__tests__stderr.snap @@ -0,0 +1,19 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: stderr +--- +error: Expected a numeric expression, but got `Double>` + ┌─ src/main.nr:3:5 + │ +3 │ type Quadruple: u32 = Double>; + │ --------------------------------------------------- + │ + +error: Type annotation needed + ┌─ src/main.nr:5:28 + │ +5 │ let b: [u32; 12] = foo(); + │ --- Could not determine the value of the generic argument `N` declared on the function `foo` + │ + +Aborting due to 2 previous errors diff --git a/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias/execute__tests__stderr.snap b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias/execute__tests__stderr.snap new file mode 100644 index 00000000000..d4bb91fd409 --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias/execute__tests__stderr.snap @@ -0,0 +1,19 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: stderr +--- +error: Cannot use a type alias inside a type alias + ┌─ src/main.nr:3:39 + │ +3 │ type Quadruple: u32 = Double::+Double::; + │ ------------------------ + │ + +error: Type annotation needed + ┌─ src/main.nr:5:28 + │ +5 │ let b: [u32; 12] = foo(); + │ --- Could not determine the value of the generic argument `N` declared on the function `foo` + │ + +Aborting due to 2 previous errors diff --git a/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias_2/execute__tests__stderr.snap b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias_2/execute__tests__stderr.snap new file mode 100644 index 00000000000..efb2d13aa8e --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_expression_with_alias_2/execute__tests__stderr.snap @@ -0,0 +1,19 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: stderr +--- +error: Cannot use a type alias inside a type alias + ┌─ src/main.nr:3:39 + │ +3 │ type Quadruple: u32 = N*(Double::+3); + │ ------------------ + │ + +error: Type annotation needed + ┌─ src/main.nr:6:28 + │ +6 │ let b: [u32; 12] = foo(); + │ --- Could not determine the value of the generic argument `N` declared on the function `foo` + │ + +Aborting due to 2 previous errors diff --git a/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_type/execute__tests__stderr.snap b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_type/execute__tests__stderr.snap new file mode 100644 index 00000000000..1498c624af0 --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_aliases_disallows_numeric_type_aliases_to_type/execute__tests__stderr.snap @@ -0,0 +1,12 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: stderr +--- +error: Type provided when a numeric generic was expected + ┌─ src/main.nr:2:21 + │ +2 │ type Foo: u32 = u32; + │ --- the numeric generic is not of type `u32` + │ + +Aborting due to 1 previous error diff --git a/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_visibility_errors_if_pub_type_alias_leaks_private_type_in_generic/execute__tests__stderr.snap b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_visibility_errors_if_pub_type_alias_leaks_private_type_in_generic/execute__tests__stderr.snap index 99a25b18129..7aedbe61887 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_visibility_errors_if_pub_type_alias_leaks_private_type_in_generic/execute__tests__stderr.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_visibility_errors_if_pub_type_alias_leaks_private_type_in_generic/execute__tests__stderr.snap @@ -3,10 +3,10 @@ source: tooling/nargo_cli/tests/execute.rs expression: stderr --- error: Type `Bar` is more private than item `FooBar` - ┌─ src/main.nr:5:27 + ┌─ src/main.nr:5:9 │ 5 │ pub type FooBar = Foo; - │ -------- + │ -------------------------- │ Aborting due to 1 previous error diff --git a/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_visibility_errors_if_type_alias_aliases_more_private_type/execute__tests__stderr.snap b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_visibility_errors_if_type_alias_aliases_more_private_type/execute__tests__stderr.snap index 52ae789fe33..05b0f811d17 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_visibility_errors_if_type_alias_aliases_more_private_type/execute__tests__stderr.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_visibility_errors_if_type_alias_aliases_more_private_type/execute__tests__stderr.snap @@ -3,10 +3,10 @@ source: tooling/nargo_cli/tests/execute.rs expression: stderr --- error: Type `Foo` is more private than item `Bar` - ┌─ src/main.nr:3:20 + ┌─ src/main.nr:3:5 │ 3 │ pub type Bar = Foo; - │ --- + │ ------------------ │ Aborting due to 1 previous error diff --git a/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_visibility_errors_if_type_alias_aliases_more_private_type_in_generic/execute__tests__stderr.snap b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_visibility_errors_if_type_alias_aliases_more_private_type_in_generic/execute__tests__stderr.snap index 0ac3e3caafb..04347fc1cf1 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_visibility_errors_if_type_alias_aliases_more_private_type_in_generic/execute__tests__stderr.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_visibility_errors_if_type_alias_aliases_more_private_type_in_generic/execute__tests__stderr.snap @@ -3,10 +3,10 @@ source: tooling/nargo_cli/tests/execute.rs expression: stderr --- error: Type `Foo` is more private than item `Bar` - ┌─ src/main.nr:4:20 + ┌─ src/main.nr:4:5 │ 4 │ pub type Bar = Generic; - │ ------------ + │ --------------------------- │ Aborting due to 1 previous error diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_generic/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_generic/execute__tests__expanded.snap new file mode 100644 index 00000000000..3b197c73153 --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/compile_success_no_bug/noirc_frontend_tests_aliases_type_alias_to_numeric_generic/execute__tests__expanded.snap @@ -0,0 +1,18 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: expanded_code +--- +type Double = N * 2; + +fn main() { + let b: [u32; 6] = foo(); + assert(b[0_u32] == 0_u32); +} + +fn foo() -> [u32; N * 2] { + let mut a: [u32; N * 2] = [0_u32; N * 2]; + for i in 0_u32..N * 2_u32 { + a[i] = i; + } + a +} diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_false_inliner_-9223372036854775808.snap b/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_false_inliner_-9223372036854775808.snap new file mode 100644 index 00000000000..a0f63a4558c --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_false_inliner_-9223372036854775808.snap @@ -0,0 +1,153 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: artifact +--- +{ + "noir_version": "[noir_version]", + "hash": "[hash]", + "abi": { + "parameters": [ + { + "name": "x", + "type": { + "kind": "field" + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "5019202896831570965": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "14225679739041873922": { + "error_kind": "string", + "string": "Index out of bounds" + } + } + }, + "bytecode": [ + "func 0", + "current witness index : _73", + "private parameters indices : [_0]", + "public parameters indices : []", + "return value indices : []", + "BRILLIG CALL func 0: inputs: [EXPR [ (1, _0) 0 ], EXPR [ 4294967296 ]], outputs: [_1, _2]", + "BLACKBOX::RANGE [(_1, 222)] []", + "BLACKBOX::RANGE [(_2, 32)] []", + "EXPR [ (1, _0) (-4294967296, _1) (-1, _2) 0 ]", + "EXPR [ (-1, _1) (-1, _3) 5096253676302562286669017222071363378443840053029366383258766538131 ]", + "BLACKBOX::RANGE [(_3, 222)] []", + "BRILLIG CALL func 1: inputs: [EXPR [ (-1, _1) 5096253676302562286669017222071363378443840053029366383258766538131 ]], outputs: [_4]", + "EXPR [ (-1, _1, _4) (5096253676302562286669017222071363378443840053029366383258766538131, _4) (1, _5) -1 ]", + "EXPR [ (-1, _1, _5) (5096253676302562286669017222071363378443840053029366383258766538131, _5) 0 ]", + "EXPR [ (1, _2, _5) (268435455, _5) (-1, _6) 0 ]", + "BLACKBOX::RANGE [(_6, 32)] []", + "EXPR [ (1, _2) (-1, _7) 6 ]", + "BRILLIG CALL func 0: inputs: [EXPR [ (1, _7) 4294967284 ], EXPR [ 4294967296 ]], outputs: [_8, _9]", + "BLACKBOX::RANGE [(_9, 32)] []", + "EXPR [ (1, _7) (-4294967296, _8) (-1, _9) 4294967284 ]", + "EXPR [ (-1, _8) 0 ]", + "EXPR [ (-1, _10) 0 ]", + "EXPR [ (-1, _11) 10 ]", + "INIT (id: 0, len: 12, witnesses: [_10, _10, _10, _10, _10, _10, _10, _10, _10, _11, _10, _10])", + "EXPR [ (1, _0) (-1, _12) 5 ]", + "MEM (id: 0, write EXPR [ (1, _12) 0 ] at: EXPR [ (1, _7) 0 ]) ", + "MEM (id: 0, read at: EXPR [ (1, _10) 0 ], value: EXPR [ (1, _13) 0 ]) ", + "EXPR [ (-1, _14) 1 ]", + "MEM (id: 0, read at: EXPR [ (1, _14) 0 ], value: EXPR [ (1, _15) 0 ]) ", + "EXPR [ (-1, _16) 2 ]", + "MEM (id: 0, read at: EXPR [ (1, _16) 0 ], value: EXPR [ (1, _17) 0 ]) ", + "EXPR [ (-1, _18) 3 ]", + "MEM (id: 0, read at: EXPR [ (1, _18) 0 ], value: EXPR [ (1, _19) 0 ]) ", + "EXPR [ (-1, _20) 4 ]", + "MEM (id: 0, read at: EXPR [ (1, _20) 0 ], value: EXPR [ (1, _21) 0 ]) ", + "EXPR [ (-1, _22) 5 ]", + "MEM (id: 0, read at: EXPR [ (1, _22) 0 ], value: EXPR [ (1, _23) 0 ]) ", + "EXPR [ (-1, _24) 6 ]", + "MEM (id: 0, read at: EXPR [ (1, _24) 0 ], value: EXPR [ (1, _25) 0 ]) ", + "EXPR [ (-1, _26) 7 ]", + "MEM (id: 0, read at: EXPR [ (1, _26) 0 ], value: EXPR [ (1, _27) 0 ]) ", + "EXPR [ (-1, _28) 8 ]", + "MEM (id: 0, read at: EXPR [ (1, _28) 0 ], value: EXPR [ (1, _29) 0 ]) ", + "EXPR [ (-1, _30) 9 ]", + "MEM (id: 0, read at: EXPR [ (1, _30) 0 ], value: EXPR [ (1, _31) 0 ]) ", + "MEM (id: 0, read at: EXPR [ (1, _11) 0 ], value: EXPR [ (1, _32) 0 ]) ", + "EXPR [ (-1, _33) 11 ]", + "MEM (id: 0, read at: EXPR [ (1, _33) 0 ], value: EXPR [ (1, _34) 0 ]) ", + "EXPR [ (-1, _15) (1, _21) (-1, _35) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _35) 0 ]], outputs: [_36]", + "EXPR [ (1, _35, _36) (1, _37) -1 ]", + "EXPR [ (1, _35, _37) 0 ]", + "EXPR [ (-1, _17) (1, _29) (-1, _38) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _38) 0 ]], outputs: [_39]", + "EXPR [ (1, _38, _39) (1, _40) -1 ]", + "EXPR [ (1, _38, _40) 0 ]", + "EXPR [ (1, _15) (-1, _19) (-1, _41) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _41) 0 ]], outputs: [_42]", + "EXPR [ (1, _41, _42) (1, _43) -1 ]", + "EXPR [ (1, _41, _43) 0 ]", + "EXPR [ (1, _37, _40) (-1, _44) 0 ]", + "EXPR [ (-1, _21) (1, _23) (-1, _45) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _45) 0 ]], outputs: [_46]", + "EXPR [ (1, _45, _46) (1, _47) -1 ]", + "EXPR [ (1, _45, _47) 0 ]", + "EXPR [ (1, _43, _44) (-1, _48) 0 ]", + "EXPR [ (-1, _23) (1, _31) (-1, _49) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _49) 0 ]], outputs: [_50]", + "EXPR [ (1, _49, _50) (1, _51) -1 ]", + "EXPR [ (1, _49, _51) 0 ]", + "EXPR [ (1, _47, _48) (-1, _52) 0 ]", + "EXPR [ (1, _17) (-1, _25) (-1, _53) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _53) 0 ]], outputs: [_54]", + "EXPR [ (1, _53, _54) (1, _55) -1 ]", + "EXPR [ (1, _53, _55) 0 ]", + "EXPR [ (1, _51, _52) (-1, _56) 0 ]", + "EXPR [ (1, _25) (-1, _27) (-1, _57) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _57) 0 ]], outputs: [_58]", + "EXPR [ (1, _57, _58) (1, _59) -1 ]", + "EXPR [ (1, _57, _59) 0 ]", + "EXPR [ (1, _55, _56) (-1, _60) 0 ]", + "EXPR [ (-1, _29) (1, _32) (-1, _61) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _61) 0 ]], outputs: [_62]", + "EXPR [ (1, _61, _62) (1, _63) -1 ]", + "EXPR [ (1, _61, _63) 0 ]", + "EXPR [ (1, _59, _60) (-1, _64) 0 ]", + "EXPR [ (1, _19) (-1, _31) (-1, _65) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _65) 0 ]], outputs: [_66]", + "EXPR [ (1, _65, _66) (1, _67) -1 ]", + "EXPR [ (1, _65, _67) 0 ]", + "EXPR [ (1, _63, _64) (-1, _68) 0 ]", + "EXPR [ (1, _27) (-1, _32) (-1, _69) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _69) 0 ]], outputs: [_70]", + "EXPR [ (1, _69, _70) (1, _71) -1 ]", + "EXPR [ (1, _69, _71) 0 ]", + "EXPR [ (1, _67, _68) (-1, _72) 0 ]", + "EXPR [ (1, _71, _72) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (-1, _21) (1, _27) (-1, _29) (1, _31) 0 ]], outputs: [_73]", + "EXPR [ (-1, _21, _73) (1, _27, _73) (-1, _29, _73) (1, _31, _73) -1 ]", + "unconstrained func 0", + "[Const { destination: Direct(10), bit_size: Integer(U32), value: 2 }, Const { destination: Direct(11), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(0), size_address: Direct(10), offset_address: Direct(11) }, BinaryFieldOp { destination: Direct(2), op: IntegerDiv, lhs: Direct(0), rhs: Direct(1) }, BinaryFieldOp { destination: Direct(1), op: Mul, lhs: Direct(2), rhs: Direct(1) }, BinaryFieldOp { destination: Direct(1), op: Sub, lhs: Direct(0), rhs: Direct(1) }, Mov { destination: Direct(0), source: Direct(2) }, Stop { return_data: HeapVector { pointer: Direct(11), size: Direct(10) } }]", + "unconstrained func 1", + "[Const { destination: Direct(21), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(20), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(0), size_address: Direct(21), offset_address: Direct(20) }, Const { destination: Direct(2), bit_size: Field, value: 0 }, BinaryFieldOp { destination: Direct(3), op: Equals, lhs: Direct(0), rhs: Direct(2) }, JumpIf { condition: Direct(3), location: 8 }, Const { destination: Direct(1), bit_size: Field, value: 1 }, BinaryFieldOp { destination: Direct(0), op: Div, lhs: Direct(1), rhs: Direct(0) }, Stop { return_data: HeapVector { pointer: Direct(20), size: Direct(21) } }]" + ], + "debug_symbols": "tZbLbqswFEX/xWMGfh+7v3J1FZGEVEiIRBSudBXl32t8NiQdGFVUnXglmL04fmBxF+fmOL0f2v5y/RBvf+7iOLRd174fuuupHttrn67eH5VY/h7GoWnSJfHSn1K3emj6Ubz1U9dV4l/dTfmmj1vdZ471kHplJZr+nJiEl7Zr5l+P6pmW5aiSCmGl9Rp33887veS93JO39md5/8zHPXlj1rzakdcyIK91sX6/Nf64LoBTe1ZAryPQjkr5sDUCFReB1C9z+EUQywIKHnmKpfjm8+Xz+aYk2JoAWmZQU3ELKF0WxLWAaNyeFQjrCsTiHlL2Fwt4zkDcs4mNdMgbVR4AbZ0itJxBSoawpwS1lqDLJcRfLUGWSvib/tWndvhyeAuZprsSKrc6tya3Nrcutz63lNuQ28gphFM67R2V4ml7KMOwDMdIilSXIkZgxAwtGcmSFkdrhmFYhmN4BjECI2YYyWCLYYthi2GLYYthi2GLYYthi2WLZYtlizXzaiRa0IEeJDCAkekkqEANwufgc7Mv7X0Hn4PPwefg85Lv8/B5+Dx8Hj4Pn4fPw+fh8/ARfAQfwUfwEXwEH8FH8BF8BF+AL8AX4AvwBfgCfAG+AF+AL8AX4YsqH71x1qVDOs46/5hfgaGtj12Dj5DL1J9evknG/7elZ/lquQ3XU3OehmZ+BXJfeik+AQ==", + "file_map": { + "5": { + "source": "use crate::meta::derive_via;\n\n#[derive_via(derive_eq)]\n// docs:start:eq-trait\npub trait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\n// docs:start:derive_eq\ncomptime fn derive_eq(s: TypeDefinition) -> Quoted {\n let signature = quote { fn eq(_self: Self, _other: Self) -> bool };\n let for_each_field = |name| quote { (_self.$name == _other.$name) };\n let body = |fields| {\n if s.fields_as_written().len() == 0 {\n quote { true }\n } else {\n fields\n }\n };\n crate::meta::make_trait_impl(\n s,\n quote { $crate::cmp::Eq },\n signature,\n for_each_field,\n quote { & },\n body,\n )\n}\n// docs:end:derive_eq\n\nimpl Eq for Field {\n fn eq(self, other: Field) -> bool {\n self == other\n }\n}\n\nimpl Eq for u128 {\n fn eq(self, other: u128) -> bool {\n self == other\n }\n}\nimpl Eq for u64 {\n fn eq(self, other: u64) -> bool {\n self == other\n }\n}\nimpl Eq for u32 {\n fn eq(self, other: u32) -> bool {\n self == other\n }\n}\nimpl Eq for u16 {\n fn eq(self, other: u16) -> bool {\n self == other\n }\n}\nimpl Eq for u8 {\n fn eq(self, other: u8) -> bool {\n self == other\n }\n}\nimpl Eq for u1 {\n fn eq(self, other: u1) -> bool {\n self == other\n }\n}\n\nimpl Eq for i8 {\n fn eq(self, other: i8) -> bool {\n self == other\n }\n}\nimpl Eq for i16 {\n fn eq(self, other: i16) -> bool {\n self == other\n }\n}\nimpl Eq for i32 {\n fn eq(self, other: i32) -> bool {\n self == other\n }\n}\nimpl Eq for i64 {\n fn eq(self, other: i64) -> bool {\n self == other\n }\n}\n\nimpl Eq for () {\n fn eq(_self: Self, _other: ()) -> bool {\n true\n }\n}\nimpl Eq for bool {\n fn eq(self, other: bool) -> bool {\n self == other\n }\n}\n\nimpl Eq for [T; N]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for [T]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for str {\n fn eq(self, other: str) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\nimpl Eq for (A, B)\nwhere\n A: Eq,\n B: Eq,\n{\n fn eq(self, other: (A, B)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1)\n }\n}\n\nimpl Eq for (A, B, C)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n{\n fn eq(self, other: (A, B, C)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2)\n }\n}\n\nimpl Eq for (A, B, C, D)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n{\n fn eq(self, other: (A, B, C, D)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3)\n }\n}\n\nimpl Eq for (A, B, C, D, E)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n E: Eq,\n{\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0)\n & self.1.eq(other.1)\n & self.2.eq(other.2)\n & self.3.eq(other.3)\n & self.4.eq(other.4)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\npub struct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n#[derive_via(derive_ord)]\n// docs:start:ord-trait\npub trait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// docs:start:derive_ord\ncomptime fn derive_ord(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::cmp::Ord };\n let signature = quote { fn cmp(_self: Self, _other: Self) -> $crate::cmp::Ordering };\n let for_each_field = |name| quote {\n if result == $crate::cmp::Ordering::equal() {\n result = _self.$name.cmp(_other.$name);\n }\n };\n let body = |fields| quote {\n let mut result = $crate::cmp::Ordering::equal();\n $fields\n result\n };\n crate::meta::make_trait_impl(s, name, signature, for_each_field, quote {}, body)\n}\n// docs:end:derive_ord\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u128 {\n fn cmp(self, other: u128) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u16 {\n fn cmp(self, other: u16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i16 {\n fn cmp(self, other: i16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for [T; N]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for [T]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let mut result = self.len().cmp(other.len());\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for (A, B)\nwhere\n A: Ord,\n B: Ord,\n{\n fn cmp(self, other: (A, B)) -> Ordering {\n let result = self.0.cmp(other.0);\n\n if result != Ordering::equal() {\n result\n } else {\n self.1.cmp(other.1)\n }\n }\n}\n\nimpl Ord for (A, B, C)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n{\n fn cmp(self, other: (A, B, C)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n{\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D, E)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n E: Ord,\n{\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n if result == Ordering::equal() {\n result = self.4.cmp(other.4);\n }\n\n result\n }\n}\n\n// Compares and returns the maximum of two values.\n//\n// Returns the second argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::max(1, 2), 2);\n// assert_eq(cmp::max(2, 2), 2);\n// ```\npub fn max(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v1\n } else {\n v2\n }\n}\n\n// Compares and returns the minimum of two values.\n//\n// Returns the first argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::min(1, 2), 1);\n// assert_eq(cmp::min(2, 2), 2);\n// ```\npub fn min(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v2\n } else {\n v1\n }\n}\n\nmod cmp_tests {\n use crate::cmp::{max, min};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0_u64, 1), 0);\n assert_eq(min(0_u64, 0), 0);\n assert_eq(min(1_u64, 1), 1);\n assert_eq(min(255_u8, 0), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0_u64, 1), 1);\n assert_eq(max(0_u64, 0), 0);\n assert_eq(max(1_u64, 1), 1);\n assert_eq(max(255_u8, 0), 255);\n }\n}\n", + "path": "std/cmp.nr" + }, + "50": { + "source": "type Double: u32 = N * 2;\n\nfn main(x: Field) {\n let mut m = new_matrix::<3, 4>();\n m.elements[3 * 2 + 3] = 10;\n m.elements[3 * 2 + x as u32] = 5 + x;\n assert(equal(m, m));\n let b = transpose(m);\n assert(b.elements != m.elements);\n assert(trace(b) != trace(m));\n assert(sum(b) == sum(m));\n\n let a = test_2::<4>(x);\n assert(a.len() == 1);\n}\n\nfn test_2(x: Field) -> BoundedVec> {\n let mut a = BoundedVec::new();\n a.push(x);\n a\n}\n\ntype MSize: u32 = N * M;\n\nstruct Matrix {\n elements: [Field; MSize::],\n}\n\nfn new_matrix() -> Matrix {\n let mut a = [0; MSize::];\n Matrix { elements: a }\n}\n\nfn trace(A: Matrix) -> Field {\n let n = if N > M { M } else { N };\n let mut s = 0;\n for i in 0..n {\n s += A.elements[i * N + i];\n }\n s\n}\n\nfn sum(A: Matrix) -> Field {\n let mut s = 0;\n for i in 0..MSize:: {\n s += A.elements[i];\n }\n s\n}\n\nfn equal(A: Matrix, B: Matrix) -> bool {\n let mut s = true;\n for i in 0..MSize:: {\n s = s | (A.elements[i] == B.elements[i]);\n }\n s\n}\n\nfn transpose(a: Matrix) -> Matrix {\n let mut b = new_matrix::();\n for i in 0..N {\n for j in 0..M {\n b.elements[j * N + i] = a.elements[i * M + j];\n }\n }\n b\n}\n", + "path": "" + } + }, + "names": [ + "main" + ], + "brillig_names": [ + "directive_integer_quotient", + "directive_invert" + ] +} diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_false_inliner_0.snap b/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_false_inliner_0.snap new file mode 100644 index 00000000000..a0f63a4558c --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_false_inliner_0.snap @@ -0,0 +1,153 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: artifact +--- +{ + "noir_version": "[noir_version]", + "hash": "[hash]", + "abi": { + "parameters": [ + { + "name": "x", + "type": { + "kind": "field" + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "5019202896831570965": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "14225679739041873922": { + "error_kind": "string", + "string": "Index out of bounds" + } + } + }, + "bytecode": [ + "func 0", + "current witness index : _73", + "private parameters indices : [_0]", + "public parameters indices : []", + "return value indices : []", + "BRILLIG CALL func 0: inputs: [EXPR [ (1, _0) 0 ], EXPR [ 4294967296 ]], outputs: [_1, _2]", + "BLACKBOX::RANGE [(_1, 222)] []", + "BLACKBOX::RANGE [(_2, 32)] []", + "EXPR [ (1, _0) (-4294967296, _1) (-1, _2) 0 ]", + "EXPR [ (-1, _1) (-1, _3) 5096253676302562286669017222071363378443840053029366383258766538131 ]", + "BLACKBOX::RANGE [(_3, 222)] []", + "BRILLIG CALL func 1: inputs: [EXPR [ (-1, _1) 5096253676302562286669017222071363378443840053029366383258766538131 ]], outputs: [_4]", + "EXPR [ (-1, _1, _4) (5096253676302562286669017222071363378443840053029366383258766538131, _4) (1, _5) -1 ]", + "EXPR [ (-1, _1, _5) (5096253676302562286669017222071363378443840053029366383258766538131, _5) 0 ]", + "EXPR [ (1, _2, _5) (268435455, _5) (-1, _6) 0 ]", + "BLACKBOX::RANGE [(_6, 32)] []", + "EXPR [ (1, _2) (-1, _7) 6 ]", + "BRILLIG CALL func 0: inputs: [EXPR [ (1, _7) 4294967284 ], EXPR [ 4294967296 ]], outputs: [_8, _9]", + "BLACKBOX::RANGE [(_9, 32)] []", + "EXPR [ (1, _7) (-4294967296, _8) (-1, _9) 4294967284 ]", + "EXPR [ (-1, _8) 0 ]", + "EXPR [ (-1, _10) 0 ]", + "EXPR [ (-1, _11) 10 ]", + "INIT (id: 0, len: 12, witnesses: [_10, _10, _10, _10, _10, _10, _10, _10, _10, _11, _10, _10])", + "EXPR [ (1, _0) (-1, _12) 5 ]", + "MEM (id: 0, write EXPR [ (1, _12) 0 ] at: EXPR [ (1, _7) 0 ]) ", + "MEM (id: 0, read at: EXPR [ (1, _10) 0 ], value: EXPR [ (1, _13) 0 ]) ", + "EXPR [ (-1, _14) 1 ]", + "MEM (id: 0, read at: EXPR [ (1, _14) 0 ], value: EXPR [ (1, _15) 0 ]) ", + "EXPR [ (-1, _16) 2 ]", + "MEM (id: 0, read at: EXPR [ (1, _16) 0 ], value: EXPR [ (1, _17) 0 ]) ", + "EXPR [ (-1, _18) 3 ]", + "MEM (id: 0, read at: EXPR [ (1, _18) 0 ], value: EXPR [ (1, _19) 0 ]) ", + "EXPR [ (-1, _20) 4 ]", + "MEM (id: 0, read at: EXPR [ (1, _20) 0 ], value: EXPR [ (1, _21) 0 ]) ", + "EXPR [ (-1, _22) 5 ]", + "MEM (id: 0, read at: EXPR [ (1, _22) 0 ], value: EXPR [ (1, _23) 0 ]) ", + "EXPR [ (-1, _24) 6 ]", + "MEM (id: 0, read at: EXPR [ (1, _24) 0 ], value: EXPR [ (1, _25) 0 ]) ", + "EXPR [ (-1, _26) 7 ]", + "MEM (id: 0, read at: EXPR [ (1, _26) 0 ], value: EXPR [ (1, _27) 0 ]) ", + "EXPR [ (-1, _28) 8 ]", + "MEM (id: 0, read at: EXPR [ (1, _28) 0 ], value: EXPR [ (1, _29) 0 ]) ", + "EXPR [ (-1, _30) 9 ]", + "MEM (id: 0, read at: EXPR [ (1, _30) 0 ], value: EXPR [ (1, _31) 0 ]) ", + "MEM (id: 0, read at: EXPR [ (1, _11) 0 ], value: EXPR [ (1, _32) 0 ]) ", + "EXPR [ (-1, _33) 11 ]", + "MEM (id: 0, read at: EXPR [ (1, _33) 0 ], value: EXPR [ (1, _34) 0 ]) ", + "EXPR [ (-1, _15) (1, _21) (-1, _35) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _35) 0 ]], outputs: [_36]", + "EXPR [ (1, _35, _36) (1, _37) -1 ]", + "EXPR [ (1, _35, _37) 0 ]", + "EXPR [ (-1, _17) (1, _29) (-1, _38) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _38) 0 ]], outputs: [_39]", + "EXPR [ (1, _38, _39) (1, _40) -1 ]", + "EXPR [ (1, _38, _40) 0 ]", + "EXPR [ (1, _15) (-1, _19) (-1, _41) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _41) 0 ]], outputs: [_42]", + "EXPR [ (1, _41, _42) (1, _43) -1 ]", + "EXPR [ (1, _41, _43) 0 ]", + "EXPR [ (1, _37, _40) (-1, _44) 0 ]", + "EXPR [ (-1, _21) (1, _23) (-1, _45) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _45) 0 ]], outputs: [_46]", + "EXPR [ (1, _45, _46) (1, _47) -1 ]", + "EXPR [ (1, _45, _47) 0 ]", + "EXPR [ (1, _43, _44) (-1, _48) 0 ]", + "EXPR [ (-1, _23) (1, _31) (-1, _49) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _49) 0 ]], outputs: [_50]", + "EXPR [ (1, _49, _50) (1, _51) -1 ]", + "EXPR [ (1, _49, _51) 0 ]", + "EXPR [ (1, _47, _48) (-1, _52) 0 ]", + "EXPR [ (1, _17) (-1, _25) (-1, _53) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _53) 0 ]], outputs: [_54]", + "EXPR [ (1, _53, _54) (1, _55) -1 ]", + "EXPR [ (1, _53, _55) 0 ]", + "EXPR [ (1, _51, _52) (-1, _56) 0 ]", + "EXPR [ (1, _25) (-1, _27) (-1, _57) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _57) 0 ]], outputs: [_58]", + "EXPR [ (1, _57, _58) (1, _59) -1 ]", + "EXPR [ (1, _57, _59) 0 ]", + "EXPR [ (1, _55, _56) (-1, _60) 0 ]", + "EXPR [ (-1, _29) (1, _32) (-1, _61) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _61) 0 ]], outputs: [_62]", + "EXPR [ (1, _61, _62) (1, _63) -1 ]", + "EXPR [ (1, _61, _63) 0 ]", + "EXPR [ (1, _59, _60) (-1, _64) 0 ]", + "EXPR [ (1, _19) (-1, _31) (-1, _65) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _65) 0 ]], outputs: [_66]", + "EXPR [ (1, _65, _66) (1, _67) -1 ]", + "EXPR [ (1, _65, _67) 0 ]", + "EXPR [ (1, _63, _64) (-1, _68) 0 ]", + "EXPR [ (1, _27) (-1, _32) (-1, _69) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _69) 0 ]], outputs: [_70]", + "EXPR [ (1, _69, _70) (1, _71) -1 ]", + "EXPR [ (1, _69, _71) 0 ]", + "EXPR [ (1, _67, _68) (-1, _72) 0 ]", + "EXPR [ (1, _71, _72) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (-1, _21) (1, _27) (-1, _29) (1, _31) 0 ]], outputs: [_73]", + "EXPR [ (-1, _21, _73) (1, _27, _73) (-1, _29, _73) (1, _31, _73) -1 ]", + "unconstrained func 0", + "[Const { destination: Direct(10), bit_size: Integer(U32), value: 2 }, Const { destination: Direct(11), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(0), size_address: Direct(10), offset_address: Direct(11) }, BinaryFieldOp { destination: Direct(2), op: IntegerDiv, lhs: Direct(0), rhs: Direct(1) }, BinaryFieldOp { destination: Direct(1), op: Mul, lhs: Direct(2), rhs: Direct(1) }, BinaryFieldOp { destination: Direct(1), op: Sub, lhs: Direct(0), rhs: Direct(1) }, Mov { destination: Direct(0), source: Direct(2) }, Stop { return_data: HeapVector { pointer: Direct(11), size: Direct(10) } }]", + "unconstrained func 1", + "[Const { destination: Direct(21), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(20), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(0), size_address: Direct(21), offset_address: Direct(20) }, Const { destination: Direct(2), bit_size: Field, value: 0 }, BinaryFieldOp { destination: Direct(3), op: Equals, lhs: Direct(0), rhs: Direct(2) }, JumpIf { condition: Direct(3), location: 8 }, Const { destination: Direct(1), bit_size: Field, value: 1 }, BinaryFieldOp { destination: Direct(0), op: Div, lhs: Direct(1), rhs: Direct(0) }, Stop { return_data: HeapVector { pointer: Direct(20), size: Direct(21) } }]" + ], + "debug_symbols": "tZbLbqswFEX/xWMGfh+7v3J1FZGEVEiIRBSudBXl32t8NiQdGFVUnXglmL04fmBxF+fmOL0f2v5y/RBvf+7iOLRd174fuuupHttrn67eH5VY/h7GoWnSJfHSn1K3emj6Ubz1U9dV4l/dTfmmj1vdZ471kHplJZr+nJiEl7Zr5l+P6pmW5aiSCmGl9Rp33887veS93JO39md5/8zHPXlj1rzakdcyIK91sX6/Nf64LoBTe1ZAryPQjkr5sDUCFReB1C9z+EUQywIKHnmKpfjm8+Xz+aYk2JoAWmZQU3ELKF0WxLWAaNyeFQjrCsTiHlL2Fwt4zkDcs4mNdMgbVR4AbZ0itJxBSoawpwS1lqDLJcRfLUGWSvib/tWndvhyeAuZprsSKrc6tya3Nrcutz63lNuQ28gphFM67R2V4ml7KMOwDMdIilSXIkZgxAwtGcmSFkdrhmFYhmN4BjECI2YYyWCLYYthi2GLYYthi2GLYYthi2WLZYtlizXzaiRa0IEeJDCAkekkqEANwufgc7Mv7X0Hn4PPwefg85Lv8/B5+Dx8Hj4Pn4fPw+fh8/ARfAQfwUfwEXwEH8FH8BF8BF+AL8AX4AvwBfgCfAG+AF+AL8AX4YsqH71x1qVDOs46/5hfgaGtj12Dj5DL1J9evknG/7elZ/lquQ3XU3OehmZ+BXJfeik+AQ==", + "file_map": { + "5": { + "source": "use crate::meta::derive_via;\n\n#[derive_via(derive_eq)]\n// docs:start:eq-trait\npub trait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\n// docs:start:derive_eq\ncomptime fn derive_eq(s: TypeDefinition) -> Quoted {\n let signature = quote { fn eq(_self: Self, _other: Self) -> bool };\n let for_each_field = |name| quote { (_self.$name == _other.$name) };\n let body = |fields| {\n if s.fields_as_written().len() == 0 {\n quote { true }\n } else {\n fields\n }\n };\n crate::meta::make_trait_impl(\n s,\n quote { $crate::cmp::Eq },\n signature,\n for_each_field,\n quote { & },\n body,\n )\n}\n// docs:end:derive_eq\n\nimpl Eq for Field {\n fn eq(self, other: Field) -> bool {\n self == other\n }\n}\n\nimpl Eq for u128 {\n fn eq(self, other: u128) -> bool {\n self == other\n }\n}\nimpl Eq for u64 {\n fn eq(self, other: u64) -> bool {\n self == other\n }\n}\nimpl Eq for u32 {\n fn eq(self, other: u32) -> bool {\n self == other\n }\n}\nimpl Eq for u16 {\n fn eq(self, other: u16) -> bool {\n self == other\n }\n}\nimpl Eq for u8 {\n fn eq(self, other: u8) -> bool {\n self == other\n }\n}\nimpl Eq for u1 {\n fn eq(self, other: u1) -> bool {\n self == other\n }\n}\n\nimpl Eq for i8 {\n fn eq(self, other: i8) -> bool {\n self == other\n }\n}\nimpl Eq for i16 {\n fn eq(self, other: i16) -> bool {\n self == other\n }\n}\nimpl Eq for i32 {\n fn eq(self, other: i32) -> bool {\n self == other\n }\n}\nimpl Eq for i64 {\n fn eq(self, other: i64) -> bool {\n self == other\n }\n}\n\nimpl Eq for () {\n fn eq(_self: Self, _other: ()) -> bool {\n true\n }\n}\nimpl Eq for bool {\n fn eq(self, other: bool) -> bool {\n self == other\n }\n}\n\nimpl Eq for [T; N]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for [T]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for str {\n fn eq(self, other: str) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\nimpl Eq for (A, B)\nwhere\n A: Eq,\n B: Eq,\n{\n fn eq(self, other: (A, B)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1)\n }\n}\n\nimpl Eq for (A, B, C)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n{\n fn eq(self, other: (A, B, C)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2)\n }\n}\n\nimpl Eq for (A, B, C, D)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n{\n fn eq(self, other: (A, B, C, D)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3)\n }\n}\n\nimpl Eq for (A, B, C, D, E)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n E: Eq,\n{\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0)\n & self.1.eq(other.1)\n & self.2.eq(other.2)\n & self.3.eq(other.3)\n & self.4.eq(other.4)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\npub struct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n#[derive_via(derive_ord)]\n// docs:start:ord-trait\npub trait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// docs:start:derive_ord\ncomptime fn derive_ord(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::cmp::Ord };\n let signature = quote { fn cmp(_self: Self, _other: Self) -> $crate::cmp::Ordering };\n let for_each_field = |name| quote {\n if result == $crate::cmp::Ordering::equal() {\n result = _self.$name.cmp(_other.$name);\n }\n };\n let body = |fields| quote {\n let mut result = $crate::cmp::Ordering::equal();\n $fields\n result\n };\n crate::meta::make_trait_impl(s, name, signature, for_each_field, quote {}, body)\n}\n// docs:end:derive_ord\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u128 {\n fn cmp(self, other: u128) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u16 {\n fn cmp(self, other: u16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i16 {\n fn cmp(self, other: i16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for [T; N]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for [T]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let mut result = self.len().cmp(other.len());\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for (A, B)\nwhere\n A: Ord,\n B: Ord,\n{\n fn cmp(self, other: (A, B)) -> Ordering {\n let result = self.0.cmp(other.0);\n\n if result != Ordering::equal() {\n result\n } else {\n self.1.cmp(other.1)\n }\n }\n}\n\nimpl Ord for (A, B, C)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n{\n fn cmp(self, other: (A, B, C)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n{\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D, E)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n E: Ord,\n{\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n if result == Ordering::equal() {\n result = self.4.cmp(other.4);\n }\n\n result\n }\n}\n\n// Compares and returns the maximum of two values.\n//\n// Returns the second argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::max(1, 2), 2);\n// assert_eq(cmp::max(2, 2), 2);\n// ```\npub fn max(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v1\n } else {\n v2\n }\n}\n\n// Compares and returns the minimum of two values.\n//\n// Returns the first argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::min(1, 2), 1);\n// assert_eq(cmp::min(2, 2), 2);\n// ```\npub fn min(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v2\n } else {\n v1\n }\n}\n\nmod cmp_tests {\n use crate::cmp::{max, min};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0_u64, 1), 0);\n assert_eq(min(0_u64, 0), 0);\n assert_eq(min(1_u64, 1), 1);\n assert_eq(min(255_u8, 0), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0_u64, 1), 1);\n assert_eq(max(0_u64, 0), 0);\n assert_eq(max(1_u64, 1), 1);\n assert_eq(max(255_u8, 0), 255);\n }\n}\n", + "path": "std/cmp.nr" + }, + "50": { + "source": "type Double: u32 = N * 2;\n\nfn main(x: Field) {\n let mut m = new_matrix::<3, 4>();\n m.elements[3 * 2 + 3] = 10;\n m.elements[3 * 2 + x as u32] = 5 + x;\n assert(equal(m, m));\n let b = transpose(m);\n assert(b.elements != m.elements);\n assert(trace(b) != trace(m));\n assert(sum(b) == sum(m));\n\n let a = test_2::<4>(x);\n assert(a.len() == 1);\n}\n\nfn test_2(x: Field) -> BoundedVec> {\n let mut a = BoundedVec::new();\n a.push(x);\n a\n}\n\ntype MSize: u32 = N * M;\n\nstruct Matrix {\n elements: [Field; MSize::],\n}\n\nfn new_matrix() -> Matrix {\n let mut a = [0; MSize::];\n Matrix { elements: a }\n}\n\nfn trace(A: Matrix) -> Field {\n let n = if N > M { M } else { N };\n let mut s = 0;\n for i in 0..n {\n s += A.elements[i * N + i];\n }\n s\n}\n\nfn sum(A: Matrix) -> Field {\n let mut s = 0;\n for i in 0..MSize:: {\n s += A.elements[i];\n }\n s\n}\n\nfn equal(A: Matrix, B: Matrix) -> bool {\n let mut s = true;\n for i in 0..MSize:: {\n s = s | (A.elements[i] == B.elements[i]);\n }\n s\n}\n\nfn transpose(a: Matrix) -> Matrix {\n let mut b = new_matrix::();\n for i in 0..N {\n for j in 0..M {\n b.elements[j * N + i] = a.elements[i * M + j];\n }\n }\n b\n}\n", + "path": "" + } + }, + "names": [ + "main" + ], + "brillig_names": [ + "directive_integer_quotient", + "directive_invert" + ] +} diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_false_inliner_9223372036854775807.snap b/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_false_inliner_9223372036854775807.snap new file mode 100644 index 00000000000..a0f63a4558c --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_false_inliner_9223372036854775807.snap @@ -0,0 +1,153 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: artifact +--- +{ + "noir_version": "[noir_version]", + "hash": "[hash]", + "abi": { + "parameters": [ + { + "name": "x", + "type": { + "kind": "field" + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "5019202896831570965": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "14225679739041873922": { + "error_kind": "string", + "string": "Index out of bounds" + } + } + }, + "bytecode": [ + "func 0", + "current witness index : _73", + "private parameters indices : [_0]", + "public parameters indices : []", + "return value indices : []", + "BRILLIG CALL func 0: inputs: [EXPR [ (1, _0) 0 ], EXPR [ 4294967296 ]], outputs: [_1, _2]", + "BLACKBOX::RANGE [(_1, 222)] []", + "BLACKBOX::RANGE [(_2, 32)] []", + "EXPR [ (1, _0) (-4294967296, _1) (-1, _2) 0 ]", + "EXPR [ (-1, _1) (-1, _3) 5096253676302562286669017222071363378443840053029366383258766538131 ]", + "BLACKBOX::RANGE [(_3, 222)] []", + "BRILLIG CALL func 1: inputs: [EXPR [ (-1, _1) 5096253676302562286669017222071363378443840053029366383258766538131 ]], outputs: [_4]", + "EXPR [ (-1, _1, _4) (5096253676302562286669017222071363378443840053029366383258766538131, _4) (1, _5) -1 ]", + "EXPR [ (-1, _1, _5) (5096253676302562286669017222071363378443840053029366383258766538131, _5) 0 ]", + "EXPR [ (1, _2, _5) (268435455, _5) (-1, _6) 0 ]", + "BLACKBOX::RANGE [(_6, 32)] []", + "EXPR [ (1, _2) (-1, _7) 6 ]", + "BRILLIG CALL func 0: inputs: [EXPR [ (1, _7) 4294967284 ], EXPR [ 4294967296 ]], outputs: [_8, _9]", + "BLACKBOX::RANGE [(_9, 32)] []", + "EXPR [ (1, _7) (-4294967296, _8) (-1, _9) 4294967284 ]", + "EXPR [ (-1, _8) 0 ]", + "EXPR [ (-1, _10) 0 ]", + "EXPR [ (-1, _11) 10 ]", + "INIT (id: 0, len: 12, witnesses: [_10, _10, _10, _10, _10, _10, _10, _10, _10, _11, _10, _10])", + "EXPR [ (1, _0) (-1, _12) 5 ]", + "MEM (id: 0, write EXPR [ (1, _12) 0 ] at: EXPR [ (1, _7) 0 ]) ", + "MEM (id: 0, read at: EXPR [ (1, _10) 0 ], value: EXPR [ (1, _13) 0 ]) ", + "EXPR [ (-1, _14) 1 ]", + "MEM (id: 0, read at: EXPR [ (1, _14) 0 ], value: EXPR [ (1, _15) 0 ]) ", + "EXPR [ (-1, _16) 2 ]", + "MEM (id: 0, read at: EXPR [ (1, _16) 0 ], value: EXPR [ (1, _17) 0 ]) ", + "EXPR [ (-1, _18) 3 ]", + "MEM (id: 0, read at: EXPR [ (1, _18) 0 ], value: EXPR [ (1, _19) 0 ]) ", + "EXPR [ (-1, _20) 4 ]", + "MEM (id: 0, read at: EXPR [ (1, _20) 0 ], value: EXPR [ (1, _21) 0 ]) ", + "EXPR [ (-1, _22) 5 ]", + "MEM (id: 0, read at: EXPR [ (1, _22) 0 ], value: EXPR [ (1, _23) 0 ]) ", + "EXPR [ (-1, _24) 6 ]", + "MEM (id: 0, read at: EXPR [ (1, _24) 0 ], value: EXPR [ (1, _25) 0 ]) ", + "EXPR [ (-1, _26) 7 ]", + "MEM (id: 0, read at: EXPR [ (1, _26) 0 ], value: EXPR [ (1, _27) 0 ]) ", + "EXPR [ (-1, _28) 8 ]", + "MEM (id: 0, read at: EXPR [ (1, _28) 0 ], value: EXPR [ (1, _29) 0 ]) ", + "EXPR [ (-1, _30) 9 ]", + "MEM (id: 0, read at: EXPR [ (1, _30) 0 ], value: EXPR [ (1, _31) 0 ]) ", + "MEM (id: 0, read at: EXPR [ (1, _11) 0 ], value: EXPR [ (1, _32) 0 ]) ", + "EXPR [ (-1, _33) 11 ]", + "MEM (id: 0, read at: EXPR [ (1, _33) 0 ], value: EXPR [ (1, _34) 0 ]) ", + "EXPR [ (-1, _15) (1, _21) (-1, _35) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _35) 0 ]], outputs: [_36]", + "EXPR [ (1, _35, _36) (1, _37) -1 ]", + "EXPR [ (1, _35, _37) 0 ]", + "EXPR [ (-1, _17) (1, _29) (-1, _38) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _38) 0 ]], outputs: [_39]", + "EXPR [ (1, _38, _39) (1, _40) -1 ]", + "EXPR [ (1, _38, _40) 0 ]", + "EXPR [ (1, _15) (-1, _19) (-1, _41) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _41) 0 ]], outputs: [_42]", + "EXPR [ (1, _41, _42) (1, _43) -1 ]", + "EXPR [ (1, _41, _43) 0 ]", + "EXPR [ (1, _37, _40) (-1, _44) 0 ]", + "EXPR [ (-1, _21) (1, _23) (-1, _45) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _45) 0 ]], outputs: [_46]", + "EXPR [ (1, _45, _46) (1, _47) -1 ]", + "EXPR [ (1, _45, _47) 0 ]", + "EXPR [ (1, _43, _44) (-1, _48) 0 ]", + "EXPR [ (-1, _23) (1, _31) (-1, _49) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _49) 0 ]], outputs: [_50]", + "EXPR [ (1, _49, _50) (1, _51) -1 ]", + "EXPR [ (1, _49, _51) 0 ]", + "EXPR [ (1, _47, _48) (-1, _52) 0 ]", + "EXPR [ (1, _17) (-1, _25) (-1, _53) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _53) 0 ]], outputs: [_54]", + "EXPR [ (1, _53, _54) (1, _55) -1 ]", + "EXPR [ (1, _53, _55) 0 ]", + "EXPR [ (1, _51, _52) (-1, _56) 0 ]", + "EXPR [ (1, _25) (-1, _27) (-1, _57) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _57) 0 ]], outputs: [_58]", + "EXPR [ (1, _57, _58) (1, _59) -1 ]", + "EXPR [ (1, _57, _59) 0 ]", + "EXPR [ (1, _55, _56) (-1, _60) 0 ]", + "EXPR [ (-1, _29) (1, _32) (-1, _61) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _61) 0 ]], outputs: [_62]", + "EXPR [ (1, _61, _62) (1, _63) -1 ]", + "EXPR [ (1, _61, _63) 0 ]", + "EXPR [ (1, _59, _60) (-1, _64) 0 ]", + "EXPR [ (1, _19) (-1, _31) (-1, _65) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _65) 0 ]], outputs: [_66]", + "EXPR [ (1, _65, _66) (1, _67) -1 ]", + "EXPR [ (1, _65, _67) 0 ]", + "EXPR [ (1, _63, _64) (-1, _68) 0 ]", + "EXPR [ (1, _27) (-1, _32) (-1, _69) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (1, _69) 0 ]], outputs: [_70]", + "EXPR [ (1, _69, _70) (1, _71) -1 ]", + "EXPR [ (1, _69, _71) 0 ]", + "EXPR [ (1, _67, _68) (-1, _72) 0 ]", + "EXPR [ (1, _71, _72) 0 ]", + "BRILLIG CALL func 1: inputs: [EXPR [ (-1, _21) (1, _27) (-1, _29) (1, _31) 0 ]], outputs: [_73]", + "EXPR [ (-1, _21, _73) (1, _27, _73) (-1, _29, _73) (1, _31, _73) -1 ]", + "unconstrained func 0", + "[Const { destination: Direct(10), bit_size: Integer(U32), value: 2 }, Const { destination: Direct(11), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(0), size_address: Direct(10), offset_address: Direct(11) }, BinaryFieldOp { destination: Direct(2), op: IntegerDiv, lhs: Direct(0), rhs: Direct(1) }, BinaryFieldOp { destination: Direct(1), op: Mul, lhs: Direct(2), rhs: Direct(1) }, BinaryFieldOp { destination: Direct(1), op: Sub, lhs: Direct(0), rhs: Direct(1) }, Mov { destination: Direct(0), source: Direct(2) }, Stop { return_data: HeapVector { pointer: Direct(11), size: Direct(10) } }]", + "unconstrained func 1", + "[Const { destination: Direct(21), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(20), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(0), size_address: Direct(21), offset_address: Direct(20) }, Const { destination: Direct(2), bit_size: Field, value: 0 }, BinaryFieldOp { destination: Direct(3), op: Equals, lhs: Direct(0), rhs: Direct(2) }, JumpIf { condition: Direct(3), location: 8 }, Const { destination: Direct(1), bit_size: Field, value: 1 }, BinaryFieldOp { destination: Direct(0), op: Div, lhs: Direct(1), rhs: Direct(0) }, Stop { return_data: HeapVector { pointer: Direct(20), size: Direct(21) } }]" + ], + "debug_symbols": "tZbLbqswFEX/xWMGfh+7v3J1FZGEVEiIRBSudBXl32t8NiQdGFVUnXglmL04fmBxF+fmOL0f2v5y/RBvf+7iOLRd174fuuupHttrn67eH5VY/h7GoWnSJfHSn1K3emj6Ubz1U9dV4l/dTfmmj1vdZ471kHplJZr+nJiEl7Zr5l+P6pmW5aiSCmGl9Rp33887veS93JO39md5/8zHPXlj1rzakdcyIK91sX6/Nf64LoBTe1ZAryPQjkr5sDUCFReB1C9z+EUQywIKHnmKpfjm8+Xz+aYk2JoAWmZQU3ELKF0WxLWAaNyeFQjrCsTiHlL2Fwt4zkDcs4mNdMgbVR4AbZ0itJxBSoawpwS1lqDLJcRfLUGWSvib/tWndvhyeAuZprsSKrc6tya3Nrcutz63lNuQ28gphFM67R2V4ml7KMOwDMdIilSXIkZgxAwtGcmSFkdrhmFYhmN4BjECI2YYyWCLYYthi2GLYYthi2GLYYthi2WLZYtlizXzaiRa0IEeJDCAkekkqEANwufgc7Mv7X0Hn4PPwefg85Lv8/B5+Dx8Hj4Pn4fPw+fh8/ARfAQfwUfwEXwEH8FH8BF8BF+AL8AX4AvwBfgCfAG+AF+AL8AX4YsqH71x1qVDOs46/5hfgaGtj12Dj5DL1J9evknG/7elZ/lquQ3XU3OehmZ+BXJfeik+AQ==", + "file_map": { + "5": { + "source": "use crate::meta::derive_via;\n\n#[derive_via(derive_eq)]\n// docs:start:eq-trait\npub trait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\n// docs:start:derive_eq\ncomptime fn derive_eq(s: TypeDefinition) -> Quoted {\n let signature = quote { fn eq(_self: Self, _other: Self) -> bool };\n let for_each_field = |name| quote { (_self.$name == _other.$name) };\n let body = |fields| {\n if s.fields_as_written().len() == 0 {\n quote { true }\n } else {\n fields\n }\n };\n crate::meta::make_trait_impl(\n s,\n quote { $crate::cmp::Eq },\n signature,\n for_each_field,\n quote { & },\n body,\n )\n}\n// docs:end:derive_eq\n\nimpl Eq for Field {\n fn eq(self, other: Field) -> bool {\n self == other\n }\n}\n\nimpl Eq for u128 {\n fn eq(self, other: u128) -> bool {\n self == other\n }\n}\nimpl Eq for u64 {\n fn eq(self, other: u64) -> bool {\n self == other\n }\n}\nimpl Eq for u32 {\n fn eq(self, other: u32) -> bool {\n self == other\n }\n}\nimpl Eq for u16 {\n fn eq(self, other: u16) -> bool {\n self == other\n }\n}\nimpl Eq for u8 {\n fn eq(self, other: u8) -> bool {\n self == other\n }\n}\nimpl Eq for u1 {\n fn eq(self, other: u1) -> bool {\n self == other\n }\n}\n\nimpl Eq for i8 {\n fn eq(self, other: i8) -> bool {\n self == other\n }\n}\nimpl Eq for i16 {\n fn eq(self, other: i16) -> bool {\n self == other\n }\n}\nimpl Eq for i32 {\n fn eq(self, other: i32) -> bool {\n self == other\n }\n}\nimpl Eq for i64 {\n fn eq(self, other: i64) -> bool {\n self == other\n }\n}\n\nimpl Eq for () {\n fn eq(_self: Self, _other: ()) -> bool {\n true\n }\n}\nimpl Eq for bool {\n fn eq(self, other: bool) -> bool {\n self == other\n }\n}\n\nimpl Eq for [T; N]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for [T]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for str {\n fn eq(self, other: str) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\nimpl Eq for (A, B)\nwhere\n A: Eq,\n B: Eq,\n{\n fn eq(self, other: (A, B)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1)\n }\n}\n\nimpl Eq for (A, B, C)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n{\n fn eq(self, other: (A, B, C)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2)\n }\n}\n\nimpl Eq for (A, B, C, D)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n{\n fn eq(self, other: (A, B, C, D)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3)\n }\n}\n\nimpl Eq for (A, B, C, D, E)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n E: Eq,\n{\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0)\n & self.1.eq(other.1)\n & self.2.eq(other.2)\n & self.3.eq(other.3)\n & self.4.eq(other.4)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\npub struct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n#[derive_via(derive_ord)]\n// docs:start:ord-trait\npub trait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// docs:start:derive_ord\ncomptime fn derive_ord(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::cmp::Ord };\n let signature = quote { fn cmp(_self: Self, _other: Self) -> $crate::cmp::Ordering };\n let for_each_field = |name| quote {\n if result == $crate::cmp::Ordering::equal() {\n result = _self.$name.cmp(_other.$name);\n }\n };\n let body = |fields| quote {\n let mut result = $crate::cmp::Ordering::equal();\n $fields\n result\n };\n crate::meta::make_trait_impl(s, name, signature, for_each_field, quote {}, body)\n}\n// docs:end:derive_ord\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u128 {\n fn cmp(self, other: u128) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u16 {\n fn cmp(self, other: u16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i16 {\n fn cmp(self, other: i16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for [T; N]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for [T]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let mut result = self.len().cmp(other.len());\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for (A, B)\nwhere\n A: Ord,\n B: Ord,\n{\n fn cmp(self, other: (A, B)) -> Ordering {\n let result = self.0.cmp(other.0);\n\n if result != Ordering::equal() {\n result\n } else {\n self.1.cmp(other.1)\n }\n }\n}\n\nimpl Ord for (A, B, C)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n{\n fn cmp(self, other: (A, B, C)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n{\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D, E)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n E: Ord,\n{\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n if result == Ordering::equal() {\n result = self.4.cmp(other.4);\n }\n\n result\n }\n}\n\n// Compares and returns the maximum of two values.\n//\n// Returns the second argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::max(1, 2), 2);\n// assert_eq(cmp::max(2, 2), 2);\n// ```\npub fn max(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v1\n } else {\n v2\n }\n}\n\n// Compares and returns the minimum of two values.\n//\n// Returns the first argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::min(1, 2), 1);\n// assert_eq(cmp::min(2, 2), 2);\n// ```\npub fn min(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v2\n } else {\n v1\n }\n}\n\nmod cmp_tests {\n use crate::cmp::{max, min};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0_u64, 1), 0);\n assert_eq(min(0_u64, 0), 0);\n assert_eq(min(1_u64, 1), 1);\n assert_eq(min(255_u8, 0), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0_u64, 1), 1);\n assert_eq(max(0_u64, 0), 0);\n assert_eq(max(1_u64, 1), 1);\n assert_eq(max(255_u8, 0), 255);\n }\n}\n", + "path": "std/cmp.nr" + }, + "50": { + "source": "type Double: u32 = N * 2;\n\nfn main(x: Field) {\n let mut m = new_matrix::<3, 4>();\n m.elements[3 * 2 + 3] = 10;\n m.elements[3 * 2 + x as u32] = 5 + x;\n assert(equal(m, m));\n let b = transpose(m);\n assert(b.elements != m.elements);\n assert(trace(b) != trace(m));\n assert(sum(b) == sum(m));\n\n let a = test_2::<4>(x);\n assert(a.len() == 1);\n}\n\nfn test_2(x: Field) -> BoundedVec> {\n let mut a = BoundedVec::new();\n a.push(x);\n a\n}\n\ntype MSize: u32 = N * M;\n\nstruct Matrix {\n elements: [Field; MSize::],\n}\n\nfn new_matrix() -> Matrix {\n let mut a = [0; MSize::];\n Matrix { elements: a }\n}\n\nfn trace(A: Matrix) -> Field {\n let n = if N > M { M } else { N };\n let mut s = 0;\n for i in 0..n {\n s += A.elements[i * N + i];\n }\n s\n}\n\nfn sum(A: Matrix) -> Field {\n let mut s = 0;\n for i in 0..MSize:: {\n s += A.elements[i];\n }\n s\n}\n\nfn equal(A: Matrix, B: Matrix) -> bool {\n let mut s = true;\n for i in 0..MSize:: {\n s = s | (A.elements[i] == B.elements[i]);\n }\n s\n}\n\nfn transpose(a: Matrix) -> Matrix {\n let mut b = new_matrix::();\n for i in 0..N {\n for j in 0..M {\n b.elements[j * N + i] = a.elements[i * M + j];\n }\n }\n b\n}\n", + "path": "" + } + }, + "names": [ + "main" + ], + "brillig_names": [ + "directive_integer_quotient", + "directive_invert" + ] +} diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_true_inliner_-9223372036854775808.snap b/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_true_inliner_-9223372036854775808.snap new file mode 100644 index 00000000000..e801f4bd1a9 --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_true_inliner_-9223372036854775808.snap @@ -0,0 +1,73 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: artifact +--- +{ + "noir_version": "[noir_version]", + "hash": "[hash]", + "abi": { + "parameters": [ + { + "name": "x", + "type": { + "kind": "field" + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "5019202896831570965": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "5727012404371710682": { + "error_kind": "string", + "string": "push out of bounds" + }, + "12049594436772143978": { + "error_kind": "string", + "string": "array ref-count underflow detected" + }, + "14225679739041873922": { + "error_kind": "string", + "string": "Index out of bounds" + }, + "17843811134343075018": { + "error_kind": "string", + "string": "Stack too deep" + } + } + }, + "bytecode": [ + "func 0", + "current witness index : _0", + "private parameters indices : [_0]", + "public parameters indices : []", + "return value indices : []", + "BRILLIG CALL func 0: inputs: [EXPR [ (1, _0) 0 ]], outputs: []", + "unconstrained func 0", + "[Const { destination: Direct(2), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(1), bit_size: Integer(U32), value: 32843 }, Const { destination: Direct(0), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(2), bit_size: Integer(U32), value: 1 }, Const { destination: Relative(3), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(32842), size_address: Relative(2), offset_address: Relative(3) }, Mov { destination: Relative(1), source: Direct(32842) }, Call { location: 12 }, Call { location: 20 }, Const { destination: Relative(1), bit_size: Integer(U32), value: 32843 }, Const { destination: Relative(2), bit_size: Integer(U32), value: 0 }, Stop { return_data: HeapVector { pointer: Relative(1), size: Relative(2) } }, Const { destination: Direct(32835), bit_size: Integer(U32), value: 0 }, Const { destination: Direct(32836), bit_size: Field, value: 0 }, Const { destination: Direct(32837), bit_size: Integer(U1), value: 1 }, Const { destination: Direct(32838), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(32839), bit_size: Integer(U32), value: 3 }, Const { destination: Direct(32840), bit_size: Integer(U32), value: 4 }, Const { destination: Direct(32841), bit_size: Integer(U32), value: 12 }, Return, Call { location: 228 }, Const { destination: Relative(2), bit_size: Field, value: 10 }, Mov { destination: Relative(3), source: Direct(1) }, Const { destination: Relative(4), bit_size: Integer(U32), value: 13 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(4) }, IndirectConst { destination_pointer: Relative(3), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(4), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, Mov { destination: Relative(5), source: Relative(4) }, Store { destination_pointer: Relative(5), source: Direct(32836) }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(5), rhs: Direct(2) }, Store { destination_pointer: Relative(5), source: Direct(32836) }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(5), rhs: Direct(2) }, Store { destination_pointer: Relative(5), source: Direct(32836) }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(5), rhs: Direct(2) }, Store { destination_pointer: Relative(5), source: Direct(32836) }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(5), rhs: Direct(2) }, Store { destination_pointer: Relative(5), source: Direct(32836) }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(5), rhs: Direct(2) }, Store { destination_pointer: Relative(5), source: Direct(32836) }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(5), rhs: Direct(2) }, Store { destination_pointer: Relative(5), source: Direct(32836) }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(5), rhs: Direct(2) }, Store { destination_pointer: Relative(5), source: Direct(32836) }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(5), rhs: Direct(2) }, Store { destination_pointer: Relative(5), source: Direct(32836) }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(5), rhs: Direct(2) }, Store { destination_pointer: Relative(5), source: Relative(2) }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(5), rhs: Direct(2) }, Store { destination_pointer: Relative(5), source: Direct(32836) }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(5), rhs: Direct(2) }, Store { destination_pointer: Relative(5), source: Direct(32836) }, Cast { destination: Relative(4), source: Relative(1), bit_size: Integer(U32) }, Cast { destination: Relative(2), source: Relative(4), bit_size: Field }, Cast { destination: Relative(4), source: Relative(2), bit_size: Integer(U32) }, Const { destination: Relative(2), bit_size: Integer(U32), value: 6 }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(2), rhs: Relative(4) }, BinaryIntOp { destination: Relative(6), op: LessThanEquals, bit_size: U32, lhs: Relative(2), rhs: Relative(5) }, JumpIf { condition: Relative(6), location: 59 }, Call { location: 234 }, Const { destination: Relative(2), bit_size: Field, value: 5 }, BinaryFieldOp { destination: Relative(4), op: Add, lhs: Relative(2), rhs: Relative(1) }, BinaryIntOp { destination: Relative(2), op: LessThan, bit_size: U32, lhs: Relative(5), rhs: Direct(32841) }, JumpIf { condition: Relative(2), location: 64 }, Call { location: 237 }, Mov { destination: Direct(32771), source: Relative(3) }, Const { destination: Direct(32772), bit_size: Integer(U32), value: 13 }, Call { location: 240 }, Mov { destination: Relative(2), source: Direct(32773) }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(2), rhs: Direct(2) }, BinaryIntOp { destination: Relative(7), op: Add, bit_size: U32, lhs: Relative(6), rhs: Relative(5) }, Store { destination_pointer: Relative(7), source: Relative(4) }, Load { destination: Relative(3), source_pointer: Relative(2) }, Const { destination: Relative(4), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(5), op: Equals, bit_size: U32, lhs: Relative(4), rhs: Relative(3) }, Not { destination: Relative(5), source: Relative(5), bit_size: U1 }, JumpIf { condition: Relative(5), location: 77 }, Call { location: 262 }, BinaryIntOp { destination: Relative(3), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, Store { destination_pointer: Relative(2), source: Relative(3) }, Const { destination: Relative(5), bit_size: Integer(U32), value: 6 }, Mov { destination: Relative(6), source: Direct(0) }, Mov { destination: Relative(7), source: Relative(2) }, Mov { destination: Relative(8), source: Relative(2) }, BinaryIntOp { destination: Direct(0), op: Add, bit_size: U32, lhs: Direct(0), rhs: Relative(5) }, Call { location: 265 }, Mov { destination: Direct(0), source: Relative(0) }, Mov { destination: Relative(3), source: Relative(7) }, JumpIf { condition: Relative(3), location: 90 }, Const { destination: Relative(5), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(5) } }, Load { destination: Relative(3), source_pointer: Relative(2) }, Const { destination: Relative(5), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(6), op: Equals, bit_size: U32, lhs: Relative(5), rhs: Relative(3) }, Not { destination: Relative(6), source: Relative(6), bit_size: U1 }, JumpIf { condition: Relative(6), location: 96 }, Call { location: 262 }, BinaryIntOp { destination: Relative(3), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, Store { destination_pointer: Relative(2), source: Relative(3) }, Const { destination: Relative(6), bit_size: Integer(U32), value: 7 }, Mov { destination: Relative(7), source: Direct(0) }, Mov { destination: Relative(8), source: Relative(2) }, BinaryIntOp { destination: Direct(0), op: Add, bit_size: U32, lhs: Direct(0), rhs: Relative(6) }, Call { location: 289 }, Mov { destination: Direct(0), source: Relative(0) }, Mov { destination: Relative(3), source: Relative(8) }, Load { destination: Relative(6), source_pointer: Relative(3) }, Const { destination: Relative(7), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(8), op: Equals, bit_size: U32, lhs: Relative(7), rhs: Relative(6) }, Not { destination: Relative(8), source: Relative(8), bit_size: U1 }, JumpIf { condition: Relative(8), location: 111 }, Call { location: 262 }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, Store { destination_pointer: Relative(3), source: Relative(6) }, Load { destination: Relative(6), source_pointer: Relative(2) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(9), op: Equals, bit_size: U32, lhs: Relative(8), rhs: Relative(6) }, Not { destination: Relative(9), source: Relative(9), bit_size: U1 }, JumpIf { condition: Relative(9), location: 119 }, Call { location: 262 }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, Store { destination_pointer: Relative(2), source: Relative(6) }, Const { destination: Relative(9), bit_size: Integer(U32), value: 10 }, Mov { destination: Relative(10), source: Direct(0) }, Mov { destination: Relative(11), source: Relative(3) }, Mov { destination: Relative(12), source: Relative(2) }, BinaryIntOp { destination: Direct(0), op: Add, bit_size: U32, lhs: Direct(0), rhs: Relative(9) }, Call { location: 353 }, Mov { destination: Direct(0), source: Relative(0) }, Mov { destination: Relative(6), source: Relative(11) }, Const { destination: Relative(9), bit_size: Integer(U1), value: 0 }, BinaryIntOp { destination: Relative(10), op: Equals, bit_size: U1, lhs: Relative(6), rhs: Relative(9) }, JumpIf { condition: Relative(10), location: 134 }, Const { destination: Relative(11), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(11) } }, Load { destination: Relative(6), source_pointer: Relative(3) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(11), op: Equals, bit_size: U32, lhs: Relative(10), rhs: Relative(6) }, Not { destination: Relative(11), source: Relative(11), bit_size: U1 }, JumpIf { condition: Relative(11), location: 140 }, Call { location: 262 }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, Store { destination_pointer: Relative(3), source: Relative(6) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 12 }, Mov { destination: Relative(12), source: Direct(0) }, Mov { destination: Relative(13), source: Relative(3) }, BinaryIntOp { destination: Direct(0), op: Add, bit_size: U32, lhs: Direct(0), rhs: Relative(11) }, Call { location: 385 }, Mov { destination: Direct(0), source: Relative(0) }, Mov { destination: Relative(6), source: Relative(13) }, Load { destination: Relative(11), source_pointer: Relative(2) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(13), op: Equals, bit_size: U32, lhs: Relative(12), rhs: Relative(11) }, Not { destination: Relative(13), source: Relative(13), bit_size: U1 }, JumpIf { condition: Relative(13), location: 155 }, Call { location: 262 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(11), rhs: Direct(2) }, Store { destination_pointer: Relative(2), source: Relative(11) }, Const { destination: Relative(13), bit_size: Integer(U32), value: 14 }, Mov { destination: Relative(14), source: Direct(0) }, Mov { destination: Relative(15), source: Relative(2) }, BinaryIntOp { destination: Direct(0), op: Add, bit_size: U32, lhs: Direct(0), rhs: Relative(13) }, Call { location: 413 }, Mov { destination: Direct(0), source: Relative(0) }, Mov { destination: Relative(11), source: Relative(15) }, BinaryFieldOp { destination: Relative(13), op: Equals, lhs: Relative(6), rhs: Relative(11) }, BinaryIntOp { destination: Relative(6), op: Equals, bit_size: U1, lhs: Relative(13), rhs: Relative(9) }, JumpIf { condition: Relative(6), location: 169 }, Const { destination: Relative(11), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(11) } }, Const { destination: Relative(9), bit_size: Integer(U32), value: 13 }, Mov { destination: Relative(13), source: Direct(0) }, Mov { destination: Relative(14), source: Relative(3) }, BinaryIntOp { destination: Direct(0), op: Add, bit_size: U32, lhs: Direct(0), rhs: Relative(9) }, Call { location: 441 }, Mov { destination: Direct(0), source: Relative(0) }, Mov { destination: Relative(6), source: Relative(14) }, Const { destination: Relative(9), bit_size: Integer(U32), value: 13 }, Mov { destination: Relative(13), source: Direct(0) }, Mov { destination: Relative(14), source: Relative(2) }, BinaryIntOp { destination: Direct(0), op: Add, bit_size: U32, lhs: Direct(0), rhs: Relative(9) }, Call { location: 461 }, Mov { destination: Direct(0), source: Relative(0) }, Mov { destination: Relative(3), source: Relative(14) }, BinaryFieldOp { destination: Relative(2), op: Equals, lhs: Relative(6), rhs: Relative(3) }, JumpIf { condition: Relative(2), location: 187 }, Const { destination: Relative(9), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(9) } }, Mov { destination: Relative(2), source: Direct(1) }, Const { destination: Relative(3), bit_size: Integer(U32), value: 9 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(3) }, IndirectConst { destination_pointer: Relative(2), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(3), op: Add, bit_size: U32, lhs: Relative(2), rhs: Direct(2) }, Mov { destination: Relative(6), source: Relative(3) }, Store { destination_pointer: Relative(6), source: Direct(32836) }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Direct(32836) }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Direct(32836) }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Direct(32836) }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Direct(32836) }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Direct(32836) }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Direct(32836) }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Direct(32836) }, Mov { destination: Relative(3), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(3), source: Relative(2) }, Mov { destination: Relative(2), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(2), source: Direct(32835) }, Const { destination: Relative(6), bit_size: Integer(U32), value: 13 }, Mov { destination: Relative(13), source: Direct(0) }, Mov { destination: Relative(14), source: Relative(3) }, Mov { destination: Relative(15), source: Relative(2) }, Mov { destination: Relative(16), source: Relative(1) }, BinaryIntOp { destination: Direct(0), op: Add, bit_size: U32, lhs: Direct(0), rhs: Relative(6) }, Call { location: 481 }, Mov { destination: Direct(0), source: Relative(0) }, Load { destination: Relative(1), source_pointer: Relative(2) }, BinaryIntOp { destination: Relative(2), op: Equals, bit_size: U32, lhs: Relative(1), rhs: Direct(32838) }, JumpIf { condition: Relative(2), location: 227 }, Const { destination: Relative(3), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(3) } }, Return, Const { destination: Direct(32772), bit_size: Integer(U32), value: 30720 }, BinaryIntOp { destination: Direct(32771), op: LessThan, bit_size: U32, lhs: Direct(0), rhs: Direct(32772) }, JumpIf { condition: Direct(32771), location: 233 }, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 17843811134343075018 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 5019202896831570965 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 14225679739041873922 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return, Load { destination: Direct(32774), source_pointer: Direct(32771) }, BinaryIntOp { destination: Direct(32775), op: Equals, bit_size: U32, lhs: Direct(32774), rhs: Direct(2) }, JumpIf { condition: Direct(32775), location: 244 }, Jump { location: 246 }, Mov { destination: Direct(32773), source: Direct(32771) }, Jump { location: 261 }, Mov { destination: Direct(32773), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(32772) }, BinaryIntOp { destination: Direct(32777), op: Add, bit_size: U32, lhs: Direct(32771), rhs: Direct(32772) }, Mov { destination: Direct(32778), source: Direct(32771) }, Mov { destination: Direct(32779), source: Direct(32773) }, BinaryIntOp { destination: Direct(32780), op: Equals, bit_size: U32, lhs: Direct(32778), rhs: Direct(32777) }, JumpIf { condition: Direct(32780), location: 258 }, Load { destination: Direct(32776), source_pointer: Direct(32778) }, Store { destination_pointer: Direct(32779), source: Direct(32776) }, BinaryIntOp { destination: Direct(32778), op: Add, bit_size: U32, lhs: Direct(32778), rhs: Direct(2) }, BinaryIntOp { destination: Direct(32779), op: Add, bit_size: U32, lhs: Direct(32779), rhs: Direct(2) }, Jump { location: 251 }, IndirectConst { destination_pointer: Direct(32773), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Direct(32774), op: Sub, bit_size: U32, lhs: Direct(32774), rhs: Direct(2) }, Jump { location: 261 }, Return, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 12049594436772143978 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return, Call { location: 228 }, Mov { destination: Relative(4), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(4), source: Direct(32837) }, Mov { destination: Relative(3), source: Direct(32835) }, Jump { location: 271 }, BinaryIntOp { destination: Relative(5), op: LessThan, bit_size: U32, lhs: Relative(3), rhs: Direct(32841) }, JumpIf { condition: Relative(5), location: 276 }, Jump { location: 274 }, Load { destination: Relative(1), source_pointer: Relative(4) }, Return, Load { destination: Relative(5), source_pointer: Relative(4) }, BinaryIntOp { destination: Relative(7), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(7), rhs: Relative(3) }, Load { destination: Relative(6), source_pointer: Relative(8) }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(2), rhs: Direct(2) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(8), rhs: Relative(3) }, Load { destination: Relative(7), source_pointer: Relative(9) }, BinaryFieldOp { destination: Relative(8), op: Equals, lhs: Relative(6), rhs: Relative(7) }, BinaryIntOp { destination: Relative(6), op: Or, bit_size: U1, lhs: Relative(5), rhs: Relative(8) }, Store { destination_pointer: Relative(4), source: Relative(6) }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(32838) }, Mov { destination: Relative(3), source: Relative(5) }, Jump { location: 271 }, Call { location: 228 }, Mov { destination: Relative(3), source: Direct(1) }, Const { destination: Relative(4), bit_size: Integer(U32), value: 13 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(4) }, IndirectConst { destination_pointer: Relative(3), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(4), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, Const { destination: Relative(5), bit_size: Integer(U32), value: 12 }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(5), rhs: Relative(4) }, Mov { destination: Relative(6), source: Relative(4) }, BinaryIntOp { destination: Relative(7), op: LessThan, bit_size: U32, lhs: Relative(6), rhs: Relative(5) }, Not { destination: Relative(7), source: Relative(7), bit_size: U1 }, JumpIf { condition: Relative(7), location: 304 }, Store { destination_pointer: Relative(6), source: Direct(32836) }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, Jump { location: 298 }, Mov { destination: Relative(4), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(4), source: Relative(3) }, Mov { destination: Relative(2), source: Direct(32835) }, Jump { location: 309 }, BinaryIntOp { destination: Relative(3), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Direct(32839) }, JumpIf { condition: Relative(3), location: 314 }, Jump { location: 312 }, Load { destination: Relative(1), source_pointer: Relative(4) }, Return, BinaryIntOp { destination: Relative(5), op: Mul, bit_size: U32, lhs: Relative(2), rhs: Direct(32840) }, Mov { destination: Relative(3), source: Direct(32835) }, Jump { location: 317 }, BinaryIntOp { destination: Relative(6), op: LessThan, bit_size: U32, lhs: Relative(3), rhs: Direct(32840) }, JumpIf { condition: Relative(6), location: 323 }, Jump { location: 320 }, BinaryIntOp { destination: Relative(3), op: Add, bit_size: U32, lhs: Relative(2), rhs: Direct(32838) }, Mov { destination: Relative(2), source: Relative(3) }, Jump { location: 309 }, BinaryIntOp { destination: Relative(6), op: Mul, bit_size: U32, lhs: Relative(3), rhs: Direct(32839) }, BinaryIntOp { destination: Relative(7), op: Add, bit_size: U32, lhs: Relative(6), rhs: Relative(2) }, BinaryIntOp { destination: Relative(8), op: LessThanEquals, bit_size: U32, lhs: Relative(6), rhs: Relative(7) }, JumpIf { condition: Relative(8), location: 328 }, Call { location: 234 }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(5), rhs: Relative(3) }, BinaryIntOp { destination: Relative(8), op: LessThanEquals, bit_size: U32, lhs: Relative(5), rhs: Relative(6) }, JumpIf { condition: Relative(8), location: 332 }, Call { location: 234 }, BinaryIntOp { destination: Relative(8), op: LessThan, bit_size: U32, lhs: Relative(6), rhs: Direct(32841) }, JumpIf { condition: Relative(8), location: 335 }, Call { location: 237 }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Relative(6) }, Load { destination: Relative(8), source_pointer: Relative(10) }, Load { destination: Relative(6), source_pointer: Relative(4) }, BinaryIntOp { destination: Relative(9), op: LessThan, bit_size: U32, lhs: Relative(7), rhs: Direct(32841) }, JumpIf { condition: Relative(9), location: 342 }, Call { location: 237 }, Mov { destination: Direct(32771), source: Relative(6) }, Const { destination: Direct(32772), bit_size: Integer(U32), value: 13 }, Call { location: 240 }, Mov { destination: Relative(9), source: Direct(32773) }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(7) }, Store { destination_pointer: Relative(11), source: Relative(8) }, Store { destination_pointer: Relative(4), source: Relative(9) }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(32838) }, Mov { destination: Relative(3), source: Relative(6) }, Jump { location: 317 }, Call { location: 228 }, Mov { destination: Relative(4), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(4), source: Direct(32837) }, Load { destination: Relative(5), source_pointer: Relative(1) }, Const { destination: Relative(6), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(7), op: Equals, bit_size: U32, lhs: Relative(6), rhs: Relative(5) }, Not { destination: Relative(7), source: Relative(7), bit_size: U1 }, JumpIf { condition: Relative(7), location: 363 }, Call { location: 262 }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(5), rhs: Direct(2) }, Store { destination_pointer: Relative(1), source: Relative(5) }, Mov { destination: Relative(3), source: Direct(32835) }, Jump { location: 367 }, BinaryIntOp { destination: Relative(5), op: LessThan, bit_size: U32, lhs: Relative(3), rhs: Direct(32841) }, JumpIf { condition: Relative(5), location: 372 }, Jump { location: 370 }, Load { destination: Relative(1), source_pointer: Relative(4) }, Return, Load { destination: Relative(5), source_pointer: Relative(4) }, BinaryIntOp { destination: Relative(7), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(7), rhs: Relative(3) }, Load { destination: Relative(6), source_pointer: Relative(8) }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(2), rhs: Direct(2) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(8), rhs: Relative(3) }, Load { destination: Relative(7), source_pointer: Relative(9) }, BinaryFieldOp { destination: Relative(8), op: Equals, lhs: Relative(6), rhs: Relative(7) }, BinaryIntOp { destination: Relative(6), op: Mul, bit_size: U1, lhs: Relative(5), rhs: Relative(8) }, Store { destination_pointer: Relative(4), source: Relative(6) }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(32838) }, Mov { destination: Relative(3), source: Relative(5) }, Jump { location: 367 }, Call { location: 228 }, Mov { destination: Relative(3), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(3), source: Direct(32836) }, Mov { destination: Relative(2), source: Direct(32835) }, Jump { location: 391 }, BinaryIntOp { destination: Relative(4), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Direct(32839) }, JumpIf { condition: Relative(4), location: 396 }, Jump { location: 394 }, Load { destination: Relative(1), source_pointer: Relative(3) }, Return, Load { destination: Relative(4), source_pointer: Relative(3) }, BinaryIntOp { destination: Relative(5), op: Mul, bit_size: U32, lhs: Relative(2), rhs: Direct(32840) }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(5), rhs: Relative(2) }, BinaryIntOp { destination: Relative(7), op: LessThanEquals, bit_size: U32, lhs: Relative(5), rhs: Relative(6) }, JumpIf { condition: Relative(7), location: 402 }, Call { location: 234 }, BinaryIntOp { destination: Relative(5), op: LessThan, bit_size: U32, lhs: Relative(6), rhs: Direct(32841) }, JumpIf { condition: Relative(5), location: 405 }, Call { location: 237 }, BinaryIntOp { destination: Relative(7), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(7), rhs: Relative(6) }, Load { destination: Relative(5), source_pointer: Relative(8) }, BinaryFieldOp { destination: Relative(6), op: Add, lhs: Relative(4), rhs: Relative(5) }, Store { destination_pointer: Relative(3), source: Relative(6) }, BinaryIntOp { destination: Relative(4), op: Add, bit_size: U32, lhs: Relative(2), rhs: Direct(32838) }, Mov { destination: Relative(2), source: Relative(4) }, Jump { location: 391 }, Call { location: 228 }, Mov { destination: Relative(3), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(3), source: Direct(32836) }, Mov { destination: Relative(2), source: Direct(32835) }, Jump { location: 419 }, BinaryIntOp { destination: Relative(4), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Direct(32839) }, JumpIf { condition: Relative(4), location: 424 }, Jump { location: 422 }, Load { destination: Relative(1), source_pointer: Relative(3) }, Return, Load { destination: Relative(4), source_pointer: Relative(3) }, BinaryIntOp { destination: Relative(5), op: Mul, bit_size: U32, lhs: Relative(2), rhs: Direct(32839) }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(5), rhs: Relative(2) }, BinaryIntOp { destination: Relative(7), op: LessThanEquals, bit_size: U32, lhs: Relative(5), rhs: Relative(6) }, JumpIf { condition: Relative(7), location: 430 }, Call { location: 234 }, BinaryIntOp { destination: Relative(5), op: LessThan, bit_size: U32, lhs: Relative(6), rhs: Direct(32841) }, JumpIf { condition: Relative(5), location: 433 }, Call { location: 237 }, BinaryIntOp { destination: Relative(7), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(7), rhs: Relative(6) }, Load { destination: Relative(5), source_pointer: Relative(8) }, BinaryFieldOp { destination: Relative(6), op: Add, lhs: Relative(4), rhs: Relative(5) }, Store { destination_pointer: Relative(3), source: Relative(6) }, BinaryIntOp { destination: Relative(4), op: Add, bit_size: U32, lhs: Relative(2), rhs: Direct(32838) }, Mov { destination: Relative(2), source: Relative(4) }, Jump { location: 419 }, Call { location: 228 }, Mov { destination: Relative(3), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(3), source: Direct(32836) }, Mov { destination: Relative(2), source: Direct(32835) }, Jump { location: 447 }, BinaryIntOp { destination: Relative(4), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Direct(32841) }, JumpIf { condition: Relative(4), location: 452 }, Jump { location: 450 }, Load { destination: Relative(1), source_pointer: Relative(3) }, Return, Load { destination: Relative(4), source_pointer: Relative(3) }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, BinaryIntOp { destination: Relative(7), op: Add, bit_size: U32, lhs: Relative(6), rhs: Relative(2) }, Load { destination: Relative(5), source_pointer: Relative(7) }, BinaryFieldOp { destination: Relative(6), op: Add, lhs: Relative(4), rhs: Relative(5) }, Store { destination_pointer: Relative(3), source: Relative(6) }, BinaryIntOp { destination: Relative(4), op: Add, bit_size: U32, lhs: Relative(2), rhs: Direct(32838) }, Mov { destination: Relative(2), source: Relative(4) }, Jump { location: 447 }, Call { location: 228 }, Mov { destination: Relative(3), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(3), source: Direct(32836) }, Mov { destination: Relative(2), source: Direct(32835) }, Jump { location: 467 }, BinaryIntOp { destination: Relative(4), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Direct(32841) }, JumpIf { condition: Relative(4), location: 472 }, Jump { location: 470 }, Load { destination: Relative(1), source_pointer: Relative(3) }, Return, Load { destination: Relative(4), source_pointer: Relative(3) }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, BinaryIntOp { destination: Relative(7), op: Add, bit_size: U32, lhs: Relative(6), rhs: Relative(2) }, Load { destination: Relative(5), source_pointer: Relative(7) }, BinaryFieldOp { destination: Relative(6), op: Add, lhs: Relative(4), rhs: Relative(5) }, Store { destination_pointer: Relative(3), source: Relative(6) }, BinaryIntOp { destination: Relative(4), op: Add, bit_size: U32, lhs: Relative(2), rhs: Direct(32838) }, Mov { destination: Relative(2), source: Relative(4) }, Jump { location: 467 }, Call { location: 228 }, Load { destination: Relative(4), source_pointer: Relative(2) }, Const { destination: Relative(5), bit_size: Integer(U32), value: 8 }, BinaryIntOp { destination: Relative(6), op: LessThan, bit_size: U32, lhs: Relative(4), rhs: Relative(5) }, JumpIf { condition: Relative(6), location: 487 }, Call { location: 502 }, Load { destination: Relative(5), source_pointer: Relative(1) }, Mov { destination: Direct(32771), source: Relative(5) }, Const { destination: Direct(32772), bit_size: Integer(U32), value: 9 }, Call { location: 240 }, Mov { destination: Relative(6), source: Direct(32773) }, BinaryIntOp { destination: Relative(7), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(7), rhs: Relative(4) }, Store { destination_pointer: Relative(8), source: Relative(3) }, BinaryIntOp { destination: Relative(3), op: Add, bit_size: U32, lhs: Relative(4), rhs: Direct(32838) }, BinaryIntOp { destination: Relative(5), op: LessThanEquals, bit_size: U32, lhs: Relative(4), rhs: Relative(3) }, JumpIf { condition: Relative(5), location: 499 }, Call { location: 234 }, Store { destination_pointer: Relative(1), source: Relative(6) }, Store { destination_pointer: Relative(2), source: Relative(3) }, Return, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 5727012404371710682 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return]" + ], + "debug_symbols": "tZnLbhs5EEX/RWsvSFbxUfmVIAgcRwkMCLah2AMMAv/78HbVbTkLBwaF2egeqbsuX8VHt34fvh+/vfz8ev/w4/HX4dPn34dv5/vT6f7n19Pj3e3z/ePD/PX3IeGj5MOnfHMoxUVc1KW6NJfuMlxsE0ku7iLuIu4i7iLuIu4i7iLuIu6i7qLuou6i7qLuou6i7qLuou6i7lLdpU6XMqW4iMt0kSnVpbl0l+EyXfTm0JJLdiku4jJd6pTq0ly6y3CxTXpyyS7FRVzcpbtLd5fuLt1d+nRpN4eRXLJLcREXdakuzaW7DBd3MXcxdzF3MXcxdzF3MXcxd7Hp0qfYJjml0BxaQiVUQ2toC+2hIzT8cvjl8Mvhl8Mvh18Ovxx+Ofxy+OXwK+GHjB7QEiqhGlpDW2gPHaHmitTeNPwk/CT8JPwk/CT8JPwk/CT8NPw0/JDmBpVQDa2hLbSHjlBzRbpvmkPDr4ZfDb8afjX8kPU5AQbBApD7DplQCELAfMyASmiEThgEOM/plzEfHDKhEISghEqAswA6YRAsAHPEIRMKAc4KUEIlNAKckTaYMw4WgHnjkAmFIAQlVEIj0NnobOFcUiJkQiEIQQmV0AidAOcGsABMKodMKAQhwHkAKqEROmEQLADTyyETCgHOBlBCJbQAJElJgE4YAUiJsm0wM7wUQOMvuFkAg2ABGPeigEwoBKz5FUBDjLtDC8DgFvQhBtehEISghEpohE4YBHOQlAiZUAhCgHMDVEIjwGdgS0WUAbB3JQD2q22bTXEJPS8FgHsEUAmN0AnY5xRgAVjiHDKhEISgBDhXQCN0wiBYABY7h0xgc7DeOSihEhqhEwbBAirbvm3p6LFtU9+gEVAx9PO2tW9gAVjiHDKhEISgBPpg+RIMSufNWLUE1UDSOlTCrIZivJC9DoOAMwbGa9AQ2etQCAjHeGFpchgByFXFWBjbjoT0X3Az+hkJqdslc1AkpEMmFIIQlDBboR3QCJ0wvFBFim6A1cZBvYaKJcWhEcxrqFgutpuRq/5L9TorcnUrHbnqMAhshbAVwlYIW4Fc3WqIXHVgKyRSQrdc3YCtQELqAAhBCd3XH0WyqQEKf8EZLgGUUAmNN3fCCGgsq7GsxrIay+osq7OszrI6y+osq7OszrI6y0Ii1e1wjPACUEIlNEIn4OCJ8cL2twFWSIdMKAQhKAHOGFMkpEMnDII5VCRk1dfXmwOfR74+n49HPI68eUCZjy1Pt+fjw/Ph08PL6XRz+Of29LLd9Ovp9mHT59vzvDr74/jwfeo0/HF/OoJeby7R6f3QeZiN4Hlc3MPrx+PRdx7f0ko85sE18e0Sbyvx2BgiPq/Ej739Jgvx8wQT8fN8sRK/17/UvhLfOf7zYLESP/byLV9X/lL8PD9EvOSl+LzHlyvLX4vHXurx9d141PE9A90ngI73DdrfRiCVPQXerAHt41UYbIMuzQHZmzBPDgvxPTMHe9aF+JpY/1pX4ueD9dgX0bHmUPdlaD4oLDn0dKmDXFuHNQcZRod5RHrPobT/byjnO4W+V6GMJYd2cRhLDnWfUBP7Uh3qvivPg9eSQx+XVsjVDv3aflhanOebnnxxWOkHS8xIk7pSAxv7+cLsTUZ+fH/fazDfbNiKQb4YlLZiIOlSg3FtDd5rgua/zOrROKttoQvGnolj6YwyjDN62MqEtlL3JEpXxq8sapb1uiROl0UxrS2K6bK7pLHoUK9zuPaU0UZlN7bR8zvnnL8Z2H7Wa1b6isH+sNOs/mHwZX65vbs///H/1Cuszve3307H+Prj5eHuzdXnf594hf9vPZ0f747fX85HOF3+5Jofn8t8AVNa/oJ/IPB1vmObTw/4Oh9vP2Oxrkm/vKIy/wE=", + "file_map": { + "5": { + "source": "use crate::meta::derive_via;\n\n#[derive_via(derive_eq)]\n// docs:start:eq-trait\npub trait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\n// docs:start:derive_eq\ncomptime fn derive_eq(s: TypeDefinition) -> Quoted {\n let signature = quote { fn eq(_self: Self, _other: Self) -> bool };\n let for_each_field = |name| quote { (_self.$name == _other.$name) };\n let body = |fields| {\n if s.fields_as_written().len() == 0 {\n quote { true }\n } else {\n fields\n }\n };\n crate::meta::make_trait_impl(\n s,\n quote { $crate::cmp::Eq },\n signature,\n for_each_field,\n quote { & },\n body,\n )\n}\n// docs:end:derive_eq\n\nimpl Eq for Field {\n fn eq(self, other: Field) -> bool {\n self == other\n }\n}\n\nimpl Eq for u128 {\n fn eq(self, other: u128) -> bool {\n self == other\n }\n}\nimpl Eq for u64 {\n fn eq(self, other: u64) -> bool {\n self == other\n }\n}\nimpl Eq for u32 {\n fn eq(self, other: u32) -> bool {\n self == other\n }\n}\nimpl Eq for u16 {\n fn eq(self, other: u16) -> bool {\n self == other\n }\n}\nimpl Eq for u8 {\n fn eq(self, other: u8) -> bool {\n self == other\n }\n}\nimpl Eq for u1 {\n fn eq(self, other: u1) -> bool {\n self == other\n }\n}\n\nimpl Eq for i8 {\n fn eq(self, other: i8) -> bool {\n self == other\n }\n}\nimpl Eq for i16 {\n fn eq(self, other: i16) -> bool {\n self == other\n }\n}\nimpl Eq for i32 {\n fn eq(self, other: i32) -> bool {\n self == other\n }\n}\nimpl Eq for i64 {\n fn eq(self, other: i64) -> bool {\n self == other\n }\n}\n\nimpl Eq for () {\n fn eq(_self: Self, _other: ()) -> bool {\n true\n }\n}\nimpl Eq for bool {\n fn eq(self, other: bool) -> bool {\n self == other\n }\n}\n\nimpl Eq for [T; N]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for [T]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for str {\n fn eq(self, other: str) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\nimpl Eq for (A, B)\nwhere\n A: Eq,\n B: Eq,\n{\n fn eq(self, other: (A, B)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1)\n }\n}\n\nimpl Eq for (A, B, C)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n{\n fn eq(self, other: (A, B, C)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2)\n }\n}\n\nimpl Eq for (A, B, C, D)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n{\n fn eq(self, other: (A, B, C, D)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3)\n }\n}\n\nimpl Eq for (A, B, C, D, E)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n E: Eq,\n{\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0)\n & self.1.eq(other.1)\n & self.2.eq(other.2)\n & self.3.eq(other.3)\n & self.4.eq(other.4)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\npub struct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n#[derive_via(derive_ord)]\n// docs:start:ord-trait\npub trait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// docs:start:derive_ord\ncomptime fn derive_ord(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::cmp::Ord };\n let signature = quote { fn cmp(_self: Self, _other: Self) -> $crate::cmp::Ordering };\n let for_each_field = |name| quote {\n if result == $crate::cmp::Ordering::equal() {\n result = _self.$name.cmp(_other.$name);\n }\n };\n let body = |fields| quote {\n let mut result = $crate::cmp::Ordering::equal();\n $fields\n result\n };\n crate::meta::make_trait_impl(s, name, signature, for_each_field, quote {}, body)\n}\n// docs:end:derive_ord\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u128 {\n fn cmp(self, other: u128) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u16 {\n fn cmp(self, other: u16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i16 {\n fn cmp(self, other: i16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for [T; N]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for [T]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let mut result = self.len().cmp(other.len());\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for (A, B)\nwhere\n A: Ord,\n B: Ord,\n{\n fn cmp(self, other: (A, B)) -> Ordering {\n let result = self.0.cmp(other.0);\n\n if result != Ordering::equal() {\n result\n } else {\n self.1.cmp(other.1)\n }\n }\n}\n\nimpl Ord for (A, B, C)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n{\n fn cmp(self, other: (A, B, C)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n{\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D, E)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n E: Ord,\n{\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n if result == Ordering::equal() {\n result = self.4.cmp(other.4);\n }\n\n result\n }\n}\n\n// Compares and returns the maximum of two values.\n//\n// Returns the second argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::max(1, 2), 2);\n// assert_eq(cmp::max(2, 2), 2);\n// ```\npub fn max(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v1\n } else {\n v2\n }\n}\n\n// Compares and returns the minimum of two values.\n//\n// Returns the first argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::min(1, 2), 1);\n// assert_eq(cmp::min(2, 2), 2);\n// ```\npub fn min(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v2\n } else {\n v1\n }\n}\n\nmod cmp_tests {\n use crate::cmp::{max, min};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0_u64, 1), 0);\n assert_eq(min(0_u64, 0), 0);\n assert_eq(min(1_u64, 1), 1);\n assert_eq(min(255_u8, 0), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0_u64, 1), 1);\n assert_eq(max(0_u64, 0), 0);\n assert_eq(max(1_u64, 1), 1);\n assert_eq(max(255_u8, 0), 255);\n }\n}\n", + "path": "std/cmp.nr" + }, + "6": { + "source": "use crate::{cmp::Eq, convert::From, runtime::is_unconstrained, static_assert};\n\n/// A `BoundedVec` is a growable storage similar to a `Vec` except that it\n/// is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented\n/// via slices and thus is not subject to the same restrictions slices are (notably, nested\n/// slices - and thus nested vectors as well - are disallowed).\n///\n/// Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by\n/// pushing an additional element is also more efficient - the length only needs to be increased\n/// by one.\n///\n/// For these reasons `BoundedVec` should generally be preferred over `Vec` when there\n/// is a reasonable maximum bound that can be placed on the vector.\n///\n/// Example:\n///\n/// ```noir\n/// let mut vector: BoundedVec = BoundedVec::new();\n/// for i in 0..5 {\n/// vector.push(i);\n/// }\n/// assert(vector.len() == 5);\n/// assert(vector.max_len() == 10);\n/// ```\npub struct BoundedVec {\n storage: [T; MaxLen],\n len: u32,\n}\n\nimpl BoundedVec {\n /// Creates a new, empty vector of length zero.\n ///\n /// Since this container is backed by an array internally, it still needs an initial value\n /// to give each element. To resolve this, each element is zeroed internally. This value\n /// is guaranteed to be inaccessible unless `get_unchecked` is used.\n ///\n /// Example:\n ///\n /// ```noir\n /// let empty_vector: BoundedVec = BoundedVec::new();\n /// assert(empty_vector.len() == 0);\n /// ```\n ///\n /// Note that whenever calling `new` the maximum length of the vector should always be specified\n /// via a type signature:\n ///\n /// ```noir\n /// fn good() -> BoundedVec {\n /// // Ok! MaxLen is specified with a type annotation\n /// let v1: BoundedVec = BoundedVec::new();\n /// let v2 = BoundedVec::new();\n ///\n /// // Ok! MaxLen is known from the type of `good`'s return value\n /// v2\n /// }\n ///\n /// fn bad() {\n /// // Error: Type annotation needed\n /// // The compiler can't infer `MaxLen` from the following code:\n /// let mut v3 = BoundedVec::new();\n /// v3.push(5);\n /// }\n /// ```\n ///\n /// This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions\n /// but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a\n /// constraint failure at runtime when the vec is pushed to.\n pub fn new() -> Self {\n let zeroed = crate::mem::zeroed();\n BoundedVec { storage: [zeroed; MaxLen], len: 0 }\n }\n\n /// Retrieves an element from the vector at the given index, starting from zero.\n ///\n /// If the given index is equal to or greater than the length of the vector, this\n /// will issue a constraint failure.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn foo(v: BoundedVec) {\n /// let first = v.get(0);\n /// let last = v.get(v.len() - 1);\n /// assert(first != last);\n /// }\n /// ```\n pub fn get(self, index: u32) -> T {\n assert(index < self.len, \"Attempted to read past end of BoundedVec\");\n self.get_unchecked(index)\n }\n\n /// Retrieves an element from the vector at the given index, starting from zero, without\n /// performing a bounds check.\n ///\n /// Since this function does not perform a bounds check on length before accessing the element,\n /// it is unsafe! Use at your own risk!\n ///\n /// Example:\n ///\n /// ```noir\n /// fn sum_of_first_three(v: BoundedVec) -> u32 {\n /// // Always ensure the length is larger than the largest\n /// // index passed to get_unchecked\n /// assert(v.len() > 2);\n /// let first = v.get_unchecked(0);\n /// let second = v.get_unchecked(1);\n /// let third = v.get_unchecked(2);\n /// first + second + third\n /// }\n /// ```\n pub fn get_unchecked(self, index: u32) -> T {\n self.storage[index]\n }\n\n /// Writes an element to the vector at the given index, starting from zero.\n ///\n /// If the given index is equal to or greater than the length of the vector, this will issue a constraint failure.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn foo(v: BoundedVec) {\n /// let first = v.get(0);\n /// assert(first != 42);\n /// v.set(0, 42);\n /// let new_first = v.get(0);\n /// assert(new_first == 42);\n /// }\n /// ```\n pub fn set(&mut self, index: u32, value: T) {\n assert(index < self.len, \"Attempted to write past end of BoundedVec\");\n self.set_unchecked(index, value)\n }\n\n /// Writes an element to the vector at the given index, starting from zero, without performing a bounds check.\n ///\n /// Since this function does not perform a bounds check on length before accessing the element, it is unsafe! Use at your own risk!\n ///\n /// Example:\n ///\n /// ```noir\n /// fn set_unchecked_example() {\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_array([1, 2]);\n ///\n /// // Here we're safely writing within the valid range of `vec`\n /// // `vec` now has the value [42, 2]\n /// vec.set_unchecked(0, 42);\n ///\n /// // We can then safely read this value back out of `vec`.\n /// // Notice that we use the checked version of `get` which would prevent reading unsafe values.\n /// assert_eq(vec.get(0), 42);\n ///\n /// // We've now written past the end of `vec`.\n /// // As this index is still within the maximum potential length of `v`,\n /// // it won't cause a constraint failure.\n /// vec.set_unchecked(2, 42);\n /// println(vec);\n ///\n /// // This will write past the end of the maximum potential length of `vec`,\n /// // it will then trigger a constraint failure.\n /// vec.set_unchecked(5, 42);\n /// println(vec);\n /// }\n /// ```\n pub fn set_unchecked(&mut self, index: u32, value: T) {\n self.storage[index] = value;\n }\n\n /// Pushes an element to the end of the vector. This increases the length\n /// of the vector by one.\n ///\n /// Panics if the new length of the vector will be greater than the max length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// v.push(1);\n /// v.push(2);\n ///\n /// // Panics with failed assertion \"push out of bounds\"\n /// v.push(3);\n /// ```\n pub fn push(&mut self, elem: T) {\n assert(self.len < MaxLen, \"push out of bounds\");\n\n self.storage[self.len] = elem;\n self.len += 1;\n }\n\n /// Returns the current length of this vector\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// assert(v.len() == 0);\n ///\n /// v.push(100);\n /// assert(v.len() == 1);\n ///\n /// v.push(200);\n /// v.push(300);\n /// v.push(400);\n /// assert(v.len() == 4);\n ///\n /// let _ = v.pop();\n /// let _ = v.pop();\n /// assert(v.len() == 2);\n /// ```\n pub fn len(self) -> u32 {\n self.len\n }\n\n /// Returns the maximum length of this vector. This is always\n /// equal to the `MaxLen` parameter this vector was initialized with.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// assert(v.max_len() == 5);\n /// v.push(10);\n /// assert(v.max_len() == 5);\n /// ```\n pub fn max_len(_self: BoundedVec) -> u32 {\n MaxLen\n }\n\n /// Returns the internal array within this vector.\n ///\n /// Since arrays in Noir are immutable, mutating the returned storage array will not mutate\n /// the storage held internally by this vector.\n ///\n /// Note that uninitialized elements may be zeroed out!\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// assert(v.storage() == [0, 0, 0, 0, 0]);\n ///\n /// v.push(57);\n /// assert(v.storage() == [57, 0, 0, 0, 0]);\n /// ```\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n /// Pushes each element from the given array to this vector.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_array([2, 4]);\n ///\n /// assert(vec.len == 2);\n /// assert(vec.get(0) == 2);\n /// assert(vec.get(1) == 4);\n /// ```\n pub fn extend_from_array(&mut self, array: [T; Len]) {\n let new_len = self.len + array.len();\n assert(new_len <= MaxLen, \"extend_from_array out of bounds\");\n for i in 0..array.len() {\n self.storage[self.len + i] = array[i];\n }\n self.len = new_len;\n }\n\n /// Pushes each element from the given slice to this vector.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_slice(&[2, 4]);\n ///\n /// assert(vec.len == 2);\n /// assert(vec.get(0) == 2);\n /// assert(vec.get(1) == 4);\n /// ```\n pub fn extend_from_slice(&mut self, slice: [T]) {\n let new_len = self.len + slice.len();\n assert(new_len <= MaxLen, \"extend_from_slice out of bounds\");\n for i in 0..slice.len() {\n self.storage[self.len + i] = slice[i];\n }\n self.len = new_len;\n }\n\n /// Pushes each element from the other vector to this vector. The length of\n /// the other vector is left unchanged.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// ```noir\n /// let mut v1: BoundedVec = BoundedVec::new();\n /// let mut v2: BoundedVec = BoundedVec::new();\n ///\n /// v2.extend_from_array([1, 2, 3]);\n /// v1.extend_from_bounded_vec(v2);\n ///\n /// assert(v1.storage() == [1, 2, 3, 0, 0]);\n /// assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]);\n /// ```\n pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) {\n let append_len = vec.len();\n let new_len = self.len + append_len;\n assert(new_len <= MaxLen, \"extend_from_bounded_vec out of bounds\");\n\n if is_unconstrained() {\n for i in 0..append_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n } else {\n let mut exceeded_len = false;\n for i in 0..Len {\n exceeded_len |= i == append_len;\n if !exceeded_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n }\n }\n self.len = new_len;\n }\n\n /// Creates a new vector, populating it with values derived from an array input.\n /// The maximum length of the vector is determined based on the type signature.\n ///\n /// Example:\n ///\n /// ```noir\n /// let bounded_vec: BoundedVec = BoundedVec::from_array([1, 2, 3])\n /// ```\n pub fn from_array(array: [T; Len]) -> Self {\n static_assert(Len <= MaxLen, \"from array out of bounds\");\n let mut vec: BoundedVec = BoundedVec::new();\n vec.extend_from_array(array);\n vec\n }\n\n /// Pops the element at the end of the vector. This will decrease the length\n /// of the vector by one.\n ///\n /// Panics if the vector is empty.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// v.push(1);\n /// v.push(2);\n ///\n /// let two = v.pop();\n /// let one = v.pop();\n ///\n /// assert(two == 2);\n /// assert(one == 1);\n ///\n /// // error: cannot pop from an empty vector\n /// let _ = v.pop();\n /// ```\n pub fn pop(&mut self) -> T {\n assert(self.len > 0);\n self.len -= 1;\n\n let elem = self.storage[self.len];\n self.storage[self.len] = crate::mem::zeroed();\n elem\n }\n\n /// Returns true if the given predicate returns true for any element\n /// in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// v.extend_from_array([2, 4, 6]);\n ///\n /// let all_even = !v.any(|elem: u32| elem % 2 != 0);\n /// assert(all_even);\n /// ```\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n if is_unconstrained() {\n for i in 0..self.len {\n ret |= predicate(self.storage[i]);\n }\n } else {\n let mut ret = false;\n let mut exceeded_len = false;\n for i in 0..MaxLen {\n exceeded_len |= i == self.len;\n if !exceeded_len {\n ret |= predicate(self.storage[i]);\n }\n }\n }\n ret\n }\n\n /// Creates a new vector of equal size by calling a closure on each element in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let result = vec.map(|value| value * 2);\n ///\n /// let expected = BoundedVec::from_array([2, 4, 6, 8]);\n /// assert_eq(result, expected);\n /// ```\n pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec {\n let mut ret = BoundedVec::new();\n ret.len = self.len();\n\n if is_unconstrained() {\n for i in 0..self.len() {\n ret.storage[i] = f(self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n ret.storage[i] = f(self.get_unchecked(i));\n }\n }\n }\n\n ret\n }\n\n /// Creates a new vector of equal size by calling a closure on each element\n /// in this vector, along with its index.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let result = vec.mapi(|i, value| i + value * 2);\n ///\n /// let expected = BoundedVec::from_array([2, 5, 8, 11]);\n /// assert_eq(result, expected);\n /// ```\n pub fn mapi(self, f: fn[Env](u32, T) -> U) -> BoundedVec {\n let mut ret = BoundedVec::new();\n ret.len = self.len();\n\n if is_unconstrained() {\n for i in 0..self.len() {\n ret.storage[i] = f(i, self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n ret.storage[i] = f(i, self.get_unchecked(i));\n }\n }\n }\n\n ret\n }\n\n /// Calls a closure on each element in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let mut result = BoundedVec::::new();\n /// vec.for_each(|value| result.push(value * 2));\n ///\n /// let expected = BoundedVec::from_array([2, 4, 6, 8]);\n /// assert_eq(result, expected);\n /// ```\n pub fn for_each(self, f: fn[Env](T) -> ()) {\n if is_unconstrained() {\n for i in 0..self.len() {\n f(self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n f(self.get_unchecked(i));\n }\n }\n }\n }\n\n /// Calls a closure on each element in this vector, along with its index.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let mut result = BoundedVec::::new();\n /// vec.for_eachi(|i, value| result.push(i + value * 2));\n ///\n /// let expected = BoundedVec::from_array([2, 5, 8, 11]);\n /// assert_eq(result, expected);\n /// ```\n pub fn for_eachi(self, f: fn[Env](u32, T) -> ()) {\n if is_unconstrained() {\n for i in 0..self.len() {\n f(i, self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n f(i, self.get_unchecked(i));\n }\n }\n }\n }\n\n /// Creates a new BoundedVec from the given array and length.\n /// The given length must be less than or equal to the length of the array.\n ///\n /// This function will zero out any elements at or past index `len` of `array`.\n /// This incurs an extra runtime cost of O(MaxLen). If you are sure your array is\n /// zeroed after that index, you can use `from_parts_unchecked` to remove the extra loop.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_parts([1, 2, 3, 0], 3);\n /// assert_eq(vec.len(), 3);\n /// ```\n pub fn from_parts(mut array: [T; MaxLen], len: u32) -> Self {\n assert(len <= MaxLen);\n let zeroed = crate::mem::zeroed();\n\n if is_unconstrained() {\n for i in len..MaxLen {\n array[i] = zeroed;\n }\n } else {\n for i in 0..MaxLen {\n if i >= len {\n array[i] = zeroed;\n }\n }\n }\n\n BoundedVec { storage: array, len }\n }\n\n /// Creates a new BoundedVec from the given array and length.\n /// The given length must be less than or equal to the length of the array.\n ///\n /// This function is unsafe because it expects all elements past the `len` index\n /// of `array` to be zeroed, but does not check for this internally. Use `from_parts`\n /// for a safe version of this function which does zero out any indices past the\n /// given length. Invalidating this assumption can notably cause `BoundedVec::eq`\n /// to give incorrect results since it will check even elements past `len`.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 0], 3);\n /// assert_eq(vec.len(), 3);\n ///\n /// // invalid use!\n /// let vec1: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 1], 3);\n /// let vec2: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 2], 3);\n ///\n /// // both vecs have length 3 so we'd expect them to be equal, but this\n /// // fails because elements past the length are still checked in eq\n /// assert_eq(vec1, vec2); // fails\n /// ```\n pub fn from_parts_unchecked(array: [T; MaxLen], len: u32) -> Self {\n assert(len <= MaxLen);\n BoundedVec { storage: array, len }\n }\n}\n\nimpl Eq for BoundedVec\nwhere\n T: Eq,\n{\n fn eq(self, other: BoundedVec) -> bool {\n // TODO: https://github.com/noir-lang/noir/issues/4837\n //\n // We make the assumption that the user has used the proper interface for working with `BoundedVec`s\n // rather than directly manipulating the internal fields as this can result in an inconsistent internal state.\n if self.len == other.len {\n self.storage == other.storage\n } else {\n false\n }\n }\n}\n\nimpl From<[T; Len]> for BoundedVec {\n fn from(array: [T; Len]) -> BoundedVec {\n BoundedVec::from_array(array)\n }\n}\n\nmod bounded_vec_tests {\n\n mod get {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test(should_fail_with = \"Attempted to read past end of BoundedVec\")]\n fn panics_when_reading_elements_past_end_of_vec() {\n let vec: BoundedVec = BoundedVec::new();\n\n crate::println(vec.get(0));\n }\n }\n\n mod set {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn set_updates_values_properly() {\n let mut vec = BoundedVec::from_array([0, 0, 0, 0, 0]);\n\n vec.set(0, 42);\n assert_eq(vec.storage, [42, 0, 0, 0, 0]);\n\n vec.set(1, 43);\n assert_eq(vec.storage, [42, 43, 0, 0, 0]);\n\n vec.set(2, 44);\n assert_eq(vec.storage, [42, 43, 44, 0, 0]);\n\n vec.set(1, 10);\n assert_eq(vec.storage, [42, 10, 44, 0, 0]);\n\n vec.set(0, 0);\n assert_eq(vec.storage, [0, 10, 44, 0, 0]);\n }\n\n #[test(should_fail_with = \"Attempted to write past end of BoundedVec\")]\n fn panics_when_writing_elements_past_end_of_vec() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.set(0, 42);\n\n // Need to use println to avoid DIE removing the write operation.\n crate::println(vec.get(0));\n }\n }\n\n mod map {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn applies_function_correctly() {\n // docs:start:bounded-vec-map-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|value| value * 2);\n // docs:end:bounded-vec-map-example\n let expected = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|value| (value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = vec.map(|value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n }\n\n mod mapi {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn applies_function_correctly() {\n // docs:start:bounded-vec-mapi-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.mapi(|i, value| i + value * 2);\n // docs:end:bounded-vec-mapi-example\n let expected = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.mapi(|i, value| (i + value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = vec.mapi(|_, value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n }\n\n mod for_each {\n use crate::collections::bounded_vec::BoundedVec;\n\n // map in terms of for_each\n fn for_each_map(\n input: BoundedVec,\n f: fn[Env](T) -> U,\n ) -> BoundedVec {\n let mut output = BoundedVec::::new();\n let output_ref = &mut output;\n input.for_each(|x| output_ref.push(f(x)));\n output\n }\n\n #[test]\n fn smoke_test() {\n let mut acc = 0;\n let acc_ref = &mut acc;\n // docs:start:bounded-vec-for-each-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.for_each(|value| { *acc_ref += value; });\n // docs:end:bounded-vec-for-each-example\n assert_eq(acc, 6);\n }\n\n #[test]\n fn applies_function_correctly() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_each_map(vec, |value| value * 2);\n let expected = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_each_map(vec, |value| (value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = for_each_map(vec, |value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n }\n\n mod for_eachi {\n use crate::collections::bounded_vec::BoundedVec;\n\n // mapi in terms of for_eachi\n fn for_eachi_mapi(\n input: BoundedVec,\n f: fn[Env](u32, T) -> U,\n ) -> BoundedVec {\n let mut output = BoundedVec::::new();\n let output_ref = &mut output;\n input.for_eachi(|i, x| output_ref.push(f(i, x)));\n output\n }\n\n #[test]\n fn smoke_test() {\n let mut acc = 0;\n let acc_ref = &mut acc;\n // docs:start:bounded-vec-for-eachi-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.for_eachi(|i, value| { *acc_ref += i * value; });\n // docs:end:bounded-vec-for-eachi-example\n\n // 0 * 1 + 1 * 2 + 2 * 3\n assert_eq(acc, 8);\n }\n\n #[test]\n fn applies_function_correctly() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_eachi_mapi(vec, |i, value| i + value * 2);\n let expected = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_eachi_mapi(vec, |i, value| (i + value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = for_eachi_mapi(vec, |_, value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n }\n\n mod from_array {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty() {\n let empty_array: [Field; 0] = [];\n let bounded_vec = BoundedVec::from_array([]);\n\n assert_eq(bounded_vec.max_len(), 0);\n assert_eq(bounded_vec.len(), 0);\n assert_eq(bounded_vec.storage(), empty_array);\n }\n\n #[test]\n fn equal_len() {\n let array = [1, 2, 3];\n let bounded_vec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 3);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage(), array);\n }\n\n #[test]\n fn max_len_greater_then_array_len() {\n let array = [1, 2, 3];\n let bounded_vec: BoundedVec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.get(0), 1);\n assert_eq(bounded_vec.get(1), 2);\n assert_eq(bounded_vec.get(2), 3);\n }\n\n #[test(should_fail_with = \"from array out of bounds\")]\n fn max_len_lower_then_array_len() {\n let _: BoundedVec = BoundedVec::from_array([0; 3]);\n }\n }\n\n mod trait_from {\n use crate::collections::bounded_vec::BoundedVec;\n use crate::convert::From;\n\n #[test]\n fn simple() {\n let array = [1, 2];\n let bounded_vec: BoundedVec = BoundedVec::from(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 2);\n assert_eq(bounded_vec.get(0), 1);\n assert_eq(bounded_vec.get(1), 2);\n }\n }\n\n mod trait_eq {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty_equality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n\n assert_eq(bounded_vec1, bounded_vec2);\n }\n\n #[test]\n fn inequality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n bounded_vec1.push(1);\n bounded_vec2.push(2);\n\n assert(bounded_vec1 != bounded_vec2);\n }\n }\n\n mod from_parts {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn from_parts() {\n // docs:start:from-parts\n let vec: BoundedVec = BoundedVec::from_parts([1, 2, 3, 0], 3);\n assert_eq(vec.len(), 3);\n\n // Any elements past the given length are zeroed out, so these\n // two BoundedVecs will be completely equal\n let vec1: BoundedVec = BoundedVec::from_parts([1, 2, 3, 1], 3);\n let vec2: BoundedVec = BoundedVec::from_parts([1, 2, 3, 2], 3);\n assert_eq(vec1, vec2);\n // docs:end:from-parts\n }\n\n #[test]\n fn from_parts_unchecked() {\n // docs:start:from-parts-unchecked\n let vec: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 0], 3);\n assert_eq(vec.len(), 3);\n\n // invalid use!\n let vec1: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 1], 3);\n let vec2: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 2], 3);\n\n // both vecs have length 3 so we'd expect them to be equal, but this\n // fails because elements past the length are still checked in eq\n assert(vec1 != vec2);\n // docs:end:from-parts-unchecked\n }\n }\n}\n", + "path": "std/collections/bounded_vec.nr" + }, + "50": { + "source": "type Double: u32 = N * 2;\n\nfn main(x: Field) {\n let mut m = new_matrix::<3, 4>();\n m.elements[3 * 2 + 3] = 10;\n m.elements[3 * 2 + x as u32] = 5 + x;\n assert(equal(m, m));\n let b = transpose(m);\n assert(b.elements != m.elements);\n assert(trace(b) != trace(m));\n assert(sum(b) == sum(m));\n\n let a = test_2::<4>(x);\n assert(a.len() == 1);\n}\n\nfn test_2(x: Field) -> BoundedVec> {\n let mut a = BoundedVec::new();\n a.push(x);\n a\n}\n\ntype MSize: u32 = N * M;\n\nstruct Matrix {\n elements: [Field; MSize::],\n}\n\nfn new_matrix() -> Matrix {\n let mut a = [0; MSize::];\n Matrix { elements: a }\n}\n\nfn trace(A: Matrix) -> Field {\n let n = if N > M { M } else { N };\n let mut s = 0;\n for i in 0..n {\n s += A.elements[i * N + i];\n }\n s\n}\n\nfn sum(A: Matrix) -> Field {\n let mut s = 0;\n for i in 0..MSize:: {\n s += A.elements[i];\n }\n s\n}\n\nfn equal(A: Matrix, B: Matrix) -> bool {\n let mut s = true;\n for i in 0..MSize:: {\n s = s | (A.elements[i] == B.elements[i]);\n }\n s\n}\n\nfn transpose(a: Matrix) -> Matrix {\n let mut b = new_matrix::();\n for i in 0..N {\n for j in 0..M {\n b.elements[j * N + i] = a.elements[i * M + j];\n }\n }\n b\n}\n", + "path": "" + } + }, + "names": [ + "main" + ], + "brillig_names": [ + "main" + ] +} diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_true_inliner_0.snap b/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_true_inliner_0.snap new file mode 100644 index 00000000000..8112b2aadf2 --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_true_inliner_0.snap @@ -0,0 +1,65 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: artifact +--- +{ + "noir_version": "[noir_version]", + "hash": "[hash]", + "abi": { + "parameters": [ + { + "name": "x", + "type": { + "kind": "field" + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "5019202896831570965": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "12049594436772143978": { + "error_kind": "string", + "string": "array ref-count underflow detected" + }, + "14225679739041873922": { + "error_kind": "string", + "string": "Index out of bounds" + }, + "17843811134343075018": { + "error_kind": "string", + "string": "Stack too deep" + } + } + }, + "bytecode": [ + "func 0", + "current witness index : _0", + "private parameters indices : [_0]", + "public parameters indices : []", + "return value indices : []", + "BRILLIG CALL func 0: inputs: [EXPR [ (1, _0) 0 ]], outputs: []", + "unconstrained func 0", + "[Const { destination: Direct(2), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(1), bit_size: Integer(U32), value: 32837 }, Const { destination: Direct(0), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(2), bit_size: Integer(U32), value: 1 }, Const { destination: Relative(3), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(32836), size_address: Relative(2), offset_address: Relative(3) }, Mov { destination: Relative(1), source: Direct(32836) }, Call { location: 12 }, Call { location: 13 }, Const { destination: Relative(1), bit_size: Integer(U32), value: 32837 }, Const { destination: Relative(2), bit_size: Integer(U32), value: 0 }, Stop { return_data: HeapVector { pointer: Relative(1), size: Relative(2) } }, Return, Call { location: 345 }, Const { destination: Relative(3), bit_size: Field, value: 0 }, Mov { destination: Relative(4), source: Direct(1) }, Const { destination: Relative(5), bit_size: Integer(U32), value: 13 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(5) }, IndirectConst { destination_pointer: Relative(4), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(4), rhs: Direct(2) }, Const { destination: Relative(6), bit_size: Integer(U32), value: 12 }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(6), rhs: Relative(5) }, Mov { destination: Relative(7), source: Relative(5) }, BinaryIntOp { destination: Relative(8), op: LessThan, bit_size: U32, lhs: Relative(7), rhs: Relative(6) }, Not { destination: Relative(8), source: Relative(8), bit_size: U1 }, JumpIf { condition: Relative(8), location: 29 }, Store { destination_pointer: Relative(7), source: Relative(3) }, BinaryIntOp { destination: Relative(7), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Jump { location: 23 }, Mov { destination: Relative(5), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Const { destination: Relative(6), bit_size: Field, value: 10 }, Mov { destination: Relative(7), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 13 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(7), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Mov { destination: Relative(9), source: Relative(8) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(6) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, Cast { destination: Relative(8), source: Relative(1), bit_size: Integer(U32) }, Cast { destination: Relative(6), source: Relative(8), bit_size: Field }, Cast { destination: Relative(8), source: Relative(6), bit_size: Integer(U32) }, Const { destination: Relative(6), bit_size: Integer(U32), value: 6 }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(6), rhs: Relative(8) }, BinaryIntOp { destination: Relative(10), op: LessThanEquals, bit_size: U32, lhs: Relative(6), rhs: Relative(9) }, JumpIf { condition: Relative(10), location: 69 }, Call { location: 351 }, Const { destination: Relative(6), bit_size: Field, value: 5 }, BinaryFieldOp { destination: Relative(8), op: Add, lhs: Relative(6), rhs: Relative(1) }, Const { destination: Relative(1), bit_size: Integer(U32), value: 12 }, BinaryIntOp { destination: Relative(6), op: LessThan, bit_size: U32, lhs: Relative(9), rhs: Relative(1) }, Const { destination: Relative(10), bit_size: Integer(U1), value: 1 }, JumpIf { condition: Relative(6), location: 76 }, Call { location: 354 }, Mov { destination: Direct(32771), source: Relative(7) }, Const { destination: Direct(32772), bit_size: Integer(U32), value: 13 }, Call { location: 357 }, Mov { destination: Relative(6), source: Direct(32773) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(11), rhs: Relative(9) }, Store { destination_pointer: Relative(12), source: Relative(8) }, Store { destination_pointer: Relative(5), source: Relative(6) }, Load { destination: Relative(7), source_pointer: Relative(6) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(9), op: Equals, bit_size: U32, lhs: Relative(8), rhs: Relative(7) }, Not { destination: Relative(9), source: Relative(9), bit_size: U1 }, JumpIf { condition: Relative(9), location: 90 }, Call { location: 379 }, BinaryIntOp { destination: Relative(7), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Relative(7) }, Mov { destination: Relative(6), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Relative(10) }, Const { destination: Relative(7), bit_size: Integer(U32), value: 0 }, Const { destination: Relative(9), bit_size: Integer(U32), value: 1 }, Mov { destination: Relative(2), source: Relative(7) }, Jump { location: 99 }, BinaryIntOp { destination: Relative(8), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Relative(1) }, JumpIf { condition: Relative(8), location: 341 }, Jump { location: 102 }, Load { destination: Relative(8), source_pointer: Relative(6) }, JumpIf { condition: Relative(8), location: 106 }, Const { destination: Relative(6), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(6) } }, Load { destination: Relative(6), source_pointer: Relative(5) }, Load { destination: Relative(8), source_pointer: Relative(6) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(12), op: Equals, bit_size: U32, lhs: Relative(11), rhs: Relative(8) }, Not { destination: Relative(12), source: Relative(12), bit_size: U1 }, JumpIf { condition: Relative(12), location: 113 }, Call { location: 379 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Relative(8) }, Load { destination: Relative(8), source_pointer: Relative(4) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(13), op: Equals, bit_size: U32, lhs: Relative(12), rhs: Relative(8) }, Not { destination: Relative(13), source: Relative(13), bit_size: U1 }, JumpIf { condition: Relative(13), location: 121 }, Call { location: 379 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, Store { destination_pointer: Relative(4), source: Relative(8) }, Mov { destination: Relative(8), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(8), source: Relative(4) }, Const { destination: Relative(4), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(13), bit_size: Integer(U32), value: 4 }, Mov { destination: Relative(2), source: Relative(7) }, Jump { location: 130 }, BinaryIntOp { destination: Relative(11), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Relative(4) }, JumpIf { condition: Relative(11), location: 302 }, Jump { location: 133 }, Load { destination: Relative(6), source_pointer: Relative(8) }, Load { destination: Relative(8), source_pointer: Relative(6) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(12), op: Equals, bit_size: U32, lhs: Relative(11), rhs: Relative(8) }, Not { destination: Relative(12), source: Relative(12), bit_size: U1 }, JumpIf { condition: Relative(12), location: 140 }, Call { location: 379 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Relative(8) }, Load { destination: Relative(8), source_pointer: Relative(5) }, Load { destination: Relative(12), source_pointer: Relative(8) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(15), op: Equals, bit_size: U32, lhs: Relative(14), rhs: Relative(12) }, Not { destination: Relative(15), source: Relative(15), bit_size: U1 }, JumpIf { condition: Relative(15), location: 149 }, Call { location: 379 }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Store { destination_pointer: Relative(8), source: Relative(12) }, Mov { destination: Relative(12), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(12), source: Relative(10) }, Load { destination: Relative(15), source_pointer: Relative(6) }, Const { destination: Relative(16), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(17), op: Equals, bit_size: U32, lhs: Relative(16), rhs: Relative(15) }, Not { destination: Relative(17), source: Relative(17), bit_size: U1 }, JumpIf { condition: Relative(17), location: 160 }, Call { location: 379 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Relative(15) }, Mov { destination: Relative(2), source: Relative(7) }, Jump { location: 164 }, BinaryIntOp { destination: Relative(11), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Relative(1) }, JumpIf { condition: Relative(11), location: 289 }, Jump { location: 167 }, Load { destination: Relative(8), source_pointer: Relative(12) }, Const { destination: Relative(11), bit_size: Integer(U1), value: 0 }, BinaryIntOp { destination: Relative(12), op: Equals, bit_size: U1, lhs: Relative(8), rhs: Relative(11) }, JumpIf { condition: Relative(12), location: 173 }, Const { destination: Relative(14), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(14) } }, Load { destination: Relative(8), source_pointer: Relative(6) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(14), op: Equals, bit_size: U32, lhs: Relative(12), rhs: Relative(8) }, Not { destination: Relative(14), source: Relative(14), bit_size: U1 }, JumpIf { condition: Relative(14), location: 179 }, Call { location: 379 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Relative(8) }, Mov { destination: Relative(8), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(8), source: Relative(3) }, Mov { destination: Relative(2), source: Relative(7) }, Jump { location: 186 }, BinaryIntOp { destination: Relative(12), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Relative(4) }, JumpIf { condition: Relative(12), location: 272 }, Jump { location: 189 }, Load { destination: Relative(12), source_pointer: Relative(8) }, Load { destination: Relative(8), source_pointer: Relative(5) }, Load { destination: Relative(13), source_pointer: Relative(8) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(15), op: Equals, bit_size: U32, lhs: Relative(14), rhs: Relative(13) }, Not { destination: Relative(15), source: Relative(15), bit_size: U1 }, JumpIf { condition: Relative(15), location: 197 }, Call { location: 379 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Store { destination_pointer: Relative(8), source: Relative(13) }, Mov { destination: Relative(13), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(13), source: Relative(3) }, Mov { destination: Relative(2), source: Relative(7) }, Jump { location: 204 }, BinaryIntOp { destination: Relative(14), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Relative(4) }, JumpIf { condition: Relative(14), location: 255 }, Jump { location: 207 }, Load { destination: Relative(4), source_pointer: Relative(13) }, BinaryFieldOp { destination: Relative(8), op: Equals, lhs: Relative(12), rhs: Relative(4) }, BinaryIntOp { destination: Relative(4), op: Equals, bit_size: U1, lhs: Relative(8), rhs: Relative(11) }, JumpIf { condition: Relative(4), location: 213 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, Mov { destination: Relative(4), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(4), source: Relative(3) }, Mov { destination: Relative(2), source: Relative(7) }, Jump { location: 218 }, BinaryIntOp { destination: Relative(8), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Relative(1) }, JumpIf { condition: Relative(8), location: 246 }, Jump { location: 221 }, Load { destination: Relative(6), source_pointer: Relative(4) }, Load { destination: Relative(4), source_pointer: Relative(5) }, Mov { destination: Relative(5), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(5), source: Relative(3) }, Mov { destination: Relative(2), source: Relative(7) }, Jump { location: 228 }, BinaryIntOp { destination: Relative(3), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Relative(1) }, JumpIf { condition: Relative(3), location: 237 }, Jump { location: 231 }, Load { destination: Relative(1), source_pointer: Relative(5) }, BinaryFieldOp { destination: Relative(2), op: Equals, lhs: Relative(6), rhs: Relative(1) }, JumpIf { condition: Relative(2), location: 236 }, Const { destination: Relative(3), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(3) } }, Return, Load { destination: Relative(3), source_pointer: Relative(5) }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(4), rhs: Direct(2) }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(8), rhs: Relative(2) }, Load { destination: Relative(7), source_pointer: Relative(10) }, BinaryFieldOp { destination: Relative(8), op: Add, lhs: Relative(3), rhs: Relative(7) }, Store { destination_pointer: Relative(5), source: Relative(8) }, BinaryIntOp { destination: Relative(3), op: Add, bit_size: U32, lhs: Relative(2), rhs: Relative(9) }, Mov { destination: Relative(2), source: Relative(3) }, Jump { location: 228 }, Load { destination: Relative(8), source_pointer: Relative(4) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(11), rhs: Relative(2) }, Load { destination: Relative(10), source_pointer: Relative(12) }, BinaryFieldOp { destination: Relative(11), op: Add, lhs: Relative(8), rhs: Relative(10) }, Store { destination_pointer: Relative(4), source: Relative(11) }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(2), rhs: Relative(9) }, Mov { destination: Relative(2), source: Relative(8) }, Jump { location: 218 }, Load { destination: Relative(14), source_pointer: Relative(13) }, BinaryIntOp { destination: Relative(15), op: Mul, bit_size: U32, lhs: Relative(2), rhs: Relative(4) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(15), rhs: Relative(2) }, BinaryIntOp { destination: Relative(17), op: LessThanEquals, bit_size: U32, lhs: Relative(15), rhs: Relative(16) }, JumpIf { condition: Relative(17), location: 261 }, Call { location: 351 }, BinaryIntOp { destination: Relative(15), op: LessThan, bit_size: U32, lhs: Relative(16), rhs: Relative(1) }, JumpIf { condition: Relative(15), location: 264 }, Call { location: 354 }, BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(17), rhs: Relative(16) }, Load { destination: Relative(15), source_pointer: Relative(18) }, BinaryFieldOp { destination: Relative(16), op: Add, lhs: Relative(14), rhs: Relative(15) }, Store { destination_pointer: Relative(13), source: Relative(16) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(2), rhs: Relative(9) }, Mov { destination: Relative(2), source: Relative(14) }, Jump { location: 204 }, Load { destination: Relative(12), source_pointer: Relative(8) }, BinaryIntOp { destination: Relative(14), op: Mul, bit_size: U32, lhs: Relative(2), rhs: Relative(13) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(14), rhs: Relative(2) }, BinaryIntOp { destination: Relative(16), op: LessThanEquals, bit_size: U32, lhs: Relative(14), rhs: Relative(15) }, JumpIf { condition: Relative(16), location: 278 }, Call { location: 351 }, BinaryIntOp { destination: Relative(14), op: LessThan, bit_size: U32, lhs: Relative(15), rhs: Relative(1) }, JumpIf { condition: Relative(14), location: 281 }, Call { location: 354 }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(16), rhs: Relative(15) }, Load { destination: Relative(14), source_pointer: Relative(17) }, BinaryFieldOp { destination: Relative(15), op: Add, lhs: Relative(12), rhs: Relative(14) }, Store { destination_pointer: Relative(8), source: Relative(15) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(2), rhs: Relative(9) }, Mov { destination: Relative(2), source: Relative(12) }, Jump { location: 186 }, Load { destination: Relative(11), source_pointer: Relative(12) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(15), rhs: Relative(2) }, Load { destination: Relative(14), source_pointer: Relative(16) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(16), rhs: Relative(2) }, Load { destination: Relative(15), source_pointer: Relative(17) }, BinaryFieldOp { destination: Relative(16), op: Equals, lhs: Relative(14), rhs: Relative(15) }, BinaryIntOp { destination: Relative(14), op: Mul, bit_size: U1, lhs: Relative(11), rhs: Relative(16) }, Store { destination_pointer: Relative(12), source: Relative(14) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(2), rhs: Relative(9) }, Mov { destination: Relative(2), source: Relative(11) }, Jump { location: 164 }, BinaryIntOp { destination: Relative(12), op: Mul, bit_size: U32, lhs: Relative(2), rhs: Relative(13) }, Mov { destination: Relative(11), source: Relative(7) }, Jump { location: 305 }, BinaryIntOp { destination: Relative(14), op: LessThan, bit_size: U32, lhs: Relative(11), rhs: Relative(13) }, JumpIf { condition: Relative(14), location: 311 }, Jump { location: 308 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(2), rhs: Relative(9) }, Mov { destination: Relative(2), source: Relative(11) }, Jump { location: 130 }, BinaryIntOp { destination: Relative(14), op: Mul, bit_size: U32, lhs: Relative(11), rhs: Relative(4) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(14), rhs: Relative(2) }, BinaryIntOp { destination: Relative(16), op: LessThanEquals, bit_size: U32, lhs: Relative(14), rhs: Relative(15) }, JumpIf { condition: Relative(16), location: 316 }, Call { location: 351 }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(12), rhs: Relative(11) }, BinaryIntOp { destination: Relative(16), op: LessThanEquals, bit_size: U32, lhs: Relative(12), rhs: Relative(14) }, JumpIf { condition: Relative(16), location: 320 }, Call { location: 351 }, BinaryIntOp { destination: Relative(16), op: LessThan, bit_size: U32, lhs: Relative(14), rhs: Relative(1) }, JumpIf { condition: Relative(16), location: 323 }, Call { location: 354 }, BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(17), rhs: Relative(14) }, Load { destination: Relative(16), source_pointer: Relative(18) }, Load { destination: Relative(14), source_pointer: Relative(8) }, BinaryIntOp { destination: Relative(17), op: LessThan, bit_size: U32, lhs: Relative(15), rhs: Relative(1) }, JumpIf { condition: Relative(17), location: 330 }, Call { location: 354 }, Mov { destination: Direct(32771), source: Relative(14) }, Const { destination: Direct(32772), bit_size: Integer(U32), value: 13 }, Call { location: 357 }, Mov { destination: Relative(17), source: Direct(32773) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(17), rhs: Direct(2) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(18), rhs: Relative(15) }, Store { destination_pointer: Relative(19), source: Relative(16) }, Store { destination_pointer: Relative(8), source: Relative(17) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(11), rhs: Relative(9) }, Mov { destination: Relative(11), source: Relative(14) }, Jump { location: 305 }, Store { destination_pointer: Relative(6), source: Relative(10) }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(2), rhs: Relative(9) }, Mov { destination: Relative(2), source: Relative(8) }, Jump { location: 99 }, Const { destination: Direct(32772), bit_size: Integer(U32), value: 30720 }, BinaryIntOp { destination: Direct(32771), op: LessThan, bit_size: U32, lhs: Direct(0), rhs: Direct(32772) }, JumpIf { condition: Direct(32771), location: 350 }, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 17843811134343075018 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 5019202896831570965 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 14225679739041873922 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return, Load { destination: Direct(32774), source_pointer: Direct(32771) }, BinaryIntOp { destination: Direct(32775), op: Equals, bit_size: U32, lhs: Direct(32774), rhs: Direct(2) }, JumpIf { condition: Direct(32775), location: 361 }, Jump { location: 363 }, Mov { destination: Direct(32773), source: Direct(32771) }, Jump { location: 378 }, Mov { destination: Direct(32773), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(32772) }, BinaryIntOp { destination: Direct(32777), op: Add, bit_size: U32, lhs: Direct(32771), rhs: Direct(32772) }, Mov { destination: Direct(32778), source: Direct(32771) }, Mov { destination: Direct(32779), source: Direct(32773) }, BinaryIntOp { destination: Direct(32780), op: Equals, bit_size: U32, lhs: Direct(32778), rhs: Direct(32777) }, JumpIf { condition: Direct(32780), location: 375 }, Load { destination: Direct(32776), source_pointer: Direct(32778) }, Store { destination_pointer: Direct(32779), source: Direct(32776) }, BinaryIntOp { destination: Direct(32778), op: Add, bit_size: U32, lhs: Direct(32778), rhs: Direct(2) }, BinaryIntOp { destination: Direct(32779), op: Add, bit_size: U32, lhs: Direct(32779), rhs: Direct(2) }, Jump { location: 368 }, IndirectConst { destination_pointer: Direct(32773), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Direct(32774), op: Sub, bit_size: U32, lhs: Direct(32774), rhs: Direct(2) }, Jump { location: 378 }, Return, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 12049594436772143978 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return]" + ], + "debug_symbols": "tZnbbts8EITfxde+4GGXh75KURRO4hQGDCdwkx/4EeTdy+Fy5ORCaiChN5nPdXZMrUZL1nnbPRzvXn/9PF0en37vvn1/291dT+fz6dfP89P94eX0dGn/+rZz+OFl9y3sd15Nkkk2KSa1S3Am3iSYRBNzCeYSzCWYSzCX0Fz8fhedSXOJTYJJNBETNUkm2aSY1C7iTMxFzEXMRcxFzEXMRcxFzEXMRc1FzUXNRc1FzUXNRc1FzUXNRc0lmUtqLtIkmEST5qJN1CSZZJNi0lzSfpediTcJJtFETNSkueQm2aSY1C7FmXiTYBJNxERNzKWYSzGXYi7VXKq51OZSm0QTMcHddC0brr3rPaC9X6AyVIemoXloGVpNvRvqh4ahw88PPyTUCyARMqEQ6gBk1cATAqH5+ggQgg7o2VQAficB8Dt4BJBJg0TIhEKoA5BOA08IhEigs9BZ6Cx0FjoLnZXOyKxHW5Bag0iAcwUoIREyoRDqAKTYwBPog7wG3Gsk1mdAHYDUGnhCIESCEJSQCJlA50znQmdkOfRhFAiRgDmDG4fcBtxcJDcgjciuQSBEghCUkAiZUAhwThh+juAJ8MkAVBUAqiqgDkC4DTwhEDBnPEAISsB86TMWkykCMJscAFUKEIISUIWF9dmKhfXpioX1+dpBCErIrEI5FtZHLKAP2Q407IO2QySksVSEVrBChNagDuhjFlehvJw+ajvo6CEiKrh2RFT6VlIIdQAiauAJgRAJ7QIFzhi5BonA24QYG9QBCC2CFBBaEQB80FWE1iARMqEQ6gCE1gArRFcRWoNIEMtqwCA2SITxMAbEWNAWxNggEOCDNSPGBkrA9oKG1/HAhh7jDtUgYlxr34axJQVAsVkXEVHFFouIqgAiQQhKwGcpIBMKoQ7AEDbwhECAMz4UMTZQQiJkQiHUAX1Qd/CEQIgEISghETKB194HNdrSB7V/f9/veFT6+XI9HnFS+nB2aieq58P1eHnZfbu8ns/73X+H82v/pd/Ph0vXl8O1vdtafrw8NG2Gj6fzEfS+v1W7+dKso7bqVKyfq/1CNTa0Xp69zNUvfLp3ftS3nXNNPbJl9cmtqcdTuKU+3errmvoYp3q/pr5M11/jXH3ZeP8W6tXlUa+6pr6djsoUgLImQW03HAYhzN5BnGXmb0GpXIK42ZuIRm3q4uIaJORpDaGss0g3i1LWdHLKYtsdZ5eQ5w2qYyNr1DUG7Tw0PU61fujklx3a+YlrCC7WGYelJmQOpLbdzl1DWJiIJTOPZaVB5X0stawx+NJtWGpBmXJQZ2dS0K0t0K0t0H/YglsK6pqx3I49o74dd+bq4+K+eBsIbn4gLFl8aTQvryG7aQ2rJkr0UxvCfBtkextkaxvkn7bBbW7DdEpbWsJfbuZXLBYfqjAdFaPbaiCrDLz8/bFeHI1fugS/9RL8xktY3uH8bYcLadUeGd1tjyyrHD6uYW6XlbpwYiqJJ6Y6V7942lE3HXzbE77uwKTT/z1EwzqLaadrZ6643WLdhXzsxfx2s7yK6m8Wn3vxo7063J+un77Uf4fX9XS4Ox/Hy8fXy/2Hd1/+f+Y7/KPA8/Xp/vjwej3C6faXgfbje9S8j7n8wPe1eNm+3Ijq8NL3d317GX+8YzF/AA==", + "file_map": { + "5": { + "source": "use crate::meta::derive_via;\n\n#[derive_via(derive_eq)]\n// docs:start:eq-trait\npub trait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\n// docs:start:derive_eq\ncomptime fn derive_eq(s: TypeDefinition) -> Quoted {\n let signature = quote { fn eq(_self: Self, _other: Self) -> bool };\n let for_each_field = |name| quote { (_self.$name == _other.$name) };\n let body = |fields| {\n if s.fields_as_written().len() == 0 {\n quote { true }\n } else {\n fields\n }\n };\n crate::meta::make_trait_impl(\n s,\n quote { $crate::cmp::Eq },\n signature,\n for_each_field,\n quote { & },\n body,\n )\n}\n// docs:end:derive_eq\n\nimpl Eq for Field {\n fn eq(self, other: Field) -> bool {\n self == other\n }\n}\n\nimpl Eq for u128 {\n fn eq(self, other: u128) -> bool {\n self == other\n }\n}\nimpl Eq for u64 {\n fn eq(self, other: u64) -> bool {\n self == other\n }\n}\nimpl Eq for u32 {\n fn eq(self, other: u32) -> bool {\n self == other\n }\n}\nimpl Eq for u16 {\n fn eq(self, other: u16) -> bool {\n self == other\n }\n}\nimpl Eq for u8 {\n fn eq(self, other: u8) -> bool {\n self == other\n }\n}\nimpl Eq for u1 {\n fn eq(self, other: u1) -> bool {\n self == other\n }\n}\n\nimpl Eq for i8 {\n fn eq(self, other: i8) -> bool {\n self == other\n }\n}\nimpl Eq for i16 {\n fn eq(self, other: i16) -> bool {\n self == other\n }\n}\nimpl Eq for i32 {\n fn eq(self, other: i32) -> bool {\n self == other\n }\n}\nimpl Eq for i64 {\n fn eq(self, other: i64) -> bool {\n self == other\n }\n}\n\nimpl Eq for () {\n fn eq(_self: Self, _other: ()) -> bool {\n true\n }\n}\nimpl Eq for bool {\n fn eq(self, other: bool) -> bool {\n self == other\n }\n}\n\nimpl Eq for [T; N]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for [T]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for str {\n fn eq(self, other: str) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\nimpl Eq for (A, B)\nwhere\n A: Eq,\n B: Eq,\n{\n fn eq(self, other: (A, B)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1)\n }\n}\n\nimpl Eq for (A, B, C)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n{\n fn eq(self, other: (A, B, C)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2)\n }\n}\n\nimpl Eq for (A, B, C, D)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n{\n fn eq(self, other: (A, B, C, D)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3)\n }\n}\n\nimpl Eq for (A, B, C, D, E)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n E: Eq,\n{\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0)\n & self.1.eq(other.1)\n & self.2.eq(other.2)\n & self.3.eq(other.3)\n & self.4.eq(other.4)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\npub struct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n#[derive_via(derive_ord)]\n// docs:start:ord-trait\npub trait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// docs:start:derive_ord\ncomptime fn derive_ord(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::cmp::Ord };\n let signature = quote { fn cmp(_self: Self, _other: Self) -> $crate::cmp::Ordering };\n let for_each_field = |name| quote {\n if result == $crate::cmp::Ordering::equal() {\n result = _self.$name.cmp(_other.$name);\n }\n };\n let body = |fields| quote {\n let mut result = $crate::cmp::Ordering::equal();\n $fields\n result\n };\n crate::meta::make_trait_impl(s, name, signature, for_each_field, quote {}, body)\n}\n// docs:end:derive_ord\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u128 {\n fn cmp(self, other: u128) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u16 {\n fn cmp(self, other: u16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i16 {\n fn cmp(self, other: i16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for [T; N]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for [T]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let mut result = self.len().cmp(other.len());\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for (A, B)\nwhere\n A: Ord,\n B: Ord,\n{\n fn cmp(self, other: (A, B)) -> Ordering {\n let result = self.0.cmp(other.0);\n\n if result != Ordering::equal() {\n result\n } else {\n self.1.cmp(other.1)\n }\n }\n}\n\nimpl Ord for (A, B, C)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n{\n fn cmp(self, other: (A, B, C)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n{\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D, E)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n E: Ord,\n{\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n if result == Ordering::equal() {\n result = self.4.cmp(other.4);\n }\n\n result\n }\n}\n\n// Compares and returns the maximum of two values.\n//\n// Returns the second argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::max(1, 2), 2);\n// assert_eq(cmp::max(2, 2), 2);\n// ```\npub fn max(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v1\n } else {\n v2\n }\n}\n\n// Compares and returns the minimum of two values.\n//\n// Returns the first argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::min(1, 2), 1);\n// assert_eq(cmp::min(2, 2), 2);\n// ```\npub fn min(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v2\n } else {\n v1\n }\n}\n\nmod cmp_tests {\n use crate::cmp::{max, min};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0_u64, 1), 0);\n assert_eq(min(0_u64, 0), 0);\n assert_eq(min(1_u64, 1), 1);\n assert_eq(min(255_u8, 0), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0_u64, 1), 1);\n assert_eq(max(0_u64, 0), 0);\n assert_eq(max(1_u64, 1), 1);\n assert_eq(max(255_u8, 0), 255);\n }\n}\n", + "path": "std/cmp.nr" + }, + "50": { + "source": "type Double: u32 = N * 2;\n\nfn main(x: Field) {\n let mut m = new_matrix::<3, 4>();\n m.elements[3 * 2 + 3] = 10;\n m.elements[3 * 2 + x as u32] = 5 + x;\n assert(equal(m, m));\n let b = transpose(m);\n assert(b.elements != m.elements);\n assert(trace(b) != trace(m));\n assert(sum(b) == sum(m));\n\n let a = test_2::<4>(x);\n assert(a.len() == 1);\n}\n\nfn test_2(x: Field) -> BoundedVec> {\n let mut a = BoundedVec::new();\n a.push(x);\n a\n}\n\ntype MSize: u32 = N * M;\n\nstruct Matrix {\n elements: [Field; MSize::],\n}\n\nfn new_matrix() -> Matrix {\n let mut a = [0; MSize::];\n Matrix { elements: a }\n}\n\nfn trace(A: Matrix) -> Field {\n let n = if N > M { M } else { N };\n let mut s = 0;\n for i in 0..n {\n s += A.elements[i * N + i];\n }\n s\n}\n\nfn sum(A: Matrix) -> Field {\n let mut s = 0;\n for i in 0..MSize:: {\n s += A.elements[i];\n }\n s\n}\n\nfn equal(A: Matrix, B: Matrix) -> bool {\n let mut s = true;\n for i in 0..MSize:: {\n s = s | (A.elements[i] == B.elements[i]);\n }\n s\n}\n\nfn transpose(a: Matrix) -> Matrix {\n let mut b = new_matrix::();\n for i in 0..N {\n for j in 0..M {\n b.elements[j * N + i] = a.elements[i * M + j];\n }\n }\n b\n}\n", + "path": "" + } + }, + "names": [ + "main" + ], + "brillig_names": [ + "main" + ] +} diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_true_inliner_9223372036854775807.snap b/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_true_inliner_9223372036854775807.snap new file mode 100644 index 00000000000..8112b2aadf2 --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__force_brillig_true_inliner_9223372036854775807.snap @@ -0,0 +1,65 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: artifact +--- +{ + "noir_version": "[noir_version]", + "hash": "[hash]", + "abi": { + "parameters": [ + { + "name": "x", + "type": { + "kind": "field" + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "5019202896831570965": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "12049594436772143978": { + "error_kind": "string", + "string": "array ref-count underflow detected" + }, + "14225679739041873922": { + "error_kind": "string", + "string": "Index out of bounds" + }, + "17843811134343075018": { + "error_kind": "string", + "string": "Stack too deep" + } + } + }, + "bytecode": [ + "func 0", + "current witness index : _0", + "private parameters indices : [_0]", + "public parameters indices : []", + "return value indices : []", + "BRILLIG CALL func 0: inputs: [EXPR [ (1, _0) 0 ]], outputs: []", + "unconstrained func 0", + "[Const { destination: Direct(2), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(1), bit_size: Integer(U32), value: 32837 }, Const { destination: Direct(0), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(2), bit_size: Integer(U32), value: 1 }, Const { destination: Relative(3), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(32836), size_address: Relative(2), offset_address: Relative(3) }, Mov { destination: Relative(1), source: Direct(32836) }, Call { location: 12 }, Call { location: 13 }, Const { destination: Relative(1), bit_size: Integer(U32), value: 32837 }, Const { destination: Relative(2), bit_size: Integer(U32), value: 0 }, Stop { return_data: HeapVector { pointer: Relative(1), size: Relative(2) } }, Return, Call { location: 345 }, Const { destination: Relative(3), bit_size: Field, value: 0 }, Mov { destination: Relative(4), source: Direct(1) }, Const { destination: Relative(5), bit_size: Integer(U32), value: 13 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(5) }, IndirectConst { destination_pointer: Relative(4), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(5), op: Add, bit_size: U32, lhs: Relative(4), rhs: Direct(2) }, Const { destination: Relative(6), bit_size: Integer(U32), value: 12 }, BinaryIntOp { destination: Relative(6), op: Add, bit_size: U32, lhs: Relative(6), rhs: Relative(5) }, Mov { destination: Relative(7), source: Relative(5) }, BinaryIntOp { destination: Relative(8), op: LessThan, bit_size: U32, lhs: Relative(7), rhs: Relative(6) }, Not { destination: Relative(8), source: Relative(8), bit_size: U1 }, JumpIf { condition: Relative(8), location: 29 }, Store { destination_pointer: Relative(7), source: Relative(3) }, BinaryIntOp { destination: Relative(7), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Jump { location: 23 }, Mov { destination: Relative(5), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Const { destination: Relative(6), bit_size: Field, value: 10 }, Mov { destination: Relative(7), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 13 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(7), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Mov { destination: Relative(9), source: Relative(8) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(6) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(3) }, Cast { destination: Relative(8), source: Relative(1), bit_size: Integer(U32) }, Cast { destination: Relative(6), source: Relative(8), bit_size: Field }, Cast { destination: Relative(8), source: Relative(6), bit_size: Integer(U32) }, Const { destination: Relative(6), bit_size: Integer(U32), value: 6 }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(6), rhs: Relative(8) }, BinaryIntOp { destination: Relative(10), op: LessThanEquals, bit_size: U32, lhs: Relative(6), rhs: Relative(9) }, JumpIf { condition: Relative(10), location: 69 }, Call { location: 351 }, Const { destination: Relative(6), bit_size: Field, value: 5 }, BinaryFieldOp { destination: Relative(8), op: Add, lhs: Relative(6), rhs: Relative(1) }, Const { destination: Relative(1), bit_size: Integer(U32), value: 12 }, BinaryIntOp { destination: Relative(6), op: LessThan, bit_size: U32, lhs: Relative(9), rhs: Relative(1) }, Const { destination: Relative(10), bit_size: Integer(U1), value: 1 }, JumpIf { condition: Relative(6), location: 76 }, Call { location: 354 }, Mov { destination: Direct(32771), source: Relative(7) }, Const { destination: Direct(32772), bit_size: Integer(U32), value: 13 }, Call { location: 357 }, Mov { destination: Relative(6), source: Direct(32773) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(11), rhs: Relative(9) }, Store { destination_pointer: Relative(12), source: Relative(8) }, Store { destination_pointer: Relative(5), source: Relative(6) }, Load { destination: Relative(7), source_pointer: Relative(6) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(9), op: Equals, bit_size: U32, lhs: Relative(8), rhs: Relative(7) }, Not { destination: Relative(9), source: Relative(9), bit_size: U1 }, JumpIf { condition: Relative(9), location: 90 }, Call { location: 379 }, BinaryIntOp { destination: Relative(7), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Relative(7) }, Mov { destination: Relative(6), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Relative(10) }, Const { destination: Relative(7), bit_size: Integer(U32), value: 0 }, Const { destination: Relative(9), bit_size: Integer(U32), value: 1 }, Mov { destination: Relative(2), source: Relative(7) }, Jump { location: 99 }, BinaryIntOp { destination: Relative(8), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Relative(1) }, JumpIf { condition: Relative(8), location: 341 }, Jump { location: 102 }, Load { destination: Relative(8), source_pointer: Relative(6) }, JumpIf { condition: Relative(8), location: 106 }, Const { destination: Relative(6), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(6) } }, Load { destination: Relative(6), source_pointer: Relative(5) }, Load { destination: Relative(8), source_pointer: Relative(6) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(12), op: Equals, bit_size: U32, lhs: Relative(11), rhs: Relative(8) }, Not { destination: Relative(12), source: Relative(12), bit_size: U1 }, JumpIf { condition: Relative(12), location: 113 }, Call { location: 379 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Relative(8) }, Load { destination: Relative(8), source_pointer: Relative(4) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(13), op: Equals, bit_size: U32, lhs: Relative(12), rhs: Relative(8) }, Not { destination: Relative(13), source: Relative(13), bit_size: U1 }, JumpIf { condition: Relative(13), location: 121 }, Call { location: 379 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, Store { destination_pointer: Relative(4), source: Relative(8) }, Mov { destination: Relative(8), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(8), source: Relative(4) }, Const { destination: Relative(4), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(13), bit_size: Integer(U32), value: 4 }, Mov { destination: Relative(2), source: Relative(7) }, Jump { location: 130 }, BinaryIntOp { destination: Relative(11), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Relative(4) }, JumpIf { condition: Relative(11), location: 302 }, Jump { location: 133 }, Load { destination: Relative(6), source_pointer: Relative(8) }, Load { destination: Relative(8), source_pointer: Relative(6) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(12), op: Equals, bit_size: U32, lhs: Relative(11), rhs: Relative(8) }, Not { destination: Relative(12), source: Relative(12), bit_size: U1 }, JumpIf { condition: Relative(12), location: 140 }, Call { location: 379 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Relative(8) }, Load { destination: Relative(8), source_pointer: Relative(5) }, Load { destination: Relative(12), source_pointer: Relative(8) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(15), op: Equals, bit_size: U32, lhs: Relative(14), rhs: Relative(12) }, Not { destination: Relative(15), source: Relative(15), bit_size: U1 }, JumpIf { condition: Relative(15), location: 149 }, Call { location: 379 }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Store { destination_pointer: Relative(8), source: Relative(12) }, Mov { destination: Relative(12), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(12), source: Relative(10) }, Load { destination: Relative(15), source_pointer: Relative(6) }, Const { destination: Relative(16), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(17), op: Equals, bit_size: U32, lhs: Relative(16), rhs: Relative(15) }, Not { destination: Relative(17), source: Relative(17), bit_size: U1 }, JumpIf { condition: Relative(17), location: 160 }, Call { location: 379 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Relative(15) }, Mov { destination: Relative(2), source: Relative(7) }, Jump { location: 164 }, BinaryIntOp { destination: Relative(11), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Relative(1) }, JumpIf { condition: Relative(11), location: 289 }, Jump { location: 167 }, Load { destination: Relative(8), source_pointer: Relative(12) }, Const { destination: Relative(11), bit_size: Integer(U1), value: 0 }, BinaryIntOp { destination: Relative(12), op: Equals, bit_size: U1, lhs: Relative(8), rhs: Relative(11) }, JumpIf { condition: Relative(12), location: 173 }, Const { destination: Relative(14), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(14) } }, Load { destination: Relative(8), source_pointer: Relative(6) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(14), op: Equals, bit_size: U32, lhs: Relative(12), rhs: Relative(8) }, Not { destination: Relative(14), source: Relative(14), bit_size: U1 }, JumpIf { condition: Relative(14), location: 179 }, Call { location: 379 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, Store { destination_pointer: Relative(6), source: Relative(8) }, Mov { destination: Relative(8), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(8), source: Relative(3) }, Mov { destination: Relative(2), source: Relative(7) }, Jump { location: 186 }, BinaryIntOp { destination: Relative(12), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Relative(4) }, JumpIf { condition: Relative(12), location: 272 }, Jump { location: 189 }, Load { destination: Relative(12), source_pointer: Relative(8) }, Load { destination: Relative(8), source_pointer: Relative(5) }, Load { destination: Relative(13), source_pointer: Relative(8) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(15), op: Equals, bit_size: U32, lhs: Relative(14), rhs: Relative(13) }, Not { destination: Relative(15), source: Relative(15), bit_size: U1 }, JumpIf { condition: Relative(15), location: 197 }, Call { location: 379 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Store { destination_pointer: Relative(8), source: Relative(13) }, Mov { destination: Relative(13), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(13), source: Relative(3) }, Mov { destination: Relative(2), source: Relative(7) }, Jump { location: 204 }, BinaryIntOp { destination: Relative(14), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Relative(4) }, JumpIf { condition: Relative(14), location: 255 }, Jump { location: 207 }, Load { destination: Relative(4), source_pointer: Relative(13) }, BinaryFieldOp { destination: Relative(8), op: Equals, lhs: Relative(12), rhs: Relative(4) }, BinaryIntOp { destination: Relative(4), op: Equals, bit_size: U1, lhs: Relative(8), rhs: Relative(11) }, JumpIf { condition: Relative(4), location: 213 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, Mov { destination: Relative(4), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(4), source: Relative(3) }, Mov { destination: Relative(2), source: Relative(7) }, Jump { location: 218 }, BinaryIntOp { destination: Relative(8), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Relative(1) }, JumpIf { condition: Relative(8), location: 246 }, Jump { location: 221 }, Load { destination: Relative(6), source_pointer: Relative(4) }, Load { destination: Relative(4), source_pointer: Relative(5) }, Mov { destination: Relative(5), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(2) }, Store { destination_pointer: Relative(5), source: Relative(3) }, Mov { destination: Relative(2), source: Relative(7) }, Jump { location: 228 }, BinaryIntOp { destination: Relative(3), op: LessThan, bit_size: U32, lhs: Relative(2), rhs: Relative(1) }, JumpIf { condition: Relative(3), location: 237 }, Jump { location: 231 }, Load { destination: Relative(1), source_pointer: Relative(5) }, BinaryFieldOp { destination: Relative(2), op: Equals, lhs: Relative(6), rhs: Relative(1) }, JumpIf { condition: Relative(2), location: 236 }, Const { destination: Relative(3), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(3) } }, Return, Load { destination: Relative(3), source_pointer: Relative(5) }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(4), rhs: Direct(2) }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(8), rhs: Relative(2) }, Load { destination: Relative(7), source_pointer: Relative(10) }, BinaryFieldOp { destination: Relative(8), op: Add, lhs: Relative(3), rhs: Relative(7) }, Store { destination_pointer: Relative(5), source: Relative(8) }, BinaryIntOp { destination: Relative(3), op: Add, bit_size: U32, lhs: Relative(2), rhs: Relative(9) }, Mov { destination: Relative(2), source: Relative(3) }, Jump { location: 228 }, Load { destination: Relative(8), source_pointer: Relative(4) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(11), rhs: Relative(2) }, Load { destination: Relative(10), source_pointer: Relative(12) }, BinaryFieldOp { destination: Relative(11), op: Add, lhs: Relative(8), rhs: Relative(10) }, Store { destination_pointer: Relative(4), source: Relative(11) }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(2), rhs: Relative(9) }, Mov { destination: Relative(2), source: Relative(8) }, Jump { location: 218 }, Load { destination: Relative(14), source_pointer: Relative(13) }, BinaryIntOp { destination: Relative(15), op: Mul, bit_size: U32, lhs: Relative(2), rhs: Relative(4) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(15), rhs: Relative(2) }, BinaryIntOp { destination: Relative(17), op: LessThanEquals, bit_size: U32, lhs: Relative(15), rhs: Relative(16) }, JumpIf { condition: Relative(17), location: 261 }, Call { location: 351 }, BinaryIntOp { destination: Relative(15), op: LessThan, bit_size: U32, lhs: Relative(16), rhs: Relative(1) }, JumpIf { condition: Relative(15), location: 264 }, Call { location: 354 }, BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(17), rhs: Relative(16) }, Load { destination: Relative(15), source_pointer: Relative(18) }, BinaryFieldOp { destination: Relative(16), op: Add, lhs: Relative(14), rhs: Relative(15) }, Store { destination_pointer: Relative(13), source: Relative(16) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(2), rhs: Relative(9) }, Mov { destination: Relative(2), source: Relative(14) }, Jump { location: 204 }, Load { destination: Relative(12), source_pointer: Relative(8) }, BinaryIntOp { destination: Relative(14), op: Mul, bit_size: U32, lhs: Relative(2), rhs: Relative(13) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(14), rhs: Relative(2) }, BinaryIntOp { destination: Relative(16), op: LessThanEquals, bit_size: U32, lhs: Relative(14), rhs: Relative(15) }, JumpIf { condition: Relative(16), location: 278 }, Call { location: 351 }, BinaryIntOp { destination: Relative(14), op: LessThan, bit_size: U32, lhs: Relative(15), rhs: Relative(1) }, JumpIf { condition: Relative(14), location: 281 }, Call { location: 354 }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(16), rhs: Relative(15) }, Load { destination: Relative(14), source_pointer: Relative(17) }, BinaryFieldOp { destination: Relative(15), op: Add, lhs: Relative(12), rhs: Relative(14) }, Store { destination_pointer: Relative(8), source: Relative(15) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(2), rhs: Relative(9) }, Mov { destination: Relative(2), source: Relative(12) }, Jump { location: 186 }, Load { destination: Relative(11), source_pointer: Relative(12) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(15), rhs: Relative(2) }, Load { destination: Relative(14), source_pointer: Relative(16) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(16), rhs: Relative(2) }, Load { destination: Relative(15), source_pointer: Relative(17) }, BinaryFieldOp { destination: Relative(16), op: Equals, lhs: Relative(14), rhs: Relative(15) }, BinaryIntOp { destination: Relative(14), op: Mul, bit_size: U1, lhs: Relative(11), rhs: Relative(16) }, Store { destination_pointer: Relative(12), source: Relative(14) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(2), rhs: Relative(9) }, Mov { destination: Relative(2), source: Relative(11) }, Jump { location: 164 }, BinaryIntOp { destination: Relative(12), op: Mul, bit_size: U32, lhs: Relative(2), rhs: Relative(13) }, Mov { destination: Relative(11), source: Relative(7) }, Jump { location: 305 }, BinaryIntOp { destination: Relative(14), op: LessThan, bit_size: U32, lhs: Relative(11), rhs: Relative(13) }, JumpIf { condition: Relative(14), location: 311 }, Jump { location: 308 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(2), rhs: Relative(9) }, Mov { destination: Relative(2), source: Relative(11) }, Jump { location: 130 }, BinaryIntOp { destination: Relative(14), op: Mul, bit_size: U32, lhs: Relative(11), rhs: Relative(4) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(14), rhs: Relative(2) }, BinaryIntOp { destination: Relative(16), op: LessThanEquals, bit_size: U32, lhs: Relative(14), rhs: Relative(15) }, JumpIf { condition: Relative(16), location: 316 }, Call { location: 351 }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(12), rhs: Relative(11) }, BinaryIntOp { destination: Relative(16), op: LessThanEquals, bit_size: U32, lhs: Relative(12), rhs: Relative(14) }, JumpIf { condition: Relative(16), location: 320 }, Call { location: 351 }, BinaryIntOp { destination: Relative(16), op: LessThan, bit_size: U32, lhs: Relative(14), rhs: Relative(1) }, JumpIf { condition: Relative(16), location: 323 }, Call { location: 354 }, BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(6), rhs: Direct(2) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(17), rhs: Relative(14) }, Load { destination: Relative(16), source_pointer: Relative(18) }, Load { destination: Relative(14), source_pointer: Relative(8) }, BinaryIntOp { destination: Relative(17), op: LessThan, bit_size: U32, lhs: Relative(15), rhs: Relative(1) }, JumpIf { condition: Relative(17), location: 330 }, Call { location: 354 }, Mov { destination: Direct(32771), source: Relative(14) }, Const { destination: Direct(32772), bit_size: Integer(U32), value: 13 }, Call { location: 357 }, Mov { destination: Relative(17), source: Direct(32773) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(17), rhs: Direct(2) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(18), rhs: Relative(15) }, Store { destination_pointer: Relative(19), source: Relative(16) }, Store { destination_pointer: Relative(8), source: Relative(17) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(11), rhs: Relative(9) }, Mov { destination: Relative(11), source: Relative(14) }, Jump { location: 305 }, Store { destination_pointer: Relative(6), source: Relative(10) }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(2), rhs: Relative(9) }, Mov { destination: Relative(2), source: Relative(8) }, Jump { location: 99 }, Const { destination: Direct(32772), bit_size: Integer(U32), value: 30720 }, BinaryIntOp { destination: Direct(32771), op: LessThan, bit_size: U32, lhs: Direct(0), rhs: Direct(32772) }, JumpIf { condition: Direct(32771), location: 350 }, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 17843811134343075018 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 5019202896831570965 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 14225679739041873922 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return, Load { destination: Direct(32774), source_pointer: Direct(32771) }, BinaryIntOp { destination: Direct(32775), op: Equals, bit_size: U32, lhs: Direct(32774), rhs: Direct(2) }, JumpIf { condition: Direct(32775), location: 361 }, Jump { location: 363 }, Mov { destination: Direct(32773), source: Direct(32771) }, Jump { location: 378 }, Mov { destination: Direct(32773), source: Direct(1) }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Direct(32772) }, BinaryIntOp { destination: Direct(32777), op: Add, bit_size: U32, lhs: Direct(32771), rhs: Direct(32772) }, Mov { destination: Direct(32778), source: Direct(32771) }, Mov { destination: Direct(32779), source: Direct(32773) }, BinaryIntOp { destination: Direct(32780), op: Equals, bit_size: U32, lhs: Direct(32778), rhs: Direct(32777) }, JumpIf { condition: Direct(32780), location: 375 }, Load { destination: Direct(32776), source_pointer: Direct(32778) }, Store { destination_pointer: Direct(32779), source: Direct(32776) }, BinaryIntOp { destination: Direct(32778), op: Add, bit_size: U32, lhs: Direct(32778), rhs: Direct(2) }, BinaryIntOp { destination: Direct(32779), op: Add, bit_size: U32, lhs: Direct(32779), rhs: Direct(2) }, Jump { location: 368 }, IndirectConst { destination_pointer: Direct(32773), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Direct(32774), op: Sub, bit_size: U32, lhs: Direct(32774), rhs: Direct(2) }, Jump { location: 378 }, Return, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 12049594436772143978 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return]" + ], + "debug_symbols": "tZnbbts8EITfxde+4GGXh75KURRO4hQGDCdwkx/4EeTdy+Fy5ORCaiChN5nPdXZMrUZL1nnbPRzvXn/9PF0en37vvn1/291dT+fz6dfP89P94eX0dGn/+rZz+OFl9y3sd15Nkkk2KSa1S3Am3iSYRBNzCeYSzCWYSzCX0Fz8fhedSXOJTYJJNBETNUkm2aSY1C7iTMxFzEXMRcxFzEXMRcxFzEXMRc1FzUXNRc1FzUXNRc1FzUXNRc0lmUtqLtIkmEST5qJN1CSZZJNi0lzSfpediTcJJtFETNSkueQm2aSY1C7FmXiTYBJNxERNzKWYSzGXYi7VXKq51OZSm0QTMcHddC0brr3rPaC9X6AyVIemoXloGVpNvRvqh4ahw88PPyTUCyARMqEQ6gBk1cATAqH5+ggQgg7o2VQAficB8Dt4BJBJg0TIhEKoA5BOA08IhEigs9BZ6Cx0FjoLnZXOyKxHW5Bag0iAcwUoIREyoRDqAKTYwBPog7wG3Gsk1mdAHYDUGnhCIESCEJSQCJlA50znQmdkOfRhFAiRgDmDG4fcBtxcJDcgjciuQSBEghCUkAiZUAhwThh+juAJ8MkAVBUAqiqgDkC4DTwhEDBnPEAISsB86TMWkykCMJscAFUKEIISUIWF9dmKhfXpioX1+dpBCErIrEI5FtZHLKAP2Q407IO2QySksVSEVrBChNagDuhjFlehvJw+ajvo6CEiKrh2RFT6VlIIdQAiauAJgRAJ7QIFzhi5BonA24QYG9QBCC2CFBBaEQB80FWE1iARMqEQ6gCE1gArRFcRWoNIEMtqwCA2SITxMAbEWNAWxNggEOCDNSPGBkrA9oKG1/HAhh7jDtUgYlxr34axJQVAsVkXEVHFFouIqgAiQQhKwGcpIBMKoQ7AEDbwhECAMz4UMTZQQiJkQiHUAX1Qd/CEQIgEISghETKB194HNdrSB7V/f9/veFT6+XI9HnFS+nB2aieq58P1eHnZfbu8ns/73X+H82v/pd/Ph0vXl8O1vdtafrw8NG2Gj6fzEfS+v1W7+dKso7bqVKyfq/1CNTa0Xp69zNUvfLp3ftS3nXNNPbJl9cmtqcdTuKU+3errmvoYp3q/pr5M11/jXH3ZeP8W6tXlUa+6pr6djsoUgLImQW03HAYhzN5BnGXmb0GpXIK42ZuIRm3q4uIaJORpDaGss0g3i1LWdHLKYtsdZ5eQ5w2qYyNr1DUG7Tw0PU61fujklx3a+YlrCC7WGYelJmQOpLbdzl1DWJiIJTOPZaVB5X0stawx+NJtWGpBmXJQZ2dS0K0t0K0t0H/YglsK6pqx3I49o74dd+bq4+K+eBsIbn4gLFl8aTQvryG7aQ2rJkr0UxvCfBtkextkaxvkn7bBbW7DdEpbWsJfbuZXLBYfqjAdFaPbaiCrDLz8/bFeHI1fugS/9RL8xktY3uH8bYcLadUeGd1tjyyrHD6uYW6XlbpwYiqJJ6Y6V7942lE3HXzbE77uwKTT/z1EwzqLaadrZ6643WLdhXzsxfx2s7yK6m8Wn3vxo7063J+un77Uf4fX9XS4Ox/Hy8fXy/2Hd1/+f+Y7/KPA8/Xp/vjwej3C6faXgfbje9S8j7n8wPe1eNm+3Ijq8NL3d317GX+8YzF/AA==", + "file_map": { + "5": { + "source": "use crate::meta::derive_via;\n\n#[derive_via(derive_eq)]\n// docs:start:eq-trait\npub trait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\n// docs:start:derive_eq\ncomptime fn derive_eq(s: TypeDefinition) -> Quoted {\n let signature = quote { fn eq(_self: Self, _other: Self) -> bool };\n let for_each_field = |name| quote { (_self.$name == _other.$name) };\n let body = |fields| {\n if s.fields_as_written().len() == 0 {\n quote { true }\n } else {\n fields\n }\n };\n crate::meta::make_trait_impl(\n s,\n quote { $crate::cmp::Eq },\n signature,\n for_each_field,\n quote { & },\n body,\n )\n}\n// docs:end:derive_eq\n\nimpl Eq for Field {\n fn eq(self, other: Field) -> bool {\n self == other\n }\n}\n\nimpl Eq for u128 {\n fn eq(self, other: u128) -> bool {\n self == other\n }\n}\nimpl Eq for u64 {\n fn eq(self, other: u64) -> bool {\n self == other\n }\n}\nimpl Eq for u32 {\n fn eq(self, other: u32) -> bool {\n self == other\n }\n}\nimpl Eq for u16 {\n fn eq(self, other: u16) -> bool {\n self == other\n }\n}\nimpl Eq for u8 {\n fn eq(self, other: u8) -> bool {\n self == other\n }\n}\nimpl Eq for u1 {\n fn eq(self, other: u1) -> bool {\n self == other\n }\n}\n\nimpl Eq for i8 {\n fn eq(self, other: i8) -> bool {\n self == other\n }\n}\nimpl Eq for i16 {\n fn eq(self, other: i16) -> bool {\n self == other\n }\n}\nimpl Eq for i32 {\n fn eq(self, other: i32) -> bool {\n self == other\n }\n}\nimpl Eq for i64 {\n fn eq(self, other: i64) -> bool {\n self == other\n }\n}\n\nimpl Eq for () {\n fn eq(_self: Self, _other: ()) -> bool {\n true\n }\n}\nimpl Eq for bool {\n fn eq(self, other: bool) -> bool {\n self == other\n }\n}\n\nimpl Eq for [T; N]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for [T]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for str {\n fn eq(self, other: str) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\nimpl Eq for (A, B)\nwhere\n A: Eq,\n B: Eq,\n{\n fn eq(self, other: (A, B)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1)\n }\n}\n\nimpl Eq for (A, B, C)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n{\n fn eq(self, other: (A, B, C)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2)\n }\n}\n\nimpl Eq for (A, B, C, D)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n{\n fn eq(self, other: (A, B, C, D)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3)\n }\n}\n\nimpl Eq for (A, B, C, D, E)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n E: Eq,\n{\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0)\n & self.1.eq(other.1)\n & self.2.eq(other.2)\n & self.3.eq(other.3)\n & self.4.eq(other.4)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\npub struct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n#[derive_via(derive_ord)]\n// docs:start:ord-trait\npub trait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// docs:start:derive_ord\ncomptime fn derive_ord(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::cmp::Ord };\n let signature = quote { fn cmp(_self: Self, _other: Self) -> $crate::cmp::Ordering };\n let for_each_field = |name| quote {\n if result == $crate::cmp::Ordering::equal() {\n result = _self.$name.cmp(_other.$name);\n }\n };\n let body = |fields| quote {\n let mut result = $crate::cmp::Ordering::equal();\n $fields\n result\n };\n crate::meta::make_trait_impl(s, name, signature, for_each_field, quote {}, body)\n}\n// docs:end:derive_ord\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u128 {\n fn cmp(self, other: u128) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u16 {\n fn cmp(self, other: u16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i16 {\n fn cmp(self, other: i16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for [T; N]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for [T]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let mut result = self.len().cmp(other.len());\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for (A, B)\nwhere\n A: Ord,\n B: Ord,\n{\n fn cmp(self, other: (A, B)) -> Ordering {\n let result = self.0.cmp(other.0);\n\n if result != Ordering::equal() {\n result\n } else {\n self.1.cmp(other.1)\n }\n }\n}\n\nimpl Ord for (A, B, C)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n{\n fn cmp(self, other: (A, B, C)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n{\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D, E)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n E: Ord,\n{\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n if result == Ordering::equal() {\n result = self.4.cmp(other.4);\n }\n\n result\n }\n}\n\n// Compares and returns the maximum of two values.\n//\n// Returns the second argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::max(1, 2), 2);\n// assert_eq(cmp::max(2, 2), 2);\n// ```\npub fn max(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v1\n } else {\n v2\n }\n}\n\n// Compares and returns the minimum of two values.\n//\n// Returns the first argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::min(1, 2), 1);\n// assert_eq(cmp::min(2, 2), 2);\n// ```\npub fn min(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v2\n } else {\n v1\n }\n}\n\nmod cmp_tests {\n use crate::cmp::{max, min};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0_u64, 1), 0);\n assert_eq(min(0_u64, 0), 0);\n assert_eq(min(1_u64, 1), 1);\n assert_eq(min(255_u8, 0), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0_u64, 1), 1);\n assert_eq(max(0_u64, 0), 0);\n assert_eq(max(1_u64, 1), 1);\n assert_eq(max(255_u8, 0), 255);\n }\n}\n", + "path": "std/cmp.nr" + }, + "50": { + "source": "type Double: u32 = N * 2;\n\nfn main(x: Field) {\n let mut m = new_matrix::<3, 4>();\n m.elements[3 * 2 + 3] = 10;\n m.elements[3 * 2 + x as u32] = 5 + x;\n assert(equal(m, m));\n let b = transpose(m);\n assert(b.elements != m.elements);\n assert(trace(b) != trace(m));\n assert(sum(b) == sum(m));\n\n let a = test_2::<4>(x);\n assert(a.len() == 1);\n}\n\nfn test_2(x: Field) -> BoundedVec> {\n let mut a = BoundedVec::new();\n a.push(x);\n a\n}\n\ntype MSize: u32 = N * M;\n\nstruct Matrix {\n elements: [Field; MSize::],\n}\n\nfn new_matrix() -> Matrix {\n let mut a = [0; MSize::];\n Matrix { elements: a }\n}\n\nfn trace(A: Matrix) -> Field {\n let n = if N > M { M } else { N };\n let mut s = 0;\n for i in 0..n {\n s += A.elements[i * N + i];\n }\n s\n}\n\nfn sum(A: Matrix) -> Field {\n let mut s = 0;\n for i in 0..MSize:: {\n s += A.elements[i];\n }\n s\n}\n\nfn equal(A: Matrix, B: Matrix) -> bool {\n let mut s = true;\n for i in 0..MSize:: {\n s = s | (A.elements[i] == B.elements[i]);\n }\n s\n}\n\nfn transpose(a: Matrix) -> Matrix {\n let mut b = new_matrix::();\n for i in 0..N {\n for j in 0..M {\n b.elements[j * N + i] = a.elements[i * M + j];\n }\n }\n b\n}\n", + "path": "" + } + }, + "names": [ + "main" + ], + "brillig_names": [ + "main" + ] +} diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__stdout.snap b/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__stdout.snap new file mode 100644 index 00000000000..e86e3de90e1 --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/execution_success/numeric_type_alias/execute__tests__stdout.snap @@ -0,0 +1,5 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: stdout +--- + diff --git a/tooling/nargo_fmt/src/formatter/alias.rs b/tooling/nargo_fmt/src/formatter/alias.rs index 96eedfd3d88..d91744c502a 100644 --- a/tooling/nargo_fmt/src/formatter/alias.rs +++ b/tooling/nargo_fmt/src/formatter/alias.rs @@ -1,18 +1,23 @@ use noirc_frontend::{ - ast::NoirTypeAlias, + ast::TypeAlias, token::{Keyword, Token}, }; use super::Formatter; impl Formatter<'_> { - pub(super) fn format_type_alias(&mut self, type_alias: NoirTypeAlias) { + pub(super) fn format_type_alias(&mut self, type_alias: TypeAlias) { self.write_indentation(); self.format_item_visibility(type_alias.visibility); self.write_keyword(Keyword::Type); self.write_space(); self.write_identifier(type_alias.name); self.format_generics(type_alias.generics); + if let Some(num_type) = type_alias.numeric_type { + self.write_token(Token::Colon); + self.write_space(); + self.format_type(num_type); + } self.write_space(); self.write_token(Token::Assign); self.write_space(); @@ -32,6 +37,13 @@ mod tests { assert_format(src, expected); } + #[test] + fn format_num_type_alias() { + let src = " pub type Foo:u32 = 2*N ; "; + let expected = "pub type Foo: u32 = 2 * N;\n"; + assert_format(src, expected); + } + #[test] fn format_generic_type_alias() { let src = " pub type Foo < A, B > = i32 ; ";