Skip to content

Commit e1f0108

Browse files
authoredFeb 11, 2021
Rollup merge of rust-lang#81479 - osa1:issue24151, r=lcnr
Allow casting mut array ref to mut ptr 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 rust-lang#24151
2 parents b16c54c + d64b749 commit e1f0108

File tree

4 files changed

+55
-25
lines changed

4 files changed

+55
-25
lines changed
 

‎compiler/rustc_mir/src/borrow_check/type_check/mod.rs

+24-15
Original file line numberDiff line numberDiff line change
@@ -2191,19 +2191,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21912191
CastKind::Pointer(PointerCast::ArrayToPointer) => {
21922192
let ty_from = op.ty(body, tcx);
21932193

2194-
let opt_ty_elem = match ty_from.kind() {
2195-
ty::RawPtr(ty::TypeAndMut {
2196-
mutbl: hir::Mutability::Not,
2197-
ty: array_ty,
2198-
}) => match array_ty.kind() {
2199-
ty::Array(ty_elem, _) => Some(ty_elem),
2200-
_ => None,
2201-
},
2194+
let opt_ty_elem_mut = match ty_from.kind() {
2195+
ty::RawPtr(ty::TypeAndMut { mutbl: array_mut, ty: array_ty }) => {
2196+
match array_ty.kind() {
2197+
ty::Array(ty_elem, _) => Some((ty_elem, *array_mut)),
2198+
_ => None,
2199+
}
2200+
}
22022201
_ => None,
22032202
};
22042203

2205-
let ty_elem = match opt_ty_elem {
2206-
Some(ty_elem) => ty_elem,
2204+
let (ty_elem, ty_mut) = match opt_ty_elem_mut {
2205+
Some(ty_elem_mut) => ty_elem_mut,
22072206
None => {
22082207
span_mirbug!(
22092208
self,
@@ -2215,11 +2214,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
22152214
}
22162215
};
22172216

2218-
let ty_to = match ty.kind() {
2219-
ty::RawPtr(ty::TypeAndMut {
2220-
mutbl: hir::Mutability::Not,
2221-
ty: ty_to,
2222-
}) => ty_to,
2217+
let (ty_to, ty_to_mut) = match ty.kind() {
2218+
ty::RawPtr(ty::TypeAndMut { mutbl: ty_to_mut, ty: ty_to }) => {
2219+
(ty_to, *ty_to_mut)
2220+
}
22232221
_ => {
22242222
span_mirbug!(
22252223
self,
@@ -2231,6 +2229,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
22312229
}
22322230
};
22332231

2232+
if ty_to_mut == Mutability::Mut && ty_mut == Mutability::Not {
2233+
span_mirbug!(
2234+
self,
2235+
rvalue,
2236+
"ArrayToPointer cast from const {:?} to mut {:?}",
2237+
ty,
2238+
ty_to
2239+
);
2240+
return;
2241+
}
2242+
22342243
if let Err(terr) = self.sub_types(
22352244
ty_elem,
22362245
ty_to,

‎compiler/rustc_typeck/src/check/cast.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -765,9 +765,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
765765
m_expr: ty::TypeAndMut<'tcx>,
766766
m_cast: ty::TypeAndMut<'tcx>,
767767
) -> Result<CastKind, CastError> {
768-
// array-ptr-cast.
769-
770-
if m_expr.mutbl == hir::Mutability::Not && m_cast.mutbl == hir::Mutability::Not {
768+
// array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
769+
if m_expr.mutbl == hir::Mutability::Mut || m_cast.mutbl == hir::Mutability::Not {
771770
if let ty::Array(ety, _) = m_expr.ty.kind() {
772771
// Due to the limitations of LLVM global constants,
773772
// region pointers end up pointing at copies of

‎src/test/ui/array-slice-vec/vector-cast-weirdness.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
// Issue #14893. Tests that casts from vectors don't behave strangely in the
22
// presence of the `_` type shorthand notation.
3+
//
34
// Update: after a change to the way casts are done, we have more type information
45
// around and so the errors here are no longer exactly the same.
6+
//
7+
// Update: With PR #81479 some of the previously rejected cases are now allowed.
8+
// New test cases added.
59

610
struct X {
711
y: [u8; 2],
@@ -12,13 +16,19 @@ fn main() {
1216

1317
// No longer a type mismatch - the `_` can be fully resolved by type inference.
1418
let p1: *const u8 = &x1.y as *const _;
19+
let p1: *mut u8 = &x1.y as *mut _;
20+
//~^ ERROR: casting `&[u8; 2]` as `*mut u8` is invalid
1521
let t1: *const [u8; 2] = &x1.y as *const _;
22+
let t1: *mut [u8; 2] = &x1.y as *mut _;
23+
//~^ ERROR: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid
1624
let h1: *const [u8; 2] = &x1.y as *const [u8; 2];
25+
let t1: *mut [u8; 2] = &x1.y as *mut [u8; 2];
26+
//~^ ERROR: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid
1727

1828
let mut x1 = X { y: [0, 0] };
1929

20-
// This is still an error since we don't allow casts from &mut [T; n] to *mut T.
21-
let p1: *mut u8 = &mut x1.y as *mut _; //~ ERROR casting
30+
let p1: *mut u8 = &mut x1.y as *mut _;
31+
let p2: *const u8 = &mut x1.y as *const _;
2232
let t1: *mut [u8; 2] = &mut x1.y as *mut _;
2333
let h1: *mut [u8; 2] = &mut x1.y as *mut [u8; 2];
2434
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
1-
error[E0606]: casting `&mut [u8; 2]` as `*mut u8` is invalid
2-
--> $DIR/vector-cast-weirdness.rs:21:23
1+
error[E0606]: casting `&[u8; 2]` as `*mut u8` is invalid
2+
--> $DIR/vector-cast-weirdness.rs:19:23
33
|
4-
LL | let p1: *mut u8 = &mut x1.y as *mut _;
5-
| ^^^^^^^^^^^^^^^^^^^
4+
LL | let p1: *mut u8 = &x1.y as *mut _;
5+
| ^^^^^^^^^^^^^^^
66

7-
error: aborting due to previous error
7+
error[E0606]: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid
8+
--> $DIR/vector-cast-weirdness.rs:22:28
9+
|
10+
LL | let t1: *mut [u8; 2] = &x1.y as *mut _;
11+
| ^^^^^^^^^^^^^^^
12+
13+
error[E0606]: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid
14+
--> $DIR/vector-cast-weirdness.rs:25:28
15+
|
16+
LL | let t1: *mut [u8; 2] = &x1.y as *mut [u8; 2];
17+
| ^^^^^^^^^^^^^^^^^^^^^
18+
19+
error: aborting due to 3 previous errors
820

921
For more information about this error, try `rustc --explain E0606`.

0 commit comments

Comments
 (0)