Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions compiler/noirc_frontend/src/monomorphization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2754,12 +2754,6 @@ pub fn append_printable_type_info_for_type(typ: Type, arguments: &mut Vec<ast::E
}

fn append_printable_type_info_inner(typ: &Type, arguments: &mut Vec<ast::Expression>) {
// Disallow printing slices and mutable references for consistency,
// since they cannot be passed from ACIR into Brillig
if matches!(typ, HirType::Reference(..)) {
unreachable!("println and format strings do not support references.");
}

let printable_type: PrintableType = typ.into();
let abi_as_string =
serde_json::to_string(&printable_type).expect("ICE: expected PrintableType to serialize");
Expand Down
44 changes: 41 additions & 3 deletions compiler/noirc_printable_type/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,14 +371,21 @@ pub fn decode_printable_value<F: AcirField>(
PrintableValue::Struct(struct_map)
}
PrintableType::Function { env, .. } => {
// we want to consume the fields from the environment, but for now they are not actually printed
// We want to consume the fields from the environment, but for now they are not actually printed.
let _env = decode_printable_value(field_iterator, env);
let func_id = field_iterator.next().expect("not enough data: expected function ID");
PrintableValue::Field(func_id)
}
PrintableType::Reference { typ, .. } => {
// we decode the reference, but it's not really used for printing
decode_printable_value(field_iterator, typ)
// We decode the reference, but it's not actually used for printing.
// The reference consists of varying number of fields, depending on type.
let num_fields = flattened_reference_size(typ);
for i in 0..num_fields {
let _ = field_iterator
.next()
.unwrap_or_else(|| panic!("not enough data: expected reference field [{i}]"));
}
PrintableValue::Other
}
PrintableType::Unit => PrintableValue::Field(F::zero()),
PrintableType::Enum { name: _, variants } => {
Expand Down Expand Up @@ -518,6 +525,37 @@ fn fetch_printable_type<F: AcirField>(
}
}

/// Calculate the number of fields used represent a reference to a type.
fn flattened_reference_size(typ: &PrintableType) -> usize {
match typ {
PrintableType::Tuple { types } => types.iter().map(flattened_reference_size).sum(),
PrintableType::Struct { fields, .. } => {
fields.iter().map(|(_, typ)| flattened_reference_size(typ)).sum()
}
PrintableType::Reference { typ, .. } => flattened_reference_size(typ),
PrintableType::Unit => 0,
PrintableType::Array { .. }
| PrintableType::String { .. }
| PrintableType::Boolean
| PrintableType::Field
| PrintableType::Function { .. }
| PrintableType::SignedInteger { .. }
| PrintableType::UnsignedInteger { .. }
| PrintableType::FmtString { .. } => 1,
PrintableType::Slice { .. } => 2, // length + pointer
PrintableType::Enum { .. } => {
// This is tricky because enums are encoded as [tag, field1, field2, ...],
// however when we have a reference to an enum variant, then even the tag
// is just a memory address, so we can't use its value to decide how many
// fields to consume.
// For example a tuple like `Bar::Baz((1, [2, 3]))` would be encoded as [0, 1, [2, 3]],
// where 0 means this is the first variant in the `Bar` enum,
// but a reference to it would be like [36065, 36057, 36058].
todo!("flattened reference size for enums is not implemented");
}
}
}

#[cfg(test)]
mod tests {
use acvm::FieldElement;
Expand Down
8 changes: 8 additions & 0 deletions test_programs/execution_success/regression_9578/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "regression_9578"
type = "bin"
authors = [""]
compiler_unstable_features = ["enums"]


[dependencies]
33 changes: 33 additions & 0 deletions test_programs/execution_success/regression_9578/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
struct Foo {
a: u32,
b: (bool, [u64; 2]),
c: [u64; 3],
}

// Printing references to enums don't work at the moment,
// because instead of the tag, we get the address of the tag,
// and we can't tell how many fields follow.
// enum Bar {
// Baz((u32, [u32; 2])),
// }

unconstrained fn main() {
show(1, ());
show(2, 123);
show(3, [1, 2, 3]);
show(4, (1, 2, 3));
show(5, [(1, 2), (3, 4)]);
show(6, ((1, 2), [3]));
show(7, "123");
show(8, (&mut (1, 2), 3));
show(9, &[1, 2, 3]);
show(9, &[(1, 2), (3, 4)]);
show(10, Foo { a: 1, b: (true, [3, 4]), c: [5, 6, 7] });
// show(11, Bar::Baz((1, [2, 3])));
}

unconstrained fn show<T>(case: u32, mut value: T) {
// Print a mutable reference and then the same type on its own,
// to see that data can continue after the reference.
println((case, &mut value, value))
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading