Repository: dtolnay/no-panic (Rust)

Issue:
issue with `mut self: std::pin::Pin<&mut Self>` parameter
Here is a reproduction _now demonstrated in PR #34_:

```rust
mod test_self_with_std_pin {
    pub struct S {
        data: usize,
    }

    impl S {
        #[no_panic]
        fn f1(mut self: std::pin::Pin<&mut Self>) { }

        fn f2(mut self: std::pin::Pin<&mut Self>) { }
    }

    fn main() { }
}
```

gives me the following output if I would paste it into the test suite:

```console
error: `mut` must be followed by a named binding
 --> /var/folders/47/6fqcq_l90jb7ffb_khxrjtbr0000gp/T/.tmpT9x81h/test_self_with_pin.rs:3:23
  |
3 |     #[no_panic] fn f1(mut self : std :: pin :: Pin < & mut Self >) {} fn
  |                       ^^^^^^^^ help: remove the `mut` prefix: `self`
  |
  = note: `mut` may be followed by `variable` and `variable @ pattern`

error[E0424]: expected unit struct, unit variant or constant, found module `self`
 --> /var/folders/47/6fqcq_l90jb7ffb_khxrjtbr0000gp/T/.tmpT9x81h/test_self_with_pin.rs:3:27
  |
3 |     #[no_panic] fn f1(mut self : std :: pin :: Pin < & mut Self >) {} fn
  |                    --     ^^^^ `self` value is a keyword and may not be bound to variables or shadowed
  |                    |
  |                    this function doesn't have a `self` parameter
  |
help: add a `self` receiver parameter to make the associated `fn` a method
  |
3 |     &self, #[no_panic] fn f1(mut self : std :: pin :: Pin < & mut Self >) {} fn
  |     ++++++

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0424`.
```

Note that this only happens with `f1` where I used `#[no_panic]`.

Please bear with my lack of proper terminology as I am still quite new with Rust.

~~I will now raise a failing PR with the reproduction.~~ ✅


Discussion:
Fixed in 0.1.18.



Patch:
diff --git a/src/lib.rs b/src/lib.rs
index 9fe4a2e..1f2701b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -127,7 +127,7 @@ use proc_macro::TokenStream;
 use proc_macro2::{Span, TokenStream as TokenStream2};
 use quote::quote;
 use syn::parse::{Nothing, Result};
-use syn::{parse_quote, Attribute, FnArg, Ident, ItemFn, PatType, ReturnType};
+use syn::{parse_quote, Attribute, FnArg, Ident, ItemFn, Pat, PatType, ReturnType};
 
 #[proc_macro_attribute]
 pub fn no_panic(args: TokenStream, input: TokenStream) -> TokenStream {
@@ -156,12 +156,17 @@ fn expand_no_panic(mut function: ItemFn) -> TokenStream2 {
     for (i, input) in function.sig.inputs.iter_mut().enumerate() {
         let numbered = Ident::new(&format!("__arg{}", i), Span::call_site());
         match input {
-            FnArg::Typed(PatType { pat, .. }) => {
+            FnArg::Typed(PatType { pat, .. })
+                if match pat.as_ref() {
+                    Pat::Ident(pat) => pat.ident != "self",
+                    _ => true,
+                } =>
+            {
                 arg_pat.push(quote!(#pat));
                 arg_val.push(quote!(#numbered));
                 *pat = parse_quote!(mut #numbered);
             }
-            FnArg::Receiver(_) => {
+            FnArg::Typed(_) | FnArg::Receiver(_) => {
                 move_self = Some(quote! {
                     if false {
                         loop {}


Test patch:
diff --git a/tests/test.rs b/tests/test.rs
index b14d92b..f6505ba 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -178,6 +178,21 @@ assert_no_panic! {
             println!("{}", s.get_mut());
         }
     }
+
+    mod test_self_with_std_pin {
+        use std::pin::Pin;
+
+        pub struct S;
+
+        impl S {
+            #[no_panic]
+            fn f(mut self: Pin<&mut Self>) {
+                let _ = self.as_mut();
+            }
+        }
+
+        fn main() {}
+    }
 }
 
 assert_link_error! {