PageSourceSearch

https://noir-lang.org/docs/assets/js/6e57af8c.5db108bb.js

js noir-lang.org collected 2026-10-03 22:54:38 UTC 9,628 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkdocs=globalThis.webpackChunkdocs||[]).push([[3746],{62593(e,n,r){r.r(n),r.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>c,metadata:()=>t,toc:()=>o});const t=JSON.parse('{"id":"language/data_types/references","title":"References","description":"Learn about reference types in Noir, including immutable references (&T) and mutable references (&mut T).","source":"@site/versioned_docs/version-v1.0.0-rc.0/language/data_types/references.md","sourceDirName":"language/data_types","slug":"/language/data_types/references","permalink":"/docs/v1.0.0-rc.0/language/data_types/references","draft":false,"unlisted":false,"editUrl":"https://github.com/noir-lang/noir/edit/master/docs/versioned_docs/version-v1.0.0-rc.0/language/data_types/references.md","tags":[],"version":"v1.0.0-rc.0","frontMatter":{"title":"References","description":"Learn about reference types in Noir, including immutable references (&T) and mutable references (&mut T).","keywords":["noir","references","mutable references","immutable references","borrowing"]},"sidebar":"sidebar","previous":{"title":"Structs","permalink":"/docs/v1.0.0-rc.0/language/data_types/structs"},"next":{"title":"Function types","permalink":"/docs/v1.0.0-rc.0/language/data_types/function_types"}}');var s=r(74848),a=r(28453);const c={title:"References",description:"Learn about reference types in Noir, including immutable references (&T) and mutable references (&mut T).",keywords:["noir","references","mutable references","immutable references","borrowing"]},i=void 0,l={},o=[{value:"Mutable References",id:"mutable-references",level:2},{value:"Immutable References",id:"immutable-references",level:2},{value:"Immutable Self References",id:"immutable-self-references",level:3},{value:"Performance in Unconstrained Code",id:"performance-in-unconstrained-code",level:3},{value:"References Exclusivity and Lifetimes",id:"references-exclusivity-and-lifetimes",level:3},{value:"References to Array Elements",id:"references-to-array-elements",level:3}];function d(e){const n={code:"code",em:"em",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["Noir supports first-class references. References point to a specific address that can be followed\nto access the data stored at that address. The ",(0,s.jsx)(n.code,{children:"&"})," operator references a variable and the ",(0,s.jsx)(n.code,{children:"*"})," operator\ndereferences it."]}),"\n",(0,s.jsx)(n.p,{children:"References come in two forms:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Immutable references"})," (",(0,s.jsx)(n.code,{children:"&T"}),") \u2014 read-only access to a value."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Mutable references"})," (",(0,s.jsx)(n.code,{children:"&mut T"}),") \u2014 read and write access to a value."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"mutable-references",children:"Mutable References"}),"\n",(0,s.jsx)(n.p,{children:"Mutable references allow a called function to mutate a value owned by the caller:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main() {\n    let mut x = 2;\n\n    // you can reference x as &mut and pass it to multiplyBy2\n    increment(&mut x);\n\n    assert_eq(x, 3);\n}\n\n// you can access &mut here\nfn increment(x: &mut Field) {\n    // and dereference it with *\n    *x += 1;\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When creating a mutable reference, the original variable must be declared ",(0,s.jsx)(n.code,{children:"mut"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"Also note that unlike Rust, Noir allows multiple mutable references to the same value.\nThis is safe because Noir has no concurrency and values are never dropped."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main() {\n    let mut array = [1, 2, 3];\n\n    let ref1 = &mut array;\n    let ref2 = &mut array;\n\n    ref1[0] = 42;\n    println(*ref2);  // [42, 2, 3]\n}\n"})}),"\n",(0,s.jsx)(n.h2,{id:"immutable-references",children:"Immutable References"}),"\n",(0,s.jsxs)(n.p,{children:["Immutable references provide read-only access to a value and can be created with ",(0,s.jsx)(n.code,{children:"&"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn sum(values: &[Field; 3]) -> Field {\n    // Auto-dereferences: you can index directly through the reference\n    values[0] + values[1] + values[2]\n}\n\nfn main() {\n    let data = [1, 2, 3];\n    let total = sum(&data);\n    assert(total == 6);\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Unlike mutable references, creating an immutable reference does not require the original variable to be declared ",(0,s.jsx)(n.code,{children:"mut"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"You cannot write through an immutable reference. Attempting to do so is a compile error:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main() {\n    let s = [0];\n    let ps = &s;\n    ps[0] = 1; // Error: `ps` is a `&` reference, so it cannot be written to\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"Since Noir has no borrow-checker, it is possible to have immutable references alongside mutable\nreferences to the same data. This is usually undesired but developers should consider this as\na corner case since it is possible for mutations to be observed from an immutable reference:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn mutate_and_print(a: &[Field; 3], b: &mut [Field; 3]) {\n    println(*a);\n    *b = [100, 200, 300];\n    println(*a);  // This line can be different from the first print if a = b\n}\n\nfn main() {\n    let mut array = [1, 2, 3];\n    mutate_and_print(&array, &mut array);\n}\n"})}),"\n",(0,s.jsx)(n.h3,{id:"immutable-self-references",children:"Immutable Self References"}),"\n",(0,s.jsxs)(n.p,{children:["Methods can take ",(0,s.jsx)(n.code,{children:"&self"})," as a shorthand for ",(0,s.jsx)(n.code,{children:"self: &Self"}),". Calling a ",(0,s.jsx)(n.code,{children:"&self"})," method\ndoes not require the variable to be mutable:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"struct Point {\n    x: Field,\n    y: Field,\n}\n\nimpl Point {\n    fn sum(&self) -> Field {\n        self.x + self.y\n    }\n}\n\nfn main() {\n    let p = Point { x: 1, y: 2 };\n    assert(p.sum() == 3);\n}\n"})}),"\n",(0,s.jsx)(n.h3,{id:"performance-in-unconstrained-code",children:"Performance in Unconstrained Code"}),"\n",(0,s.jsx)(n.p,{children:"References only affect performance in unconstrained code. In constrained code, references\nhave no performance impact at all."}),"\n",(0,s.jsxs)(n.p,{children:["In unconstrained code, arrays use reference counting with copy-on-write semantics. Passing an array\nby value increments its reference count. Passing it by immutable reference does ",(0,s.jsx)(n.em,{children:"not"})," increment\nthe reference count."]}),"\n",(0,s.jsx)(n.p,{children:"When arrays are mutated in unconstrained code and the reference count is not 1, they are cloned.\nThus, passing around arrays by reference avoids reference count increases and can lead to fewer\nclones at runtime."}),"\n",(0,s.jsxs)(n.p,{children:["If you are writing helper functions which are unconstrained or may be run in an unconstrained\ncontext that only need to read an array, prefer taking ",(0,s.jsx)(n.code,{children:"&[T; N]"})," over ",(0,s.jsx)(n.code,{children:"[T; N]"})," to avoid the\nreference-count overhead and to possibly reduce clones later on if the array is ever mutated."]}),"\n",(0,s.jsx)(n.h3,{id:"references-exclusivity-and-lifetimes",children:"References Exclusivity and Lifetimes"}),"\n",(0,s.jsxs)(n.p,{children:["Unlike Rust, Noir does ",(0,s.jsx)(n.strong,{children:"not"})," enforce reference exclusivity. An immutable reference\n(",(0,s.jsx)(n.code,{children:"&T"}),") and a mutable reference (",(0,s.jsx)(n.code,{children:"&mut T"}),") to the same value can exist at the same time.\nNoir also does not have lifetimes on references. Instead, referenced memory lasts for\nthe entire program."]}),"\n",(0,s.jsx)(n.h3,{id:"references-to-array-elements",children:"References to Array Elements"}),"\n",(0,s.jsx)(n.p,{children:"Mutable references to array elements are not supported:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn foo(x: &mut u32) {\n    *x += 1;\n}\nfn main() {\n    let mut state: [u32; 4] = [1, 2, 3, 4];\n    foo(&mut state[0]);\n    assert_eq(state[0], 2);\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"The above will error with:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"error: Mutable references to array elements are currently unsupported\n  \u250c\u2500 src/main.nr:6:18\n  \u2502\n6 \u2502         foo(&mut state[0]);\n  \u2502                  -------- Try storing the element in a fresh variable first\n  \u2502\n"})})]})}function u(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},28453(e,n,r){r.d(n,{R:()=>c,x:()=>i});var t=r(96540);const s={},a=t.createContext(s);function c(e){const n=t.useContext(a);return t.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:c(e.components),t.createElement(a.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.