61

I was trying to manipulate the field x of the struct Foo by borrowing a mutable reference from its instance foo.

If I try to print the field x using the moved binding y of the instance foo after the move of the original instance, it keeps printing the value that haven't changed.

Simplified example below:

struct Foo {
    x: i32,
}

fn main() {
    let mut foo = Foo { x: 42 };
    let x = &mut foo.x;
    *x = 13;
    let y = foo;
    println!("{}", y.x); // -> 42; expected result: 13
}

Instead, if I print the moved binding y itself, it prints the changed value.

println!("{:?}", y); // -> Foo { x: 13 }

Or, if I print something else like x or foo.x before the move, it prints the thing as expected.

println!("{}", x); // -> 13
let y = foo;
println!("{}", y.x); // -> 13

Is this an intended behavior?

vallentin
  • 23,478
  • 6
  • 59
  • 81
Ohjun Kwon
  • 593
  • 4
  • 8
  • 13
    It looks like this is a pretty serious bug, introduced in Rust 1.45 – Peter Hall Jul 25 '20 at 11:05
  • 5
    I've opened [an issue](https://github.com/rust-lang/rust/issues/74739) for this. – mcarton Jul 25 '20 at 11:12
  • If it benefits, this also `println!("{:?}", (&y).x);` prints expected result and if you execute `println!("{:?}", y.x);` after the previous println it also prints expected result : https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c41cf262517cda8802fd8defbe42a3fe – Ömer Erden Jul 25 '20 at 11:59
  • 1
    This no longer seems to happen with [1.46.0-beta.2](https://play.rust-lang.org/?version=beta&mode=debug&edition=2018&gist=89d7618f4eec8b6c2f0e7eaddafe3d9e) or 1.47.0-nightly. – IInspectable Jul 25 '20 at 12:03
  • It seems that the bug was known and fixed a month ago, but somehow wasn't included in the beta, and that went unnoticed until now. – Peter Hall Jul 25 '20 at 12:21
  • @PeterHall Indeed, this bug was fixed already. It can be a symptom of a much more serious problem: the tests are not doing what they should. – rodrigocfd Jul 27 '20 at 11:56
  • @rodrigocfd it takes 6 weeks to 3 months for a PR to land in stable rustc (up to 6 weeks in nightly depending on when the last release was made, then 6 weeks from beta to stable), so it's normal for a bug found and fixed one month ago not to have landed in stable by default. This is more of a human problem: Someone should have realized the cause of the bug was already in beta and decided to backport it. This takes a lot of time and resources, and this bug was, after all, not that critical. – mcarton Jul 27 '20 at 15:23
  • Bug's fixed and the fix is released: https://blog.rust-lang.org/2020/07/30/Rust-1.45.1.html#fix-const-propagation-with-references – mcarton Jul 30 '20 at 20:23

1 Answers1

52

This is a known bug in the compiler which only affects rustc 1.45. rustc 1.44 is not affected and the issue has already been fixed on Beta which means it will be fixed on rustc 1.46.

An issue has been opened to track it.

While this issue seem critical, it is very unlikely to be found in real code according to oli-obk, one of the main contributor to rustc, and in particular on const expressions:

The bug is almost impossible to trigger on real world code. You need all values that are going into the bug to be constant values and there can't be any control flow or function calls in between.

Version 1.45.1 has been released and contains a backport of the fix from beta, among other things. Later version 1.45.2 was released with more (unrelated) fixes.

mcarton
  • 27,633
  • 5
  • 85
  • 95