diff options
| author | Ömer Sinan Ağacan <omeragacan@gmail.com> | 2021-01-28 20:22:33 +0300 |
|---|---|---|
| committer | Ömer Sinan Ağacan <omeragacan@gmail.com> | 2021-02-10 15:44:41 +0300 |
| commit | d64b749f2cebcfec942ecbbb87e24a9f8cc28469 (patch) | |
| tree | 4beeddf028a59d62fbe674d92e0c680049e26ae2 | |
| parent | 6523b721c3d8a92cf06aab04dd15ebe7fd5a9fb7 (diff) | |
| download | rust-d64b749f2cebcfec942ecbbb87e24a9f8cc28469.tar.gz rust-d64b749f2cebcfec942ecbbb87e24a9f8cc28469.zip | |
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
| -rw-r--r-- | compiler/rustc_mir/src/borrow_check/type_check/mod.rs | 39 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/cast.rs | 5 | ||||
| -rw-r--r-- | src/test/ui/array-slice-vec/vector-cast-weirdness.rs | 14 | ||||
| -rw-r--r-- | src/test/ui/array-slice-vec/vector-cast-weirdness.stderr | 22 |
4 files changed, 55 insertions, 25 deletions
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index 3ba06bdd6e0..52b1ff3877d 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -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, diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 7924ffe8a6f..16c344e8e2b 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -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 diff --git a/src/test/ui/array-slice-vec/vector-cast-weirdness.rs b/src/test/ui/array-slice-vec/vector-cast-weirdness.rs index 79b9243765b..e8f2c71477a 100644 --- a/src/test/ui/array-slice-vec/vector-cast-weirdness.rs +++ b/src/test/ui/array-slice-vec/vector-cast-weirdness.rs @@ -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]; } diff --git a/src/test/ui/array-slice-vec/vector-cast-weirdness.stderr b/src/test/ui/array-slice-vec/vector-cast-weirdness.stderr index 37055bb75f5..6fdb1ac9e30 100644 --- a/src/test/ui/array-slice-vec/vector-cast-weirdness.stderr +++ b/src/test/ui/array-slice-vec/vector-cast-weirdness.stderr @@ -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`. |
