Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
60169c4
Add integration test
aakoshh Oct 10, 2025
b306375
Handle foreign and intrinsic functions in printing from the SSA inter…
aakoshh Oct 10, 2025
859af4b
Nits
aakoshh Oct 10, 2025
6d842d7
Move visitor into monomorphization
aakoshh Oct 13, 2025
0e24220
Move to_hir_type to noirc_frontend
aakoshh Oct 13, 2025
409ea40
Add proxies module and pass
aakoshh Oct 13, 2025
b31bb3c
Add more test cases
aakoshh Oct 13, 2025
ed4a71b
Add insta
aakoshh Oct 13, 2025
2916a49
Add unit test to show the AST
aakoshh Oct 13, 2025
3215b1f
Clippy
aakoshh Oct 13, 2025
89e8d12
Add defunctionalize pre-check
aakoshh Oct 13, 2025
9ac6e63
Ignore the regression test in the --minimal-ssa integration test
aakoshh Oct 13, 2025
2a9582e
Clippy
aakoshh Oct 13, 2025
8d67ca4
Keep both function types in the Ident
aakoshh Oct 13, 2025
ecbca24
Map a tuple of mAST functions back to a single HIR function
aakoshh Oct 15, 2025
02cf5ec
Merge remote-tracking branch 'origin/master' into af/10156-print-an-o…
aakoshh Nov 3, 2025
52b3cca
Move to_hir_type back into the fuzzer
aakoshh Nov 3, 2025
e9b916a
The test using blake2s as a function value no longer panics
aakoshh Nov 3, 2025
32d65ae
Update insta
aakoshh Nov 3, 2025
eac13e1
Fix formatting
aakoshh Nov 3, 2025
eb39da3
Fix clippy
aakoshh Nov 3, 2025
e64f3cc
oracle wrappers before defining function metas in the elaborator
vezenovm Nov 3, 2025
392e871
add back take_bar
vezenovm Nov 3, 2025
7316155
Merge branch 'master' into mv/foreign-func-wrappers
jfecher Dec 4, 2025
ba71598
Update proxy test
jfecher Dec 4, 2025
75559f0
Update more snapshots
jfecher Dec 5, 2025
4454153
Merge branch 'master' into mv/foreign-func-wrappers
jfecher Dec 5, 2025
19b3286
Merge master = more snapshots broke
jfecher Dec 5, 2025
b8958b0
update snap
vezenovm Dec 5, 2025
3ceed01
Update SSA backtrace
jfecher Dec 5, 2025
bee9f5a
Format
jfecher Dec 5, 2025
621065e
is_ok_and
jfecher Dec 5, 2025
dc5fa03
Merge master, don't remove proxies pass yet
jfecher Dec 5, 2025
4a18f2f
Merge branch 'master' of https://github.com/noir-lang/noir into mv/fo…
jfecher Dec 8, 2025
4563316
2 issues: panic with instantiation_bindings, and error locations are …
jfecher Dec 8, 2025
c486b33
Remove .snap.new file
jfecher Dec 8, 2025
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
2 changes: 1 addition & 1 deletion compiler/noirc_evaluator/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ impl RuntimeError {
);

if std::env::var(SHOW_INVALID_SSA_ENV_KEY).is_err() {
diagnostic.notes.push(format!("Set the {SHOW_INVALID_SSA_ENV_KEY} env var to see the SSA."));
diagnostic.notes.push(format!("Set the environment variable {SHOW_INVALID_SSA_ENV_KEY}=1 to see the SSA."));
}

