1"use strict";(globalThis.webpackChunkdocs=globalThis.webpackChunkdocs||[]).push([[3910],{58411(e,n,o){o.r(n),o.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>h,frontMatter:()=>l,metadata:()=>r,toc:()=>t});const r=JSON.parse('{"id":"project_structure/modules","title":"Modules","description":"Learn how to organize your files using modules in Noir, following the same convention as Rust\'s module system. Examples included.","source":"@site/versioned_docs/version-v1.0.0-rc.0/project_structure/modules.md","sourceDirName":"project_structure","slug":"/project_structure/modules","permalink":"/docs/v1.0.0-rc.0/project_structure/modules","draft":false,"unlisted":false,"editUrl":"https://github.com/noir-lang/noir/edit/master/docs/versioned_docs/version-v1.0.0-rc.0/project_structure/modules.md","tags":[],"version":"v1.0.0-rc.0","frontMatter":{"title":"Modules","description":"Learn how to organize your files using modules in Noir, following the same convention as Rust\'s module system. Examples included.","keywords":["Noir","Rust","modules","organizing files","sub-modules"]},"sidebar":"sidebar","previous":{"title":"Dependencies","permalink":"/docs/v1.0.0-rc.0/project_structure/dependencies"},"next":{"title":"Workspaces","permalink":"/docs/v1.0.0-rc.0/project_structure/workspaces"}}');var s=o(74848),i=o(28453);const l={title:"Modules",description:"Learn how to organize your files using modules in Noir, following the same convention as Rust's module system. Examples included.",keywords:["Noir","Rust","modules","organizing files","sub-modules"]},d=void 0,c={},t=[{value:"Purpose of Modules",id:"purpose-of-modules",level:2},{value:"Examples",id:"examples",level:2},{value:"Importing a module in the crate root",id:"importing-a-module-in-the-crate-root",level:3},{value:"Importing a module throughout the tree",id:"importing-a-module-throughout-the-tree",level:3},{value:"Sub-modules",id:"sub-modules",level:3},{value:"Referencing a parent module",id:"referencing-a-parent-module",level:3},{value:"Import Syntax",id:"import-syntax",level:2},{value:"Basic imports",id:"basic-imports",level:3},{value:"Aliases",id:"aliases",level:3},{value:"Grouped imports",id:"grouped-imports",level:3},{value:"Path prefixes",id:"path-prefixes",level:3},{value:"Re-exports",id:"re-exports",level:3},{value:"The Prelude",id:"the-prelude",level:2},{value:"Visibility",id:"visibility",level:3}];function a(e){const n={code:"code",em:"em",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["Noir's module system follows the same convention as the ",(0,s.jsx)(n.em,{children:"newer"})," version of Rust's module system."]}),"\n",(0,s.jsx)(n.h2,{id:"purpose-of-modules",children:"Purpose of Modules"}),"\n",(0,s.jsx)(n.p,{children:"Modules are used to organize files. Without modules all of your code would need to live in a single\nfile. In Noir, the compiler does not automatically scan all of your files to detect modules. This\nmust be done explicitly by the developer."}),"\n",(0,s.jsx)(n.h2,{id:"examples",children:"Examples"}),"\n",(0,s.jsx)(n.h3,{id:"importing-a-module-in-the-crate-root",children:"Importing a module in the crate root"}),"\n",(0,s.jsxs)(n.p,{children:["Filename : ",(0,s.jsx)(n.code,{children:"src/main.nr"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"mod foo;\n\nfn main() {\n foo::hello_world();\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Filename : ",(0,s.jsx)(n.code,{children:"src/foo.nr"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn from_foo() {}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["In the above snippet, the crate root is the ",(0,s.jsx)(n.code,{children:"src/main.nr"})," file. The compiler sees the module\ndeclaration ",(0,s.jsx)(n.code,{children:"mod foo"})," which prompts it to look for a foo.nr file."]}),"\n",(0,s.jsx)(n.p,{children:"Visually this module hierarchy looks like the following :"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"crate\n \u251c\u2500\u2500 main\n \u2502\n \u2514\u2500\u2500 foo\n \u2514\u2500\u2500 from_foo\n\n"})}
1),"\n",(0,s.jsxs)(n.p,{children:["The module filename may also be the name of the module as a directory with the contents in a\nfile named ",(0,s.jsx)(n.code,{children:"mod.nr"})," within that directory. The above example can alternatively be expressed like this:"]}),"\n",(0,s.jsxs)(n.p,{children:["Filename : ",(0,s.jsx)(n.code,{children:"src/main.nr"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"mod foo;\n\nfn main() {\n foo::hello_world();\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Filename : ",(0,s.jsx)(n.code,{children:"src/foo/mod.nr"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn from_foo() {}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Note that it's an error to have both files ",(0,s.jsx)(n.code,{children:"src/foo.nr"})," and ",(0,s.jsx)(n.code,{children:"src/foo/mod.nr"})," in the filesystem."]}),"\n",(0,s.jsx)(n.h3,{id:"importing-a-module-throughout-the-tree",children:"Importing a module throughout the tree"}),"\n",(0,s.jsxs)(n.p,{children:["All modules are accessible from the ",(0,s.jsx)(n.code,{children:"crate::"})," namespace."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"crate\n \u251c\u2500\u2500 bar\n \u251c\u2500\u2500 foo\n \u2514\u2500\u2500 main\n\n"})}),"\n",(0,s.jsxs)(n.p,{children:["In the above snippet, if ",(0,s.jsx)(n.code,{children:"bar"})," would like to use functions in ",(0,s.jsx)(n.code,{children:"foo"}),", it can do so by ",(0,s.jsx)(n.code,{children:"use crate::foo::function_name"}),"."]}),"\n",(0,s.jsx)(n.h3,{id:"sub-modules",children:"Sub-modules"}),"\n",(0,s.jsxs)(n.p,{children:["Filename : ",(0,s.jsx)(n.code,{children:"src/main.nr"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"mod foo;\n\nfn main() {\n foo::from_foo();\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Filename : ",(0,s.jsx)(n.code,{children:"src/foo.nr"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"mod bar;\nfn from_foo() {}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Filename : ",(0,s.jsx)(n.code,{children:"src/foo/bar.nr"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn from_bar() {}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["In the above snippet, we have added an extra module to the module tree; ",(0,s.jsx)(n.code,{children:"bar"}),". ",(0,s.jsx)(n.code,{children:"bar"})," is a submodule\nof ",(0,s.jsx)(n.code,{children:"foo"})," hence we declare bar in ",(0,s.jsx)(n.code,{children:"foo.nr"})," with ",(0,s.jsx)(n.code,{children:"mod bar"}),". Since ",(0,s.jsx)(n.code,{children:"foo"})," is not the crate root, the\ncompiler looks for the file associated with the ",(0,s.jsx)(n.code,{children:"bar"})," module in ",(0,s.jsx)(n.code,{children:"src/foo/bar.nr"})]}),"\n",(0,s.jsx)(n.p,{children:"Visually the module hierarchy looks as follows:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"crate\n \u251c\u2500\u2500 main\n \u2502\n \u2514\u2500\u2500 foo\n \u251c\u2500\u2500 from_foo\n \u2514\u2500\u2500 bar\n \u2514\u2500\u2500 from_bar\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Similar to importing a module in the crate root, modules can be placed in a ",(0,s.jsx)(n.code,{children:"mod.nr"})," file, like this:"]}),"\n",(0,s.jsxs)(n.p,{children:["Filename : ",(0,s.jsx)(n.code,{children:"src/main.nr"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"mod foo;\n\nfn main() {\n foo::from_foo();\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Filename : ",(0,s.jsx)(n.code,{children:"src/foo/mod.nr"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"mod bar;\nfn from_foo() {}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Filename : ",(0,s.jsx)(n.code,{children:"src/foo/bar/mod.nr"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn from_bar() {}\n"})}),"\n",(0,s.jsx)(n.h3,{id:"referencing-a-parent-module",children:"Referencing a parent module"}),"\n",(0,s.jsxs)(n.p,{children:["Given a submodule, you can refer to its parent module using the ",(0,s.jsx)(n.code,{children:"super"})," keyword."]}),"\n",(0,s.jsxs)(n.p,{children:["Filename : ",(0,s.jsx)(n.code,{children:"src/main.nr"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"mod foo;\n\nfn main() {\n foo::from_foo();\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Filename : ",(0,s.jsx)(n.code,{children:"src/foo.nr"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"mod bar;\n\nfn from_foo() {}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Filename : ",(0,s.jsx)(n.code,{children:"src/foo/bar.nr"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"// Same as foo::from_foo\nuse super::from_foo; \n\nfn from_bar() {\n from_foo(); // invokes super::from_foo(), which is foo::from_foo()\n super::from_foo(); // also invokes foo::from_foo()\n}\n"})}),"\n",(0,s.jsx)(n.h2,{id:"import-syntax",children:"Import Syntax"}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"use"})," keyword brings items from other modules into scope. There are several forms:"]}),"\n",(0,s.jsx)(n.h3,{id:"basic-imports",children:"Basic imports"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"use crate::foo::bar; // Import 'bar' from the 'foo' module in the crate root\nuse super::sibling_fn; // Import from the parent module\nuse some_dependency::item; // Import from a dependency (plain path)\n"})}),"\n",(0,s.jsx)(n.h3,{id:"aliases",children:"Aliases"}),"\n",(0,s.jsxs)(n.p,{children:["You can rename an import with ",(0,s.jsx)(n.code,{children:"as"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"use crate::foo::bar as my_bar;\n"})}),"\n",(0,s.jsxs)(n.p,{children:["You can also alias a trait to ",(0,s.jsx)(n.code,{children:"_"})," to import its methods without bringing the trait name into scope:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"use crate::foo::MyTrait as _;\n"})}),"\n",(0,s.jsx)(n.p,{children:"This is useful when you need to call methods defined by a trait but don't want the trait name to be accessible in the current module."}),"\n",(0,s.jsx)(n.h3,{id:"grouped-imports",children:"Grouped imports"}),"\n",(0,s.jsx)(n.p,{children:"Import multiple items from the same path:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"use crate::foo::{bar, baz};\nuse crate::{foo::{bar2 as b, baz}, qux::{c, d}};\n"})}),"\n",(0,s.jsx)(n.h3,{id:"path-prefixes",children:"Path prefixes"}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Prefix"}),(0,s.jsx)(n.th,{children:"Meaning"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"crate::"})}),(0,s.jsx)(n.td,{children:"From the root of the current crate"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"super::"})}),(0,s.jsx)(n.td,{children:"From the parent module"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"::"})}),(0,s.jsx)(n.td,{children:"An absolute path"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.em,{children:"(plain)"})}),(0,s.jsx)(n.td,{children:"Relative to the current module, or a dependency name"})]})]})]}),"\n",(0,s.jsx)(n.h3,{id:"re-exports",children:"Re-exports"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"use"})," declarations are private to the containing module by default. However, like functions,\nthey can be marked as ",(0,s.jsx)(n.code,{children:"pub"})," or ",(0,s.jsx)(n.code,{children:"pub(crate)"}),". A public ",(0,s.jsx)(n.code,{children:"use"})," declaration serves to ",(0,s.jsx)(n.em,{children:"re-export"})," a name.\nA public ",(0,s.jsx)(n.code,{children:"use"})," declaration can therefore redirect some public name to a different target definition:\neven a definition with a private canonical path, inside a different module."]}),"\n",(0,s.jsx)(n.p,{children:"An example of re-exporting:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"mod some_module {\n pub use foo::{bar, baz};\n mod foo {\n pub fn bar() {}\n pub fn baz() {}\n }\n}\n\nfn main() {\n some_module::bar();\n some_module::baz();\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["In this example, the module ",(0,s.jsx)(n.code,{children:"some_module"})," re-exports two public names defined in ",(0,s.jsx)(n.code,{children:"foo"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"the-prelude",children:"The Prelude"}),"\n",(0,s.jsxs)(n.p,{children:["Noir automatically imports a set of commonly used items into every file via the ",(0,s.jsx)(n.em,{children:"prelude"}),". These items are available without an explicit ",(0,s.jsx)(n.code,{children:"use"})," statement:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"assert_constant"}),", ",(0,s.jsx)(n.code,{children:"print"}),", ",(0,s.jsx)(n.code,{children:"println"})," -- built-in functions"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"Eq"}),", ",(0,s.jsx)(n.code,{children:"Ord"})," -- comparison traits (from ",(0,s.jsx)(n.code,{children:"std::cmp"}),")"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"BoundedVec"})," -- bounded vector type (from ",(0,s.jsx)(n.code,{children:"std::collections"}),")"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"From"}),", ",(0,s.jsx)(n.code,{children:"Into"})," -- conversion traits (from ",(0,s.jsx)(n.code,{children:"std::convert"}),")"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"Default"})," -- default value trait (from ",(0,s.jsx)(n.code,{children:"std::default"}),")"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"derive"}),", ",(0,s.jsx)(n.code,{children:"derive_via"})," -- derive macros (from ",(0,s.jsx)(n.code,{children:"std::meta"}),")"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"Option"})," -- optional value type (from ",(0,s.jsx)(n.code,{children:"std::option"}),")"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"panic"})," -- halt execution with a message (from ",(0,s.jsx)(n.code,{children:"std::panic"}),")"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"visibility",children:"Visibility"}),"\n",(0,s.jsxs)(n.p,{children:["By default, like functions, modules are private to the module (or crate) they exist in. You can use ",(0,s.jsx)(n.code,{children:"pub"}),"\nto make the module public or ",(0,s.jsx)(n.code,{children:"pub(crate)"})," to make it public to just its crate:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"// This module is now public and can be seen by other crates.\npub mod foo;\n"})})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}},28453(e,n,o){o.d(n,{R:()=>l,x:()=>d});var r=o(96540);const s={},i=r.createContext(s);function l(e){const n=r.useContext(i);return r.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:l(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.