about summary refs log tree commit diff
path: root/compiler/rustc_mir_dataflow
diff options
context:
space:
mode:
authorThe rustc-josh-sync Cronjob Bot <github-actions@github.com>2025-09-25 04:16:26 +0000
committerThe rustc-josh-sync Cronjob Bot <github-actions@github.com>2025-09-25 04:16:26 +0000
commitff7e7319837d5029ed4f522601debc2a7bc33274 (patch)
tree42dbcb2d8c347a2e7c97c7e4361b1c361143da0b /compiler/rustc_mir_dataflow
parent3280c210dd6e5f26595ff4857572f8feba678992 (diff)
parentd226e7aa93425ba2090f423642341a99ab047838 (diff)
Merge ref 'caccb4d0368b' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: caccb4d0368bd918ef6668af8e13834d07040417
Filtered ref: 0f345ed05d559bbfb754f1403b16199366cda2e0
Upstream diff: https://github.com/rust-lang/rust/compare/21a19c297d4f5a03501d92ca251bd7a17073c08a...caccb4d0368bd918ef6668af8e13834d07040417

This merge was created using https://github.com/rust-lang/josh-sync.
Diffstat (limited to 'compiler/rustc_mir_dataflow')
-rw-r--r--compiler/rustc_mir_dataflow/Cargo.toml1
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs15
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/liveness.rs37
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/mod.rs3
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs38
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs10
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/mod.rs17
-rw-r--r--compiler/rustc_mir_dataflow/src/points.rs68
-rw-r--r--compiler/rustc_mir_dataflow/src/rustc_peek.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs11
11 files changed, 53 insertions, 150 deletions
diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml
index 293bcbef21b..9621f9f20bd 100644
--- a/compiler/rustc_mir_dataflow/Cargo.toml
+++ b/compiler/rustc_mir_dataflow/Cargo.toml
@@ -13,7 +13,6 @@ rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_graphviz = { path = "../rustc_graphviz" }
-rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index f86a15a8f92..b85b82b8f6d 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -8,14 +8,13 @@ use std::sync::OnceLock;
 use std::{io, ops, str};
 
 use regex::Regex;
-use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::DenseBitSet;
 use rustc_middle::mir::{
-    self, BasicBlock, Body, Location, create_dump_file, dump_enabled, graphviz_safe_def_name,
-    traversal,
+    self, BasicBlock, Body, Location, MirDumper, graphviz_safe_def_name, traversal,
 };
 use rustc_middle::ty::TyCtxt;
 use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_span::def_id::DefId;
 use rustc_span::{Symbol, sym};
 use tracing::debug;
 use {rustc_ast as ast, rustc_graphviz as dot};
@@ -61,11 +60,13 @@ where
                 fs::File::create_buffered(&path)?
             }
 
-            None if dump_enabled(tcx, A::NAME, def_id) => {
-                create_dump_file(tcx, "dot", false, A::NAME, &pass_name.unwrap_or("-----"), body)?
+            None => {
+                let Some(dumper) = MirDumper::new(tcx, A::NAME, body) else {
+                    return Ok(());
+                };
+                let disambiguator = &pass_name.unwrap_or("-----");
+                dumper.set_disambiguator(disambiguator).create_dump_file("dot", body)?
             }
-
-            _ => return Ok(()),
         }
     };
     let mut file = match file {
diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
index 9abb8343432..a4e4e30a8bb 100644
--- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
@@ -91,7 +91,6 @@ where
             | Rvalue::Use(..)
             | Rvalue::ThreadLocalRef(..)
             | Rvalue::Repeat(..)
-            | Rvalue::Len(..)
             | Rvalue::BinaryOp(..)
             | Rvalue::NullaryOp(..)
             | Rvalue::UnaryOp(..)
diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
index 6ec1b03a34e..5eba474a60c 100644
--- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
@@ -92,7 +92,7 @@ impl<'tcx> Visitor<'tcx> for TransferFunction<'_> {
         }
 
         match DefUse::for_place(*place, context) {
-            Some(DefUse::Def) => {
+            DefUse::Def => {
                 if let PlaceContext::MutatingUse(
                     MutatingUseContext::Call | MutatingUseContext::AsmOutput,
                 ) = context
@@ -105,8 +105,8 @@ impl<'tcx> Visitor<'tcx> for TransferFunction<'_> {
                     self.0.kill(place.local);
                 }
             }
-            Some(DefUse::Use) => self.0.gen_(place.local),
-            None => {}
+            DefUse::Use => self.0.gen_(place.local),
+            DefUse::PartialWrite | DefUse::NonUse => {}
         }
 
         self.visit_projection(place.as_ref(), context, location);
