diff options
| author | Jacob Pratt <jacob@jhpratt.dev> | 2025-04-13 17:37:52 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-13 17:37:52 -0400 |
| commit | 60c76b9dfd6e52f6605e0a63b7a33ad09dab96d3 (patch) | |
| tree | 2b1b147444ade59436a237550ad51536051ec025 | |
| parent | d04df1cba9fa67c597e58311623ce1053ee23b92 (diff) | |
| parent | a34c42fefabc774af2d8b2c5a5a100c0697d2ba9 (diff) | |
| download | rust-60c76b9dfd6e52f6605e0a63b7a33ad09dab96d3.tar.gz rust-60c76b9dfd6e52f6605e0a63b7a33ad09dab96d3.zip | |
Rollup merge of #138962 - xizheyin:issue-138836, r=compiler-errors
Expect an array when expected and acutal types are both arrays during cast Closes #138836
| -rw-r--r-- | compiler/rustc_hir_typeck/src/cast.rs | 39 | ||||
| -rw-r--r-- | tests/ui/cast/cast-array-issue-138836.rs | 5 | ||||
| -rw-r--r-- | tests/ui/cast/cast-array-issue-138836.stderr | 9 | ||||
| -rw-r--r-- | tests/ui/consts/const-cast-wrong-type.rs | 2 | ||||
| -rw-r--r-- | tests/ui/consts/const-cast-wrong-type.stderr | 6 |
5 files changed, 38 insertions, 23 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<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) diff --git a/tests/ui/cast/cast-array-issue-138836.rs b/tests/ui/cast/cast-array-issue-138836.rs new file mode 100644 index 00000000000..3f8098e76fd --- /dev/null +++ b/tests/ui/cast/cast-array-issue-138836.rs @@ -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 +} diff --git a/tests/ui/cast/cast-array-issue-138836.stderr b/tests/ui/cast/cast-array-issue-138836.stderr new file mode 100644 index 00000000000..309474c29f9 --- /dev/null +++ b/tests/ui/cast/cast-array-issue-138836.stderr @@ -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`. 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`. |
