Arcis supports many of Rust’s native operations and extends them for encrypted data, allowing you to write private computations using familiar Rust syntax. See the tables below for a detailed list of supported and unsupported operations.Documentation Index
Fetch the complete documentation index at: https://docs.arcium.com/llms.txt
Use this file to discover all available pages before exploring further.
Quick Summary
Works:if/else, for loops, arithmetic, comparisons, iterators (except filter)
Doesn’t work: while, loop, break, match, return, .filter()
See tables below for full details.
Table of contents
Expression support
| Expression Name | Example | Support | Comments |
|---|---|---|---|
| Array literal | [a, b] | Supported | |
| Assignment | a = b; | Supported | |
| Async block | async { ... } | Unsupported | |
| Await | foo().await | Unsupported | |
| Binary expression | a + b | Partial Support | See table below for supported binary expressions. |
| Block expression | { ... } | Supported | |
| Break | break; | Unsupported | |
| Function call | f(a, b) | Partial Support | See table below for supported functions. |
| Casts | a as u16 | Partial Support | See table below for supported conversions. |
| Closures | |a, b | a + b | Supported | |
| Const block | const { ... } | Supported | |
| Continue | continue; | Unsupported | |
| Field access/set | obj.field | Supported | |
| For loop | for i in expr { ... } | Supported | Note that expr will have its length known at compile-time. |
| If | if cond { ... } else { ... } | Supported | Complexity is O(then_block + else_block). |
| Indexing | a[idx] | Supported | Complexity is O(a.len()) if idx isn’t compile-time known (all positions are checked to hide which index was accessed). |
| If let | if let Some(x) = ... | Unsupported | |
| Literals | 1u128 | Partial Support | See table below for supported literals. |
| Loops | loop { ... } | Unsupported | MPC circuits have fixed structure—variable iteration counts would require dynamic circuit size. Use for with compile-time bounds instead. |
| Macros | println!("{}", q) | Partial Support | See table below for supported macros. |
| Match | match n { ... } | Unsupported | |
| Method calls | x.foo(a, b) | Partial Support | See table below for supported methods. |
| Parentheses | (a + b) | Supported | |
| Paths | Foo::bar | Partial Support | See table below for supported paths. |
| Ranges | 4..5 | Partial Support | Not supported in arr[4..16]. |
| Raw addresses | &raw const foo | Unsupported | |
| References | &mut foo | Supported | |
| Repeat arrays | [4u8; 128] | Supported | |
| Return | return false; | Unsupported | |
| Struct literals | MyStruct { a: 12, b } | Supported | |
| Try expression | this_call_can_err()?; | Unsupported | |
| Tuple literal | (a, 4, c) | Supported | |
| Unary expressions | !x | Partial Support | User-defined unary operations are not supported. |
| Unsafe | unsafe { ... } | Unsupported | |
| While loops | while x < 64 { ... } | Unsupported | Cannot be supported as the number of iterations is not known. |
Why both branches count: In MPC, both
if and else branches are always evaluated—the condition only selects which result to use. This ensures the execution pattern does not leak information about the condition value. See Thinking in MPC for details.Binary expressions
User-defined binary operations are currently unsupported.| Example | Supported types |
|---|---|
a + b | Integers, floats, BaseField25519 |
a - b | Integers, floats, BaseField25519 |
a * b | Integers, floats, BaseField25519 |
a / b | Integers, floats |
a % b | Integers |
a && b | Booleans |
a || b | Booleans |
a ^ b | Booleans |
a & b | Booleans |
a | b | Booleans |
a << b | None |
a >> b | Integers, if b is known at compile time. |
a == b | All. Use derive(PartialEq) for structs. |
a != b | All. Use derive(PartialEq) for structs. |
a < b | Booleans, integers, floats, BaseField25519 |
a <= b | Booleans, integers, floats, BaseField25519 |
a >= b | Booleans, integers, floats, BaseField25519 |
a > b | Booleans, integers, floats, BaseField25519 |
a += b | Integers, floats, BaseField25519 |
a -= b | Integers, floats, BaseField25519 |
a *= b | Integers, floats, BaseField25519 |
a /= b | Integers, floats |
a %= b | Integers |
a ^= b | Booleans |
a &= b | Booleans |
a |= b | Booleans |
a <<= b | None |
a >>= b | Integers, if b is known at compile time |
BaseField25519 does not support /, %, >>, or <<. Note that &, |, ^ are booleans-only across all types. Use .field_division() or .euclidean_division() for division on field elements. See BaseField25519 Operations.Cast expressions
a as MyType is only supported:
| From Type | To Type |
|---|---|
| integer type | integer type |
bool | integer type |
| integer type | bool |
&...&T | &T |
Function calls
The following function calls are supported:- user-defined function calls (without recursion)
ArcisRNG::bool()to generate a boolean.ArcisRNG::gen_uniform::<T>()to generate a uniform value of type T (bool, integer, or combination). Requires explicit type parameter.ArcisRNG::gen_integer_from_width(width: usize) -> u128. Generates a secret integer between 0 and 2^width - 1 included.ArcisRNG::gen_public_integer_from_width(width: usize) -> u128. Generates a public integer between 0 and 2^width - 1 included.ArcisRNG::gen_integer_in_range(min: u128, max: u128, n_attempts: usize) -> (u128, bool). Generates a random integer in[min, max]using rejection sampling.n_attemptsmust be compile-time known. Returns(result, success)wheresuccess=falseindicates all attempts were rejected. Withn_attempts=24, failure probability is<2^-24.ArcisRNG::shuffle(slice)on slices. Complexity is inO(n*log³(n) + n*log²(n)*sizeof(T)).Mxe::get()to be able to create MXE-owned secret data.Shared::new(arcis_public_key)to share private data witharcis_public_key.ArcisX25519Pubkey::from_base58(base58_byte_string)to create a public key from a base58-encoded address.ArcisX25519Pubkey::from_uint8(u8_byte_slice)to create a public key from a Uint8 array.SolanaPublicKey::from_serialized(value)to create a Solana public key from serialized form.SolanaPublicKey::from_base58(byte_string)to create a Solana public key from base58.ArcisMath::sigmoid(x)for the sigmoid activation function.LogisticRegression::new(coef, intercept)for logistic regression models.LinearRegression::new(coef, intercept)for linear regression models.Pack::new(value)to bit-pack data for onchain storage (multiple small values fit into fewer field elements).ArcisX25519Pubkey::new_from_x(x: BaseField25519)to create a public key from its Curve25519 Montgomery X-coordinate.ArcisX25519Pubkey::to_x() -> BaseField25519to extract the Montgomery X-coordinate from a public key.BaseField25519::from_u8(x)…BaseField25519::from_u128(x)to convert unsigned integers to field elements. Signed variants (from_i8…from_i128) andfrom_bool,from_usize,from_isizealso available.BaseField25519::power_of_two(exp)to compute2^expas a field element.
Literal expressions
| Example | Support |
|---|---|
"foo" | Unsupported |
b"foo" | Supported |
c"foo" | Unsupported |
b'f' | Supported |
'a' | Unsupported |
1 | Supported |
1u16 | Supported |
1f64 | Supported |
1.0e10f64 | Supported |
true | Supported |
Macros
The following macros are supported:debug_assert!,debug_assert_ne!,debug_assert_eq!to assert conditions during debugging. They do not change instruction behavior.eprint!,eprintln!,print!,println!to print debug output. They do not change instruction behavior.arcis_static_panic!(message)to fail compilation when the branch is reached. Useful for enforcing constraints that must be known before circuit generation.include_bytes!("file_path")to include raw bytes from a file in Arcis circuits.include!("file_path")to include a file in item position (not expression position).assert_current_module!(crate::path::to::module)to enablecrate::absolute paths within the current module. Place at the top of any module that needs to reference items via absolute paths.encrypted_mod!("path/to/module.rs")orencrypted_mod!("path/to/module.rs", alias_name)to use another file as a module within an#[encrypted]module. The target file must use the#[encrypted_library]attribute. Items are accessible via the filename stem (or alias) as a namespace, e.g.,module_name::ITEM.
arcis_static_panic! triggers at compile time when the Arcis compiler evaluates the branch. Try changing ARRAY_LEN to 1 above—the compile error demonstrates how this macro enforces constraints that must be validated before circuit generation.Method calls
The following method calls are supported:- user-defined method calls (with generics but without recursion)
.clone()on allCloneobjects..len(),.is_empty(),.swap(a, b),.fill(value),.reverse(),.iter(),.iter_mut(),.into_iter(),.windows(width),.copy_from_slice(src),.clone_from_slice(src),.split_at(mid),.split_at_mut(mid),.rotate_left(mid),.rotate_right(mid),.contains(item),.starts_with(needle),.ends_with(needle)on arrays and slices..sort()on arrays of integers. Complexity is inO(n*log²(n)*bit_size)..enumerate(),.chain(other),.cloned(),.copied(),.count(),.rev(),.zip(other),.map(func),.for_each(func),.fold(init, func),.sum(),.product()on iterators..take(n),.skip(n),.step_by(n)on iterators whennis compile-time known..reveal()if not inside aniforelseblock where the condition is not a compile-time constant.to_arcis()onEncs.from_arcis(x)onOwners (objects of typesMxeorShared) if not inside aniforelseblock where the condition is not a compile-time constant.abs(),.min(x),.max(x)on integers and floats.abs_diff(other),.is_positive(),.is_negative(),.div_ceil(other)on integers.to_le_bytes(),.to_be_bytes()on typed integers (does not work on integers whose type the interpreter does not know).exp(),.exp2(),.ln(),.log2(),.sqrt()on floats..unpack()onPack<T>to extract the original value from packed storage..to_arcis_with_pubkey_and_nonce(pubkey, nonce)onEncData<T>to decrypt when the key is shared across inputs (avoids duplicate decryption gates). See EncData for details..dataonEnc<Owner, T>to extract only theEncData<T>ciphertext for smaller callback payloads..safe_inverse()onBaseField25519to get the field inverse (returns 0 for inverse of 0)..field_division(divisor)onBaseField25519for field division (returns 0 for division by 0)..euclidean_division(divisor)onBaseField25519for signed Euclidean division (panics on division by 0)..to_u8_unchecked()….to_u128_unchecked()onBaseField25519to extract as unsigned int. Silently produces incorrect results if value exceeds target range. Signed variants (to_i8_unchecked…to_i128_unchecked) andto_bool_uncheckedalso available.
Paths
The following paths are supported:IntType::BITS,IntType::MINandIntType::MAXwhereIntTypeis an integer type.- Paths to user-defined constants, functions and structs, as long as they are inside the
#[encrypted]area. Bothsuper::paths andcrate::paths (whenassert_current_module!is declared) are supported. std::mem::replaceandstd::mem::swapBox::leak,Box::new,Cell::new,Cell::from_mut
Code Organization with Modules
Arcis supports nested modules,super:: parent references, crate:: absolute paths, and multi-file projects. #[instruction] functions can be placed at any module depth, not just at the top level.
Submodules with super:: and crate:: paths:
encrypted_mod!:
Each file imported via
encrypted_mod! must use #[encrypted_library] (not #[encrypted]). Items are accessible through the filename stem as a namespace (e.g., helpers::Config), or you can provide an alias: encrypted_mod!("helpers.rs", utils) makes items accessible as utils::Config.Item support
| Item Name | Example | Support | Comments |
|---|---|---|---|
| Constant | const MAX: u16 = 65535 | Supported | |
| Enum | enum MyEnum { ... } | Unsupported | |
| Extern | extern ... | Unsupported | |
| Functions | fn foo() -> u8 { 0 } | Partial Support | Recursive functions are not supported. |
| Impls | impl MyType { ... } | Supported | Generics and custom traits are supported. MyType must not be a reference. |
| Macro Definitions | macro_rules! ... | Unsupported | |
| Macro Invocations | println!(...) | Partial Support | See table above for supported macros. |
| Modules | mod my_module { ... } | Supported | |
| Statics | static ... | Unsupported | |
| Structs | struct MyStruct { ... } | Supported | |
| Traits | trait MyTrait { ... } | Partial Support | Custom traits with associated types and constants. Standard library traits forbidden.¹ |
| Type Aliases | type MyId = usize; | Supported | |
| Union | union MyUnion { ... } | Unsupported | |
| Use | use arcis::* | Partial Support | Only use arcis::* is supported. |
| Arcis Circuit | #[arcis_circuit = "name"] | Supported | Use a pre-built optimized circuit by name. For internal/advanced use. |
¹ Forbidden trait implementations: You cannot manually implement
Drop, Deref, AsRef, AsMut, From, Into, TryFrom, TryInto, PartialEq, Eq, PartialOrd, Ord, Clone, ToOwned, ToString, Default, Iterator, IntoIterator, DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, Fn, FnMut, FnOnce, Future, IntoFuture, AsyncFn, AsyncFnMut, or AsyncFnOnce.Why? These traits have special runtime semantics (drop ordering, lazy evaluation, dynamic dispatch) that cannot be correctly translated to fixed MPC circuits. The Arcis compiler provides built-in implementations that work within MPC constraints.Use #[derive(...)] for Clone, PartialEq, etc., which generates MPC-compatible implementations.Pattern support
The following patterns are supported in function arguments andlet statements:
- simple idents:
let ident = ...; - mutable idents:
let mut ident = ...; - ref idents:
let ref ident = ...; - mutable ref idents:
let ref mut ident = ...; - parentheses around a supported pattern:
let (...) = ...; - reference of a supported pattern:
let &... = ...; - array of supported patterns:
let [...] = ...; - struct of supported patterns:
let MyStruct { ... } = ...; - tuple of supported patterns:
let (...) = ...; - tuple struct of supported patterns:
let MyStruct(...) = ...; - type pattern of a supported pattern:
let ...: ty = ...; - wild pattern:
let _ = ...;
.. pattern is currently unsupported.
Generics
Arcis supports Rust generics with some constraints. Generic types must be known at compile time. Runtime polymorphism is not supported.Generic Functions
Generic Structs
Custom Traits
Generic Constraints
| Feature | Supported | Notes |
|---|---|---|
Type parameters <T> | Yes | Must be known at compile time |
Trait bounds T: Trait | Yes | Including ArcisType |
| Associated types | Yes | type Output; |
| Associated constants | Yes | const SIZE: usize; |
| Where clauses | Yes | where T: Clone |
Turbofish ::<T> | Yes | For explicit type specification |
| Runtime polymorphism | No | No dyn Trait or trait objects |
Iterators
Most iterator methods work in Arcis, with the notable exception of.filter().
Supported Iterator Methods
Complete Iterator Support
| Method | Supported | Notes |
|---|---|---|
.iter() | Yes | Creates iterator of references |
.iter_mut() | Yes | Mutable references |
.into_iter() | Yes | Consumes collection |
.map(f) | Yes | Transform elements |
.enumerate() | Yes | Add indices |
.zip(other) | Yes | Pair with another iterator |
.chain(other) | Yes | Concatenate iterators |
.rev() | Yes | Reverse order |
.cloned() | Yes | Clone elements |
.copied() | Yes | Copy elements |
.fold(init, f) | Yes | Reduce with accumulator |
.sum() | Yes | Sum all elements |
.product() | Yes | Multiply all elements |
.count() | Yes | Count elements |
.take(n) | Yes | n must be compile-time known |
.skip(n) | Yes | n must be compile-time known |
.step_by(n) | Yes | n must be compile-time known |
.for_each(f) | Yes | Apply function to each |
.filter(f) | No | Would produce variable-length output |
.find(f) | No | Would require early exit |
.any(f) | No | Would require early exit |
.all(f) | No | Would require early exit |
Filter Alternative
Since.filter() is not supported (it produces variable-length output), use a manual loop with conditionals:
What’s next?
Primitives
RNG, cryptography, and data packing operations.
Best Practices
Performance tips, debugging, and testing strategies.