Repository: noir-lang/noir (Rust)

Issue:
Unused `self` in trait impl generates warning
### Aim

On my machine `tests::execution_success::test_trait_impl_base_type` failed with the following error:

```
command=`"/Users/aakoshh/Work/aztec/noir/target/debug/nargo" "--program-dir" "/Users/aakoshh/Work/aztec/noir/test_programs/execution_success/trait_impl_base_type" "execute" "--force"`
code=1
stdout=""
stderr=```
warning: unused variable self
   ┌─ /Users/aakoshh/Work/aztec/noir/test_programs/execution_success/trait_impl_base_type/src/main.nr:38:17
   │
38 │     fn to_field(self) -> Field {
   │                 ---- unused variable 
```



### Expected Behavior

The test should compile without warning.

### Bug

The method is an implementation of `Fieldable::to_field`. We can't use `_self` to silence this, and Rust does not warn about it.


### To Reproduce

```
cargo test -p nargo_cli test_trait_impl_base_type
```

### Workaround

Yes

### Workaround Description

Add `let _ = self;` to the method body.

Another one suggested in the comments below is to use `_self: Self` (or `_: Self`).

### Additional Context

_No response_

### Project Impact

None

### Blocker Context

_No response_

### Nargo Version

_No response_

### NoirJS Version

_No response_

### Proving Backend Tooling & Version

_No response_

### Would you like to submit a PR for this Issue?

Yes

### Support Needs

_No response_


Discussion:
> The method is an implementation of Fieldable::to_field. We can't use _self to silence this, and Rust does not warn about it.

Why can't we use `_self: Self`?
You're right, if we specify the type as `: Self` we can use `_self`, I haven't tried that 👍 

I meant that if I just try to use `_self` , the compiler says: 
```
`Fieldable::to_field` expects 1 parameter, but this method has 0`.
```

NB the Rust compiler doesn't seem to like `_self: Self`: 
```
method `to_field` has a `self` declaration in the trait, but not in the impl
expected `self` in impl`
```
> NB the Rust compiler doesn't seem to like _self: Self:

Yep, this is a difference between Rust and Noir. Noir is a bit more permissive with methods, you don't need a `self` parameter to call something as a method. Just an impl and the first type must match.



Patch:
diff --git a/compiler/noirc_frontend/src/elaborator/mod.rs b/compiler/noirc_frontend/src/elaborator/mod.rs
index 5067ac05c44..dafafe421eb 100644
--- a/compiler/noirc_frontend/src/elaborator/mod.rs
+++ b/compiler/noirc_frontend/src/elaborator/mod.rs
@@ -404,7 +404,8 @@ impl<'context> Elaborator<'context> {
         // so we need to reintroduce the same IDs into scope here.
         for parameter in &func_meta.parameter_idents {
             let name = self.interner.definition_name(parameter.id).to_owned();
-            self.add_existing_variable_to_scope(name, parameter.clone(), true);
+            let warn_if_unused = !(func_meta.trait_impl.is_some() && name == "self");
+            self.add_existing_variable_to_scope(name, parameter.clone(), warn_if_unused);
         }
 
         self.add_trait_constraints_to_scope(&func_meta);


Test patch:
diff --git a/compiler/noirc_frontend/src/tests/unused_items.rs b/compiler/noirc_frontend/src/tests/unused_items.rs
index 51bdf785688..86f77fc397a 100644
--- a/compiler/noirc_frontend/src/tests/unused_items.rs
+++ b/compiler/noirc_frontend/src/tests/unused_items.rs
@@ -274,3 +274,23 @@ fn no_warning_on_indirect_struct_if_it_has_an_abi_attribute() {
     "#;
     assert_no_errors(src);
 }
+
+#[test]
+fn no_warning_on_self_in_trait_impl() {
+    let src = r#" 
+    struct Bar {}
+
+    trait Foo {
+        fn foo(self, a: u64);
+    }
+
+    impl Foo for Bar {
+        fn foo(self, _a: u64) {}
+    }
+
+    fn main() {
+        let _ = Bar {};
+    }
+    "#;
+    assert_no_errors(src);
+}