Skip to content

Idea: suggest coercing to &T from &mut T if it satisfies type check #109352

Closed
@ErichDonGubler

Description

@ErichDonGubler

Finally getting around to filing this issue at @estebank's encouragement in this (rather embarrassing) Reddit thread. CC @WalterSmuts and @pali6.

Code

I've tried to capture things in this Playground link; to summarize:

struct Foo;

impl std::ops::Mul for &Foo {
    type Output = Foo;

    fn mul(self, _rhs: Self) -> Self::Output {
        unimplemented!()
    }
}

#[test]
fn it_works() {
    let ref_mut_foo: &mut Foo = &mut Foo;
    let ref_foo: &Foo = &Foo;
    let owned_foo: Foo = Foo;
    
    // The following assignments cause compiler errors that can be resolved by
    // getting immutable borrows of `ref_mut_foo`'s pointee (i.e.,
    // `&*ref_mut_foo`):
    let _ = ref_mut_foo * ref_foo;
    let _ = ref_mut_foo * ref_mut_foo;
    let _ = ref_mut_foo * &owned_foo;
    // …but we currently miss the opportunity to inform a user of the
    // possibility (😢).
}

Current output

error[E0369]: cannot multiply `&mut Foo` by `&Foo`
  --> src/lib.rs:20:25
   |
20 |     let _ = ref_mut_foo * ref_foo;
   |             ----------- ^ ------- &Foo
   |             |
   |             &mut Foo

error[E0369]: cannot multiply `&mut Foo` by `&mut Foo`
  --> src/lib.rs:21:25
   |
21 |     let _ = ref_mut_foo * ref_mut_foo;
   |             ----------- ^ ----------- &mut Foo
   |             |
   |             &mut Foo

error[E0369]: cannot multiply `&mut Foo` by `&Foo`
  --> src/lib.rs:22:25
   |
22 |     let _ = ref_mut_foo * &owned_foo;
   |             ----------- ^ ---------- &Foo
   |             |
   |             &mut Foo

Desired output

error[E0369]: cannot multiply `&mut Foo` by `&Foo`
  --> src/lib.rs:20:25
   |
20 |     let _ = ref_mut_foo * ref_foo;
   |             ----------- ^ ------- &Foo
   |             |
   |             &mut Foo
   |
   = help: consider re-borrowing here: `&*ref_mut_foo * ref_foo`

error[E0369]: cannot multiply `&mut Foo` by `&mut Foo`
  --> src/lib.rs:21:25
   |
21 |     let _ = ref_mut_foo * ref_mut_foo;
   |             ----------- ^ ----------- &mut Foo
   |             |
   |             &mut Foo
   |
   = help: consider re-borrowing here: `&*ref_mut_foo * &*ref_mut_foo`

error[E0369]: cannot multiply `&mut Foo` by `&Foo`
  --> src/lib.rs:22:25
   |
22 |     let _ = ref_mut_foo * &owned_foo;
   |             ----------- ^ ---------- &Foo
   |             |
   |             &mut Foo
   |
   = help: consider re-borrowing here: `&*ref_mut_foo * &owned_foo`

Rationale and extra context

It seems like this should generally be a valid suggestion, and we have to create a diagnostic for this; current error output doesn't help the user to discover the "right" solution at all.

Other cases

No response

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`T-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