about summary refs log tree commit diff
path: root/compiler/rustc_mir_build/src/builder
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_build/src/builder')
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs24
-rw-r--r--compiler/rustc_mir_build/src/builder/mod.rs6
2 files changed, 24 insertions, 6 deletions
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
index a4ef6e92739..3a5839f2d40 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
@@ -8,6 +8,7 @@ use rustc_middle::middle::region;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
+use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::cast::{CastTy, mir_cast_kind};
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, Ty, UpvarArgs};
@@ -656,6 +657,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         block.and(rvalue)
     }
 
+    /// Recursively inspect a THIR expression and probe through unsizing
+    /// operations that can be const-folded today.
+    fn check_constness(&self, mut kind: &'a ExprKind<'tcx>) -> bool {
+        loop {
+            debug!(?kind, "check_constness");
+            match kind {
+                &ExprKind::ValueTypeAscription { source: eid, user_ty: _, user_ty_span: _ }
+                | &ExprKind::Use { source: eid }
+                | &ExprKind::PointerCoercion {
+                    cast: PointerCoercion::Unsize,
+                    source: eid,
+                    is_from_as_cast: _,
+                }
+                | &ExprKind::Scope { region_scope: _, lint_level: _, value: eid } => {
+                    kind = &self.thir[eid].kind
+                }
+                _ => return matches!(Category::of(&kind), Some(Category::Constant)),
+            }
+        }
+    }
+
     fn build_zero_repeat(
         &mut self,
         mut block: BasicBlock,
@@ -666,7 +688,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let this = self;
         let value_expr = &this.thir[value];
         let elem_ty = value_expr.ty;
-        if let Some(Category::Constant) = Category::of(&value_expr.kind) {
+        if this.check_constness(&value_expr.kind) {
             // Repeating a const does nothing
         } else {
             // For a non-const, we may need to generate an appropriate `Drop`
diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs
index cdb2c5561ce..7ca94e655fb 100644
--- a/compiler/rustc_mir_build/src/builder/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/mod.rs
@@ -395,12 +395,10 @@ enum NeedsTemporary {
     Maybe,
 }
 
-///////////////////////////////////////////////////////////////////////////
 /// The `BlockAnd` "monad" packages up the new basic block along with a
 /// produced value (sometimes just unit, of course). The `unpack!`
 /// macro (and methods below) makes working with `BlockAnd` much more
 /// convenient.
-
 #[must_use = "if you don't use one of these results, you're leaving a dangling edge"]
 struct BlockAnd<T>(BasicBlock, T);
 
@@ -438,9 +436,7 @@ macro_rules! unpack {
     }};
 }
 
-///////////////////////////////////////////////////////////////////////////
-/// the main entry point for building MIR for a function
-
+/// The main entry point for building MIR for a function.
 fn construct_fn<'tcx>(
     tcx: TyCtxt<'tcx>,
     fn_def: LocalDefId,