Skip to content

Commit 92a4c5d

Browse files
authored
chore: pull frontend changes from sync PR (#9935)
Please read [contributing guidelines](CONTRIBUTING.md) and remove this line.
1 parent b12d3e4 commit 92a4c5d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+3264
-1776
lines changed

noir/noir-repo/Cargo.lock

+14-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use iter_extended::vecmap;
66
use noirc_abi::{
77
Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue, AbiVisibility, Sign,
88
};
9+
use noirc_errors::Span;
910
use noirc_evaluator::ErrorType;
1011
use noirc_frontend::ast::{Signedness, Visibility};
1112
use noirc_frontend::TypeBinding;
@@ -40,11 +41,21 @@ pub(super) fn gen_abi(
4041
Abi { parameters, return_type, error_types }
4142
}
4243

44+
// Get the Span of the root crate's main function, or else a dummy span if that fails
45+
fn get_main_function_span(context: &Context) -> Span {
46+
if let Some(func_id) = context.get_main_function(context.root_crate_id()) {
47+
context.function_meta(&func_id).location.span
48+
} else {
49+
Span::default()
50+
}
51+
}
52+
4353
fn build_abi_error_type(context: &Context, typ: ErrorType) -> AbiErrorType {
4454
match typ {
4555
ErrorType::Dynamic(typ) => {
4656
if let Type::FmtString(len, item_types) = typ {
47-
let length = len.evaluate_to_u32().expect("Cannot evaluate fmt length");
57+
let span = get_main_function_span(context);
58+
let length = len.evaluate_to_u32(span).expect("Cannot evaluate fmt length");
4859
let Type::Tuple(item_types) = item_types.as_ref() else {
4960
unreachable!("FmtString items must be a tuple")
5061
};
@@ -63,8 +74,9 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType {
6374
match typ {
6475
Type::FieldElement => AbiType::Field,
6576
Type::Array(size, typ) => {
77+
let span = get_main_function_span(context);
6678
let length = size
67-
.evaluate_to_u32()
79+
.evaluate_to_u32(span)
6880
.expect("Cannot have variable sized arrays as a parameter to main");
6981
let typ = typ.as_ref();
7082
AbiType::Array { length, typ: Box::new(abi_type_from_hir_type(context, typ)) }
@@ -91,8 +103,9 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType {
91103
}
92104
Type::Bool => AbiType::Boolean,
93105
Type::String(size) => {
106+
let span = get_main_function_span(context);
94107
let size = size
95-
.evaluate_to_u32()
108+
.evaluate_to_u32(span)
96109
.expect("Cannot have variable sized strings as a parameter to main");
97110
AbiType::String { length: size }
98111
}
@@ -107,6 +120,7 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType {
107120
AbiType::Struct { fields, path }
108121
}
109122
Type::Alias(def, args) => abi_type_from_hir_type(context, &def.borrow().get_type(args)),
123+
Type::CheckedCast { to, .. } => abi_type_from_hir_type(context, to),
110124
Type::Tuple(fields) => {
111125
let fields = vecmap(fields, |typ| abi_type_from_hir_type(context, typ));
112126
AbiType::Tuple { fields }

noir/noir-repo/compiler/noirc_driver/src/lib.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -456,9 +456,8 @@ fn compile_contract_inner(
456456
.secondary
457457
.iter()
458458
.filter_map(|attr| match attr {
459-
SecondaryAttribute::Tag(attribute) | SecondaryAttribute::Meta(attribute) => {
460-
Some(attribute.contents.clone())
461-
}
459+
SecondaryAttribute::Tag(attribute) => Some(attribute.contents.clone()),
460+
SecondaryAttribute::Meta(attribute) => Some(attribute.to_string()),
462461
_ => None,
463462
})
464463
.collect();

noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,8 @@ fn split_public_and_private_inputs(
371371
func_sig
372372
.0
373373
.iter()
374-
.map(|(_, typ, visibility)| {
375-
let num_field_elements_needed = typ.field_count() as usize;
374+
.map(|(pattern, typ, visibility)| {
375+
let num_field_elements_needed = typ.field_count(&pattern.location()) as usize;
376376
let witnesses = input_witnesses[idx..idx + num_field_elements_needed].to_vec();
377377
idx += num_field_elements_needed;
378378
(visibility, witnesses)

noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl DataBusBuilder {
4848
ast::Visibility::CallData(id) => DatabusVisibility::CallData(id),
4949
ast::Visibility::ReturnData => DatabusVisibility::ReturnData,
5050
};
51-
let len = param.1.field_count() as usize;
51+
let len = param.1.field_count(&param.0.location()) as usize;
5252
params_is_databus.extend(vec![is_databus; len]);
5353
}
5454
params_is_databus

noir/noir-repo/compiler/noirc_frontend/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ strum_macros = "0.24"
3636

3737
[dev-dependencies]
3838
base64.workspace = true
39+
proptest.workspace = true
40+
proptest-derive = "0.5.0"
3941

4042
[features]
4143
experimental_parser = []
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Seeds for failure cases proptest has generated in the past. It is
2+
# automatically read and these particular cases re-run before any
3+
# novel cases are generated.
4+
#
5+
# It is recommended to check this file in to source control so that
6+
# everyone who runs the test benefits from these saved cases.
7+
cc fc27f4091dfa5f938973048209b5fcf22aefa1cfaffaaa3e349f30e9b1f93f49 # shrinks to infix_and_bindings = (((0: numeric bool) % (Numeric(Shared(RefCell { value: Unbound('2, Numeric(bool)) }): bool) + Numeric(Shared(RefCell { value: Unbound('0, Numeric(bool)) }): bool))), [('0, (0: numeric bool)), ('1, (0: numeric bool)), ('2, (0: numeric bool))])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Seeds for failure cases proptest has generated in the past. It is
2+
# automatically read and these particular cases re-run before any
3+
# novel cases are generated.
4+
#
5+
# It is recommended to check this file in to source control so that
6+
# everyone who runs the test benefits from these saved cases.
7+
cc fc27f4091dfa5f938973048209b5fcf22aefa1cfaffaaa3e349f30e9b1f93f49 # shrinks to infix_and_bindings = (((0: numeric bool) % (Numeric(Shared(RefCell { value: Unbound('2, Numeric(bool)) }): bool) + Numeric(Shared(RefCell { value: Unbound('0, Numeric(bool)) }): bool))), [('0, (0: numeric bool)), ('1, (0: numeric bool)), ('2, (0: numeric bool))])

noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ impl UnresolvedGeneric {
9898
UnresolvedGeneric::Variable(_) => Ok(Kind::Normal),
9999
UnresolvedGeneric::Numeric { typ, .. } => {
100100
let typ = self.resolve_numeric_kind_type(typ)?;
101-
Ok(Kind::Numeric(Box::new(typ)))
101+
Ok(Kind::numeric(typ))
102102
}
103103
UnresolvedGeneric::Resolved(..) => {
104104
panic!("Don't know the kind of a resolved generic here")
@@ -504,7 +504,7 @@ impl FunctionDefinition {
504504
}
505505

506506
pub fn is_test(&self) -> bool {
507-
if let Some(attribute) = &self.attributes.function {
507+
if let Some(attribute) = self.attributes.function() {
508508
matches!(attribute, FunctionAttribute::Test(..))
509509
} else {
510510
false

noir/noir-repo/compiler/noirc_frontend/src/ast/function.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl NoirFunction {
7777
&self.def.attributes
7878
}
7979
pub fn function_attribute(&self) -> Option<&FunctionAttribute> {
80-
self.def.attributes.function.as_ref()
80+
self.def.attributes.function()
8181
}
8282
pub fn secondary_attributes(&self) -> &[SecondaryAttribute] {
8383
self.def.attributes.secondary.as_ref()
@@ -108,7 +108,7 @@ impl NoirFunction {
108108
impl From<FunctionDefinition> for NoirFunction {
109109
fn from(fd: FunctionDefinition) -> Self {
110110
// The function type is determined by the existence of a function attribute
111-
let kind = match fd.attributes.function {
111+
let kind = match fd.attributes.function() {
112112
Some(FunctionAttribute::Builtin(_)) => FunctionKind::Builtin,
113113
Some(FunctionAttribute::Foreign(_)) => FunctionKind::LowLevel,
114114
Some(FunctionAttribute::Test { .. }) => FunctionKind::Normal,

noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ pub use visitor::Visitor;
1919
pub use expression::*;
2020
pub use function::*;
2121

22+
#[cfg(test)]
23+
use proptest_derive::Arbitrary;
24+
2225
use acvm::FieldElement;
2326
pub use docs::*;
2427
use noirc_errors::Span;
@@ -37,6 +40,7 @@ use crate::{
3740
use acvm::acir::AcirField;
3841
use iter_extended::vecmap;
3942

43+
#[cfg_attr(test, derive(Arbitrary))]
4044
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Ord, PartialOrd)]
4145
pub enum IntegerBitSize {
4246
One,

noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -445,11 +445,6 @@ impl Path {
445445
self.span
446446
}
447447

448-
pub fn first_segment(&self) -> PathSegment {
449-
assert!(!self.segments.is_empty());
450-
self.segments.first().unwrap().clone()
451-
}
452-
453448
pub fn last_segment(&self) -> PathSegment {
454449
assert!(!self.segments.is_empty());
455450
self.segments.last().unwrap().clone()
@@ -459,9 +454,8 @@ impl Path {
459454
self.last_segment().ident
460455
}
461456

462-
pub fn first_name(&self) -> &str {
463-
assert!(!self.segments.is_empty());
464-
&self.segments.first().unwrap().ident.0.contents
457+
pub fn first_name(&self) -> Option<&str> {
458+
self.segments.first().map(|segment| segment.ident.0.contents.as_str())
465459
}
466460

467461
pub fn last_name(&self) -> &str {

noir/noir-repo/compiler/noirc_frontend/src/ast/visitor.rs

+15-6
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::{
1616
InternedUnresolvedTypeData, QuotedTypeId,
1717
},
1818
parser::{Item, ItemKind, ParsedSubModule},
19-
token::{CustomAttribute, SecondaryAttribute, Tokens},
19+
token::{MetaAttribute, SecondaryAttribute, Tokens},
2020
ParsedModule, QuotedType,
2121
};
2222

@@ -474,7 +474,9 @@ pub trait Visitor {
474474
true
475475
}
476476

477-
fn visit_custom_attribute(&mut self, _: &CustomAttribute, _target: AttributeTarget) {}
477+
fn visit_meta_attribute(&mut self, _: &MetaAttribute, _target: AttributeTarget) -> bool {
478+
true
479+
}
478480
}
479481

480482
impl ParsedModule {
@@ -1441,15 +1443,22 @@ impl SecondaryAttribute {
14411443
}
14421444

14431445
pub fn accept_children(&self, target: AttributeTarget, visitor: &mut impl Visitor) {
1444-
if let SecondaryAttribute::Meta(custom) = self {
1445-
custom.accept(target, visitor);
1446+
if let SecondaryAttribute::Meta(meta_attribute) = self {
1447+
meta_attribute.accept(target, visitor);
14461448
}
14471449
}
14481450
}
14491451

1450-
impl CustomAttribute {
1452+
impl MetaAttribute {
14511453
pub fn accept(&self, target: AttributeTarget, visitor: &mut impl Visitor) {
1452-
visitor.visit_custom_attribute(self, target);
1454+
if visitor.visit_meta_attribute(self, target) {
1455+
self.accept_children(visitor);
1456+
}
1457+
}
1458+
1459+
pub fn accept_children(&self, visitor: &mut impl Visitor) {
1460+
self.name.accept(visitor);
1461+
visit_expressions(&self.arguments, visitor);
14531462
}
14541463
}
14551464

noir/noir-repo/compiler/noirc_frontend/src/elaborator/comptime.rs

+11-51
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,9 @@ use crate::{
1919
resolution::errors::ResolverError,
2020
},
2121
hir_def::expr::{HirExpression, HirIdent},
22-
lexer::Lexer,
2322
node_interner::{DefinitionKind, DependencyId, FuncId, NodeInterner, StructId, TraitId},
24-
parser::{Item, ItemKind, Parser},
25-
token::SecondaryAttribute,
23+
parser::{Item, ItemKind},
24+
token::{MetaAttribute, SecondaryAttribute},
2625
Type, TypeBindings, UnificationError,
2726
};
2827

@@ -162,10 +161,9 @@ impl<'context> Elaborator<'context> {
162161
if let SecondaryAttribute::Meta(attribute) = attribute {
163162
self.elaborate_in_comptime_context(|this| {
164163
if let Err(error) = this.run_comptime_attribute_name_on_item(
165-
&attribute.contents,
164+
attribute,
166165
item.clone(),
167166
span,
168-
attribute.contents_span,
169167
attribute_context,
170168
generated_items,
171169
) {
@@ -177,27 +175,21 @@ impl<'context> Elaborator<'context> {
177175

178176
fn run_comptime_attribute_name_on_item(
179177
&mut self,
180-
attribute: &str,
178+
attribute: &MetaAttribute,
181179
item: Value,
182180
span: Span,
183-
attribute_span: Span,
184181
attribute_context: AttributeContext,
185182
generated_items: &mut CollectedItems,
186183
) -> Result<(), (CompilationError, FileId)> {
187184
self.file = attribute_context.attribute_file;
188185
self.local_module = attribute_context.attribute_module;
189186

190-
let location = Location::new(attribute_span, self.file);
191-
let Some((function, arguments)) = Self::parse_attribute(attribute, location)? else {
192-
return Err((
193-
ResolverError::UnableToParseAttribute {
194-
attribute: attribute.to_string(),
195-
span: attribute_span,
196-
}
197-
.into(),
198-
self.file,
199-
));
187+
let location = Location::new(attribute.span, self.file);
188+
let function = Expression {
189+
kind: ExpressionKind::Variable(attribute.name.clone()),
190+
span: attribute.span,
200191
};
192+
let arguments = attribute.arguments.clone();
201193

202194
// Elaborate the function, rolling back any errors generated in case it is unknown
203195
let error_count = self.errors.len();
@@ -211,7 +203,7 @@ impl<'context> Elaborator<'context> {
211203
return Err((
212204
ResolverError::AttributeFunctionIsNotAPath {
213205
function: function_string,
214-
span: attribute_span,
206+
span: attribute.span,
215207
}
216208
.into(),
217209
self.file,
@@ -223,7 +215,7 @@ impl<'context> Elaborator<'context> {
223215
return Err((
224216
ResolverError::AttributeFunctionNotInScope {
225217
name: function_string,
226-
span: attribute_span,
218+
span: attribute.span,
227219
}
228220
.into(),
229221
self.file,
@@ -269,38 +261,6 @@ impl<'context> Elaborator<'context> {
269261
Ok(())
270262
}
271263

272-
/// Parses an attribute in the form of a function call (e.g. `#[foo(a b, c d)]`) into
273-
/// the function and quoted arguments called (e.g. `("foo", vec![(a b, location), (c d, location)])`)
274-
#[allow(clippy::type_complexity)]
275-
pub(crate) fn parse_attribute(
276-
annotation: &str,
277-
location: Location,
278-
) -> Result<Option<(Expression, Vec<Expression>)>, (CompilationError, FileId)> {
279-
let (tokens, mut lexing_errors) = Lexer::lex(annotation);
280-
if !lexing_errors.is_empty() {
281-
return Err((lexing_errors.swap_remove(0).into(), location.file));
282-
}
283-
284-
let Some(expression) = Parser::for_tokens(tokens).parse_option(Parser::parse_expression)
285-
else {
286-
return Ok(None);
287-
};
288-
289-
let (mut func, mut arguments) = match expression.kind {
290-
ExpressionKind::Call(call) => (*call.func, call.arguments),
291-
ExpressionKind::Variable(_) => (expression, Vec::new()),
292-
_ => return Ok(None),
293-
};
294-
295-
func.span = func.span.shift_by(location.span.start());
296-
297-
for argument in &mut arguments {
298-
argument.span = argument.span.shift_by(location.span.start());
299-
}
300-
301-
Ok(Some((func, arguments)))
302-
}
303-
304264
fn handle_attribute_arguments(
305265
interpreter: &mut Interpreter,
306266
item: &Value,

0 commit comments

Comments
 (0)