Skip to content

Commit

Permalink
Merge branch 'master' into mv/ssa-globals-1
Browse files Browse the repository at this point in the history
  • Loading branch information
vezenovm authored Jan 9, 2025
2 parents 74a7358 + 56c931a commit df5eef0
Show file tree
Hide file tree
Showing 22 changed files with 249 additions and 135 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/reports.yml
Original file line number Diff line number Diff line change
Expand Up @@ -303,11 +303,11 @@ jobs:
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-inner, take_average: true }
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-tail, take_average: true }
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-reset, take_average: true }
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-root }
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-root, take_average: true }
#- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-block-root }
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-block-merge }
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-private }
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-public }
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-block-merge, take_average: true }
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-private, take_average: true }
- project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-public, take_average: true }

name: External repo compilation and execution reports - ${{ matrix.project.repo }}/${{ matrix.project.path }}
steps:
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_evaluator/src/acir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2172,7 +2172,7 @@ impl<'a> Context<'a> {

let Type::Array(result_type, array_length) = dfg.type_of_value(result_ids[0])
else {
unreachable!("ICE: ToRadix result must be an array");
unreachable!("ICE: ToBits result must be an array");
};

self.acir_context
Expand Down
79 changes: 34 additions & 45 deletions compiler/noirc_frontend/src/elaborator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ use crate::{
TraitImplKind, TraitMethodId,
},
token::SecondaryAttribute,
Generics, Kind, ResolvedGeneric, Shared, StructType, Type, TypeBinding, TypeBindings,
UnificationError,
Generics, Kind, ResolvedGeneric, Type, TypeBinding, TypeBindings, UnificationError,
};

