From a34c42fefabc774af2d8b2c5a5a100c0697d2ba9 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Wed, 26 Mar 2025 11:31:58 +0800 Subject: [PATCH] Expect an array when expected and acutal types are both arrays during cast Signed-off-by: xizheyin --- compiler/rustc_hir_typeck/src/cast.rs | 37 ++++++++++---------- tests/ui/cast/cast-array-issue-138836.rs | 2 +- tests/ui/cast/cast-array-issue-138836.stderr | 9 ++--- tests/ui/consts/const-cast-wrong-type.rs | 2 +- tests/ui/consts/const-cast-wrong-type.stderr | 6 ++-- 5 files changed, 27 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 8f5fddd19d7..b19d9efe2c6 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -1042,30 +1042,31 @@ impl<'a, 'tcx> CastCheck<'tcx> { m_cast: ty::TypeAndMut<'tcx>, ) -> Result> { // 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. + 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!( + // 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) diff --git a/tests/ui/cast/cast-array-issue-138836.rs b/tests/ui/cast/cast-array-issue-138836.rs index 6fd65d5878a..3f8098e76fd 100644 --- a/tests/ui/cast/cast-array-issue-138836.rs +++ b/tests/ui/cast/cast-array-issue-138836.rs @@ -1,5 +1,5 @@ fn main() { let a: [u8; 3] = [1,2,3]; let b = &a; - let c = b as *const [u32; 3]; //~ ERROR mismatched types [E0308] + let c = b as *const [u32; 3]; //~ ERROR casting `&[u8; 3]` as `*const [u32; 3]` is invalid } diff --git a/tests/ui/cast/cast-array-issue-138836.stderr b/tests/ui/cast/cast-array-issue-138836.stderr index fe20d429a49..309474c29f9 100644 --- a/tests/ui/cast/cast-array-issue-138836.stderr +++ b/tests/ui/cast/cast-array-issue-138836.stderr @@ -1,12 +1,9 @@ -error[E0308]: mismatched types +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]; - | ^^^^^^^^^^^^^^^^^^^^ expected `[u8; 3]`, found `[u32; 3]` - | - = note: expected array `[u8; 3]` - found array `[u32; 3]` + | ^^^^^^^^^^^^^^^^^^^^ 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`. diff --git a/tests/ui/consts/const-cast-wrong-type.rs b/tests/ui/consts/const-cast-wrong-type.rs index 6e055a2bcd3..9936a660936 100644 --- a/tests/ui/consts/const-cast-wrong-type.rs +++ b/tests/ui/consts/const-cast-wrong-type.rs @@ -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() { } diff --git a/tests/ui/consts/const-cast-wrong-type.stderr b/tests/ui/consts/const-cast-wrong-type.stderr index 44361f15d8a..0730bac2235 100644 --- a/tests/ui/consts/const-cast-wrong-type.stderr +++ b/tests/ui/consts/const-cast-wrong-type.stderr @@ -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`.