if call_stack.is_empty() {
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ fn validate_ssa_or_err(ssa: Ssa) -> Result<Ssa, RuntimeError> {
if let Err(payload) = result {
// Print the SSA, but it's potentially massive, and if we resume the unwind it might be displayed
// under the panic message, which makes it difficult to see what went wrong.
if std::env::var(SHOW_INVALID_SSA_ENV_KEY).is_ok() {
if std::env::var(SHOW_INVALID_SSA_ENV_KEY).is_ok_and(|value| value == "1") {
eprintln!("--- The SSA failed to validate:\n{ssa}\n");
}

Expand Down
155 changes: 154 additions & 1 deletion compiler/noirc_frontend/src/elaborator/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
types::{WildcardAllowed, WildcardDisallowedContext},
},
hir::{
def_collector::dc_crate::{ImplMap, UnresolvedFunctions, UnresolvedTraitImpl},
def_collector::{
dc_crate::{ImplMap, UnresolvedFunctions, UnresolvedTraitImpl},
errors::{DefCollectorErrorKind, DuplicateType},
},
def_map::ModuleId,
resolution::errors::ResolverError,
type_check::TypeCheckError,
},
Expand All @@ -33,6 +37,7 @@
},
node_interner::{DefinitionKind, DependencyId, FuncId, FunctionModifiers, TraitId},
shared::Visibility,
token::Attributes,
validity::length_is_zero,
};

Expand Down Expand Up @@ -73,6 +78,10 @@
function_set: &mut UnresolvedFunctions,
extra_constraints: &[(TraitConstraint, Location)],
) {
// Transform oracle, lowlevel, & builtin functions into wrappers

Check warning on line 81 in compiler/noirc_frontend/src/elaborator/function.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (lowlevel)
self.make_wrappers_for_special_functions(function_set);

// Define metas for all functions
for (local_module, id, func) in &mut function_set.functions {
self.local_module = Some(*local_module);
self.recover_generics(|this| {
Expand Down Expand Up @@ -579,4 +588,148 @@
self.interner.update_fn(id, hir_func);
self.current_item = old_item;
}

/// Transforms oracle, lowlevel, & builtin functions into wrapper functions that can be passed by value.
/// For each of these functions:

Check warning on line 593 in compiler/noirc_frontend/src/elaborator/function.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (lowlevel)
/// 1. Rename it to `name_inner`
/// 2. Creates a new wrapper function with the original name that calls `name_inner`
fn make_wrappers_for_special_functions(&mut self, function_set: &mut UnresolvedFunctions) {
use crate::ast::{
BlockExpression, CallExpression, Expression, ExpressionKind, Ident, NoirFunction,
Pattern, Statement, StatementKind,
};

let mut wrappers = Vec::new();

for (local_module, func_id, func) in &mut function_set.functions {
use FunctionKind::*;
if !matches!(func.kind, Oracle | LowLevel | Builtin) || func.def.is_comptime {
continue;
}

let original_name = func.def.name.clone();
let new_name = format!("{}_inner", original_name.as_str());
let new_name_ident = Ident::new(new_name.clone(), original_name.location());

// Rename the original function in both the AST and interner
func.def.name = new_name_ident.clone();

// Update the function name in the interner's modifiers
let modifiers = self.interner.function_modifiers_mut(func_id);
modifiers.name = new_name.clone();
modifiers.name_location = original_name.location();

// Update the module's def_map to reflect the rename
let module_id = ModuleId { krate: self.crate_id, local_id: *local_module };
let module_data =
&mut self.def_maps.get_mut(&module_id.krate).expect("ICE: should have def_map")
[module_id.local_id];

// Remove the old name and re-declare with new name
module_data.remove_function(&original_name);
let visibility = func.def.visibility;
match module_data.declare_function(new_name_ident, visibility, *func_id) {
Ok(_) => {}
Err((first_def, second_def)) => {
let error = DefCollectorErrorKind::Duplicate {
typ: DuplicateType::Function,
first_def,
second_def,
};
self.errors.push(error.into());
}
}

// Create the wrapper function body: wrapper_name(param1, param2, ...)
let wrapper_path = crate::ast::Path::from_single(new_name, original_name.location());
let wrapper_expr = Expression {
kind: ExpressionKind::Variable(wrapper_path),
location: original_name.location(),
};

// Create arguments from parameters
let arguments: Vec<Expression> = func
.def
.parameters
.iter()
.map(|param| {
// Extract the identifier from the pattern
let ident = match &param.pattern {
Pattern::Identifier(_) | Pattern::Mutable(_, _, _) => {
param.pattern.name_ident().clone()
}
_ => {
// For complex patterns, create a dummy identifier
Ident::new("_param".to_string(), param.location)
}
};

let path =
crate::ast::Path::from_single(ident.as_string().clone(), ident.location());
Expression { kind: ExpressionKind::Variable(path), location: ident.location() }
})
.collect();

// Create call expression: wrapper_name(...)
let call_expr = Expression {
kind: ExpressionKind::Call(Box::new(CallExpression {
func: Box::new(wrapper_expr),
arguments,
is_macro_call: false,
})),
location: original_name.location(),
};

// Wrap in a statement
let call_stmt = Statement {
kind: StatementKind::Expression(call_expr),
location: original_name.location(),
};

// Create wrapper function definition
let wrapper_def = crate::ast::FunctionDefinition {
name: original_name.clone(),
attributes: Attributes::empty(),
is_unconstrained: func.def.is_unconstrained,
is_comptime: func.def.is_comptime,
visibility: func.def.visibility,
generics: func.def.generics.clone(),
parameters: func.def.parameters.clone(),
body: BlockExpression { statements: vec![call_stmt] },
location: func.def.location,
where_clause: func.def.where_clause.clone(),
return_type: func.def.return_type.clone(),
return_visibility: func.def.return_visibility,
};

// Create a new FuncId for the wrapper
let wrapper_id = self.interner.push_empty_fn();

self.interner.push_function(
wrapper_id,
&wrapper_def,
module_id,
original_name.location(),
);

// Register the wrapper in the module's def_map with the original name
match module_data.declare_function(original_name, wrapper_def.visibility, wrapper_id) {
Ok(_) => {}
Err((first_def, second_def)) => {
let error = DefCollectorErrorKind::Duplicate {
typ: DuplicateType::Function,
first_def,
second_def,
};
self.errors.push(error.into());
}
}

let wrapper_func = NoirFunction { kind: Normal, def: wrapper_def };
wrappers.push((*local_module, wrapper_id, wrapper_func));
}

// Add all wrappers to the function set
function_set.functions.extend(wrappers);
}
}
6 changes: 1 addition & 5 deletions compiler/noirc_frontend/src/monomorphization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ mod debug;
pub mod debug_types;
pub mod errors;
pub mod printer;
pub mod proxies;
pub mod tests;
pub mod visitor;

Expand Down Expand Up @@ -159,9 +158,7 @@ pub fn monomorphize_debug(
let function_sig = monomorphizer.compile_main(main)?;

monomorphizer.process_queue()?;

let program = monomorphizer.into_program(function_sig);
Ok(program)
Ok(monomorphizer.into_program(function_sig))
}

impl<'interner> Monomorphizer<'interner> {
Expand Down Expand Up @@ -282,7 +279,6 @@ impl<'interner> Monomorphizer<'interner> {
debug_types,
)
.handle_ownership()
.create_foreign_proxies()
}

pub(super) fn next_local_id(&mut self) -> LocalId {
Expand Down
Loading
Loading