Skip to content

Inconsistent auto-reborrowing behavior of generic functions #65279

Closed
@tcbbd

Description

@tcbbd

Look at this piece of code:

fn f<T>(x: T, y: T) {}

fn main() {
    let x = &mut 0i32;
    let y = &mut 1i32;
    f(x, y);
    let z = &mut *y;
    println!("{} {} {}", x, y, z);
}

From the internet, I get the impression that generic functions will not auto-reborrow if the type of parameter cannot be determined to be a mutable reference before instantiation.

It works as expected for x:

error[E0382]: borrow of moved value: `x`
  --> src/main.rs:21:26
   |
17 |     let x = &mut 0i32;
   |         - move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
18 |     let y = &mut 1i32;
19 |     f(x, y);
   |       - value moved here
20 |     let z = &mut *y;
21 |     println!("{} {} {}", x, y, z);
   |                          ^ value borrowed here after move

But does auto-reborrow for y:

error[E0502]: cannot borrow `y` as immutable because it is also borrowed as mutable
  --> src/main.rs:21:29
   |
20 |     let z = &mut *y;
   |             ------- mutable borrow occurs here
21 |     println!("{} {} {}", x, y, z);
   |                             ^  - mutable borrow later used here
   |                             |
   |                             immutable borrow occurs here

Now this is really confusing. What's the exact rules for auto-reborrow? When does it happen, before or after type inference?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions