Change:
noticed this 1.63→1.64 change in I tried this code: I expected to see this happen: because is non-, an error about moving out from behind a reference, like happened in 1.63 , this happened: it compiles fine in 1.64 in nightly is probably cased by Change enum-int casts to not go through MIR casts which is mentioned in It's unclear to me whether this is intentional under the banner of " behaviour", since there's no trait involved.
Prioritized as P-critical in meeting just now. This needs to be fixed by 1.65 at a minimum.
labels +T-compiler This needs work from T-compiler! :)
labels -I-lang-nominated Meeting consensus is that the current behavior is wrong and needs to be fixed.

Discussion:
// create all the steps directly in MIR with operations all backends need to support anyway. let (source, ty) = if let ty::Adt(adt_def, ..) = source.ty.kind() && adt_def.is_enum() { let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx); <del> let place = unpack!(block = this.as_place(block, source)); </del> <ins> let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not)); </ins> let discr = this.temp(discr_ty, source.span); this.cfg.push_assign( block, source_info, discr, <del> Rvalue::Discriminant(place), </del> <ins> Rvalue::Discriminant(temp.into()), </ins> ); (Operand::Move(discr), discr_ty)

fn bar(_1: Bar) -> usize { debug bar => _1;                     // in scope 0 at $DIR/enum_cast.rs:+0:8: +0:11 let mut _0: usize;                   // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26 <del> let mut _2: isize;                   // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 </del> <ins> let _2: Bar;                         // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 let mut _3: isize;                   // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 </ins> bb0: { <del> _2 = discriminant(_1);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 _0 = move _2 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 </del> <ins> StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 _0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17 </ins> return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2 } }

fn boo(_1: Boo) -> usize { debug boo => _1;                     // in scope 0 at $DIR/enum_cast.rs:+0:8: +0:11 let mut _0: usize;                   // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26 <del> let mut _2: u8;                      // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 </del> <ins> let _2: Boo;                         // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 let mut _3: u8;                      // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 </ins> bb0: { <del> _2 = discriminant(_1);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 _0 = move _2 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 </del> <ins> StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 _0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17 </ins> return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2 } }

let mut _0: ();                      // return place in scope 0 at $DIR/enum_cast.rs:+0:13: +0:13 let _1: ();                          // in scope 0 at $DIR/enum_cast.rs:+1:5: +6:6 let _2: Droppy;                      // in scope 0 at $DIR/enum_cast.rs:+2:13: +2:14 <del> let mut _4: isize;                   // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18 let _5: Droppy;                      // in scope 0 at $DIR/enum_cast.rs:+7:9: +7:10 </del> <ins> let _4: Droppy;                      // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18 let mut _5: isize;                   // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18 let _6: Droppy;                      // in scope 0 at $DIR/enum_cast.rs:+7:9: +7:10 </ins> scope 1 { debug x => _2;                   // in scope 1 at $DIR/enum_cast.rs:+2:13: +2:14 scope 2 {

} } scope 4 { <del> debug z => _5;                   // in scope 4 at $DIR/enum_cast.rs:+7:9: +7:10 </del> <ins> debug z => _6;                   // in scope 4 at $DIR/enum_cast.rs:+7:9: +7:10 </ins> } bb0: {

_2 = Droppy::C;                  // scope 0 at $DIR/enum_cast.rs:+2:17: +2:26 FakeRead(ForLet(None), _2);      // scope 0 at $DIR/enum_cast.rs:+2:13: +2:14 StorageLive(_3);                 // scope 3 at $DIR/enum_cast.rs:+5:13: +5:14 <del> _4 = discriminant(_2);           // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27 _3 = move _4 as usize (IntToInt); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27 </del> <ins> StorageLive(_4);                 // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18 _4 = move _2;                    // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18 _5 = discriminant(_4);           // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27 _3 = move _5 as usize (IntToInt); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27 drop(_4) -> [return: bb1, unwind: bb4]; // scope 3 at $DIR/enum_cast.rs:+5:26: +5:27 } bb1: { StorageDead(_4);                 // scope 3 at $DIR/enum_cast.rs:+5:26: +5:27 </ins> FakeRead(ForLet(None), _3);      // scope 3 at $DIR/enum_cast.rs:+5:13: +5:14 _1 = const ();                   // scope 0 at $DIR/enum_cast.rs:+1:5: +6:6 StorageDead(_3);                 // scope 1 at $DIR/enum_cast.rs:+6:5: +6:6 <del> drop(_2) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6 </del> <ins> drop(_2) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6 </ins> } <del> bb1: { </del> <ins> bb2: { </ins> StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6 StorageDead(_1);                 // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6 <del> StorageLive(_5);                 // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10 _5 = Droppy::B;                  // scope 0 at $DIR/enum_cast.rs:+7:13: +7:22 FakeRead(ForLet(None), _5);      // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10 </del> <ins> StorageLive(_6);                 // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10 _6 = Droppy::B;                  // scope 0 at $DIR/enum_cast.rs:+7:13: +7:22 FakeRead(ForLet(None), _6);      // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10 </ins> _0 = const ();                   // scope 0 at $DIR/enum_cast.rs:+0:13: +8:2 <del> drop(_5) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2 </del> <ins> drop(_6) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2 </ins> } <del> bb2: { StorageDead(_5);                 // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2 </del> <ins> bb3: { StorageDead(_6);                 // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2 </ins> return;                          // scope 0 at $DIR/enum_cast.rs:+8:2: +8:2 } <del> bb3 (cleanup): { </del> <ins> bb4 (cleanup): { drop(_2) -> bb5;                 // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6 } bb5 (cleanup): { </ins> resume;                          // scope 0 at $DIR/enum_cast.rs:+0:1: +8:2 } }

fn foo(_1: Foo) -> usize { debug foo => _1;                     // in scope 0 at $DIR/enum_cast.rs:+0:8: +0:11 let mut _0: usize;                   // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26 <del> let mut _2: isize;                   // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 </del> <ins> let _2: Foo;                         // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 let mut _3: isize;                   // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 </ins> bb0: { <del> _2 = discriminant(_1);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 _0 = move _2 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 </del> <ins> StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 _0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17 </ins> return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2 } }

{ let e = E::C; assert_eq!(e as u32, 2); <del> assert_eq!(FLAG.load(Ordering::SeqCst), 0); </del> <ins> assert_eq!(FLAG.load(Ordering::SeqCst), 1); </ins> } assert_eq!(FLAG.load(Ordering::SeqCst), 1); }

<ins> enum Enum { A, B, C } fn func(inbounds: &Enum, array: &[i16; 3]) -> i16 { array[*inbounds as usize] //~^ ERROR [E0507] } fn main() {} </ins>

<ins> error[E0507]: cannot move out of `*inbounds` which is behind a shared reference --> $DIR/issue-102389.rs:4:11 | LL |     array[*inbounds as usize] |           ^^^^^^^^^ move occurs because `*inbounds` has type `Enum`, which does not implement the `Copy` trait error: aborting due to previous error For more information about this error, try `rustc --explain E0507`. </ins>