Skip to content

Commit 49a3fab

Browse files
committed
Track elaborate reason when calling comptime builtin
1 parent 982f6ff commit 49a3fab

File tree

4 files changed

+115
-94
lines changed

4 files changed

+115
-94
lines changed

compiler/noirc_frontend/src/elaborator/comptime.rs

+21-30
Original file line numberDiff line numberDiff line change
@@ -342,14 +342,11 @@ impl<'context> Elaborator<'context> {
342342
generated_items: &mut CollectedItems,
343343
location: Location,
344344
) {
345-
let previous_errors =
346-
self.push_elaborate_reason_and_take_errors(ElaborateReason::RunningAttribute, location);
347-
348-
for item in items {
349-
self.add_item(item, generated_items, location);
350-
}
351-
352-
self.pop_elaborate_reason(previous_errors);
345+
self.with_elaborate_reason(ElaborateReason::RunningAttribute(location), |elaborator| {
346+
for item in items {
347+
elaborator.add_item(item, generated_items, location);
348+
}
349+
})
353350
}
354351

355352
pub(crate) fn add_item(
@@ -558,14 +555,10 @@ impl<'context> Elaborator<'context> {
558555
});
559556

560557
if !generated_items.is_empty() {
561-
let previous_errors = self.push_elaborate_reason_and_take_errors(
562-
ElaborateReason::RunningAttribute,
563-
location,
564-
);
565-
566-
self.elaborate_items(generated_items);
567-
568-
self.pop_elaborate_reason(previous_errors);
558+
let reason = ElaborateReason::RunningAttribute(location);
559+
self.with_elaborate_reason(reason, |elaborator| {
560+
elaborator.elaborate_items(generated_items)
561+
});
569562
}
570563
}
571564
}
@@ -652,33 +645,31 @@ impl<'context> Elaborator<'context> {
652645
}
653646
}
654647

