Change:
cc is this a coercion that's expected to work?
triage: I-nominated
The first cast is from to , the second is from to . I'm not actually sure if this is meant to work, I guess it should. The intention here is to give a way to treat arrays like C-arrays and get a pointer to the start of the array. It seems that if the array is mutable, then the pointer should be too. I recommend this is P-low - it is backwards compatible, rare, and just a bug by omission, really. The fix should be pretty easy though.
Ah I wasn't sure if this was intended, if it's actually intended then I don't mind removing the nomination as well!
I'm not sure how intended this is, but it doesn't seem too harmful. ;)
P-low, (perhaps "just a bug", perhaps a minor feature.)
Triage: no change
This still happens today (with ), but the error message is slightly different: is another -related issue.

Discussion:
CastKind::Pointer(PointerCast::ArrayToPointer) => { let ty_from = op.ty(body, tcx); <del> let opt_ty_elem = match ty_from.kind() { ty::RawPtr(ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: array_ty, }) => match array_ty.kind() { ty::Array(ty_elem, _) => Some(ty_elem), _ => None, }, </del> <ins> let opt_ty_elem_mut = match ty_from.kind() { ty::RawPtr(ty::TypeAndMut { mutbl: array_mut, ty: array_ty }) => { match array_ty.kind() { ty::Array(ty_elem, _) => Some((ty_elem, *array_mut)), _ => None, } } </ins> _ => None, }; <del> let ty_elem = match opt_ty_elem { Some(ty_elem) => ty_elem, </del> <ins> let (ty_elem, ty_mut) = match opt_ty_elem_mut { Some(ty_elem_mut) => ty_elem_mut, </ins> None => { span_mirbug!( self,

} }; <del> let ty_to = match ty.kind() { ty::RawPtr(ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: ty_to, }) => ty_to, </del> <ins> let (ty_to, ty_to_mut) = match ty.kind() { ty::RawPtr(ty::TypeAndMut { mutbl: ty_to_mut, ty: ty_to }) => { (ty_to, *ty_to_mut) } </ins> _ => { span_mirbug!( self,

} }; <ins> if ty_to_mut == Mutability::Mut && ty_mut == Mutability::Not { span_mirbug!( self, rvalue, "ArrayToPointer cast from const {:?} to mut {:?}", ty, ty_to ); return; } </ins> if let Err(terr) = self.sub_types( ty_elem, ty_to,

m_expr: ty::TypeAndMut<'tcx>, m_cast: ty::TypeAndMut<'tcx>, ) -> Result<CastKind, CastError> { <del> // array-ptr-cast. if m_expr.mutbl == hir::Mutability::Not && m_cast.mutbl == hir::Mutability::Not { </del> <ins> // array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const if m_expr.mutbl == hir::Mutability::Mut || m_cast.mutbl == hir::Mutability::Not { </ins> if let ty::Array(ety, _) = m_expr.ty.kind() { // Due to the limitations of LLVM global constants, // region pointers end up pointing at copies of

// Issue #14893. Tests that casts from vectors don't behave strangely in the // presence of the `_` type shorthand notation. <ins> // </ins> // Update: after a change to the way casts are done, we have more type information // around and so the errors here are no longer exactly the same. <ins> // // Update: With PR #81479 some of the previously rejected cases are now allowed. // New test cases added. </ins> struct X { y: [u8; 2],

// No longer a type mismatch - the `_` can be fully resolved by type inference. let p1: *const u8 = &x1.y as *const _; <ins> let p1: *mut u8 = &x1.y as *mut _; //~^ ERROR: casting `&[u8; 2]` as `*mut u8` is invalid </ins> let t1: *const [u8; 2] = &x1.y as *const _; <ins> let t1: *mut [u8; 2] = &x1.y as *mut _; //~^ ERROR: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid </ins> let h1: *const [u8; 2] = &x1.y as *const [u8; 2]; <ins> let t1: *mut [u8; 2] = &x1.y as *mut [u8; 2]; //~^ ERROR: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid </ins> let mut x1 = X { y: [0, 0] }; <del> // This is still an error since we don't allow casts from &mut [T; n] to *mut T. let p1: *mut u8 = &mut x1.y as *mut _;  //~ ERROR casting </del> <ins> let p1: *mut u8 = &mut x1.y as *mut _; let p2: *const u8 = &mut x1.y as *const _; </ins> let t1: *mut [u8; 2] = &mut x1.y as *mut _; let h1: *mut [u8; 2] = &mut x1.y as *mut [u8; 2]; }

<del> error[E0606]: casting `&mut [u8; 2]` as `*mut u8` is invalid --> $DIR/vector-cast-weirdness.rs:21:23 </del> <ins> error[E0606]: casting `&[u8; 2]` as `*mut u8` is invalid --> $DIR/vector-cast-weirdness.rs:19:23 </ins> | <del> LL |     let p1: *mut u8 = &mut x1.y as *mut _; |                       ^^^^^^^^^^^^^^^^^^^ </del> <ins> LL |     let p1: *mut u8 = &x1.y as *mut _; |                       ^^^^^^^^^^^^^^^ </ins> <del> error: aborting due to previous error </del> <ins> error[E0606]: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid --> $DIR/vector-cast-weirdness.rs:22:28 | LL |     let t1: *mut [u8; 2] = &x1.y as *mut _; |                            ^^^^^^^^^^^^^^^ error[E0606]: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid --> $DIR/vector-cast-weirdness.rs:25:28 | LL |     let t1: *mut [u8; 2] = &x1.y as *mut [u8; 2]; |                            ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors </ins> For more information about this error, try `rustc --explain E0606`.