about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2023-01-24 17:43:07 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2023-02-02 23:09:51 +0000
commitb62a9da0c839fa3e722d4baf3e50ce58b749bc8e (patch)
tree905e65075b4a85d402d6c03487bccd23bd42cc5f
parent20dd5e09fdeec25a7a6206e95ea8706e20ab8a01 (diff)
downloadrust-b62a9da0c839fa3e722d4baf3e50ce58b749bc8e.tar.gz
rust-b62a9da0c839fa3e722d4baf3e50ce58b749bc8e.zip
Handle aggregates in DataflowConstProp.
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs25
1 files changed, 25 insertions, 0 deletions
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index c75fe2327de..949a59a97bf 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -5,6 +5,7 @@
 use rustc_const_eval::const_eval::CheckAlignment;
 use rustc_const_eval::interpret::{ConstValue, ImmTy, Immediate, InterpCx, Scalar};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def::DefKind;
 use rustc_middle::mir::visit::{MutVisitor, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -85,6 +86,30 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> {
         state: &mut State<Self::Value>,
     ) {
         match rvalue {
+            Rvalue::Aggregate(kind, operands) => {
+                let target = self.map().find(target.as_ref());
+                if let Some(target) = target {
+                    state.flood_idx_with(target, self.map(), FlatSet::Bottom);
+                    let field_based = match **kind {
+                        AggregateKind::Tuple | AggregateKind::Closure(..) => true,
+                        AggregateKind::Adt(def_id, ..) => {
+                            matches!(self.tcx.def_kind(def_id), DefKind::Struct)
+                        }
+                        _ => false,
+                    };
+                    if field_based {
+                        for (field_index, operand) in operands.iter().enumerate() {
+                            if let Some(field) = self
+                                .map()
+                                .apply(target, TrackElem::Field(Field::from_usize(field_index)))
+                            {
+                                let result = self.handle_operand(operand, state);
+                                state.assign_idx(field, result, self.map());
+                            }
+                        }
+                    }
+                }
+            }
             Rvalue::CheckedBinaryOp(op, box (left, right)) => {
                 let target = self.map().find(target.as_ref());
                 if let Some(target) = target {