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 /compiler | |
| 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
Diffstat (limited to 'compiler')
| -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 |
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 |
