about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs11
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs8
-rw-r--r--compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs4
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/as_constant.rs42
-rw-r--r--compiler/rustc_mir_transform/src/known_panics_lint.rs4
-rw-r--r--tests/crashes/129109.rs10
-rw-r--r--tests/crashes/130970.rs9
-rw-r--r--tests/crashes/131347.rs9
-rw-r--r--tests/ui/mir/unsized-extern-static.rs13
-rw-r--r--tests/ui/mir/unsized-extern-static.stderr20
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`.