Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expect an array when expected and acutal types are both arrays during cast #138962

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 20 additions & 19 deletions compiler/rustc_hir_typeck/src/cast.rs
Original file line number Diff line number Diff line change
@@ -1042,30 +1042,31 @@ impl<'a, 'tcx> CastCheck<'tcx> {
m_cast: ty::TypeAndMut<'tcx>,
) -> Result<CastKind, CastError<'tcx>> {
// array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
if m_expr.mutbl >= m_cast.mutbl {
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
// vector elements instead of the original values.
// To allow raw pointers to work correctly, we
// need to special-case obtaining a raw pointer
// from a region pointer to a vector.

// Coerce to a raw pointer so that we generate RawPtr in MIR.
let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr.ty, m_expr.mutbl);
fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
.unwrap_or_else(|_| {
bug!(
if m_expr.mutbl >= m_cast.mutbl
&& let ty::Array(ety, _) = m_expr.ty.kind()
&& fcx.can_eq(fcx.param_env, *ety, m_cast.ty)
{
// Due to the limitations of LLVM global constants,
// region pointers end up pointing at copies of
// vector elements instead of the original values.
// To allow raw pointers to work correctly, we
// need to special-case obtaining a raw pointer
// from a region pointer to a vector.

// Coerce to a raw pointer so that we generate RawPtr in MIR.
let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr.ty, m_expr.mutbl);
fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
.unwrap_or_else(|_| {
bug!(
"could not cast from reference to array to pointer to array ({:?} to {:?})",
self.expr_ty,
array_ptr_type,
)
});
});

// this will report a type mismatch if needed
fcx.demand_eqtype(self.span, *ety, m_cast.ty);
return Ok(CastKind::ArrayPtrCast);
}
// this will report a type mismatch if needed
fcx.demand_eqtype(self.span, *ety, m_cast.ty);
return Ok(CastKind::ArrayPtrCast);
}

Err(CastError::IllegalCast)
5 changes: 5 additions & 0 deletions tests/ui/cast/cast-array-issue-138836.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main() {
let a: [u8; 3] = [1,2,3];
let b = &a;
let c = b as *const [u32; 3]; //~ ERROR casting `&[u8; 3]` as `*const [u32; 3]` is invalid
}
9 changes: 9 additions & 0 deletions tests/ui/cast/cast-array-issue-138836.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0606]: casting `&[u8; 3]` as `*const [u32; 3]` is invalid
--> $DIR/cast-array-issue-138836.rs:4:13
|
LL | let c = b as *const [u32; 3];
| ^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0606`.
2 changes: 1 addition & 1 deletion tests/ui/consts/const-cast-wrong-type.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const a: [u8; 3] = ['h' as u8, 'i' as u8, 0 as u8];
const b: *const i8 = &a as *const i8; //~ ERROR mismatched types
const b: *const i8 = &a as *const i8; //~ ERROR casting `&[u8; 3]` as `*const i8` is invalid

fn main() {
}
6 changes: 3 additions & 3 deletions tests/ui/consts/const-cast-wrong-type.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
error[E0308]: mismatched types
error[E0606]: casting `&[u8; 3]` as `*const i8` is invalid
--> $DIR/const-cast-wrong-type.rs:2:22
|
LL | const b: *const i8 = &a as *const i8;
| ^^^^^^^^^^^^^^^ expected `u8`, found `i8`
| ^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.
For more information about this error, try `rustc --explain E0606`.
Loading
Oops, something went wrong.