-
Notifications
You must be signed in to change notification settings - Fork 248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add some traits to the stdlib #3796
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
--- | ||
title: Traits | ||
description: Noir's stdlib provides a few commonly used traits. | ||
keywords: [traits, trait, interface, protocol, default, add, eq] | ||
--- | ||
|
||
## `std::default` | ||
|
||
### `std::default::Default` | ||
|
||
```rust | ||
trait Default { | ||
fn default() -> Self; | ||
} | ||
``` | ||
|
||
Constructs a default value of a type. | ||
|
||
Implementations: | ||
```rust | ||
impl Default for Field { .. } | ||
|
||
impl Default for i8 { .. } | ||
impl Default for i16 { .. } | ||
impl Default for i32 { .. } | ||
impl Default for i64 { .. } | ||
|
||
impl Default for u8 { .. } | ||
impl Default for u16 { .. } | ||
impl Default for u32 { .. } | ||
impl Default for u64 { .. } | ||
|
||
impl Default for () { .. } | ||
impl Default for bool { .. } | ||
|
||
impl<T, N> Default for [T; N] | ||
where T: Default { .. } | ||
|
||
impl<A, B> Default for (A, B) | ||
where A: Default, B: Default { .. } | ||
|
||
impl<A, B, C> Default for (A, B, C) | ||
where A: Default, B: Default, C: Default { .. } | ||
|
||
impl<A, B, C, D> Default for (A, B, C, D) | ||
where A: Default, B: Default, C: Default, D: Default { .. } | ||
|
||
impl<A, B, C, D, E> Default for (A, B, C, D, E) | ||
where A: Default, B: Default, C: Default, D: Default, E: Default { .. } | ||
``` | ||
|
||
For primitive integer types, the return value of `default` is `0`. Container | ||
types such as arrays are filled with default values of their element type. | ||
|
||
## `std::ops` | ||
|
||
### `std::ops::Eq` | ||
|
||
```rust | ||
trait Eq { | ||
fn eq(self, other: Self) -> bool; | ||
} | ||
``` | ||
Returns `true` if `self` is equal to `other`. | ||
|
||
Implementations: | ||
```rust | ||
impl Eq for Field { .. } | ||
|
||
impl Eq for i8 { .. } | ||
impl Eq for i16 { .. } | ||
impl Eq for i32 { .. } | ||
impl Eq for i64 { .. } | ||
|
||
impl Eq for u8 { .. } | ||
impl Eq for u16 { .. } | ||
impl Eq for u32 { .. } | ||
impl Eq for u64 { .. } | ||
|
||
impl Eq for () { .. } | ||
impl Eq for bool { .. } | ||
|
||
impl<T, N> Eq for [T; N] | ||
where T: Eq { .. } | ||
|
||
impl<A, B> Eq for (A, B) | ||
where A: Eq, B: Eq { .. } | ||
|
||
impl<A, B, C> Eq for (A, B, C) | ||
where A: Eq, B: Eq, C: Eq { .. } | ||
|
||
impl<A, B, C, D> Eq for (A, B, C, D) | ||
where A: Eq, B: Eq, C: Eq, D: Eq { .. } | ||
|
||
impl<A, B, C, D, E> Eq for (A, B, C, D, E) | ||
where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } | ||
``` | ||
|
||
### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` | ||
|
||
These traits abstract over addition, subtraction, multiplication, and division respectively. | ||
Although Noir does not currently have operator overloading, in the future implementing these | ||
traits for a given type will also allow that type to be used with the corresponding operator | ||
for that trait (`+` for Add, etc) in addition to the normal method names. | ||
|
||
```rust | ||
trait Add { | ||
fn add(self, other: Self) -> Self; | ||
} | ||
|
||
trait Sub { | ||
fn sub(self, other: Self) -> Self; | ||
} | ||
|
||
trait Mul { | ||
fn mul(self, other: Self) -> Self; | ||
} | ||
|
||
trait Div { | ||
fn div(self, other: Self) -> Self; | ||
} | ||
``` | ||
|
||
The implementations block below is given for the `Add` trait, but the same types that implement | ||
`Add` also implement `Sub`, `Mul`, and `Div`. | ||
|
||
Implementations: | ||
```rust | ||
impl Add for Field { .. } | ||
|
||
impl Add for i8 { .. } | ||
impl Add for i16 { .. } | ||
impl Add for i32 { .. } | ||
impl Add for i64 { .. } | ||
|
||
impl Add for u8 { .. } | ||
impl Add for u16 { .. } | ||
impl Add for u32 { .. } | ||
impl Add for u64 { .. } | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
trait Default { | ||
fn default() -> Self; | ||
} | ||
|
||
impl Default for Field { fn default() -> Field { 0 } } | ||
|
||
impl Default for u8 { fn default() -> u8 { 0 } } | ||
impl Default for u16 { fn default() -> u16 { 0 } } | ||
impl Default for u32 { fn default() -> u32 { 0 } } | ||
impl Default for u64 { fn default() -> u64 { 0 } } | ||
|
||
impl Default for i8 { fn default() -> i8 { 0 } } | ||
impl Default for i16 { fn default() -> i16 { 0 } } | ||
impl Default for i32 { fn default() -> i32 { 0 } } | ||
impl Default for i64 { fn default() -> i64 { 0 } } | ||
|
||
impl Default for () { fn default() -> () { () } } | ||
impl Default for bool { fn default() -> bool { false } } | ||
|
||
impl<T, N> Default for [T; N] where T: Default { | ||
fn default() -> [T; N] { | ||
[T::default(); N] | ||
} | ||
} | ||
|
||
impl<A, B> Default for (A, B) where A: Default, B: Default { | ||
fn default() -> (A, B) { | ||
(A::default(), B::default()) | ||
} | ||
} | ||
|
||
impl<A, B, C> Default for (A, B, C) where A: Default, B: Default, C: Default { | ||
fn default() -> (A, B, C) { | ||
(A::default(), B::default(), C::default()) | ||
} | ||
} | ||
|
||
impl<A, B, C, D> Default for (A, B, C, D) where A: Default, B: Default, C: Default, D: Default { | ||
fn default() -> (A, B, C, D) { | ||
(A::default(), B::default(), C::default(), D::default()) | ||
} | ||
} | ||
|
||
impl<A, B, C, D, E> Default for (A, B, C, D, E) where A: Default, B: Default, C: Default, D: Default, E: Default { | ||
fn default() -> (A, B, C, D, E) { | ||
(A::default(), B::default(), C::default(), D::default(), E::default()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
|
||
trait Add { | ||
fn add(self, other: Self) -> Self; | ||
} | ||
|
||
impl Add for Field { fn add(self, other: Field) -> Field { self + other } } | ||
|
||
impl Add for u8 { fn add(self, other: u8) -> u8 { self + other } } | ||
impl Add for u16 { fn add(self, other: u16) -> u16 { self + other } } | ||
impl Add for u32 { fn add(self, other: u32) -> u32 { self + other } } | ||
impl Add for u64 { fn add(self, other: u64) -> u64 { self + other } } | ||
|
||
impl Add for i8 { fn add(self, other: i8) -> i8 { self + other } } | ||
impl Add for i16 { fn add(self, other: i16) -> i16 { self + other } } | ||
impl Add for i32 { fn add(self, other: i32) -> i32 { self + other } } | ||
impl Add for i64 { fn add(self, other: i64) -> i64 { self + other } } | ||
|
||
trait Sub { | ||
fn sub(self, other: Self) -> Self; | ||
} | ||
|
||
impl Sub for Field { fn sub(self, other: Field) -> Field { self - other } } | ||
|
||
impl Sub for u8 { fn sub(self, other: u8) -> u8 { self - other } } | ||
impl Sub for u16 { fn sub(self, other: u16) -> u16 { self - other } } | ||
impl Sub for u32 { fn sub(self, other: u32) -> u32 { self - other } } | ||
impl Sub for u64 { fn sub(self, other: u64) -> u64 { self - other } } | ||
|
||
impl Sub for i8 { fn sub(self, other: i8) -> i8 { self - other } } | ||
impl Sub for i16 { fn sub(self, other: i16) -> i16 { self - other } } | ||
impl Sub for i32 { fn sub(self, other: i32) -> i32 { self - other } } | ||
impl Sub for i64 { fn sub(self, other: i64) -> i64 { self - other } } | ||
|
||
trait Mul { | ||
fn mul(self, other: Self) -> Self; | ||
} | ||
|
||
impl Mul for Field { fn mul(self, other: Field) -> Field { self * other } } | ||
|
||
impl Mul for u8 { fn mul(self, other: u8) -> u8 { self * other } } | ||
impl Mul for u16 { fn mul(self, other: u16) -> u16 { self * other } } | ||
impl Mul for u32 { fn mul(self, other: u32) -> u32 { self * other } } | ||
impl Mul for u64 { fn mul(self, other: u64) -> u64 { self * other } } | ||
|
||
impl Mul for i8 { fn mul(self, other: i8) -> i8 { self * other } } | ||
impl Mul for i16 { fn mul(self, other: i16) -> i16 { self * other } } | ||
impl Mul for i32 { fn mul(self, other: i32) -> i32 { self * other } } | ||
impl Mul for i64 { fn mul(self, other: i64) -> i64 { self * other } } | ||
|
||
trait Div { | ||
fn div(self, other: Self) -> Self; | ||
} | ||
|
||
impl Div for Field { fn div(self, other: Field) -> Field { self / other } } | ||
|
||
impl Div for u8 { fn div(self, other: u8) -> u8 { self / other } } | ||
impl Div for u16 { fn div(self, other: u16) -> u16 { self / other } } | ||
impl Div for u32 { fn div(self, other: u32) -> u32 { self / other } } | ||
impl Div for u64 { fn div(self, other: u64) -> u64 { self / other } } | ||
|
||
impl Div for i8 { fn div(self, other: i8) -> i8 { self / other } } | ||
impl Div for i16 { fn div(self, other: i16) -> i16 { self / other } } | ||
impl Div for i32 { fn div(self, other: i32) -> i32 { self / other } } | ||
impl Div for i64 { fn div(self, other: i64) -> i64 { self / other } } | ||
|
||
trait Eq { | ||
fn eq(self, other: Self) -> bool; | ||
} | ||
|
||
impl Eq for Field { fn eq(self, other: Field) -> bool { self == other } } | ||
|
||
impl Eq for u8 { fn eq(self, other: u8) -> bool { self == other } } | ||
impl Eq for u16 { fn eq(self, other: u16) -> bool { self == other } } | ||
impl Eq for u32 { fn eq(self, other: u32) -> bool { self == other } } | ||
impl Eq for u64 { fn eq(self, other: u64) -> bool { self == other } } | ||
|
||
impl Eq for i8 { fn eq(self, other: i8) -> bool { self == other } } | ||
impl Eq for i16 { fn eq(self, other: i16) -> bool { self == other } } | ||
impl Eq for i32 { fn eq(self, other: i32) -> bool { self == other } } | ||
impl Eq for i64 { fn eq(self, other: i64) -> bool { self == other } } | ||
|
||
impl Eq for () { fn eq(_self: Self, _other: ()) -> bool { true } } | ||
impl Eq for bool { fn eq(self, other: bool) -> bool { self == other } } | ||
|
||
impl<T, N> Eq for [T; N] where T: Eq { | ||
fn eq(self, other: [T; N]) -> bool { | ||
let mut result = true; | ||
for i in 0 .. self.len() { | ||
result &= self[i].eq(other[i]); | ||
} | ||
result | ||
} | ||
} | ||
|
||
impl<A, B> Eq for (A, B) where A: Eq, B: Eq { | ||
fn eq(self, other: (A, B)) -> bool { | ||
self.0.eq(other.0) & self.1.eq(other.1) | ||
} | ||
} | ||
|
||
impl<A, B, C> Eq for (A, B, C) where A: Eq, B: Eq, C: Eq { | ||
fn eq(self, other: (A, B, C)) -> bool { | ||
self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) | ||
} | ||
} | ||
|
||
impl<A, B, C, D> Eq for (A, B, C, D) where A: Eq, B: Eq, C: Eq, D: Eq { | ||
fn eq(self, other: (A, B, C, D)) -> bool { | ||
self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) | ||
} | ||
} | ||
|
||
impl<A, B, C, D, E> Eq for (A, B, C, D, E) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { | ||
fn eq(self, other: (A, B, C, D, E)) -> bool { | ||
self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) & self.4.eq(other.4) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,21 @@ | ||
fn main() { | ||
let a: [[[[Field; 2]; 2]; 2]; 2] = [[[[1, 2], [3, 4]], [[5, 6], [7, 8]]], [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]]; | ||
assert(a.eq(a)); | ||
assert(a.my_eq(a)); | ||
} | ||
|
||
trait Eq { | ||
fn eq(self, other: Self) -> bool; | ||
trait MyEq { | ||
fn my_eq(self, other: Self) -> bool; | ||
} | ||
|
||
impl<T> Eq for [T; 2] where T: Eq { | ||
fn eq(self, other: Self) -> bool { | ||
self[0].eq(other[0]) | ||
& self[0].eq(other[0]) | ||
impl<T> MyEq for [T; 2] where T: MyEq { | ||
fn my_eq(self, other: Self) -> bool { | ||
self[0].my_eq(other[0]) | ||
& self[0].my_eq(other[0]) | ||
} | ||
} | ||
// Impl for u32 but not Field | ||
impl Eq for u32 { | ||
fn eq(self, other: Self) -> bool { | ||
impl MyEq for u32 { | ||
fn my_eq(self, other: Self) -> bool { | ||
self == other | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey sorry I'm a bit late for this PR, wondering if it would be worth to have some examples @jfecher ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Issue created: #3969