use super::{lints, path_resolution::PathResolutionItem, Elaborator, UnsafeBlockStatus};
Expand Down Expand Up @@ -1320,9 +1319,6 @@ impl<'context> Elaborator<'context> {
has_self_arg: bool,
) -> Option<HirMethodReference> {
match object_type.follow_bindings() {
Type::Struct(typ, _args) => {
self.lookup_struct_method(object_type, method_name, span, has_self_arg, typ)
}
// TODO: We should allow method calls on `impl Trait`s eventually.
// For now it is fine since they are only allowed on return types.
Type::TraitAsType(..) => {
Expand All @@ -1338,11 +1334,9 @@ impl<'context> Elaborator<'context> {
}
// Mutable references to another type should resolve to methods of their element type.
// This may be a struct or a primitive type.
Type::MutableReference(element) => self
.interner
.lookup_primitive_trait_method_mut(element.as_ref(), method_name, has_self_arg)
.map(HirMethodReference::FuncId)
.or_else(|| self.lookup_method(&element, method_name, span, has_self_arg)),
Type::MutableReference(element) => {
self.lookup_method(&element, method_name, span, has_self_arg)
}

// If we fail to resolve the object to a struct type, we have no way of type
// checking its arguments as we can't even resolve the name of the function
Expand All @@ -1354,39 +1348,29 @@ impl<'context> Elaborator<'context> {
None
}

other => match self.interner.lookup_primitive_method(&other, method_name, has_self_arg)
{
Some(method_id) => Some(HirMethodReference::FuncId(method_id)),
None => {
// It could be that this type is a composite type that is bound to a trait,
// for example `x: (T, U) ... where (T, U): SomeTrait`
// (so this case is a generalization of the NamedGeneric case)
self.lookup_method_in_trait_constraints(object_type, method_name, span)
}
},
other => {
self.lookup_struct_or_primitive_method(&other, method_name, span, has_self_arg)
}
}
}

fn lookup_struct_method(
fn lookup_struct_or_primitive_method(
&mut self,
object_type: &Type,
method_name: &str,
span: Span,
has_self_arg: bool,
typ: Shared<StructType>,
) -> Option<HirMethodReference> {
let id = typ.borrow().id;

// First search in the struct methods
if let Some(method_id) =
self.interner.lookup_direct_method(object_type, id, method_name, has_self_arg)
self.interner.lookup_direct_method(object_type, method_name, has_self_arg)
{
return Some(HirMethodReference::FuncId(method_id));
}

// Next lookup all matching trait methods.
let trait_methods =
self.interner.lookup_trait_methods(object_type, id, method_name, has_self_arg);
self.interner.lookup_trait_methods(object_type, method_name, has_self_arg);

if trait_methods.is_empty() {
// If we couldn't find any trait methods, search in
Expand All @@ -1397,26 +1381,31 @@ impl<'context> Elaborator<'context> {
return Some(HirMethodReference::FuncId(func_id));
}

// Otherwise it's an error
let has_field_with_function_type = typ
.borrow()
.get_fields_as_written()
.into_iter()
.any(|field| field.name.0.contents == method_name && field.typ.is_function());
if has_field_with_function_type {
self.push_err(TypeCheckError::CannotInvokeStructFieldFunctionType {
method_name: method_name.to_string(),
object_type: object_type.clone(),
span,
});
if let Type::Struct(struct_type, _) = object_type {
let has_field_with_function_type =
struct_type.borrow().get_fields_as_written().into_iter().any(|field| {
field.name.0.contents == method_name && field.typ.is_function()
});
if has_field_with_function_type {
self.push_err(TypeCheckError::CannotInvokeStructFieldFunctionType {
method_name: method_name.to_string(),
object_type: object_type.clone(),
span,
});
} else {
self.push_err(TypeCheckError::UnresolvedMethodCall {
method_name: method_name.to_string(),
object_type: object_type.clone(),
span,
});
}
return None;
} else {
self.push_err(TypeCheckError::UnresolvedMethodCall {
method_name: method_name.to_string(),
object_type: object_type.clone(),
span,
});
// It could be that this type is a composite type that is bound to a trait,
// for example `x: (T, U) ... where (T, U): SomeTrait`
// (so this case is a generalization of the NamedGeneric case)
return self.lookup_method_in_trait_constraints(object_type, method_name, span);
}
return None;
}

// We found some trait methods... but is only one of them currently in scope?
Expand Down Expand Up @@ -1526,7 +1515,7 @@ impl<'context> Elaborator<'context> {
) -> Option<HirMethodReference> {
let func_id = match self.current_item {
Some(DependencyId::Function(id)) => id,
_ => panic!("unexpected method outside a function"),
_ => panic!("unexpected method outside a function: {method_name}"),
};
let func_meta = self.interner.function_meta(&func_id);

Expand Down
22 changes: 22 additions & 0 deletions compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ impl<'local, 'context> Interpreter<'local, 'context> {
"struct_def_set_fields" => struct_def_set_fields(interner, arguments, location),
"to_be_radix" => to_be_radix(arguments, return_type, location),
"to_le_radix" => to_le_radix(arguments, return_type, location),
"to_be_bits" => to_be_bits(arguments, return_type, location),
"to_le_bits" => to_le_bits(arguments, return_type, location),
"trait_constraint_eq" => trait_constraint_eq(arguments, location),
"trait_constraint_hash" => trait_constraint_hash(arguments, location),
"trait_def_as_trait_constraint" => {
Expand Down Expand Up @@ -776,6 +778,26 @@ fn quoted_tokens(arguments: Vec<(Value, Location)>, location: Location) -> IResu
))
}

fn to_be_bits(
arguments: Vec<(Value, Location)>,
return_type: Type,
location: Location,
) -> IResult<Value> {
let value = check_one_argument(arguments, location)?;
let radix = (Value::U32(2), value.1);
to_be_radix(vec![value, radix], return_type, location)
}

fn to_le_bits(
arguments: Vec<(Value, Location)>,
return_type: Type,
location: Location,
) -> IResult<Value> {
let value = check_one_argument(arguments, location)?;
let radix = (Value::U32(2), value.1);
to_le_radix(vec![value, radix], return_type, location)
}

fn to_be_radix(
arguments: Vec<(Value, Location)>,
return_type: Type,
Expand Down
2 changes: 2 additions & 0 deletions compiler/noirc_frontend/src/hir/comptime/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use crate::node_interner::FuncId;
use crate::parse_program;

/// Create an interpreter for a code snippet and pass it to a test function.
///
/// The stdlib is not made available as a dependency.
pub(crate) fn with_interpreter<T>(
src: &str,
f: impl FnOnce(&mut Interpreter, FuncId, &[(CompilationError, FileId)]) -> T,
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/hir_def/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1862,7 +1862,7 @@ impl Type {
if let (Type::Array(_size, element1), Type::Slice(element2)) = (&this, &target) {
// We can only do the coercion if the `as_slice` method exists.
// This is usually true, but some tests don't have access to the standard library.
if let Some(as_slice) = interner.lookup_primitive_method(&this, "as_slice", true) {
if let Some(as_slice) = interner.lookup_direct_method(&this, "as_slice", true) {
// Still have to ensure the element types match.
// Don't need to issue an error here if not, it will be done in unify_with_coercions
let mut bindings = TypeBindings::new();
Expand Down
Loading

0 comments on commit df5eef0

Please sign in to comment.