Skip to content

Commit

Permalink
feat: Sync from noir (#8543)
Browse files Browse the repository at this point in the history
Automated pull of development from the
[noir](https://github.com/noir-lang/noir) programming language, a
dependency of Aztec.
BEGIN_COMMIT_OVERRIDE
feat: add `Expr::as_for` and `Expr::as_for_range`
(noir-lang/noir#6039)
fix: Fix canonicalization bug
(noir-lang/noir#6033)
fix: Parse a statement as an expression
(noir-lang/noir#6040)
chore: rename CustomAtrribute to CustomAttribute
(noir-lang/noir#6038)
fix: error on `&mut x` when `x` is not mutable
(noir-lang/noir#6037)
feat: add `Expr::as_constructor`
(noir-lang/noir#5980)
chore: Fix docs (noir-lang/noir#6035)
chore: document array methods
(noir-lang/noir#6034)
END_COMMIT_OVERRIDE

---------

Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>
  • Loading branch information
AztecBot and TomAFrench authored Sep 17, 2024
1 parent ae26474 commit 7ea4709
Show file tree
Hide file tree
Showing 91 changed files with 1,802 additions and 500 deletions.
2 changes: 1 addition & 1 deletion .noir-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
fc74c55ffed892962413c6fe15af62e1d2e7b785
5bbd9ba9a6d6494fd16813b44036b78c871f6613
2 changes: 1 addition & 1 deletion noir-projects/aztec-nr/aztec/src/keys/getters/test.nr
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ fn setup() -> (TestEnvironment, PrivateContext, TestAccount) {

#[test(should_fail_with="Invalid public keys hint for address")]
fn test_get_current_keys_unknown_unregistered() {
let (_, context, account) = setup();
let (_, mut context, account) = setup();

let _ = OracleMock::mock("getPublicKeysAndPartialAddress").returns([0; KEY_ORACLE_RESPONSE_LENGTH]).times(1);
let _ = get_current_public_keys(&mut context, account.address);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ contract NFT {
let from_ovpk_m = get_current_public_keys(&mut context, from).ovpk_m;
let to_keys = get_current_public_keys(&mut context, to);

let new_note = NFTNote::new(token_id, to_keys.npk_m.hash());
let mut new_note = NFTNote::new(token_id, to_keys.npk_m.hash());
nfts.at(to).insert(&mut new_note).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk_m, to_keys.ivpk_m, to));
}

Expand Down
8 changes: 5 additions & 3 deletions noir/noir-repo/aztec_macros/src/transforms/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,11 @@ pub fn generate_storage_implementation(
})
.collect();

let storage_constructor_statement = make_statement(StatementKind::Expression(expression(
ExpressionKind::constructor((chained_path!(storage_struct_name), field_constructors)),
)));
let storage_constructor_statement =
make_statement(StatementKind::Expression(expression(ExpressionKind::constructor((
UnresolvedType::from_path(chained_path!(storage_struct_name)),
field_constructors,
)))));

// This is the type over which the impl is generic.
let generic_context_ident = ident("Context");
Expand Down
3 changes: 2 additions & 1 deletion noir/noir-repo/aztec_macros/src/utils/parse_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ fn empty_expression(expression: &mut Expression) {
ExpressionKind::Quote(..)
| ExpressionKind::Resolved(_)
| ExpressionKind::Interned(_)
| ExpressionKind::InternedStatement(_)
| ExpressionKind::Error => (),
}
}
Expand Down Expand Up @@ -505,7 +506,7 @@ fn empty_method_call_expression(method_call_expression: &mut MethodCallExpressio
}

fn empty_constructor_expression(constructor_expression: &mut ConstructorExpression) {
empty_path(&mut constructor_expression.type_name);
empty_unresolved_type(&mut constructor_expression.typ);
for (name, expression) in constructor_expression.fields.iter_mut() {
empty_ident(name);
empty_expression(expression);
Expand Down
17 changes: 12 additions & 5 deletions noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::ast::{
};
use crate::hir::def_collector::errors::DefCollectorErrorKind;
use crate::macros_api::StructId;
use crate::node_interner::{ExprId, InternedExpressionKind, QuotedTypeId};
use crate::node_interner::{ExprId, InternedExpressionKind, InternedStatementKind, QuotedTypeId};
use crate::token::{Attributes, FunctionAttribute, Token, Tokens};
use crate::{Kind, Type};
use acvm::{acir::AcirField, FieldElement};
Expand Down Expand Up @@ -48,6 +48,10 @@ pub enum ExpressionKind {
// The actual ExpressionKind can be retrieved with a NodeInterner.
Interned(InternedExpressionKind),

/// Interned statements are allowed to be parsed as expressions in case they resolve
/// to an StatementKind::Expression or StatementKind::Semi.
InternedStatement(InternedStatementKind),

Error,
}

Expand Down Expand Up @@ -200,9 +204,11 @@ impl ExpressionKind {
ExpressionKind::Literal(Literal::FmtStr(contents))
}

pub fn constructor((type_name, fields): (Path, Vec<(Ident, Expression)>)) -> ExpressionKind {
pub fn constructor(
(typ, fields): (UnresolvedType, Vec<(Ident, Expression)>),
) -> ExpressionKind {
ExpressionKind::Constructor(Box::new(ConstructorExpression {
type_name,
typ,
fields,
struct_type: None,
}))
Expand Down Expand Up @@ -536,7 +542,7 @@ pub struct MethodCallExpression {

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ConstructorExpression {
pub type_name: Path,
pub typ: UnresolvedType,
pub fields: Vec<(Ident, Expression)>,

/// This may be filled out during macro expansion
Expand Down Expand Up @@ -615,6 +621,7 @@ impl Display for ExpressionKind {
write!(f, "quote {{ {} }}", tokens.join(" "))
}
AsTraitPath(path) => write!(f, "{path}"),
InternedStatement(_) => write!(f, "?InternedStatement"),
}
}
}
Expand Down Expand Up @@ -717,7 +724,7 @@ impl Display for ConstructorExpression {
let fields =
self.fields.iter().map(|(ident, expr)| format!("{ident}: {expr}")).collect::<Vec<_>>();

write!(f, "({} {{ {} }})", self.type_name, fields.join(", "))
write!(f, "({} {{ {} }})", self.typ, fields.join(", "))
}
}

Expand Down
13 changes: 13 additions & 0 deletions noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,19 @@ impl UnresolvedType {
pub(crate) fn is_type_expression(&self) -> bool {
matches!(&self.typ, UnresolvedTypeData::Expression(_))
}

pub fn from_path(mut path: Path) -> Self {
let span = path.span;
let last_segment = path.segments.last_mut().unwrap();
let generics = last_segment.generics.take();
let generic_type_args = if let Some(generics) = generics {
GenericTypeArgs { ordered_args: generics, named_args: Vec::new() }
} else {
GenericTypeArgs::default()
};
let typ = UnresolvedTypeData::Named(path, generic_type_args, true);
UnresolvedType { typ, span }
}
}

impl UnresolvedTypeData {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ impl Pattern {
}
Some(Expression {
kind: ExpressionKind::Constructor(Box::new(ConstructorExpression {
type_name: path.clone(),
typ: UnresolvedType::from_path(path.clone()),
fields,
struct_type: None,
})),
Expand Down
3 changes: 2 additions & 1 deletion noir/noir-repo/compiler/noirc_frontend/src/ast/structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ use crate::token::SecondaryAttribute;
use iter_extended::vecmap;
use noirc_errors::Span;

use super::Documented;
use super::{Documented, ItemVisibility};

/// Ast node for a struct
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct NoirStruct {
pub name: Ident,
pub attributes: Vec<SecondaryAttribute>,
pub visibility: ItemVisibility,
pub generics: UnresolvedGenerics,
pub fields: Vec<Documented<StructField>>,
pub span: Span,
Expand Down
1 change: 1 addition & 0 deletions noir/noir-repo/compiler/noirc_frontend/src/ast/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub struct NoirTrait {
pub span: Span,
pub items: Vec<Documented<TraitItem>>,
pub attributes: Vec<SecondaryAttribute>,
pub visibility: ItemVisibility,
}

/// Any declaration inside the body of a trait that a user is required to
Expand Down
9 changes: 5 additions & 4 deletions noir/noir-repo/compiler/noirc_frontend/src/ast/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
InternedUnresolvedTypeData, QuotedTypeId,
},
parser::{Item, ItemKind, ParsedSubModule},
token::{CustomAtrribute, SecondaryAttribute, Tokens},
token::{CustomAttribute, SecondaryAttribute, Tokens},
ParsedModule, QuotedType,
};

Expand Down Expand Up @@ -461,7 +461,7 @@ pub trait Visitor {
true
}

fn visit_custom_attribute(&mut self, _: &CustomAtrribute, _target: AttributeTarget) {}
fn visit_custom_attribute(&mut self, _: &CustomAttribute, _target: AttributeTarget) {}
}

impl ParsedModule {
Expand Down Expand Up @@ -841,6 +841,7 @@ impl Expression {
ExpressionKind::Quote(tokens) => visitor.visit_quote(tokens),
ExpressionKind::Resolved(expr_id) => visitor.visit_resolved_expression(*expr_id),
ExpressionKind::Interned(id) => visitor.visit_interned_expression(*id),
ExpressionKind::InternedStatement(id) => visitor.visit_interned_statement(*id),
ExpressionKind::Error => visitor.visit_error_expression(),
}
}
Expand Down Expand Up @@ -948,7 +949,7 @@ impl ConstructorExpression {
}

pub fn accept_children(&self, visitor: &mut impl Visitor) {
self.type_name.accept(visitor);
self.typ.accept(visitor);

for (_field_name, expression) in &self.fields {
expression.accept(visitor);
Expand Down Expand Up @@ -1377,7 +1378,7 @@ impl SecondaryAttribute {
}
}

impl CustomAtrribute {
impl CustomAttribute {
pub fn accept(&self, target: AttributeTarget, visitor: &mut impl Visitor) {
visitor.visit_custom_attribute(self, target);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ impl<'context> Elaborator<'context> {
elaborator.function_context.push(FunctionContext::default());
elaborator.scopes.start_function();

elaborator.local_module = self.local_module;
elaborator.file = self.file;

setup(&mut elaborator);

elaborator.populate_scope_from_comptime_scopes();
Expand Down Expand Up @@ -316,7 +319,7 @@ impl<'context> Elaborator<'context> {
// If the function is varargs, push the type of the last slice element N times
// to account for N extra arguments.
let modifiers = interpreter.elaborator.interner.function_modifiers(&function);
let is_varargs = modifiers.attributes.is_varargs();
let is_varargs = modifiers.attributes.has_varargs();
let varargs_type = if is_varargs { parameters.pop() } else { None };

let varargs_elem_type = varargs_type.as_ref().and_then(|t| t.slice_element_type());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use rustc_hash::FxHashSet as HashSet;

use crate::{
ast::{
ArrayLiteral, ConstructorExpression, IfExpression, InfixExpression, Lambda,
UnresolvedTypeExpression,
ArrayLiteral, ConstructorExpression, IfExpression, InfixExpression, Lambda, UnaryOp,
UnresolvedTypeData, UnresolvedTypeExpression,
},
hir::{
comptime::{self, InterpreterError},
Expand All @@ -25,9 +25,9 @@ use crate::{
macros_api::{
BlockExpression, CallExpression, CastExpression, Expression, ExpressionKind, HirLiteral,
HirStatement, Ident, IndexExpression, Literal, MemberAccessExpression,
MethodCallExpression, PrefixExpression,
MethodCallExpression, PrefixExpression, StatementKind,
},
node_interner::{DefinitionKind, ExprId, FuncId, TraitMethodId},
node_interner::{DefinitionKind, ExprId, FuncId, InternedStatementKind, TraitMethodId},
token::Tokens,
QuotedType, Shared, StructType, Type,
};
Expand Down Expand Up @@ -67,6 +67,9 @@ impl<'context> Elaborator<'context> {
let expr = Expression::new(expr_kind.clone(), expr.span);
return self.elaborate_expression(expr);
}
ExpressionKind::InternedStatement(id) => {
return self.elaborate_interned_statement_as_expr(id, expr.span);
}
ExpressionKind::Error => (HirExpression::Error, Type::Error),
ExpressionKind::Unquote(_) => {
self.push_err(ResolverError::UnquoteUsedOutsideQuote { span: expr.span });
Expand All @@ -80,6 +83,29 @@ impl<'context> Elaborator<'context> {
(id, typ)
}

fn elaborate_interned_statement_as_expr(
&mut self,
id: InternedStatementKind,
span: Span,
) -> (ExprId, Type) {
match self.interner.get_statement_kind(id) {
StatementKind::Expression(expr) | StatementKind::Semi(expr) => {
self.elaborate_expression(expr.clone())
}
StatementKind::Interned(id) => self.elaborate_interned_statement_as_expr(*id, span),
StatementKind::Error => {
let expr = Expression::new(ExpressionKind::Error, span);
self.elaborate_expression(expr)
}
other => {
let statement = other.to_string();
self.push_err(ResolverError::InvalidInternedStatementInExpr { statement, span });
let expr = Expression::new(ExpressionKind::Error, span);
self.elaborate_expression(expr)
}
}
}

pub(super) fn elaborate_block(&mut self, block: BlockExpression) -> (HirExpression, Type) {
let (block, typ) = self.elaborate_block_expression(block);
(HirExpression::Block(block), typ)
Expand Down Expand Up @@ -248,10 +274,17 @@ impl<'context> Elaborator<'context> {
}

fn elaborate_prefix(&mut self, prefix: PrefixExpression, span: Span) -> (ExprId, Type) {
let rhs_span = prefix.rhs.span;

let (rhs, rhs_type) = self.elaborate_expression(prefix.rhs);
let trait_id = self.interner.get_prefix_operator_trait_method(&prefix.operator);

let operator = prefix.operator;

if let UnaryOp::MutableReference = operator {
self.check_can_mutate(rhs, rhs_span);
}

let expr =
HirExpression::Prefix(HirPrefixExpression { operator, rhs, trait_method_id: trait_id });
let expr_id = self.interner.push_expr(expr);
Expand All @@ -264,6 +297,26 @@ impl<'context> Elaborator<'context> {
(expr_id, typ)
}

fn check_can_mutate(&mut self, expr_id: ExprId, span: Span) {
let expr = self.interner.expression(&expr_id);
match expr {
HirExpression::Ident(hir_ident, _) => {
if let Some(definition) = self.interner.try_definition(hir_ident.id) {
if !definition.mutable {
self.push_err(TypeCheckError::CannotMutateImmutableVariable {
name: definition.name.clone(),
span,
});
}
}
}
HirExpression::MemberAccess(member_access) => {
self.check_can_mutate(member_access.lhs, span);
}
_ => (),
}
}

fn elaborate_index(&mut self, index_expr: IndexExpression) -> (HirExpression, Type) {
let span = index_expr.index.span;
let (index, index_type) = self.elaborate_expression(index_expr.index);
Expand Down Expand Up @@ -436,22 +489,43 @@ impl<'context> Elaborator<'context> {
&mut self,
constructor: ConstructorExpression,
) -> (HirExpression, Type) {
let span = constructor.typ.span;

// A constructor type can either be a Path or an interned UnresolvedType.
// We represent both as UnresolvedType (with Path being a Named UnresolvedType)
// and error if we don't get a Named path.
let mut typ = constructor.typ.typ;
if let UnresolvedTypeData::Interned(id) = typ {
typ = self.interner.get_unresolved_type_data(id).clone();
}
let UnresolvedTypeData::Named(mut path, generics, _) = typ else {
self.push_err(ResolverError::NonStructUsedInConstructor { typ: typ.to_string(), span });
return (HirExpression::Error, Type::Error);
};

let last_segment = path.segments.last_mut().unwrap();
if !generics.ordered_args.is_empty() {
last_segment.generics = Some(generics.ordered_args);
}

let exclude_last_segment = true;
self.check_unsupported_turbofish_usage(&constructor.type_name, exclude_last_segment);
self.check_unsupported_turbofish_usage(&path, exclude_last_segment);

let span = constructor.type_name.span();
let last_segment = constructor.type_name.last_segment();
let last_segment = path.last_segment();
let is_self_type = last_segment.ident.is_self_type_name();

let (r#type, struct_generics) = if let Some(struct_id) = constructor.struct_type {
let typ = self.interner.get_struct(struct_id);
let generics = typ.borrow().instantiate(self.interner);
(typ, generics)
} else {
match self.lookup_type_or_error(constructor.type_name) {
match self.lookup_type_or_error(path) {
Some(Type::Struct(r#type, struct_generics)) => (r#type, struct_generics),
Some(typ) => {
self.push_err(ResolverError::NonStructUsedInConstructor { typ, span });
self.push_err(ResolverError::NonStructUsedInConstructor {
typ: typ.to_string(),
span,
});
return (HirExpression::Error, Type::Error);
}
None => return (HirExpression::Error, Type::Error),
Expand Down
Loading

0 comments on commit 7ea4709

Please sign in to comment.