Allow casting mut array ref to mut ptr
We now allow two new casts: - mut array reference to mut ptr. Example: let mut x: [usize; 2] = [0, 0]; let p = &mut x as *mut usize; We allow casting const array references to const pointers so not allowing mut references to mut pointers was inconsistent. - mut array reference to const ptr. Example: let mut x: [usize; 2] = [0, 0]; let p = &mut x as *const usize; This was similarly inconsistent as we allow casting mut references to const pointers. Existing test 'vector-cast-weirdness' updated to test both cases. Fixes #24151
This commit is contained in:
parent
6523b721c3
commit
d64b749f2c
|
@ -2191,19 +2191,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
CastKind::Pointer(PointerCast::ArrayToPointer) => {
|
||||
let ty_from = op.ty(body, tcx);
|
||||
|
||||
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,
|
||||
},
|
||||
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,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let ty_elem = match opt_ty_elem {
|
||||
Some(ty_elem) => ty_elem,
|
||||
let (ty_elem, ty_mut) = match opt_ty_elem_mut {
|
||||
Some(ty_elem_mut) => ty_elem_mut,
|
||||
None => {
|
||||
span_mirbug!(
|
||||
self,
|
||||
|
@ -2215,11 +2214,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
let ty_to = match ty.kind() {
|
||||
ty::RawPtr(ty::TypeAndMut {
|
||||
mutbl: hir::Mutability::Not,
|
||||
ty: ty_to,
|
||||
}) => ty_to,
|
||||
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)
|
||||
}
|
||||
_ => {
|
||||
span_mirbug!(
|
||||
self,
|
||||
|
@ -2231,6 +2229,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
if ty_to_mut == Mutability::Mut && ty_mut == Mutability::Not {
|
||||
span_mirbug!(
|
||||
self,
|
||||
rvalue,
|
||||
"ArrayToPointer cast from const {:?} to mut {:?}",
|
||||
ty,
|
||||
ty_to
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if let Err(terr) = self.sub_types(
|
||||
ty_elem,
|
||||
ty_to,
|
||||
|
|
|
@ -765,9 +765,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
m_expr: ty::TypeAndMut<'tcx>,
|
||||
m_cast: ty::TypeAndMut<'tcx>,
|
||||
) -> Result<CastKind, CastError> {
|
||||
// array-ptr-cast.
|
||||
|
||||
if m_expr.mutbl == hir::Mutability::Not && m_cast.mutbl == hir::Mutability::Not {
|
||||
// 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 {
|
||||
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
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
// Issue #14893. Tests that casts from vectors don't behave strangely in the
|
||||
// presence of the `_` type shorthand notation.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Update: With PR #81479 some of the previously rejected cases are now allowed.
|
||||
// New test cases added.
|
||||
|
||||
struct X {
|
||||
y: [u8; 2],
|
||||
|
@ -12,13 +16,19 @@ fn main() {
|
|||
|
||||
// No longer a type mismatch - the `_` can be fully resolved by type inference.
|
||||
let p1: *const u8 = &x1.y as *const _;
|
||||
let p1: *mut u8 = &x1.y as *mut _;
|
||||
//~^ ERROR: casting `&[u8; 2]` as `*mut u8` is invalid
|
||||
let t1: *const [u8; 2] = &x1.y as *const _;
|
||||
let t1: *mut [u8; 2] = &x1.y as *mut _;
|
||||
//~^ ERROR: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid
|
||||
let h1: *const [u8; 2] = &x1.y as *const [u8; 2];
|
||||
let t1: *mut [u8; 2] = &x1.y as *mut [u8; 2];
|
||||
//~^ ERROR: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid
|
||||
|
||||
let mut x1 = X { y: [0, 0] };
|
||||
|
||||
// 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
|
||||
let p1: *mut u8 = &mut x1.y as *mut _;
|
||||
let p2: *const u8 = &mut x1.y as *const _;
|
||||
let t1: *mut [u8; 2] = &mut x1.y as *mut _;
|
||||
let h1: *mut [u8; 2] = &mut x1.y as *mut [u8; 2];
|
||||
}
|
||||
|
|
|
@ -1,9 +1,21 @@
|
|||
error[E0606]: casting `&mut [u8; 2]` as `*mut u8` is invalid
|
||||
--> $DIR/vector-cast-weirdness.rs:21:23
|
||||
error[E0606]: casting `&[u8; 2]` as `*mut u8` is invalid
|
||||
--> $DIR/vector-cast-weirdness.rs:19:23
|
||||
|
|
||||
LL | let p1: *mut u8 = &mut x1.y as *mut _;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
LL | let p1: *mut u8 = &x1.y as *mut _;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
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
|
||||
|
||||
For more information about this error, try `rustc --explain E0606`.
|
||||
|
|
Loading…
Reference in New Issue