Skip to content

diagnostics: pin_ergonomics: unused_mut spans are wrong, would destroy code #142077

Open
@matthiaskrgr

Description

@matthiaskrgr

Using the following flags

--force-warn unused_mut

this code:

//@ check-pass

#![feature(pin_ergonomics)]
#![allow(dead_code, incomplete_features)]

// Makes sure we can handle `&pin mut self` and `&pin const self` as sugar for
// `self: Pin<&mut Self>` and `self: Pin<&Self>`.

use std::pin::Pin;

struct Foo;

impl Foo {
    fn baz(&pin mut self) {}

    fn baz_const(&pin const self) {}

    fn baz_lt<'a>(&'a pin mut self) {}

    fn baz_const_lt(&'_ pin const self) {}
}

fn foo(_: &pin mut Foo) {}

fn foo_const(_: &pin const Foo) {}

fn bar(x: &pin mut Foo) {
    // For the calls below to work we need to automatically reborrow,
    // as if the user had written `foo(x.as_mut())`.
    foo(x);
    foo(x);

    Foo::baz(x);
    Foo::baz(x);

    // make sure we can reborrow &mut as &.
    foo_const(x);
    Foo::baz_const(x);

    let x: &pin const _ = Pin::new(&Foo);

    foo_const(x); // make sure reborrowing from & to & works.
    foo_const(x);
}

fn main() {}

caused the following diagnostics:

    Checking _sugar-self v0.1.0 (/tmp/icemaker_global_tempdir.gxuJJcqHPycq/icemaker_clippyfix_tempdir.30ZwUknRE7ge/_sugar-self)
warning: variable does not need to be mutable
  --> src/main.rs:14:12
   |
14 |     fn baz(&pin mut self) {}
   |            -----^^^^^^^^
   |            |
   |            help: remove this `mut`
   |
   = note: requested on the command line with `--force-warn unused-mut`

warning: variable does not need to be mutable
  --> src/main.rs:18:19
   |
18 |     fn baz_lt<'a>(&'a pin mut self) {}
   |                   ----^^^^^^^^^^^^
   |                   |
   |                   help: remove this `mut`

warning: `_sugar-self` (bin "_sugar-self") generated 2 warnings (run `cargo clippy --fix --bin "_sugar-self"` to apply 2 suggestions)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.11s

However after applying these diagnostics, the resulting code:

//@ check-pass

#![feature(pin_ergonomics)]
#![allow(dead_code, incomplete_features)]

// Makes sure we can handle `&pin mut self` and `&pin const self` as sugar for
// `self: Pin<&mut Self>` and `self: Pin<&Self>`.

use std::pin::Pin;

struct Foo;

impl Foo {
    fn baz(self) {}

    fn baz_const(&pin const self) {}

    fn baz_lt<'a>(in mut self) {}

    fn baz_const_lt(&'_ pin const self) {}
}

fn foo(_: &pin mut Foo) {}

fn foo_const(_: &pin const Foo) {}

fn bar(x: &pin mut Foo) {
    // For the calls below to work we need to automatically reborrow,
    // as if the user had written `foo(x.as_mut())`.
    foo(x);
    foo(x);

    Foo::baz(x);
    Foo::baz(x);

    // make sure we can reborrow &mut as &.
    foo_const(x);
    Foo::baz_const(x);

    let x: &pin const _ = Pin::new(&Foo);

    foo_const(x); // make sure reborrowing from & to & works.
    foo_const(x);
}

fn main() {}

no longer compiled:

    Checking _sugar-self v0.1.0 (/tmp/icemaker_global_tempdir.gxuJJcqHPycq/icemaker_clippyfix_tempdir.30ZwUknRE7ge/_sugar-self)
error: expected parameter name, found keyword `in`
  --> src/main.rs:18:19
   |
18 |     fn baz_lt<'a>(in mut self) {}
   |                   ^^ expected parameter name

error[E0308]: mismatched types
  --> src/main.rs:33:14
   |
33 |     Foo::baz(x);
   |     -------- ^ expected `Foo`, found `Pin<&mut Foo>`
   |     |
   |     arguments to this function are incorrect
   |
   = note: expected struct `Foo`
              found struct `std::pin::Pin<&mut Foo>`
note: method defined here
  --> src/main.rs:14:8
   |
14 |     fn baz(self) {}
   |        ^^^ ----

error[E0308]: mismatched types
  --> src/main.rs:34:14
   |
34 |     Foo::baz(x);
   |     -------- ^ expected `Foo`, found `Pin<&mut Foo>`
   |     |
   |     arguments to this function are incorrect
   |
   = note: expected struct `Foo`
              found struct `std::pin::Pin<&mut Foo>`
note: method defined here
  --> src/main.rs:14:8
   |
14 |     fn baz(self) {}
   |        ^^^ ----

For more information about this error, try `rustc --explain E0308`.
error: could not compile `_sugar-self` (bin "_sugar-self") due to 3 previous errors
warning: build failed, waiting for other jobs to finish...
error: could not compile `_sugar-self` (bin "_sugar-self" test) due to 3 previous errors

Version:

rustc 1.89.0-nightly (425e14268 2025-06-05)
binary: rustc
commit-hash: 425e142686242c7e73f5e32c79071ae266f0f355
commit-date: 2025-06-05
host: x86_64-unknown-linux-gnu
release: 1.89.0-nightly
LLVM version: 20.1.5

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.C-bugCategory: This is a bug.D-imprecise-spansDiagnostics: spans don't point to exactly the erroneous codeF-pin_ergonomics`#![feature(pin_ergonomics)]`L-unused_mutLint: unused_mutT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions