about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
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
commitd64b749f2cebcfec942ecbbb87e24a9f8cc28469 (patch)
tree4beeddf028a59d62fbe674d92e0c680049e26ae2 /compiler
parent6523b721c3d8a92cf06aab04dd15ebe7fd5a9fb7 (diff)
downloadrust-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
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_mir/src/borrow_check/type_check/mod.rs39
-rw-r--r--compiler/rustc_typeck/src/check/cast.rs5
2 files changed, 26 insertions, 18 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