diff options
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/operand.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/place.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/builder/expr/as_constant.rs | 42 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/known_panics_lint.rs | 4 | ||||
| -rw-r--r-- | tests/crashes/129109.rs | 10 | ||||
| -rw-r--r-- | tests/crashes/130970.rs | 9 | ||||
| -rw-r--r-- | tests/crashes/131347.rs | 9 | ||||
| -rw-r--r-- | tests/ui/mir/unsized-extern-static.rs | 13 | ||||
| -rw-r--r-- | tests/ui/mir/unsized-extern-static.stderr | 20 |
10 files changed, 62 insertions, 68 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 2c779489272..21afd082a05 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -243,17 +243,6 @@ impl<'tcx, Prov: Provenance> std::ops::Deref for ImmTy<'tcx, Prov> { } impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { - #[inline(always)] - pub fn try_from_immediate(imm: Immediate<Prov>, layout: TyAndLayout<'tcx>) -> Option<Self> { - let matches_abi = match (imm, layout.backend_repr) { - (Immediate::Scalar(..), BackendRepr::Scalar(..)) => true, - (Immediate::ScalarPair(..), BackendRepr::ScalarPair(..)) => true, - (Immediate::Uninit, _) => layout.is_sized(), - _ => false, - }; - if matches_abi { Some(ImmTy { imm, layout }) } else { None } - } - #[inline] pub fn from_scalar(val: Scalar<Prov>, layout: TyAndLayout<'tcx>) -> Self { debug_assert!(layout.backend_repr.is_scalar(), "`ImmTy::from_scalar` on non-scalar layout"); diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index a8cfe276b49..e2284729efd 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -314,14 +314,6 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for PlaceTy<'tcx, Prov> { // These are defined here because they produce a place. impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> { #[inline(always)] - pub fn try_as_immediate(&self) -> Option<ImmTy<'tcx, Prov>> { - match self.op() { - Operand::Indirect(_) => None, - Operand::Immediate(imm) => ImmTy::try_from_immediate(*imm, self.layout), - } - } - - #[inline(always)] pub fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> { match self.op() { Operand::Indirect(mplace) => Left(MPlaceTy { mplace: *mplace, layout: self.layout }), diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs index 9825b947fe0..ddb405acec7 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs @@ -309,7 +309,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { | ExprKind::ConstParam { .. } | ExprKind::ConstBlock { .. } => { Ok(Operand::Constant(Box::new( - as_constant_inner(expr, |_| None, self.tcx) + as_constant_inner(self.tcx, self.typing_env, expr, |_| None) ))) }, _ => self.parse_place(expr_id).map(Operand::Copy), @@ -393,7 +393,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { | ExprKind::NamedConst { .. } | ExprKind::NonHirLiteral { .. } | ExprKind::ConstBlock { .. } => Ok({ - let value = as_constant_inner(expr, |_| None, self.tcx); + let value = as_constant_inner(self.tcx, self.typing_env, expr, |_| None); value.const_.eval_bits(self.tcx, self.typing_env) }), ) diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index 0e0c7a7fa4f..5eb324f4b51 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::{ self, CanonicalUserType, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt as _, - UserTypeAnnotationIndex, + TypingEnv, UserTypeAnnotationIndex, }; use rustc_middle::{bug, mir, span_bug}; use tracing::{instrument, trace}; @@ -19,32 +19,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, yielding a compile-time constant. Assumes that /// `expr` is a valid compile-time constant! pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> ConstOperand<'tcx> { - let this = self; - let tcx = this.tcx; let Expr { ty, temp_lifetime: _, span, ref kind } = *expr; match kind { ExprKind::Scope { region_scope: _, lint_level: _, value } => { - this.as_constant(&this.thir[*value]) + self.as_constant(&self.thir[*value]) } - _ => as_constant_inner( - expr, - |user_ty| { - Some(this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { - span, - user_ty: user_ty.clone(), - inferred_ty: ty, - })) - }, - tcx, - ), + _ => as_constant_inner(self.tcx, self.typing_env(), expr, |user_ty| { + Some(self.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { + span, + user_ty: user_ty.clone(), + inferred_ty: ty, + })) + }), } } } pub(crate) fn as_constant_inner<'tcx>( + tcx: TyCtxt<'tcx>, + typing_env: TypingEnv<'tcx>, expr: &Expr<'tcx>, push_cuta: impl FnMut(&Box<CanonicalUserType<'tcx>>) -> Option<UserTypeAnnotationIndex>, - tcx: TyCtxt<'tcx>, ) -> ConstOperand<'tcx> { let Expr { ty, temp_lifetime: _, span, ref kind } = *expr; match *kind { @@ -88,8 +83,19 @@ pub(crate) fn as_constant_inner<'tcx>( ConstOperand { user_ty: None, span, const_ } } ExprKind::StaticRef { alloc_id, ty, .. } => { - let const_val = ConstValue::Scalar(Scalar::from_pointer(alloc_id.into(), &tcx)); - let const_ = Const::Val(const_val, ty); + let pointee = ty.builtin_deref(true).expect("StaticRef's type must be pointer"); + let const_ = if pointee.is_sized(tcx, typing_env) { + let const_val = ConstValue::Scalar(Scalar::from_pointer(alloc_id.into(), &tcx)); + Const::Val(const_val, ty) + } else { + // Ill-formed code may produce instances where `pointee` is not `Sized`. + // This should be reported by wfcheck on the static itself. + // Still, producing a single scalar constant would be inconsistent, as pointers to + // non-`Sized` types are scalar pairs. Avoid an ICE by producing an error constant. + let guar = + tcx.dcx().span_delayed_bug(span, format!("static's type `{ty}` is not Sized")); + Const::Ty(ty, ty::Const::new_error(tcx, guar)) + }; ConstOperand { span, user_ty: None, const_ } } diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index cebbc404923..481c7941909 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -263,7 +263,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // manually normalized. let val = self.tcx.try_normalize_erasing_regions(self.typing_env, c.const_).ok()?; - self.use_ecx(|this| this.ecx.eval_mir_constant(&val, c.span, None))?.try_as_immediate() + self.use_ecx(|this| this.ecx.eval_mir_constant(&val, c.span, None))? + .as_mplace_or_imm() + .right() } /// Returns the value, if any, of evaluating `place`. diff --git a/tests/crashes/129109.rs b/tests/crashes/129109.rs deleted file mode 100644 index 0db53b98a71..00000000000 --- a/tests/crashes/129109.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: rust-lang/rust#129109 -//@ compile-flags: -Zmir-enable-passes=+GVN -Zvalidate-mir - -extern "C" { - pub static mut symbol: [i8]; -} - -fn main() { - println!("C", unsafe { &symbol }); -} diff --git a/tests/crashes/130970.rs b/tests/crashes/130970.rs deleted file mode 100644 index 698c2b478e1..00000000000 --- a/tests/crashes/130970.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #130970 -//@ compile-flags: -Zmir-enable-passes=+GVN -Zvalidate-mir - -fn main() { - extern "C" { - static symbol: [usize]; - } - println!("{}", symbol[0]); -} diff --git a/tests/crashes/131347.rs b/tests/crashes/131347.rs deleted file mode 100644 index 08f7d068e25..00000000000 --- a/tests/crashes/131347.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #131347 -//@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir - -struct S; -static STUFF: [i8] = [0; S::N]; - -fn main() { - assert_eq!(STUFF, [0; 63]); -} diff --git a/tests/ui/mir/unsized-extern-static.rs b/tests/ui/mir/unsized-extern-static.rs new file mode 100644 index 00000000000..386842556ba --- /dev/null +++ b/tests/ui/mir/unsized-extern-static.rs @@ -0,0 +1,13 @@ +//! Regression test for #129109 +//! MIR building used to produce erroneous constants when referring to statics of unsized type. +//@ compile-flags: -Zmir-enable-passes=+GVN -Zvalidate-mir + +extern "C" { + pub static mut symbol: [i8]; + //~^ ERROR the size for values of type `[i8]` +} + +fn main() { + println!("C", unsafe { &symbol }); + //~^ ERROR argument never used +} diff --git a/tests/ui/mir/unsized-extern-static.stderr b/tests/ui/mir/unsized-extern-static.stderr new file mode 100644 index 00000000000..93aed3549d7 --- /dev/null +++ b/tests/ui/mir/unsized-extern-static.stderr @@ -0,0 +1,20 @@ +error: argument never used + --> $DIR/unsized-extern-static.rs:11:19 + | +LL | println!("C", unsafe { &symbol }); + | --- ^^^^^^^^^^^^^^^^^^ argument never used + | | + | formatting specifier missing + +error[E0277]: the size for values of type `[i8]` cannot be known at compilation time + --> $DIR/unsized-extern-static.rs:6:5 + | +LL | pub static mut symbol: [i8]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i8]` + = note: statics and constants must have a statically known size + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. |