655-
/// Pushes an ElaborateReason but also `std::mem::take`s the current errors and returns them.
656-
pub(crate) fn push_elaborate_reason_and_take_errors(
657-
&mut self,
658-
reason: ElaborateReason,
659-
location: Location,
660-
) -> Vec<CompilationError> {
661-
self.elaborate_reasons.push_back((reason, location));
662-
std::mem::take(&mut self.errors)
663-
}
648+
pub(crate) fn with_elaborate_reason<F, T>(&mut self, reason: ElaborateReason, f: F) -> T
649+
where
650+
F: FnOnce(&mut Elaborator) -> T,
651+
{
652+
self.elaborate_reasons.push_back(reason);
653+
let previous_errors = std::mem::take(&mut self.errors);
654+
655+
let value = f(self);
664656

665-
/// Pops en ElaborateREason. Receives the errors that were returned by `push_elaborate_reason`
666-
/// so they are restored, while also wrapping errors in the current Elaborator in a ComptimeError.
667-
pub(crate) fn pop_elaborate_reason(&mut self, previous_errors: Vec<CompilationError>) {
668657
let new_errors = std::mem::take(&mut self.errors);
669658
let new_errors = self.wrap_errors_in_macro_error(new_errors);
670659
self.errors = previous_errors;
671660
self.push_errors(new_errors);
672661
self.elaborate_reasons.pop_back();
662+
663+
value
673664
}
674665

675666
fn wrap_errors_in_macro_error(&self, errors: Vec<CompilationError>) -> Vec<CompilationError> {
676667
vecmap(errors, |error| self.wrap_error_in_macro_error(error))
677668
}
678669

679670
fn wrap_error_in_macro_error(&self, mut error: CompilationError) -> CompilationError {
680-
for (reason, location) in self.elaborate_reasons.iter().rev() {
681-
error = CompilationError::ComptimeError(reason.to_macro_error(error, *location));
671+
for reason in self.elaborate_reasons.iter().rev() {
672+
error = CompilationError::ComptimeError(reason.to_macro_error(error));
682673
}
683674
error
684675
}

compiler/noirc_frontend/src/elaborator/mod.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -199,25 +199,26 @@ pub struct Elaborator<'context> {
199199
/// Sometimes items are elaborated because a function attribute ran and generated items.
200200
/// The Elaborator keeps track of these reasons so that when an error is produced it will
201201
/// be wrapped in another error that will include this reason.
202-
pub(crate) elaborate_reasons: im::Vector<(ElaborateReason, Location)>,
202+
pub(crate) elaborate_reasons: im::Vector<ElaborateReason>,
203203
}
204204

205205
#[derive(Copy, Clone)]
206206
pub enum ElaborateReason {
207207
/// A function attribute generated an item that's being elaborated.
208-
RunningAttribute,
209-
/// Evaluating `Module::add_item`
210-
AddingItemToModule,
208+
RunningAttribute(Location),
209+
/// Evaluating a comptime call like `Module::add_item`
210+
EvaluatingComptimeCall(&'static str, Location),
211211
}
212212

213213
impl ElaborateReason {
214-
fn to_macro_error(self, error: CompilationError, location: Location) -> ComptimeError {
214+
fn to_macro_error(self, error: CompilationError) -> ComptimeError {
215215
match self {
216-
ElaborateReason::RunningAttribute => {
216+
ElaborateReason::RunningAttribute(location) => {
217217
ComptimeError::ErrorRunningAttribute { error: Box::new(error), location }
218218
}
219-
ElaborateReason::AddingItemToModule => {
220-
ComptimeError::ErrorAddingItemToModule { error: Box::new(error), location }
219+
ElaborateReason::EvaluatingComptimeCall(method_name, location) => {
220+
let error = Box::new(error);
221+
ComptimeError::ErrorEvaluatingComptimeCall { method_name, error, location }
221222
}
222223
}
223224
}
@@ -251,7 +252,7 @@ impl<'context> Elaborator<'context> {
251252
crate_id: CrateId,
252253
interpreter_call_stack: im::Vector<Location>,
253254
options: ElaboratorOptions<'context>,
254-
elaborate_reasons: im::Vector<(ElaborateReason, Location)>,
255+
elaborate_reasons: im::Vector<ElaborateReason>,
255256
) -> Self {
256257
Self {
257258
scopes: ScopeForest::default(),

compiler/noirc_frontend/src/hir/comptime/errors.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -703,15 +703,22 @@ impl<'a> From<&'a InterpreterError> for CustomDiagnostic {
703703
/// comptime call or macro "something" that eventually led to that error.
704704
#[derive(Debug, Clone, PartialEq, Eq)]
705705
pub enum ComptimeError {
706-
ErrorRunningAttribute { error: Box<CompilationError>, location: Location },
707-
ErrorAddingItemToModule { error: Box<CompilationError>, location: Location },
706+
ErrorRunningAttribute {
707+
error: Box<CompilationError>,
708+
location: Location,
709+
},
710+
ErrorEvaluatingComptimeCall {
711+
method_name: &'static str,
712+
error: Box<CompilationError>,
713+
location: Location,
714+
},
708715
}
709716

710717
impl ComptimeError {
711718
pub fn location(&self) -> Location {
712719
match self {
713720
ComptimeError::ErrorRunningAttribute { location, .. }
714-
| ComptimeError::ErrorAddingItemToModule { location, .. } => *location,
721+
| ComptimeError::ErrorEvaluatingComptimeCall { location, .. } => *location,
715722
}
716723
}
717724
}
@@ -724,9 +731,9 @@ impl<'a> From<&'a ComptimeError> for CustomDiagnostic {
724731
diagnostic.add_secondary("While running this function attribute".into(), *location);
725732
diagnostic
726733
}
727-
ComptimeError::ErrorAddingItemToModule { error, location } => {
734+
ComptimeError::ErrorEvaluatingComptimeCall { method_name, error, location } => {
728735
let mut diagnostic = CustomDiagnostic::from(&**error);
729-
diagnostic.add_secondary("While interpreting `Module::add_item`".into(), *location);
736+
diagnostic.add_secondary(format!("While evaluating `{method_name}`"), *location);
730737
diagnostic
731738
}
732739
}

compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs

+72-50
Original file line numberDiff line numberDiff line change
@@ -833,9 +833,12 @@ fn quoted_as_module(
833833
parse(interpreter.elaborator, argument, Parser::parse_path_no_turbofish_or_error, "a path")
834834
.ok();
835835
let option_value = path.and_then(|path| {
836-
let module = interpreter
837-
.elaborate_in_function(interpreter.current_function, |elaborator| {
838-
elaborator.resolve_module_by_path(path)
836+
let module =
837+
interpreter.elaborate_in_function(interpreter.current_function, |elaborator| {
838+
let reason = ElaborateReason::EvaluatingComptimeCall("Quoted::as_module", location);
839+
elaborator.with_elaborate_reason(reason, |elaborator| {
840+
elaborator.resolve_module_by_path(path)
841+
})
839842
});
840843
module.map(Value::ModuleDefinition)
841844
});
@@ -858,7 +861,11 @@ fn quoted_as_trait_constraint(
858861
)?;
859862
let bound = interpreter
860863
.elaborate_in_function(interpreter.current_function, |elaborator| {
861-
elaborator.resolve_trait_bound(&trait_bound)
864+
let reason =
865+
ElaborateReason::EvaluatingComptimeCall("Quoted::as_trait_constraint", location);
866+
elaborator.with_elaborate_reason(reason, |elaborator| {
867+
elaborator.resolve_trait_bound(&trait_bound)
868+
})
862869
})
863870
.ok_or(InterpreterError::FailedToResolveTraitBound { trait_bound, location })?;
864871

@@ -873,8 +880,10 @@ fn quoted_as_type(
873880
) -> IResult<Value> {
874881
let argument = check_one_argument(arguments, location)?;
875882
let typ = parse(interpreter.elaborator, argument, Parser::parse_type_or_error, "a type")?;
876-
let typ = interpreter
877-
.elaborate_in_function(interpreter.current_function, |elab| elab.resolve_type(typ));
883+
let typ = interpreter.elaborate_in_function(interpreter.current_function, |elaborator| {
884+
let reason = ElaborateReason::EvaluatingComptimeCall("Quoted::as_type", location);
885+
elaborator.with_elaborate_reason(reason, |elaborator| elaborator.resolve_type(typ))
886+
});
878887
Ok(Value::Type(typ))
879888
}
880889

@@ -2292,32 +2301,37 @@ fn expr_resolve(
22922301
interpreter.current_function
22932302
};
22942303

2295-
interpreter.elaborate_in_function(function_to_resolve_in, |elaborator| match expr_value {
2296-
ExprValue::Expression(expression_kind) => {
2297-
let expr = Expression { kind: expression_kind, location: self_argument_location };
2298-
let (expr_id, _) = elaborator.elaborate_expression(expr);
2299-
Ok(Value::TypedExpr(TypedExpr::ExprId(expr_id)))
2300-
}
2301-
ExprValue::Statement(statement_kind) => {
2302-
let statement = Statement { kind: statement_kind, location: self_argument_location };
2303-
let (stmt_id, _) = elaborator.elaborate_statement(statement);
2304-
Ok(Value::TypedExpr(TypedExpr::StmtId(stmt_id)))
2305-
}
2306-
ExprValue::LValue(lvalue) => {
2307-
let expr = lvalue.as_expression();
2308-
let (expr_id, _) = elaborator.elaborate_expression(expr);
2309-
Ok(Value::TypedExpr(TypedExpr::ExprId(expr_id)))
2310-
}
2311-
ExprValue::Pattern(pattern) => {
2312-
if let Some(expression) = pattern.try_as_expression(elaborator.interner) {
2313-
let (expr_id, _) = elaborator.elaborate_expression(expression);
2304+
interpreter.elaborate_in_function(function_to_resolve_in, |elaborator| {
2305+
let reason = ElaborateReason::EvaluatingComptimeCall("Expr::resolve", location);
2306+
elaborator.with_elaborate_reason(reason, |elaborator| match expr_value {
2307+
ExprValue::Expression(expression_kind) => {
2308+
let expr = Expression { kind: expression_kind, location: self_argument_location };
2309+
let (expr_id, _) = elaborator.elaborate_expression(expr);
23142310
Ok(Value::TypedExpr(TypedExpr::ExprId(expr_id)))
2315-
} else {
2316-
let expression = Value::pattern(pattern).display(elaborator.interner).to_string();
2317-
let location = self_argument_location;
2318-
Err(InterpreterError::CannotResolveExpression { location, expression })
23192311
}
2320-
}
2312+
ExprValue::Statement(statement_kind) => {
2313+
let statement =
2314+
Statement { kind: statement_kind, location: self_argument_location };
2315+
let (stmt_id, _) = elaborator.elaborate_statement(statement);
2316+
Ok(Value::TypedExpr(TypedExpr::StmtId(stmt_id)))
2317+
}
2318+
ExprValue::LValue(lvalue) => {
2319+
let expr = lvalue.as_expression();
2320+
let (expr_id, _) = elaborator.elaborate_expression(expr);
2321+
Ok(Value::TypedExpr(TypedExpr::ExprId(expr_id)))
2322+
}
2323+
ExprValue::Pattern(pattern) => {
2324+
if let Some(expression) = pattern.try_as_expression(elaborator.interner) {
2325+
let (expr_id, _) = elaborator.elaborate_expression(expression);
2326+
Ok(Value::TypedExpr(TypedExpr::ExprId(expr_id)))
2327+
} else {
2328+
let expression =
2329+
Value::pattern(pattern).display(elaborator.interner).to_string();
2330+
let location = self_argument_location;
2331+
Err(InterpreterError::CannotResolveExpression { location, expression })
2332+
}
2333+
}
2334+
})
23212335
})
23222336
}
23232337

@@ -2427,7 +2441,11 @@ fn function_def_as_typed_expr(
24272441
let expr_id = interpreter.elaborator.interner.push_expr(hir_expr);
24282442
interpreter.elaborator.interner.push_expr_location(expr_id, location);
24292443
let typ = interpreter.elaborate_in_function(interpreter.current_function, |elaborator| {
2430-
elaborator.type_check_variable(hir_ident, expr_id, generics)
2444+
let reason =
2445+
ElaborateReason::EvaluatingComptimeCall("FunctionDefinition::as_typed_expr", location);
2446+
elaborator.with_elaborate_reason(reason, |elaborator| {
2447+
elaborator.type_check_variable(hir_ident, expr_id, generics)
2448+
})
24312449
});
24322450
interpreter.elaborator.interner.push_expr_type(expr_id, typ);
24332451
Ok(Value::TypedExpr(TypedExpr::ExprId(expr_id)))
@@ -2635,13 +2653,19 @@ fn function_def_set_parameters(
26352653
)?;
26362654

26372655
let hir_pattern = interpreter.elaborate_in_function(Some(func_id), |elaborator| {
2638-
elaborator.elaborate_pattern_and_store_ids(
2639-
parameter_pattern,
2640-
parameter_type.clone(),
2641-
DefinitionKind::Local(None),
2642-
&mut parameter_idents,
2643-
true, // warn_if_unused
2644-
)
2656+
let reason = ElaborateReason::EvaluatingComptimeCall(
2657+
"FunctionDefinition::set_parameters",
2658+
location,
2659+
);
2660+
elaborator.with_elaborate_reason(reason, |elaborator| {
2661+
elaborator.elaborate_pattern_and_store_ids(
2662+
parameter_pattern,
2663+
parameter_type.clone(),
2664+
DefinitionKind::Local(None),
2665+
&mut parameter_idents,
2666+
true, // warn_if_unused
2667+
)
2668+
})
26452669
});
26462670

26472671
parameters.push((hir_pattern, parameter_type.clone(), Visibility::Private));
@@ -2750,20 +2774,18 @@ fn module_add_item(
27502774
let top_level_statements = parse(interpreter.elaborator, item, parser, "a top-level item")?;
27512775

27522776
interpreter.elaborate_in_module(module_id, |elaborator| {
2753-
let previous_errors = elaborator
2754-
.push_elaborate_reason_and_take_errors(ElaborateReason::AddingItemToModule, location);
2755-
2756-
let mut generated_items = CollectedItems::default();
2777+
let reason = ElaborateReason::EvaluatingComptimeCall("Module::add_item", location);
2778+
elaborator.with_elaborate_reason(reason, |elaborator| {
2779+
let mut generated_items = CollectedItems::default();
27572780

2758-
for top_level_statement in top_level_statements {
2759-
elaborator.add_item(top_level_statement, &mut generated_items, location);
2760-
}
2761-
2762-
if !generated_items.is_empty() {
2763-
elaborator.elaborate_items(generated_items);
2764-
}
2781+
for top_level_statement in top_level_statements {
2782+
elaborator.add_item(top_level_statement, &mut generated_items, location);
2783+
}
27652784

2766-
elaborator.pop_elaborate_reason(previous_errors);
2785+
if !generated_items.is_empty() {
2786+
elaborator.elaborate_items(generated_items);
2787+
}
2788+
});
27672789
});
27682790

27692791
Ok(Value::Unit)

0 commit comments

Comments
 (0)