-
Notifications
You must be signed in to change notification settings - Fork 219
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(frontend): Call trait method with mut self from generic definition (
#5041) # Description ## Problem\* Resolves <!-- Link to GitHub Issue --> Not sure if there is another issue for this I will have to look again, but I found this bug when trying to implement #4514 ## Summary\* When type checking a `MethodCall` from the HIR now we also add a mutable reference to the object type when we have a `HirMethodReference::TraitMethodId`. We were previously only doing this for a `HirMethodReference::FuncId`. For example that meant this program would fail with the following errors laid out in the comments: ```rust fn hash_simple_array<H>(input: [Field; 2]) -> Field where H: Hasher + Default { // Check that we can a trait method to instead a trait implementation let mut hasher: H = H::default(); // Regression that the object is converted to a mutable reference type `&mut _`. // Otherwise will see `Expected type &mut _, found type H`. // Then we need to make sure to also auto dereference later in the type checking process // when searching for a matching impl or else we will get `No matching impl found for `&mut H: Hasher` hasher.write(input[0]); hasher.write(input[1]); hasher.finish() } ``` I also had to add auto dereferencing when verifying the trait constraints later inside of `type_check_func`. So first we add a mutable reference to the method call's object type to avoid a mismatched type error, and then we later dereference it to find the appropriate trait implementation. ## Additional Context ## Documentation\* Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[For Experimental Features]** Documentation to be submitted in a separate PR. # PR Checklist\* - [ ] I have tested the changes locally. - [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Jake Fecher <jake@aztecprotocol.com> Co-authored-by: Jake Fecher <jfecher11@gmail.com> Co-authored-by: Tom French <tom@tomfren.ch>
- Loading branch information
1 parent
226724e
commit 89846cf
Showing
6 changed files
with
113 additions
and
13 deletions.
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
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
7 changes: 7 additions & 0 deletions
7
test_programs/execution_success/trait_method_mut_self/Nargo.toml
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,7 @@ | ||
[package] | ||
name = "trait_method_mut_self" | ||
type = "bin" | ||
authors = [""] | ||
compiler_version = ">=0.29.0" | ||
|
||
[dependencies] |
2 changes: 2 additions & 0 deletions
2
test_programs/execution_success/trait_method_mut_self/Prover.toml
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,2 @@ | ||
x = "5" | ||
y = "10" |
74 changes: 74 additions & 0 deletions
74
test_programs/execution_success/trait_method_mut_self/src/main.nr
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,74 @@ | ||
use dep::std::hash::Hasher; | ||
use dep::std::hash::poseidon2::Poseidon2Hasher; | ||
|
||
fn main(x: Field, y: pub Field) { | ||
let mut a_mut_ref = AType { x }; | ||
|
||
pass_trait_by_value(a_mut_ref, y); | ||
assert(a_mut_ref.x == x); | ||
|
||
pass_trait_by_value_impl_param(a_mut_ref, y); | ||
assert(a_mut_ref.x == x); | ||
|
||
pass_trait_by_mut_ref(&mut a_mut_ref, y); | ||
assert(a_mut_ref.x == y); | ||
|
||
let mut hasher = Poseidon2Hasher::default(); | ||
hasher.write(x); | ||
hasher.write(y); | ||
let expected_hash = hasher.finish(); | ||
// Check that we get the same result when using the hasher in a | ||
// method that purely uses trait methods without a supplied implementation. | ||
assert(hash_simple_array::<Poseidon2Hasher>([x, y]) == expected_hash); | ||
} | ||
|
||
trait SomeTrait { | ||
fn set_value(&mut self, new_value: Field) -> (); | ||
|
||
fn get_value(self) -> Field; | ||
} | ||
|
||
struct AType { | ||
x: Field | ||
} | ||
|
||
impl SomeTrait for AType { | ||
fn set_value(&mut self, new_value: Field) -> () { | ||
self.x = new_value; | ||
} | ||
|
||
fn get_value(self) -> Field { | ||
self.x | ||
} | ||
} | ||
|
||
fn pass_trait_by_value_impl_param(mut a_mut_ref: impl SomeTrait, value: Field) { | ||
// We auto add a mutable reference to the object type if the method call expects a mutable self | ||
a_mut_ref.set_value(value); | ||
assert(a_mut_ref.get_value() == value); | ||
} | ||
|
||
fn pass_trait_by_value<T>(mut a_mut_ref: T, value: Field) where T: SomeTrait { | ||
// We auto add a mutable reference to the object type if the method call expects a mutable self | ||
a_mut_ref.set_value(value); | ||
assert(a_mut_ref.get_value() == value); | ||
} | ||
|
||
fn pass_trait_by_mut_ref<T>(a_mut_ref: &mut T, value: Field) where T: SomeTrait { | ||
// We auto add a mutable reference to the object type if the method call expects a mutable self | ||
a_mut_ref.set_value(value); | ||
} | ||
|
||
fn hash_simple_array<H>(input: [Field; 2]) -> Field where H: Hasher + Default { | ||
// Check that we can call a trait method instead of a trait implementation | ||
// TODO: Need to remove the need for this type annotation | ||
// TODO: Curently, without the annotation we will get `Expression type is ambiguous` when trying to use the `hasher` | ||
let mut hasher: H = H::default(); | ||
// Regression that the object is converted to a mutable reference type `&mut _`. | ||
// Otherwise will see `Expected type &mut _, found type H`. | ||
// Then we need to make sure to also auto dereference later in the type checking process | ||
// when searching for a matching impl or else we will get `No matching impl found for `&mut H: Hasher` | ||
hasher.write(input[0]); | ||
hasher.write(input[1]); | ||
hasher.finish() | ||
} |