Change:
The following code ICEs, when it should produce a cannot move error
Worse, the following compiles:
regression from stable-to-beta and stable-to-nightly
triage: P-high

Discussion:
} }; <ins> // The move path index of the first union that we find. Once this is // some we stop creating child move paths, since moves from unions // move the whole thing. // We continue looking for other move errors though so that moving // from `*(u.f: &_)` isn't allowed. let mut union_path = None; </ins> for (i, elem) in place.projection.iter().enumerate() { let proj_base = &place.projection[..i]; let body = self.builder.body;

InteriorOfTypeWithDestructor { container_ty: place_ty }, )); } <del> // move out of union - always move the entire union </del> ty::Adt(adt, _) if adt.is_union() => { <del> return Err(MoveError::UnionMove { path: base }); </del> <ins> union_path.get_or_insert(base); </ins> } ty::Slice(_) => { return Err(MoveError::cannot_move_out_of(

_ => {} }; <del> base = self.add_move_path(base, elem, |tcx| { Place { base: place.base.clone(), projection: tcx.intern_place_elems(&place.projection[..i+1]), } }); </del> <ins> if union_path.is_none() { base = self.add_move_path(base, elem, |tcx| { Place { base: place.base.clone(), projection: tcx.intern_place_elems(&place.projection[..i+1]), } }); } </ins> } <del> Ok(base) </del> <ins> if let Some(base) = union_path { // Move out of union - always move the entire union. Err(MoveError::UnionMove { path: base }) } else { Ok(base) } </ins> } fn add_move_path(

<ins> // Moving from a reference/raw pointer should be an error, even when they're // the field of a union. #![feature(untagged_unions)] union Pointers { a: &'static String, b: &'static mut String, c: *const String, d: *mut String, } unsafe fn move_ref(u: Pointers) -> String { *u.a //~^ ERROR cannot move out of `*u.a` } unsafe fn move_ref_mut(u: Pointers) -> String { *u.b //~^ ERROR cannot move out of `*u.b` } unsafe fn move_ptr(u: Pointers) -> String { *u.c //~^ ERROR cannot move out of `*u.c` } unsafe fn move_ptr_mut(u: Pointers) -> String { *u.d //~^ ERROR cannot move out of `*u.d` } fn main() {} </ins>

<ins> error[E0507]: cannot move out of `*u.a` which is behind a shared reference --> $DIR/move-from-union-field-issue-66500.rs:14:5 | LL |     *u.a |     ^^^^ move occurs because `*u.a` has type `std::string::String`, which does not implement the `Copy` trait error[E0507]: cannot move out of `*u.b` which is behind a mutable reference --> $DIR/move-from-union-field-issue-66500.rs:18:5 | LL |     *u.b |     ^^^^ move occurs because `*u.b` has type `std::string::String`, which does not implement the `Copy` trait error[E0507]: cannot move out of `*u.c` which is behind a raw pointer --> $DIR/move-from-union-field-issue-66500.rs:22:5 | LL |     *u.c |     ^^^^ move occurs because `*u.c` has type `std::string::String`, which does not implement the `Copy` trait error[E0507]: cannot move out of `*u.d` which is behind a raw pointer --> $DIR/move-from-union-field-issue-66500.rs:26:5 | LL |     *u.d |     ^^^^ move occurs because `*u.d` has type `std::string::String`, which does not implement the `Copy` trait error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0507`. </ins>