1"use strict";(globalThis.webpackChunkdocs=globalThis.webpackChunkdocs||[]).push([[2129],{37874(e,n,i){i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>p,frontMatter:()=>s,metadata:()=>t,toc:()=>c});const t=JSON.parse('{"id":"language/data_types/index","title":"Data Types","description":"Get a clear understanding of the two categories of Noir data types - primitive types and compound types. Learn about their characteristics, differences, and how to use them in your Noir programming.","source":"@site/versioned_docs/version-v1.0.0-rc.2/language/data_types/index.md","sourceDirName":"language/data_types","slug":"/language/data_types/","permalink":"/docs/language/data_types/","draft":false,"unlisted":false,"editUrl":"https://github.com/noir-lang/noir/edit/master/docs/versioned_docs/version-v1.0.0-rc.2/language/data_types/index.md","tags":[],"version":"v1.0.0-rc.2","frontMatter":{"title":"Data Types","description":"Get a clear understanding of the two categories of Noir data types - primitive types and compound types. Learn about their characteristics, differences, and how to use them in your Noir programming.","keywords":["noir","data types","primitive types","compound types","private types","public types"]},"sidebar":"sidebar","previous":{"title":"Workspaces","permalink":"/docs/project_structure/workspaces"},"next":{"title":"Fields","permalink":"/docs/language/data_types/fields"}}');var r=i(74848),a=i(28453);const s={title:"Data Types",description:"Get a clear understanding of the two categories of Noir data types - primitive types and compound types. Learn about their characteristics, differences, and how to use them in your Noir programming.",keywords:["noir","data types","primitive types","compound types","private types","public types"]},o=void 0,l={},c=[{value:"Private & Public Types",id:"private--public-types",level:2},{value:"pub Modifier",id:"pub-modifier",level:3},{value:"Type Aliases",id:"type-aliases",level:2},{value:"Numeric type aliases",id:"numeric-type-aliases",level:3},{value:"Wildcard Type",id:"wildcard-type",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",h3:"h3",p:"p",pre:"pre",strong:"strong",...(0,a.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.p,{children:"Every value in Noir has a type, which determines which operations are valid for it."}),"\n",(0,r.jsxs)(n.p,{children:["All values in Noir are fundamentally composed of ",(0,r.jsx)(n.code,{children:"Field"})," elements. For a more approachable\ndeveloping experience, abstractions are added on top to introduce different data types in Noir."]}),"\n",(0,r.jsxs)(n.p,{children:["Noir has two category of data types: primitive types (e.g. ",(0,r.jsx)(n.code,{children:"Field"}),", integers, ",(0,r.jsx)(n.code,{children:"bool"}),") and compound\ntypes that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or\npublic."]}),"\n",(0,r.jsx)(n.h2,{id:"private--public-types",children:"Private & Public Types"}),"\n",(0,r.jsxs)(n.p,{children:["A ",(0,r.jsx)(n.strong,{children:"private value"})," is known only to the Prover, while a ",(0,r.jsx)(n.strong,{children:"public value"})," is known by both the\nProver and Verifier. Mark values as ",(0,r.jsx)(n.code,{children:"private"})," when the value should only be known to the prover. All\nprimitive types (including individual fields of compound types) in Noir are private by default, and\ncan be marked public when certain values are intended to be revealed to the Verifier."]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Note:"})," For public values defined in Noir programs paired with smart contract verifiers, once\nthe proofs are verified on-chain the values can be considered known to everyone that has access to\nthat blockchain."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Public data types are treated no differently to private types apart from the fact that their values\nwill be revealed in proofs generated. Simply changing the value of a public type will not change the\ncircuit (where the same goes for changing values of private types as well)."}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.em,{children:"Private values"})," are also referred to as ",(0,r.jsx)(n.em,{children:"witnesses"})," sometimes."]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Note:"})," The terms private and public when applied to a type (e.g. ",(0,r.jsx)(n.code,{children:"pub Field"}),") have a different\nmeaning than when applied to a function (e.g. ",(0,r.jsx)(n.code,{children:"pub fn foo() {}"}),")."]}),"\n",(0,r.jsx)(n.p,{children:"The former is a visibility modifier for the Prover to interpret if a value should be made known to\nthe Verifier, while the latter is a visibility modifier for the compiler to interpret if a\nfunction should be made accessible to external Noir programs like in other languages."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"pub-modifier",children:"pub Modifier"}),"\n",(0,r.jsxs)(n.p,{children:["All data types in Noir are private by default. Types are explicitly declared as public using the\n",(0,r.jsx)(n.code,{children:"pub"})," modifier:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"fn main(x: u32, y: pub u32) -> pub u32 {\n x + y\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["In this example, ",(0,r.jsx)(n.code,{children:"x"})," is ",(0,r.jsx)(n.strong,{children:"private"})," while ",(0,r.jsx)(n.code,{children:"y"})," and ",(0,r.jsx)(n.code,{children:"x + y"})," (the return value) are ",(0,r.jsx)(n.strong,{children:"public"}),". Note\nthat visibility is handled ",(0,r.jsx)(n.strong,{children:"per variable"}),", so it is perfectly valid to have one input that is\nprivate and another that is public."]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Note:"})," Public types can only be declared through parameters on ",(0,r.jsx)(n.code,{children:"main"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"type-aliases",children:"Type Aliases"}),"\n",(0,r.jsxs)(n.p,{children:["A type alias is a new name for an existing type. Type aliases are declared with the keyword ",(0,r.jsx)(n.code,{children:"type"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"type Id = u8;\n\nfn main() {\n let id: Id = 1;\n let zero: u8 = 0;\n assert(zero + 1 == id);\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Type aliases can also be used with ",(0,r.jsx)(n.a,{href:"/docs/language/generics",children:"generics"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"type Id<Size> = Size;\n\nfn main() {\n let id: Id<u32> = 1;\n let zero: u32 = 0;\n assert(zero + 1 == id);\n}\n"})}),"\n",(0,r.jsx)(n.p,{children:"Type aliases can even refer to other aliases. An error will be issued if they form a cycle:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"// Ok!\ntype A = B;\ntype B = Field;\n\ntype Bad1 = Bad2;\n\n// error: Dependency cycle found\ntype Bad2 = Bad1;\n// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2\n"})}),"\n",(0,r.jsxs)(n.p,{children:["By default, like functions, type aliases are private to the module they exist in. You can use ",(0,r.jsx)(n.code,{children:"pub"}),"\nto make the type alias public or ",(0,r.jsx)(n.code,{children:"pub(crate)"})," to make it public to just its crate:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"// This type alias is now public\npub type Id = u8;\n"})}),"\n",(0,r.jsx)(n.h3,{id:"numeric-type-aliases",children:"Numeric type aliases"}),"\n",(0,r.jsx)(n.p,{children:"Type aliases can also be defined for numeric types, which can help cut down on longer type expressions."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"type Double<let N: u32>: u32 = N * 2;\n\n// When used in an array position we need to use the turbofish operator to specify any\n// generics in a numeric type alias\nfn concat_self<let N: u32>(array: [u32; N]) -> [u32; Double::<N>] {\n let mut result = [0; Double::<N>];\n for i in 0..array.len() {\n result[i] = array[i];\n result[i + array.len()] = array[i];\n }\n result\n}\n\nstruct Array<T, let N: u32> {\n data: [T; N],\n}\n\n// When used within other type positions, however, we can refer to it without the `::`\nfn concat_self2<let N: u32>(array: Array<u32, N>) -> Array<u32, Double<N>>
1 {\n Array { data: concat_self(array.data) }\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"wildcard-type",children:"Wildcard Type"}),"\n",(0,r.jsxs)(n.p,{children:["Noir can usually infer the type of the variable from the context, so specifying the type of a variable is only required when it cannot be inferred. However, specifying a complex type can be tedious, especially when it has multiple generic arguments. Often some of the generic types can be inferred from the context, and Noir only needs a hint to properly infer the other types. We can partially specify a variable's type by using ",(0,r.jsx)(n.code,{children:"_"})," as a marker, indicating where we still want the compiler to infer the type."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"let a: [_; 4] = foo(b);\n"})})]})}function p(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},28453(e,n,i){i.d(n,{R:()=>s,x:()=>o});var t=i(96540);const r={},a=t.createContext(r);function s(e){const n=t.useContext(a);return t.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(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.