Skip to content

Commit

Permalink
feat: Sync from noir (#8635)
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: Implement type paths (noir-lang/noir#6093)
feat: let LSP suggest macro calls too
(noir-lang/noir#6090)
fix: Unify macro result type with actual type
(noir-lang/noir#6086)
fix: Initialise databus using return values
(noir-lang/noir#6074)
END_COMMIT_OVERRIDE

---------

Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>
Co-authored-by: TomAFrench <tom@tomfren.ch>
  • Loading branch information
3 people authored Sep 19, 2024
1 parent 3e0067a commit b330e87
Show file tree
Hide file tree
Showing 35 changed files with 560 additions and 180 deletions.
2 changes: 1 addition & 1 deletion .noir-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
78262c96d5b116c77e50653f9059da60824db812
2174ffb92b5d88e7e0926c91f42bc7f849e8ddc1
Original file line number Diff line number Diff line change
Expand Up @@ -290,11 +290,11 @@ global TUBE_PROOF_LENGTH = RECURSIVE_PROOF_LENGTH; // in the future these can di
global VERIFICATION_KEY_LENGTH_IN_FIELDS = 128;

// The length is 2 + AvmFlavor::NUM_PRECOMPUTED_ENTITIES * 4
global AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS = 2 + 16 * 4;
global AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS: u32 = 2 + 16 * 4;
// `AVM_PROOF_LENGTH_IN_FIELDS` must be updated when AVM circuit changes.
// To determine latest value, hover `COMPUTED_AVM_PROOF_LENGTH_IN_FIELDS`
// in barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.hpp
global AVM_PROOF_LENGTH_IN_FIELDS = 3812;
global AVM_PROOF_LENGTH_IN_FIELDS: u32 = 3812;
/**
* Enumerate the hash_indices which are used for pedersen hashing.
* We start from 1 to avoid the default generators. The generator indices are listed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,7 @@ pub fn inject_note_exports(
note.borrow().id,
"get_note_type_id",
false,
true,
)
.ok_or((
AztecMacroError::CouldNotExportStorageLayout {
Expand Down
1 change: 1 addition & 0 deletions noir/noir-repo/aztec_macros/src/transforms/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ pub fn assign_storage_slots(
storage_struct.borrow().id,
"init",
false,
true,
)
.ok_or((
AztecMacroError::CouldNotAssignStorageSlots {
Expand Down
6 changes: 6 additions & 0 deletions noir/noir-repo/aztec_macros/src/utils/parse_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,12 @@ fn empty_expression(expression: &mut Expression) {
empty_unresolved_type(&mut path.typ);
empty_path(&mut path.trait_path);
empty_ident(&mut path.impl_item);
empty_type_args(&mut path.trait_generics);
}
ExpressionKind::TypePath(path) => {
empty_unresolved_type(&mut path.typ);
empty_ident(&mut path.item);
empty_type_args(&mut path.turbofish);
}
ExpressionKind::Quote(..)
| ExpressionKind::Resolved(_)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1944,6 +1944,15 @@ impl<F: AcirField> AcirContext<F> {
Ok(())
}

/// Insert the MemoryInit for the Return Data array, using the provided witnesses
pub(crate) fn initialize_return_data(&mut self, block_id: BlockId, init: Vec<Witness>) {
self.acir_ir.push_opcode(Opcode::MemoryInit {
block_id,
init,
block_type: BlockType::ReturnData,
});
}

/// Initializes an array in memory with the given values `optional_values`.
/// If `optional_values` is empty, then the array is initialized with zeros.
pub(crate) fn initialize_array(
Expand Down
68 changes: 33 additions & 35 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,16 +434,9 @@ impl<'a> Context<'a> {
for instruction_id in entry_block.instructions() {
warnings.extend(self.convert_ssa_instruction(*instruction_id, dfg, ssa, brillig)?);
}

let (return_vars, return_warnings) =
self.convert_ssa_return(entry_block.unwrap_terminator(), dfg)?;

let call_data_arrays: Vec<ValueId> =
self.data_bus.call_data.iter().map(|cd| cd.array_id).collect();
for call_data_array in call_data_arrays {
self.ensure_array_is_initialized(call_data_array, dfg)?;
}

// TODO: This is a naive method of assigning the return values to their witnesses as
// we're likely to get a number of constraints which are asserting one witness to be equal to another.
//
Expand All @@ -452,13 +445,42 @@ impl<'a> Context<'a> {
self.acir_context.assert_eq_var(*witness_var, return_var, None)?;
}

self.initialize_databus(&return_witnesses, dfg)?;
warnings.extend(return_warnings);
warnings.extend(self.acir_context.warnings.clone());

// Add the warnings from the alter Ssa passes
Ok(self.acir_context.finish(input_witness, return_witnesses, warnings))
}

fn initialize_databus(
&mut self,
witnesses: &Vec<Witness>,
dfg: &DataFlowGraph,
) -> Result<(), RuntimeError> {
// Initialize return_data using provided witnesses
if let Some(return_data) = self.data_bus.return_data {
let block_id = self.block_id(&return_data);
let already_initialized = self.initialized_arrays.contains(&block_id);
if !already_initialized {
// We hijack ensure_array_is_initialized() because we want the return data to use the return value witnesses,
// but the databus contains the computed values instead, that have just been asserted to be equal to the return values.
// We do not use initialize_array either for the case where a constant value is returned.
// In that case, the constant value has already been assigned a witness and the returned acir vars will be
// converted to it, instead of the corresponding return value witness.
self.acir_context.initialize_return_data(block_id, witnesses.to_owned());
}
}

// Initialize call_data
let call_data_arrays: Vec<ValueId> =
self.data_bus.call_data.iter().map(|cd| cd.array_id).collect();
for call_data_array in call_data_arrays {
self.ensure_array_is_initialized(call_data_array, dfg)?;
}
Ok(())
}

fn convert_brillig_main(
mut self,
main_func: &Function,
Expand Down Expand Up @@ -1792,19 +1814,9 @@ impl<'a> Context<'a> {
_ => unreachable!("ICE: Program must have a singular return"),
};

return_values.iter().fold(0, |acc, value_id| {
let is_databus = self
.data_bus
.return_data
.map_or(false, |return_databus| dfg[*value_id] == dfg[return_databus]);

if is_databus {
// We do not return value for the data bus.
acc
} else {
acc + dfg.type_of_value(*value_id).flattened_size()
}
})
return_values
.iter()
.fold(0, |acc, value_id| acc + dfg.type_of_value(*value_id).flattened_size())
}

/// Converts an SSA terminator's return values into their ACIR representations
Expand All @@ -1824,27 +1836,13 @@ impl<'a> Context<'a> {
let mut has_constant_return = false;
let mut return_vars: Vec<AcirVar> = Vec::new();
for value_id in return_values {
let is_databus = self
.data_bus
.return_data
.map_or(false, |return_databus| dfg[*value_id] == dfg[return_databus]);
let value = self.convert_value(*value_id, dfg);

// `value` may or may not be an array reference. Calling `flatten` will expand the array if there is one.
let acir_vars = self.acir_context.flatten(value)?;
for (acir_var, _) in acir_vars {
has_constant_return |= self.acir_context.is_constant(&acir_var);
if is_databus {
// We do not return value for the data bus.
self.ensure_array_is_initialized(
self.data_bus.return_data.expect(
"`is_databus == true` implies `data_bus.return_data` is `Some`",
),
dfg,
)?;
} else {
return_vars.push(acir_var);
}
return_vars.push(acir_var);
}
}

Expand Down
14 changes: 13 additions & 1 deletion noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use acvm::{acir::AcirField, FieldElement};
use iter_extended::vecmap;
use noirc_errors::{Span, Spanned};

use super::{AsTraitPath, UnaryRhsMemberAccess};
use super::{AsTraitPath, TypePath, UnaryRhsMemberAccess};

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExpressionKind {
Expand All @@ -38,6 +38,7 @@ pub enum ExpressionKind {
Comptime(BlockExpression, Span),
Unsafe(BlockExpression, Span),
AsTraitPath(AsTraitPath),
TypePath(TypePath),

// This variant is only emitted when inlining the result of comptime
// code. It is used to translate function values back into the AST while
Expand Down Expand Up @@ -621,6 +622,7 @@ impl Display for ExpressionKind {
write!(f, "quote {{ {} }}", tokens.join(" "))
}
AsTraitPath(path) => write!(f, "{path}"),
TypePath(path) => write!(f, "{path}"),
InternedStatement(_) => write!(f, "?InternedStatement"),
}
}
Expand Down Expand Up @@ -787,6 +789,16 @@ impl Display for AsTraitPath {
}
}

impl Display for TypePath {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}::{}", self.typ, self.item)?;
if !self.turbofish.is_empty() {
write!(f, "::{}", self.turbofish)?;
}
Ok(())
}
}

impl FunctionDefinition {
pub fn normal(
name: &Ident,
Expand Down
10 changes: 10 additions & 0 deletions noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,16 @@ pub struct AsTraitPath {
pub impl_item: Ident,
}

/// A special kind of path in the form `Type::ident::<turbofish>`
/// Unlike normal paths, the type here can be a primitive type or
/// interned type.
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct TypePath {
pub typ: UnresolvedType,
pub item: Ident,
pub turbofish: GenericTypeArgs,
}

// Note: Path deliberately doesn't implement Recoverable.
// No matter which default value we could give in Recoverable::error,
// it would most likely cause further errors during name resolution
Expand Down
20 changes: 19 additions & 1 deletion noir/noir-repo/compiler/noirc_frontend/src/ast/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{

use super::{
FunctionReturnType, GenericTypeArgs, IntegerBitSize, ItemVisibility, Pattern, Signedness,
TraitImplItemKind, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType,
TraitImplItemKind, TypePath, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType,
UnresolvedTypeData, UnresolvedTypeExpression,
};

Expand Down Expand Up @@ -340,6 +340,10 @@ pub trait Visitor {
true
}

fn visit_type_path(&mut self, _: &TypePath, _: Span) -> bool {
true
}

fn visit_unresolved_type(&mut self, _: &UnresolvedType) -> bool {
true
}
Expand Down Expand Up @@ -838,6 +842,7 @@ impl Expression {
ExpressionKind::AsTraitPath(as_trait_path) => {
as_trait_path.accept(self.span, visitor);
}
ExpressionKind::TypePath(path) => path.accept(self.span, visitor),
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),
Expand Down Expand Up @@ -1208,6 +1213,19 @@ impl AsTraitPath {
}
}

impl TypePath {
pub fn accept(&self, span: Span, visitor: &mut impl Visitor) {
if visitor.visit_type_path(self, span) {
self.accept_children(visitor);
}
}

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

impl UnresolvedType {
pub fn accept(&self, visitor: &mut impl Visitor) {
if visitor.visit_unresolved_type(self) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::{
HirArrayLiteral, HirBinaryOp, HirBlockExpression, HirCallExpression, HirCastExpression,
HirConstructorExpression, HirExpression, HirIfExpression, HirIndexExpression,
HirInfixExpression, HirLambda, HirMemberAccess, HirMethodCallExpression,
HirMethodReference, HirPrefixExpression,
HirPrefixExpression,
},
traits::TraitConstraint,
},
Expand Down Expand Up @@ -76,6 +76,7 @@ impl<'context> Elaborator<'context> {
(HirExpression::Error, Type::Error)
}
ExpressionKind::AsTraitPath(_) => todo!("Implement AsTraitPath"),
ExpressionKind::TypePath(path) => return self.elaborate_type_path(path),
};
let id = self.interner.push_expr(hir_expr);
self.interner.push_expr_location(id, expr.span, self.file);
Expand Down Expand Up @@ -406,21 +407,13 @@ impl<'context> Elaborator<'context> {

let method_name_span = method_call.method_name.span();
let method_name = method_call.method_name.0.contents.as_str();
match self.lookup_method(&object_type, method_name, span) {
match self.lookup_method(&object_type, method_name, span, true) {
Some(method_ref) => {
// Automatically add `&mut` if the method expects a mutable reference and
// the object is not already one.
let func_id = match &method_ref {
HirMethodReference::FuncId(func_id) => *func_id,
HirMethodReference::TraitMethodId(method_id, _) => {
let id = self.interner.trait_method_id(*method_id);
let definition = self.interner.definition(id);
let DefinitionKind::Function(func_id) = definition.kind else {
unreachable!("Expected trait function to be a DefinitionKind::Function")
};
func_id
}
};
let func_id = method_ref
.func_id(self.interner)
.expect("Expected trait function to be a DefinitionKind::Function");

let generics = if func_id != FuncId::dummy_id() {
let function_type = self.interner.function_meta(&func_id).typ.clone();
Expand Down Expand Up @@ -478,7 +471,17 @@ impl<'context> Elaborator<'context> {

// Type check the new call now that it has been changed from a method call
// to a function call. This way we avoid duplicating code.
let typ = self.type_check_call(&function_call, func_type, function_args, span);
let mut typ = self.type_check_call(&function_call, func_type, function_args, span);
if is_macro_call {
if self.in_comptime_context() {
typ = self.interner.next_type_variable();
} else {
let args = function_call.arguments.clone();
return self
.call_macro(function_call.func, args, location, typ)
.unwrap_or_else(|| (HirExpression::Error, Type::Error));
}
}
(HirExpression::Call(function_call), typ)
}
None => (HirExpression::Error, Type::Error),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ pub struct Elaborator<'context> {

def_maps: &'context mut DefMaps,

file: FileId,
pub(crate) file: FileId,

in_unsafe_block: bool,
nested_loops: usize,
Expand Down
Loading

0 comments on commit b330e87

Please sign in to comment.