Skip to content

Commit

Permalink
Merge branch 'master' into mv/treat-globals-as-const-in-dfg
Browse files Browse the repository at this point in the history
  • Loading branch information
vezenovm authored Jan 15, 2025
2 parents 2bbed37 + 3b8d1da commit e54caf6
Show file tree
Hide file tree
Showing 14 changed files with 386 additions and 22 deletions.
30 changes: 26 additions & 4 deletions .github/workflows/reports.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,19 @@ jobs:
- name: Generate Brillig bytecode size report
working-directory: ./test_programs
run: |
./gates_report_brillig.sh
mv gates_report_brillig.json ../gates_report_brillig.json
mkdir ./reports
./gates_report_brillig.sh 9223372036854775807
jq '.programs |= map(.package_name |= (. + "_inliner_max"))' gates_report_brillig.json > ./reports/gates_report_brillig_inliner_max.json
./gates_report_brillig.sh 0
jq '.programs |= map(.package_name |= (. + "_inliner_zero"))' gates_report_brillig.json > ./reports/gates_report_brillig_inliner_zero.json
./gates_report_brillig.sh -9223372036854775808
jq '.programs |= map(.package_name |= (. + "_inliner_min"))' gates_report_brillig.json > ./reports/gates_report_brillig_inliner_min.json
# Merge all reports
jq -s '{ programs: map(.programs) | add }' ./reports/* > ../gates_report_brillig.json
- name: Compare Brillig bytecode size reports
id: brillig_bytecode_diff
Expand Down Expand Up @@ -165,8 +176,19 @@ jobs:
- name: Generate Brillig execution report
working-directory: ./test_programs
run: |
./gates_report_brillig_execution.sh
mv gates_report_brillig_execution.json ../gates_report_brillig_execution.json
mkdir ./reports
./gates_report_brillig_execution.sh 9223372036854775807
jq '.programs |= map(.package_name |= (. + "_inliner_max"))' gates_report_brillig_execution.json > ./reports/gates_report_brillig_execution_inliner_max.json
./gates_report_brillig_execution.sh 0
jq '.programs |= map(.package_name |= (. + "_inliner_zero"))' gates_report_brillig_execution.json > ./reports/gates_report_brillig_execution_inliner_zero.json
./gates_report_brillig_execution.sh -9223372036854775808
jq '.programs |= map(.package_name |= (. + "_inliner_min"))' gates_report_brillig_execution.json > ./reports/gates_report_brillig_execution_inliner_min.json
# Merge all reports
jq -s '{ programs: map(.programs) | add }' ./reports/* > ../gates_report_brillig_execution.json
- name: Compare Brillig execution reports
id: brillig_execution_diff
Expand Down
54 changes: 51 additions & 3 deletions compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,10 @@ impl<'local, 'context> Interpreter<'local, 'context> {
"struct_def_add_generic" => struct_def_add_generic(interner, arguments, location),
"struct_def_as_type" => struct_def_as_type(interner, arguments, location),
"struct_def_eq" => struct_def_eq(arguments, location),
"struct_def_fields" => struct_def_fields(interner, arguments, location),
"struct_def_fields" => struct_def_fields(interner, arguments, location, call_stack),
"struct_def_fields_as_written" => {
struct_def_fields_as_written(interner, arguments, location)
}
"struct_def_generics" => struct_def_generics(interner, arguments, location),
"struct_def_has_named_attribute" => {
struct_def_has_named_attribute(interner, arguments, location)
Expand Down Expand Up @@ -482,12 +485,57 @@ fn struct_def_has_named_attribute(
Ok(Value::Bool(has_named_attribute(&name, interner.struct_attributes(&struct_id))))
}

/// fn fields(self) -> [(Quoted, Type)]
/// Returns (name, type) pairs of each field of this StructDefinition
/// fn fields(self, generic_args: [Type]) -> [(Quoted, Type)]
/// Returns (name, type) pairs of each field of this StructDefinition.
/// Applies the given generic arguments to each field.
fn struct_def_fields(
interner: &mut NodeInterner,
arguments: Vec<(Value, Location)>,
location: Location,
call_stack: &im::Vector<Location>,
) -> IResult<Value> {
let (typ, generic_args) = check_two_arguments(arguments, location)?;
let struct_id = get_struct(typ)?;
let struct_def = interner.get_struct(struct_id);
let struct_def = struct_def.borrow();

let args_location = generic_args.1;
let generic_args = get_slice(interner, generic_args)?.0;
let generic_args = try_vecmap(generic_args, |arg| get_type((arg, args_location)))?;

let actual = generic_args.len();
let expected = struct_def.generics.len();
if actual != expected {
let s = if expected == 1 { "" } else { "s" };
let was_were = if actual == 1 { "was" } else { "were" };
let message = Some(format!("`StructDefinition::fields` expected {expected} generic{s} for `{}` but {actual} {was_were} given", struct_def.name));
let location = args_location;
let call_stack = call_stack.clone();
return Err(InterpreterError::FailingConstraint { message, location, call_stack });
}

let mut fields = im::Vector::new();

for (field_name, field_type) in struct_def.get_fields(&generic_args) {
let name = Value::Quoted(Rc::new(vec![Token::Ident(field_name)]));
fields.push_back(Value::Tuple(vec![name, Value::Type(field_type)]));
}

let typ = Type::Slice(Box::new(Type::Tuple(vec![
Type::Quoted(QuotedType::Quoted),
Type::Quoted(QuotedType::Type),
])));
Ok(Value::Slice(fields, typ))
}

/// fn fields_as_written(self) -> [(Quoted, Type)]
/// Returns (name, type) pairs of each field of this StructDefinition.
///
/// Note that any generic arguments won't be applied: if you need them to be, use `fields`.
fn struct_def_fields_as_written(
interner: &mut NodeInterner,
arguments: Vec<(Value, Location)>,
location: Location,
) -> IResult<Value> {
let argument = check_one_argument(arguments, location)?;
let struct_id = get_struct(argument)?;
Expand Down
13 changes: 12 additions & 1 deletion docs/docs/noir/standard_library/meta/struct_def.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,18 @@ comptime fn example(foo: StructDefinition) {

#include_code fields noir_stdlib/src/meta/struct_def.nr rust

Returns each field of this struct as a pair of (field name, field type).
Returns (name, type) pairs of each field in this struct.
Any generic types used in each field type is automatically substituted with the
provided generic arguments.

### fields_as_written

#include_code fields_as_written noir_stdlib/src/meta/struct_def.nr rust

Returns (name, type) pairs of each field in this struct. Each type is as-is
with any generic arguments unchanged. Unless the field types are not needed,
users should generally prefer to use `StructDefinition::fields` over this
function if possible.

### has_named_attribute

Expand Down
2 changes: 1 addition & 1 deletion noir_stdlib/src/cmp.nr
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ comptime fn derive_eq(s: StructDefinition) -> Quoted {
let signature = quote { fn eq(_self: Self, _other: Self) -> bool };
let for_each_field = |name| quote { (_self.$name == _other.$name) };
let body = |fields| {
if s.fields().len() == 0 {
if s.fields_as_written().len() == 0 {
quote { true }
} else {
fields
Expand Down
6 changes: 3 additions & 3 deletions noir_stdlib/src/meta/mod.nr
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub comptime fn make_trait_impl<Env1, Env2>(
let where_clause = s.generics().map(|name| quote { $name: $trait_name }).join(quote {,});

// `for_each_field(field1) $join_fields_with for_each_field(field2) $join_fields_with ...`
let fields = s.fields().map(|f: (Quoted, Type)| {
let fields = s.fields_as_written().map(|f: (Quoted, Type)| {
let name = f.0;
for_each_field(name)
});
Expand Down Expand Up @@ -155,7 +155,7 @@ mod tests {

comptime fn derive_field_count(s: StructDefinition) -> Quoted {
let typ = s.as_type();
let field_count = s.fields().len();
let field_count = s.fields_as_written().len();
quote {
impl FieldCount for $typ {
fn field_count() -> u32 {
Expand All @@ -174,7 +174,7 @@ mod tests {

comptime fn assert_field_is_type(s: StructDefinition, typ: Type) {
// Assert the first field in `s` has type `typ`
let fields = s.fields();
let fields = s.fields([]);
assert_eq(fields[0].1, typ);
}
// docs:end:annotation-arguments-example
Expand Down
16 changes: 13 additions & 3 deletions noir_stdlib/src/meta/struct_def.nr
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,23 @@ impl StructDefinition {
pub comptime fn generics(self) -> [Type] {}
// docs:end:generics

/// Returns (name, type) pairs of each field in this struct. Each type is as-is
/// with any generic arguments unchanged.
/// Returns (name, type) pairs of each field in this struct.
/// Any generic types used in each field type is automatically substituted with the
/// provided generic arguments.
#[builtin(struct_def_fields)]
// docs:start:fields
pub comptime fn fields(self) -> [(Quoted, Type)] {}
pub comptime fn fields(self, generic_args: [Type]) -> [(Quoted, Type)] {}
// docs:end:fields

/// Returns (name, type) pairs of each field in this struct. Each type is as-is
/// with any generic arguments unchanged. Unless the field types are not needed,
/// users should generally prefer to use `StructDefinition::fields` over this
/// function if possible.
#[builtin(struct_def_fields_as_written)]
// docs:start:fields_as_written
pub comptime fn fields_as_written(self) -> [(Quoted, Type)] {}
// docs:end:fields_as_written

#[builtin(struct_def_module)]
// docs:start:module
pub comptime fn module(self) -> Module {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub struct I32AndField {
comptime fn my_comptime_fn(typ: StructDefinition) {
let _ = typ.as_type();
assert_eq(typ.generics().len(), 3);
assert_eq(typ.fields().len(), 2);
assert_eq(typ.fields_as_written().len(), 2);
assert_eq(typ.name(), quote { MyType });
}

Expand Down Expand Up @@ -44,4 +44,22 @@ mod foo {
// docs:end:add-generic-example
}

fn main() {}
fn main() {
comptime {
let typ = quote { MyType<i8, i16, i32> }.as_type();
let (struct_def, generics) = typ.as_struct().unwrap();

let fields = struct_def.fields(generics);
assert_eq(fields.len(), 2);

let (field1_name, field1_type) = fields[0];
let (field2_name, field2_type) = fields[1];

assert_eq(field1_name, quote { field1 });
assert_eq(field2_name, quote { field2 });

// Ensure .fields(generics) actually performs substitutions on generics
assert_eq(field1_type, quote { [i8; 10] }.as_type());
assert_eq(field2_type, quote { (i16, i32) }.as_type());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ fn main() {
let foo = Foo { x: 0 };
let foo_type = type_of(foo);
let (struct_definition, generics) = foo_type.as_struct().unwrap();
let fields = struct_definition.fields();
let fields = struct_definition.fields(generics);
assert_eq(fields.len(), 1);

assert_eq(generics.len(), 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ comptime fn derive_default(typ: StructDefinition) -> Quoted {
);

let type_name = typ.as_type();
let fields = typ.fields();
let fields = typ.fields_as_written();

let fields = join(make_field_exprs(fields));

Expand Down
2 changes: 1 addition & 1 deletion test_programs/gates_report_brillig.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ done

echo "]" >> Nargo.toml

nargo info --force-brillig --json | jq -r ".programs[].functions = []" > gates_report_brillig.json
nargo info --silence-warnings --force-brillig --json --inliner-aggressiveness $1 | jq -r ".programs[].functions = []" > gates_report_brillig.json

rm Nargo.toml
2 changes: 1 addition & 1 deletion test_programs/gates_report_brillig_execution.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ done

echo "]" >> Nargo.toml

nargo info --profile-execution --json | jq -r ".programs[].functions = []" > gates_report_brillig_execution.json
nargo info --silence-warnings --profile-execution --json --inliner-aggressiveness $1 | jq -r ".programs[].functions = []" > gates_report_brillig_execution.json

rm Nargo.toml
3 changes: 3 additions & 0 deletions tooling/lsp/src/requests/code_action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use super::{process_request, to_lsp_location};
mod fill_struct_fields;
mod implement_missing_members;
mod import_or_qualify;
mod import_trait;
mod remove_bang_from_call;
mod remove_unused_import;
mod tests;
Expand Down Expand Up @@ -285,6 +286,8 @@ impl<'a> Visitor for CodeActionFinder<'a> {
self.remove_bang_from_call(method_call.method_name.span());
}

self.import_trait_in_method_call(method_call);

true
}
}
Loading

0 comments on commit e54caf6

Please sign in to comment.