diff --git a/.gitignore b/.gitignore index 351f5e16a7f..a3d669b44e3 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ result *.pk *.vk **/Verifier.toml +**/target diff --git a/crates/nargo/src/ops/execute.rs b/crates/nargo/src/ops/execute.rs index a46c440c76c..8a147561a96 100644 --- a/crates/nargo/src/ops/execute.rs +++ b/crates/nargo/src/ops/execute.rs @@ -1,4 +1,6 @@ -use acvm::pwg::{solve, PartialWitnessGeneratorStatus}; +use acvm::acir::brillig_vm::ForeignCallResult; +use acvm::acir::circuit::Opcode; +use acvm::pwg::{solve, PartialWitnessGeneratorStatus, UnresolvedBrilligCall}; use acvm::PartialWitnessGenerator; use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap, pwg::block::Blocks}; @@ -11,8 +13,39 @@ pub fn execute_circuit( ) -> Result { let mut blocks = Blocks::default(); let solver_status = solve(backend, &mut initial_witness, &mut blocks, circuit.opcodes)?; - if matches!(solver_status, PartialWitnessGeneratorStatus::RequiresOracleData { .. }) { - todo!("Add oracle support to nargo execute") + + // TODO(#1615): Nargo only supports "oracle_print_impl" functions that print a singular value and nothing else + // expand this in a general logging refactor + if let PartialWitnessGeneratorStatus::RequiresOracleData { + unresolved_brillig_calls, + required_oracle_data, + unsolved_opcodes, + } = solver_status + { + if !required_oracle_data.is_empty() { + unreachable!("oracles are not supported by nargo execute") + } + for unresolved_brillig_call in unresolved_brillig_calls { + let UnresolvedBrilligCall { foreign_call_wait_info, mut brillig } = + unresolved_brillig_call; + let value = foreign_call_wait_info.inputs[0]; + + // Execute foreign call "oracle_print_impl" + println!("{:?}", value.to_field().to_hex()); + + // TODO(#1615): "oracle_print_impl" is just an identity func + brillig.foreign_call_results.push(ForeignCallResult { values: vec![value] }); + + let mut next_opcodes_for_solving = vec![Opcode::Brillig(brillig)]; + next_opcodes_for_solving.extend_from_slice(&unsolved_opcodes[..]); + + let solver_status = + solve(backend, &mut initial_witness, &mut blocks, next_opcodes_for_solving)?; + if matches!(solver_status, PartialWitnessGeneratorStatus::RequiresOracleData { .. }) { + todo!("Add multiple foreign call support to nargo execute") + // TODO 1557 + } + } } Ok(initial_witness) diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_oracle/Nargo.toml b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_oracle/Nargo.toml new file mode 100644 index 00000000000..e0b467ce5da --- /dev/null +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_oracle/Nargo.toml @@ -0,0 +1,5 @@ +[package] +authors = [""] +compiler_version = "0.1" + +[dependencies] \ No newline at end of file diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_oracle/Prover.toml b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_oracle/Prover.toml new file mode 100644 index 00000000000..2b26a4ce471 --- /dev/null +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_oracle/Prover.toml @@ -0,0 +1,2 @@ +x = "10" + diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_oracle/src/main.nr b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_oracle/src/main.nr new file mode 100644 index 00000000000..ac824a1d680 --- /dev/null +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_oracle/src/main.nr @@ -0,0 +1,15 @@ +// Tests oracle usage in brillig/unconstrained functions +fn main(x: Field) { + // call through a brillig wrapper + oracle_print_wrapper(x); +} + + +#[oracle(oracle_print_impl)] +unconstrained fn oracle_print(_x : Field) {} + +unconstrained fn oracle_print_wrapper(x: Field) { + oracle_print(x); +} + + diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen.rs b/crates/noirc_evaluator/src/brillig/brillig_gen.rs index 519e341b2be..d6a4da6708c 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen.rs @@ -14,10 +14,12 @@ use crate::ssa_refactor::ir::{ }; use acvm::{ acir::brillig_vm::{ - BinaryIntOp, Opcode as BrilligOpcode, RegisterIndex, Value as BrilligValue, + BinaryIntOp, Opcode as BrilligOpcode, RegisterIndex, RegisterValueOrArray, + Value as BrilligValue, }, FieldElement, }; +use iter_extended::vecmap; use std::collections::HashMap; #[derive(Default)] @@ -205,6 +207,21 @@ impl BrilligGen { }; self.push_code(opcode); } + Instruction::ForeignCall { func, arguments } => { + let result_ids = dfg.instruction_results(instruction_id); + + let input_registers = + vecmap(arguments, |value_id| self.convert_ssa_value(*value_id, dfg)); + let output_registers = + vecmap(result_ids, |value_id| self.convert_ssa_value(*value_id, dfg)); + + let opcode = BrilligOpcode::ForeignCall { + function: func.to_owned(), + destination: RegisterValueOrArray::RegisterIndex(output_registers[0]), + input: RegisterValueOrArray::RegisterIndex(input_registers[0]), + }; + self.push_code(opcode); + } _ => todo!("ICE: Instruction not supported {instruction:?}"), }; } @@ -300,6 +317,7 @@ impl BrilligGen { brillig.convert_ssa_function(func); + brillig.push_code(BrilligOpcode::Stop); brillig.obj } diff --git a/crates/noirc_evaluator/src/ssa/ssa_gen.rs b/crates/noirc_evaluator/src/ssa/ssa_gen.rs index 31817b0bded..082758468a6 100644 --- a/crates/noirc_evaluator/src/ssa/ssa_gen.rs +++ b/crates/noirc_evaluator/src/ssa/ssa_gen.rs @@ -189,9 +189,7 @@ impl IrGenerator { let function_node_id = self.context.get_or_create_opcode_node_id(opcode); Ok(Value::Node(function_node_id)) } - Definition::Oracle(_, _) => { - unimplemented!("oracles not supported by deprecated SSA") - } + Definition::Oracle(_) => unimplemented!("oracles not supported by deprecated SSA"), } } } @@ -499,8 +497,8 @@ impl IrGenerator { match expr { Expression::Ident(ident) => self.ssa_gen_identifier(ident), Expression::Binary(binary) => { - // Note: we disallows structs/tuples in infix expressions. - // The type checker currently disallows this as well but not if they come from generic type + // Note: we disallow structs/tuples in infix expressions. + // The type checker currently disallows this as well but not if they come from a generic type // We could allow some in the future, e.g. struct == struct let lhs = self.ssa_gen_expression(&binary.lhs)?.to_node_ids(); let rhs = self.ssa_gen_expression(&binary.rhs)?.to_node_ids(); diff --git a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs index 12c1fde04c9..5854537c3fe 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs @@ -179,11 +179,19 @@ impl Context { // Generate the brillig code of the function let code = BrilligArtifact::default().link(&brillig[*id]); let outputs = self.acir_context.brillig(code, inputs, result_ids.len()); + + if Self::is_return_type_unit(result_ids, dfg) { + return; + } + for (result, output) in result_ids.iter().zip(outputs) { let result_acir_type = dfg.type_of_value(*result).into(); self.ssa_values.insert(*result, AcirValue::Var(output, result_acir_type)); } } + RuntimeType::Oracle(_) => unimplemented!( + "expected an intrinsic/brillig call, but found {func:?}. All Oracle methods should be wrapped in an unconstrained fn" + ), } } Value::Intrinsic(intrinsic) => { @@ -236,6 +244,7 @@ impl Context { Instruction::Load { .. } => { unreachable!("Expected all load instructions to be removed before acir_gen") } + _ => unreachable!("instruction cannot be converted to ACIR"), } } @@ -298,11 +307,7 @@ impl Context { _ => unreachable!("ICE: Program must have a singular return"), }; - // Check if the program returns the `Unit/None` type. - // This type signifies that the program returns nothing. - let is_return_unit_type = - return_values.len() == 1 && dfg.type_of_value(return_values[0]) == Type::Unit; - if is_return_unit_type { + if Self::is_return_type_unit(return_values, dfg) { return; } @@ -344,6 +349,9 @@ impl Context { } Value::Intrinsic(..) => todo!(), Value::Function(..) => unreachable!("ICE: All functions should have been inlined"), + Value::ForeignFunction(_) => unimplemented!( + "Oracle calls directly in constrained functions are not yet available." + ), Value::Instruction { .. } | Value::Param { .. } => { unreachable!("ICE: Should have been in cache {value:?}") } @@ -606,6 +614,12 @@ impl Context { } } } + + /// Check if the program returns the `Unit/None` type. + /// This type signifies that the program returns nothing. + fn is_return_type_unit(return_values: &[ValueId], dfg: &DataFlowGraph) -> bool { + return_values.len() == 1 && dfg.type_of_value(return_values[0]) == Type::Unit + } } #[cfg(test)] diff --git a/crates/noirc_evaluator/src/ssa_refactor/ir/dfg.rs b/crates/noirc_evaluator/src/ssa_refactor/ir/dfg.rs index ad4f8f3ad4e..03e703bf329 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ir/dfg.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ir/dfg.rs @@ -54,6 +54,11 @@ pub(crate) struct DataFlowGraph { /// represented by only 1 ValueId within this function. intrinsics: HashMap, + /// Contains each foreign function that has been imported into the current function. + /// This map is used to ensure that the ValueId for any given foreign functôn is always + /// represented by only 1 ValueId within this function. + foreign_functions: HashMap, + /// Function signatures of external methods signatures: DenseMap, @@ -189,6 +194,11 @@ impl DataFlowGraph { self.values.insert(Value::Function(function)) } + /// Gets or creates a ValueId for the given FunctionId. + pub(crate) fn import_foreign_function(&mut self, function: &str) -> ValueId { + self.values.insert(Value::ForeignFunction(function.to_owned())) + } + /// Gets or creates a ValueId for the given Intrinsic. pub(crate) fn import_intrinsic(&mut self, intrinsic: Intrinsic) -> ValueId { if let Some(existing) = self.intrinsics.get(&intrinsic) { diff --git a/crates/noirc_evaluator/src/ssa_refactor/ir/function.rs b/crates/noirc_evaluator/src/ssa_refactor/ir/function.rs index 2bb1846c94b..d3b6cd70da0 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ir/function.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ir/function.rs @@ -6,12 +6,14 @@ use super::map::Id; use super::types::Type; use super::value::ValueId; -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug)] pub(crate) enum RuntimeType { // A noir function, to be compiled in ACIR and executed by ACVM Acir, // Unconstrained function, to be compiled to brillig and executed by the Brillig VM Brillig, + // Oracle function, to be compiled to a Brillig external/foreign call + Oracle(String), } /// A function holds a list of instructions. /// These instructions are further grouped into Basic blocks @@ -59,7 +61,7 @@ impl Function { /// Runtime type of the function. pub(crate) fn runtime(&self) -> RuntimeType { - self.runtime + self.runtime.clone() } /// Set runtime type of the function. diff --git a/crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs b/crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs index a9767bc3777..fd31946ed62 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs @@ -92,6 +92,10 @@ pub(crate) enum Instruction { /// Performs a function call with a list of its arguments. Call { func: ValueId, arguments: Vec }, + /// Executes an "oracle" call + /// These are unconstrained functions that may access external state. + ForeignCall { func: String, arguments: Vec }, + /// Allocates a region of memory. Note that this is not concerned with /// the type of memory, the type of element is determined when loading this memory. /// This is used for representing mutable variables and references. @@ -128,9 +132,10 @@ impl Instruction { } Instruction::ArraySet { array, .. } => InstructionResultType::Operand(*array), Instruction::Constrain(_) | Instruction::Store { .. } => InstructionResultType::None, - Instruction::Load { .. } | Instruction::ArrayGet { .. } | Instruction::Call { .. } => { - InstructionResultType::Unknown - } + Instruction::Load { .. } + | Instruction::ArrayGet { .. } + | Instruction::Call { .. } + | Instruction::ForeignCall { .. } => InstructionResultType::Unknown, } } @@ -158,6 +163,10 @@ impl Instruction { max_bit_size: *max_bit_size, }, Instruction::Constrain(value) => Instruction::Constrain(f(*value)), + Instruction::ForeignCall { func, arguments } => Instruction::ForeignCall { + func: func.to_owned(), + arguments: vecmap(arguments.iter().copied(), f), + }, Instruction::Call { func, arguments } => Instruction::Call { func: f(*func), arguments: vecmap(arguments.iter().copied(), f), @@ -245,6 +254,7 @@ impl Instruction { } Instruction::Truncate { .. } => None, Instruction::Call { .. } => None, + Instruction::ForeignCall { .. } => None, Instruction::Allocate { .. } => None, Instruction::Load { .. } => None, Instruction::Store { .. } => None, diff --git a/crates/noirc_evaluator/src/ssa_refactor/ir/printer.rs b/crates/noirc_evaluator/src/ssa_refactor/ir/printer.rs index 2829c6768b8..129b45e51ea 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ir/printer.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ir/printer.rs @@ -71,7 +71,9 @@ fn value(function: &Function, id: ValueId) -> String { let elements = vecmap(array, |element| value(function, *element)); format!("[{}]", elements.join(", ")) } - Value::Param { .. } | Value::Instruction { .. } => id.to_string(), + Value::Param { .. } | Value::Instruction { .. } | Value::ForeignFunction(_) => { + id.to_string() + } } } @@ -148,6 +150,9 @@ pub(crate) fn display_instruction( Instruction::Call { func, arguments } => { writeln!(f, "call {}({})", show(*func), value_list(function, arguments)) } + Instruction::ForeignCall { func, arguments } => { + writeln!(f, "foreign call {}({})", func, value_list(function, arguments)) + } Instruction::Allocate => writeln!(f, "allocate"), Instruction::Load { address } => writeln!(f, "load {}", show(*address)), Instruction::Store { address, value } => { diff --git a/crates/noirc_evaluator/src/ssa_refactor/ir/value.rs b/crates/noirc_evaluator/src/ssa_refactor/ir/value.rs index 30468a0a669..fca871ae895 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ir/value.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ir/value.rs @@ -50,6 +50,11 @@ pub(crate) enum Value { /// An Intrinsic is a special kind of builtin function that may be handled internally /// or optimized into a special form. Intrinsic(Intrinsic), + + /// This Value refers to an external function in the IR. + /// ForeignFunction's always have the type Type::Function and have simlar semantics to Function, + /// other than generating different backend operations and being only accessible through Brillig. + ForeignFunction(String), } impl Value { @@ -62,6 +67,7 @@ impl Value { Value::Array { element_type, array } => Type::Array(element_type.clone(), array.len()), Value::Function { .. } => Type::Function, Value::Intrinsic { .. } => Type::Function, + Value::ForeignFunction { .. } => Type::Function, } } } diff --git a/crates/noirc_evaluator/src/ssa_refactor/opt/inlining.rs b/crates/noirc_evaluator/src/ssa_refactor/opt/inlining.rs index a403ef9b161..e569baa5f8e 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/opt/inlining.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/opt/inlining.rs @@ -207,6 +207,9 @@ impl<'function> PerFunctionContext<'function> { } Value::Function(function) => self.context.builder.import_function(*function), Value::Intrinsic(intrinsic) => self.context.builder.import_intrinsic_id(*intrinsic), + Value::ForeignFunction(function) => { + self.context.builder.import_foreign_function(function) + } Value::Array { array, element_type } => { let elements = array.iter().map(|value| self.translate_value(*value)).collect(); self.context.builder.array_constant(elements, element_type.clone()) @@ -327,7 +330,7 @@ impl<'function> PerFunctionContext<'function> { Instruction::Call { func, arguments } => match self.get_function(*func) { Some(function) => match ssa.functions[&function].runtime() { RuntimeType::Acir => self.inline_function(ssa, *id, function, arguments), - RuntimeType::Brillig => { + RuntimeType::Brillig | RuntimeType::Oracle(_) => { self.context.failed_to_inline_a_call = true; self.push_instruction(*id); } diff --git a/crates/noirc_evaluator/src/ssa_refactor/ssa_builder/mod.rs b/crates/noirc_evaluator/src/ssa_refactor/ssa_builder/mod.rs index 902278e286a..dfc73df5f95 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ssa_builder/mod.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ssa_builder/mod.rs @@ -217,7 +217,7 @@ impl FunctionBuilder { self.insert_instruction(Instruction::Constrain(boolean), None); } - /// Insert a call instruction a the end of the current block and return + /// Insert a call instruction at the end of the current block and return /// the results of the call. pub(crate) fn insert_call( &mut self, @@ -228,6 +228,18 @@ impl FunctionBuilder { self.insert_instruction(Instruction::Call { func, arguments }, Some(result_types)).results() } + /// Insert a foreign call instruction at the end of the current block and return + /// the results of the call. + pub(crate) fn insert_foreign_call( + &mut self, + func: String, + arguments: Vec, + result_types: Vec, + ) -> &[ValueId] { + self.insert_instruction(Instruction::ForeignCall { func, arguments }, Some(result_types)) + .results() + } + /// Insert an instruction to extract an element from an array pub(crate) fn insert_array_get( &mut self, @@ -290,6 +302,12 @@ impl FunctionBuilder { self.current_function.dfg.import_function(function) } + /// Returns a ValueId pointing to the given oracle/foreign function or imports the oracle + /// into the current function if it was not already, and returns that ID. + pub(crate) fn import_foreign_function(&mut self, function: &str) -> ValueId { + self.current_function.dfg.import_foreign_function(function) + } + /// Retrieve a value reference to the given intrinsic operation. /// Returns None if there is no intrinsic matching the given name. pub(crate) fn import_intrinsic(&mut self, name: &str) -> Option { diff --git a/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/context.rs b/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/context.rs index e20a54ba8cc..3decd705f7e 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/context.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/context.rs @@ -260,6 +260,25 @@ impl<'a> FunctionContext<'a> { reshaped_return_values } + pub(super) fn insert_foreign_call( + &mut self, + function: String, + arguments: Vec, + result_type: &ast::Type, + ) -> Values { + let result_types = Self::convert_type(result_type).flatten(); + let results = self.builder.insert_foreign_call(function, arguments, result_types); + + let mut i = 0; + let reshaped_return_values = Self::map_type(result_type, |_| { + let result = results[i].into(); + i += 1; + result + }); + assert_eq!(i, results.len()); + reshaped_return_values + } + /// Create a const offset of an address for an array load or store pub(super) fn make_offset(&mut self, mut address: ValueId, offset: u128) -> ValueId { if offset != 0 { diff --git a/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/mod.rs b/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/mod.rs index 14b3203128a..2d9a70d0237 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/mod.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/mod.rs @@ -92,16 +92,18 @@ impl<'a> FunctionContext<'a> { self.codegen_expression(expr).into_leaf().eval(self) } + /// Codegen for identifiers fn codegen_ident(&mut self, ident: &ast::Ident) -> Values { match &ident.definition { ast::Definition::Local(id) => self.lookup(*id).map(|value| value.eval(self).into()), ast::Definition::Function(id) => self.get_or_queue_function(*id), - ast::Definition::Builtin(name) - | ast::Definition::LowLevel(name) - | ast::Definition::Oracle(name, _) => match self.builder.import_intrinsic(name) { - Some(builtin) => builtin.into(), - None => panic!("No builtin function named '{name}' found"), - }, + ast::Definition::Oracle(name) => self.builder.import_foreign_function(name).into(), + ast::Definition::Builtin(name) | ast::Definition::LowLevel(name) => { + match self.builder.import_intrinsic(name) { + Some(builtin) => builtin.into(), + None => panic!("No builtin function named '{name}' found"), + } + } } } @@ -337,14 +339,19 @@ impl<'a> FunctionContext<'a> { /// Generate SSA for a function call. Note that calls to built-in functions /// and intrinsics are also represented by the function call instruction. fn codegen_call(&mut self, call: &ast::Call) -> Values { - let function = self.codegen_non_tuple_expression(&call.func); - let arguments = call .arguments .iter() .flat_map(|argument| self.codegen_expression(argument).into_value_list(self)) .collect(); + if let ast::Expression::Ident(ident) = call.func.as_ref() { + if let ast::Definition::Oracle(func) = &ident.definition { + return self.insert_foreign_call(func.to_owned(), arguments, &call.return_type); + } + } + + let function = self.codegen_non_tuple_expression(&call.func); self.insert_call(function, arguments, &call.return_type) } diff --git a/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/value.rs b/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/value.rs index 0637641528e..059f29a650a 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/value.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/value.rs @@ -58,7 +58,7 @@ impl Value { /// A tree of values. /// /// Compared to Value alone, the addition of being able to represent structs/tuples as -/// a Tree::Branch means this type can hold any kind of value an frontend expression may return. +/// a Tree::Branch means this type can hold any kind of value a frontend expression may return. /// This is why it is used as the return type for every codegen_* function in ssa_gen/mod.rs. pub(super) type Values = Tree; diff --git a/crates/noirc_frontend/src/hir/resolution/resolver.rs b/crates/noirc_frontend/src/hir/resolution/resolver.rs index 67d0e2cf2a4..883b323ce66 100644 --- a/crates/noirc_frontend/src/hir/resolution/resolver.rs +++ b/crates/noirc_frontend/src/hir/resolution/resolver.rs @@ -305,7 +305,6 @@ impl<'a> Resolver<'a> { fn intern_function(&mut self, func: NoirFunction, id: FuncId) -> (HirFunction, FuncMeta) { let func_meta = self.extract_meta(&func, id); - let hir_func = match func.kind { FunctionKind::Builtin | FunctionKind::LowLevel | FunctionKind::Oracle => { HirFunction::empty() diff --git a/crates/noirc_frontend/src/monomorphization/ast.rs b/crates/noirc_frontend/src/monomorphization/ast.rs index 61541c85fc0..aaaf7c5bb2f 100644 --- a/crates/noirc_frontend/src/monomorphization/ast.rs +++ b/crates/noirc_frontend/src/monomorphization/ast.rs @@ -45,7 +45,7 @@ pub enum Definition { Builtin(String), LowLevel(String), // used as a foreign/externally defined unconstrained function - Oracle(String, FuncId), + Oracle(String), } /// ID of a local definition, e.g. from a let binding or diff --git a/crates/noirc_frontend/src/monomorphization/mod.rs b/crates/noirc_frontend/src/monomorphization/mod.rs index 0f8fb0ea059..8c588acbf90 100644 --- a/crates/noirc_frontend/src/monomorphization/mod.rs +++ b/crates/noirc_frontend/src/monomorphization/mod.rs @@ -153,13 +153,11 @@ impl<'interner> Monomorphizer<'interner> { let id = self.queue_function(id, expr_id, typ); Definition::Function(id) } - FunctionKind::Oracle => { let attr = meta.attributes.expect("Oracle function must have an oracle attribute"); - let id = self.queue_function(id, expr_id, typ); match attr { - Attribute::Oracle(name) => Definition::Oracle(name, id), + Attribute::Oracle(name) => Definition::Oracle(name), _ => unreachable!("Oracle function must have an oracle attribute"), } } diff --git a/crates/noirc_frontend/src/monomorphization/printer.rs b/crates/noirc_frontend/src/monomorphization/printer.rs index 825a800801c..39c6db8734b 100644 --- a/crates/noirc_frontend/src/monomorphization/printer.rs +++ b/crates/noirc_frontend/src/monomorphization/printer.rs @@ -273,7 +273,7 @@ impl Display for Definition { Definition::Function(id) => write!(f, "f{}", id.0), Definition::Builtin(name) => write!(f, "{name}"), Definition::LowLevel(name) => write!(f, "{name}"), - Definition::Oracle(name, _) => write!(f, "{name}"), + Definition::Oracle(name) => write!(f, "{name}"), } } }