@@ -131,23 +131,29 @@ impl<'tcx> Visitor<'tcx> for YieldResumeEffect<'_> {
 }
 
 #[derive(Eq, PartialEq, Clone)]
-enum DefUse {
+pub enum DefUse {
+    /// Full write to the local.
     Def,
+    /// Read of any part of the local.
     Use,
+    /// Partial write to the local.
+    PartialWrite,
+    /// Non-use, like debuginfo.
+    NonUse,
 }
 
 impl DefUse {
     fn apply(state: &mut DenseBitSet<Local>, place: Place<'_>, context: PlaceContext) {
         match DefUse::for_place(place, context) {
-            Some(DefUse::Def) => state.kill(place.local),
-            Some(DefUse::Use) => state.gen_(place.local),
-            None => {}
+            DefUse::Def => state.kill(place.local),
+            DefUse::Use => state.gen_(place.local),
+            DefUse::PartialWrite | DefUse::NonUse => {}
         }
     }
 
-    fn for_place(place: Place<'_>, context: PlaceContext) -> Option<DefUse> {
+    pub fn for_place(place: Place<'_>, context: PlaceContext) -> DefUse {
         match context {
-            PlaceContext::NonUse(_) => None,
+            PlaceContext::NonUse(_) => DefUse::NonUse,
 
             PlaceContext::MutatingUse(
                 MutatingUseContext::Call
@@ -156,21 +162,20 @@ impl DefUse {
                 | MutatingUseContext::Store
                 | MutatingUseContext::Deinit,
             ) => {
+                // Treat derefs as a use of the base local. `*p = 4` is not a def of `p` but a use.
                 if place.is_indirect() {
-                    // Treat derefs as a use of the base local. `*p = 4` is not a def of `p` but a
-                    // use.
-                    Some(DefUse::Use)
+                    DefUse::Use
                 } else if place.projection.is_empty() {
-                    Some(DefUse::Def)
+                    DefUse::Def
                 } else {
-                    None
+                    DefUse::PartialWrite
                 }
             }
 
             // Setting the discriminant is not a use because it does no reading, but it is also not
             // a def because it does not overwrite the whole place
             PlaceContext::MutatingUse(MutatingUseContext::SetDiscriminant) => {
-                place.is_indirect().then_some(DefUse::Use)
+                if place.is_indirect() { DefUse::Use } else { DefUse::PartialWrite }
             }
 
             // All other contexts are uses...
@@ -188,7 +193,7 @@ impl DefUse {
                 | NonMutatingUseContext::PlaceMention
                 | NonMutatingUseContext::FakeBorrow
                 | NonMutatingUseContext::SharedBorrow,
-            ) => Some(DefUse::Use),
+            ) => DefUse::Use,
 
             PlaceContext::MutatingUse(MutatingUseContext::Projection)
             | PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => {
diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs
index 3f29b819a6d..6d573e1c00e 100644
--- a/compiler/rustc_mir_dataflow/src/impls/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs
@@ -9,7 +9,8 @@ pub use self::initialized::{
     MaybeUninitializedPlaces, MaybeUninitializedPlacesDomain,
 };
 pub use self::liveness::{
-    MaybeLiveLocals, MaybeTransitiveLiveLocals, TransferFunction as LivenessTransferFunction,
+    DefUse, MaybeLiveLocals, MaybeTransitiveLiveLocals,
+    TransferFunction as LivenessTransferFunction,
 };
 pub use self::storage_liveness::{
     MaybeRequiresStorage, MaybeStorageDead, MaybeStorageLive, always_storage_live_locals,
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
deleted file mode 100644
index d056ad3d4b4..00000000000
--- a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-//! The move-analysis portion of borrowck needs to work in an abstract
-//! domain of lifted `Place`s. Most of the `Place` variants fall into a
-//! one-to-one mapping between the concrete and abstract (e.g., a
-//! field-deref on a local variable, `x.field`, has the same meaning
-//! in both domains). Indexed projections are the exception: `a[x]`
-//! needs to be treated as mapping to the same move path as `a[y]` as
-//! well as `a[13]`, etc. So we map these `x`/`y` values to `()`.
-//!
-//! (In theory, the analysis could be extended to work with sets of
-//! paths, so that `a[0]` and `a[13]` could be kept distinct, while
-//! `a[x]` would still overlap them both. But that is not this
-//! representation does today.)
-
-use rustc_middle::mir::{PlaceElem, ProjectionElem, ProjectionKind};
-
-pub(crate) trait Lift {
-    fn lift(&self) -> ProjectionKind;
-}
-
-impl<'tcx> Lift for PlaceElem<'tcx> {
-    fn lift(&self) -> ProjectionKind {
-        match *self {
-            ProjectionElem::Deref => ProjectionElem::Deref,
-            ProjectionElem::Field(f, _ty) => ProjectionElem::Field(f, ()),
-            ProjectionElem::OpaqueCast(_ty) => ProjectionElem::OpaqueCast(()),
-            ProjectionElem::Index(_i) => ProjectionElem::Index(()),
-            ProjectionElem::Subslice { from, to, from_end } => {
-                ProjectionElem::Subslice { from, to, from_end }
-            }
-            ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
-                ProjectionElem::ConstantIndex { offset, min_length, from_end }
-            }
-            ProjectionElem::Downcast(a, u) => ProjectionElem::Downcast(a, u),
-            ProjectionElem::Subtype(_ty) => ProjectionElem::Subtype(()),
-            ProjectionElem::UnwrapUnsafeBinder(_ty) => ProjectionElem::UnwrapUnsafeBinder(()),
-        }
-    }
-}
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 8bbc89fdcec..72d4cd72c2b 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -7,7 +7,6 @@ use rustc_middle::{bug, span_bug};
 use smallvec::{SmallVec, smallvec};
 use tracing::debug;
 
-use super::abs_domain::Lift;
 use super::{
     Init, InitIndex, InitKind, InitLocation, LocationMap, LookupResult, MoveData, MoveOut,
     MoveOutIndex, MovePath, MovePathIndex, MovePathLookup,
@@ -153,7 +152,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
                     | ty::Slice(_)
                     | ty::FnDef(_, _)
                     | ty::FnPtr(..)
-                    | ty::Dynamic(_, _, _)
+                    | ty::Dynamic(_, _)
                     | ty::Closure(..)
                     | ty::CoroutineClosure(..)
                     | ty::Coroutine(_, _)
@@ -197,7 +196,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
                     | ty::Ref(_, _, _)
                     | ty::FnDef(_, _)
                     | ty::FnPtr(..)
-                    | ty::Dynamic(_, _, _)
+                    | ty::Dynamic(_, _)
                     | ty::CoroutineWitness(..)
                     | ty::Never
                     | ty::UnsafeBinder(_)
@@ -241,7 +240,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
             if union_path.is_none() {
                 // inlined from add_move_path because of a borrowck conflict with the iterator
                 base =
-                    *data.rev_lookup.projections.entry((base, elem.lift())).or_insert_with(|| {
+                    *data.rev_lookup.projections.entry((base, elem.kind())).or_insert_with(|| {
                         new_move_path(
                             &mut data.move_paths,
                             &mut data.path_map,
@@ -272,7 +271,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
             tcx,
             ..
         } = self;
-        *rev_lookup.projections.entry((base, elem.lift())).or_insert_with(move || {
+        *rev_lookup.projections.entry((base, elem.kind())).or_insert_with(move || {
             new_move_path(move_paths, path_map, init_path_map, Some(base), mk_place(*tcx))
         })
     }
@@ -414,7 +413,6 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
             Rvalue::Ref(..)
             | Rvalue::RawPtr(..)
             | Rvalue::Discriminant(..)
-            | Rvalue::Len(..)
             | Rvalue::NullaryOp(
                 NullOp::SizeOf
                 | NullOp::AlignOf
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
index 18985ba0da2..466416d63f5 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
@@ -1,3 +1,15 @@
+//! The move-analysis portion of borrowck needs to work in an abstract domain of lifted `Place`s.
+//! Most of the `Place` variants fall into a one-to-one mapping between the concrete and abstract
+//! (e.g., a field projection on a local variable, `x.field`, has the same meaning in both
+//! domains). In other words, all field projections for the same field on the same local do not
+//! have meaningfully different types if ever. Indexed projections are the exception: `a[x]` needs
+//! to be treated as mapping to the same move path as `a[y]` as well as `a[13]`, etc. So we map
+//! these `x`/`y` values to `()`.
+//!
+//! (In theory, the analysis could be extended to work with sets of paths, so that `a[0]` and
+//! `a[13]` could be kept distinct, while `a[x]` would still overlap them both. But that is not
+//! what this representation does today.)
+
 use std::fmt;
 use std::ops::{Index, IndexMut};
 
@@ -8,11 +20,8 @@ use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_span::Span;
 use smallvec::SmallVec;
 
-use self::abs_domain::Lift;
 use crate::un_derefer::UnDerefer;
 
-mod abs_domain;
-
 rustc_index::newtype_index! {
     #[orderable]
     #[debug_format = "mp{}"]
@@ -324,7 +333,7 @@ impl<'tcx> MovePathLookup<'tcx> {
         };
 
         for (_, elem) in self.un_derefer.iter_projections(place) {
-            if let Some(&subpath) = self.projections.get(&(result, elem.lift())) {
+            if let Some(&subpath) = self.projections.get(&(result, elem.kind())) {
                 result = subpath;
             } else {
                 return LookupResult::Parent(Some(result));
diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs
index 70d1a34b5fb..e3d1e04a319 100644
--- a/compiler/rustc_mir_dataflow/src/points.rs
+++ b/compiler/rustc_mir_dataflow/src/points.rs
@@ -1,9 +1,5 @@
-use rustc_index::bit_set::DenseBitSet;
-use rustc_index::interval::SparseIntervalMatrix;
 use rustc_index::{Idx, IndexVec};
-use rustc_middle::mir::{self, BasicBlock, Body, Location};
-
-use crate::framework::{Analysis, Results, ResultsVisitor, visit_results};
+use rustc_middle::mir::{BasicBlock, Body, Location};
 
 /// Maps between a `Location` and a `PointIndex` (and vice versa).
 pub struct DenseLocationMap {
@@ -93,65 +89,3 @@ rustc_index::newtype_index! {
     #[debug_format = "PointIndex({})"]
     pub struct PointIndex {}
 }
-
-/// Add points depending on the result of the given dataflow analysis.
-pub fn save_as_intervals<'tcx, N, A>(
-    elements: &DenseLocationMap,
-    body: &mir::Body<'tcx>,
-    mut analysis: A,
-    results: Results<A::Domain>,
-) -> SparseIntervalMatrix<N, PointIndex>
-where
-    N: Idx,
-    A: Analysis<'tcx, Domain = DenseBitSet<N>>,
-{
-    let values = SparseIntervalMatrix::new(elements.num_points());
-    let mut visitor = Visitor { elements, values };
-    visit_results(
-        body,
-        body.basic_blocks.reverse_postorder().iter().copied(),
-        &mut analysis,
-        &results,
-        &mut visitor,
-    );
-    visitor.values
-}
-
-struct Visitor<'a, N: Idx> {
-    elements: &'a DenseLocationMap,
-    values: SparseIntervalMatrix<N, PointIndex>,
-}
-
-impl<'tcx, A, N> ResultsVisitor<'tcx, A> for Visitor<'_, N>
-where
-    A: Analysis<'tcx, Domain = DenseBitSet<N>>,
-    N: Idx,
-{
-    fn visit_after_primary_statement_effect<'mir>(
-        &mut self,
-        _analysis: &mut A,
-        state: &A::Domain,
-        _statement: &'mir mir::Statement<'tcx>,
-        location: Location,
-    ) {
-        let point = self.elements.point_from_location(location);
-        // Use internal iterator manually as it is much more efficient.
-        state.iter().for_each(|node| {
-            self.values.insert(node, point);
-        });
-    }
-
-    fn visit_after_primary_terminator_effect<'mir>(
-        &mut self,
-        _analysis: &mut A,
-        state: &A::Domain,
-        _terminator: &'mir mir::Terminator<'tcx>,
-        location: Location,
-    ) {
-        let point = self.elements.point_from_location(location);
-        // Use internal iterator manually as it is much more efficient.
-        state.iter().for_each(|node| {
-            self.values.insert(node, point);
-        });
-    }
-}
diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
index 1682f332857..a899ec1fa88 100644
--- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs
+++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
@@ -1,7 +1,7 @@
 use rustc_ast::MetaItem;
-use rustc_hir::def_id::DefId;
 use rustc_middle::mir::{self, Body, Local, Location};
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::def_id::DefId;
 use rustc_span::{Span, Symbol, sym};
 use tracing::{debug, info};
 
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 005e7973130..bf5ec8f459e 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -6,7 +6,7 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet, StdEntry};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_index::IndexVec;
 use rustc_index::bit_set::DenseBitSet;
-use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
+use rustc_middle::mir::visit::{PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use tracing::debug;
@@ -891,7 +891,7 @@ pub fn iter_fields<'tcx>(
                     let field_ty = f_def.ty(tcx, args);
                     let field_ty = tcx
                         .try_normalize_erasing_regions(typing_env, field_ty)
-                        .unwrap_or_else(|_| tcx.erase_regions(field_ty));
+                        .unwrap_or_else(|_| tcx.erase_and_anonymize_regions(field_ty));
                     f(variant, f_index.into(), field_ty);
                 }
             }
@@ -917,12 +917,7 @@ pub fn excluded_locals(body: &Body<'_>) -> DenseBitSet<Local> {
 
     impl<'tcx> Visitor<'tcx> for Collector {
         fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
-            if (context.is_borrow()
-                || context.is_address_of()
-                || context.is_drop()
-                || context == PlaceContext::MutatingUse(MutatingUseContext::AsmOutput))
-                && !place.is_indirect()
-            {
+            if context.may_observe_address() && !place.is_indirect() {
                 // A pointer to a place could be used to access other places with the same local,
                 // hence we have to exclude the local completely.
                 self.result.insert(place.local);