diff --git a/crates/noirc_driver/src/lib.rs b/crates/noirc_driver/src/lib.rs index 3511fbeabb6..d719c29d7bd 100644 --- a/crates/noirc_driver/src/lib.rs +++ b/crates/noirc_driver/src/lib.rs @@ -22,6 +22,8 @@ mod program; pub use contract::{CompiledContract, ContractFunction, ContractFunctionType}; pub use program::CompiledProgram; +const STD_CRATE_NAME: &str = "std"; + #[derive(Args, Clone, Debug, Default, Serialize, Deserialize)] pub struct CompileOptions { /// Emit debug information for the intermediate SSA IR @@ -58,16 +60,30 @@ pub fn compile_file( /// Adds the file from the file system at `Path` to the crate graph as a root file pub fn prepare_crate(context: &mut Context, file_name: &Path) -> CrateId { + let path_to_std_lib_file = Path::new(STD_CRATE_NAME).join("lib.nr"); + let std_file_id = context.file_manager.add_file(&path_to_std_lib_file).unwrap(); + let std_crate_id = context.crate_graph.add_stdlib(std_file_id); + let root_file_id = context.file_manager.add_file(file_name).unwrap(); - context.crate_graph.add_crate_root(root_file_id) + let root_crate_id = context.crate_graph.add_crate_root(root_file_id); + + add_dep(context, root_crate_id, std_crate_id, STD_CRATE_NAME.parse().unwrap()); + + root_crate_id } // Adds the file from the file system at `Path` to the crate graph pub fn prepare_dependency(context: &mut Context, file_name: &Path) -> CrateId { let root_file_id = context.file_manager.add_file(file_name).unwrap(); - context.crate_graph.add_crate(root_file_id) + let crate_id = context.crate_graph.add_crate(root_file_id); + + // Every dependency has access to stdlib + let std_crate_id = context.stdlib_crate_id(); + add_dep(context, crate_id, *std_crate_id, STD_CRATE_NAME.parse().unwrap()); + + crate_id } /// Adds a edge in the crate graph for two crates @@ -83,23 +99,6 @@ pub fn add_dep( .expect("cyclic dependency triggered"); } -/// Propagates a given dependency to every other crate. -pub fn propagate_dep( - context: &mut Context, - dep_to_propagate: CrateId, - dep_to_propagate_name: &CrateName, -) { - let crate_ids: Vec<_> = - context.crate_graph.iter_keys().filter(|crate_id| *crate_id != dep_to_propagate).collect(); - - for crate_id in crate_ids { - context - .crate_graph - .add_dep(crate_id, dep_to_propagate_name.clone(), dep_to_propagate) - .expect("ice: cyclic error triggered with std library"); - } -} - /// Run the lexing, parsing, name resolution, and type checking passes. /// /// This returns a (possibly empty) vector of any warnings found on success. @@ -109,19 +108,6 @@ pub fn check_crate( crate_id: CrateId, deny_warnings: bool, ) -> Result { - // Add the stdlib before we check the crate - // TODO: This should actually be done when constructing the driver and then propagated to each dependency when added; - // however, the `create_non_local_crate` panics if you add the stdlib as the first crate in the graph and other - // parts of the code expect the `0` FileID to be the crate root. See also #1681 - let std_crate_name = "std"; - let path_to_std_lib_file = Path::new(std_crate_name).join("lib.nr"); - let root_file_id = context.file_manager.add_file(&path_to_std_lib_file).unwrap(); - - // You can add any crate type to the crate graph - // but you cannot depend on Binaries - let std_crate = context.crate_graph.add_stdlib(root_file_id); - propagate_dep(context, std_crate, &std_crate_name.parse().unwrap()); - let mut errors = vec![]; CrateDefMap::collect_defs(crate_id, context, &mut errors); diff --git a/crates/noirc_frontend/src/graph/mod.rs b/crates/noirc_frontend/src/graph/mod.rs index 0305854ca32..c6d69059869 100644 --- a/crates/noirc_frontend/src/graph/mod.rs +++ b/crates/noirc_frontend/src/graph/mod.rs @@ -130,6 +130,13 @@ impl CrateGraph { .expect("ICE: A root crate should exist in the CrateGraph") } + pub fn stdlib_crate_id(&self) -> &CrateId { + self.arena + .keys() + .find(|crate_id| crate_id.is_stdlib()) + .expect("Something about no crates in graph") + } + pub fn add_crate_root(&mut self, file_id: FileId) -> CrateId { for (crate_id, crate_data) in self.arena.iter() { if crate_id.is_root() { diff --git a/crates/noirc_frontend/src/hir/mod.rs b/crates/noirc_frontend/src/hir/mod.rs index d0b24e90a76..707f2b20251 100644 --- a/crates/noirc_frontend/src/hir/mod.rs +++ b/crates/noirc_frontend/src/hir/mod.rs @@ -63,6 +63,10 @@ impl Context { self.crate_graph.root_crate_id() } + pub fn stdlib_crate_id(&self) -> &CrateId { + self.crate_graph.stdlib_crate_id() + } + // TODO: Decide if we actually need `function_name` and `fully_qualified_function_name` pub fn function_name(&self, id: &FuncId) -> &str { self.def_interner.function_name(id) diff --git a/crates/wasm/src/compile.rs b/crates/wasm/src/compile.rs index 01f286f924f..69a405d5e28 100644 --- a/crates/wasm/src/compile.rs +++ b/crates/wasm/src/compile.rs @@ -3,8 +3,8 @@ use fm::FileManager; use gloo_utils::format::JsValueSerdeExt; use log::debug; use noirc_driver::{ - check_crate, compile_contracts, compile_no_check, prepare_crate, prepare_dependency, - propagate_dep, CompileOptions, CompiledContract, + add_dep, check_crate, compile_contracts, compile_no_check, prepare_crate, prepare_dependency, + CompileOptions, CompiledContract, }; use noirc_frontend::{graph::CrateGraph, hir::Context}; use serde::{Deserialize, Serialize}; @@ -58,11 +58,32 @@ impl Default for WASMCompileOptions { } } -fn add_noir_lib(context: &mut Context, crate_name: &str) { - let path_to_lib = Path::new(&crate_name).join("lib.nr"); - let library_crate = prepare_dependency(context, &path_to_lib); - - propagate_dep(context, library_crate, &crate_name.parse().unwrap()); +fn add_noir_lib(context: &mut Context, library_name: &str) { + let path_to_lib = Path::new(&library_name).join("lib.nr"); + let library_crate_id = prepare_dependency(context, &path_to_lib); + + add_dep(context, *context.root_crate_id(), library_crate_id, library_name.parse().unwrap()); + + // TODO: Remove this code that attaches every crate to every other crate as a dependency + let root_crate_id = context.root_crate_id(); + let stdlib_crate_id = context.stdlib_crate_id(); + let other_crate_ids: Vec<_> = context + .crate_graph + .iter_keys() + .filter(|crate_id| { + // We don't want to attach this crate to itself or stdlib, nor re-attach it to the root crate + crate_id != &library_crate_id + && crate_id != root_crate_id + && crate_id != stdlib_crate_id + }) + .collect(); + + for crate_id in other_crate_ids { + context + .crate_graph + .add_dep(crate_id, library_name.parse().unwrap(), library_crate_id) + .expect(&format!("ICE: Cyclic error triggered by {} library", library_name)); + } } #[wasm_bindgen]