about summary refs log tree commit diff
path: root/compiler/rustc_mir_transform/src
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2025-09-23 09:28:24 +0200
committerRalf Jung <post@ralfj.de>2025-09-23 09:28:24 +0200
commit0cd72a2f8d90672d0c7ce38a4e0d6ac3975aafbb (patch)
tree406fd3b8a96508cae5b1ac33ccc57ca641f4cc85 /compiler/rustc_mir_transform/src
parent3c8d8da693eb5d63099eef5cf4a73106a3a2ba25 (diff)
parentf6092f224d2b1774b31033f12d0bee626943b02f (diff)
downloadrust-0cd72a2f8d90672d0c7ce38a4e0d6ac3975aafbb.tar.gz
rust-0cd72a2f8d90672d0c7ce38a4e0d6ac3975aafbb.zip
Merge ref 'f6092f224d2b' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: f6092f224d2b1774b31033f12d0bee626943b02f
Filtered ref: f843cd4f29bdcd8d474dbb9e5e4365eb7f263ec6

This merge was created using https://github.com/rust-lang/josh-sync.
Diffstat (limited to 'compiler/rustc_mir_transform/src')
-rw-r--r--compiler/rustc_mir_transform/src/impossible_predicates.rs33
-rw-r--r--compiler/rustc_mir_transform/src/ref_prop.rs33
2 files changed, 33 insertions, 33 deletions
diff --git a/compiler/rustc_mir_transform/src/impossible_predicates.rs b/compiler/rustc_mir_transform/src/impossible_predicates.rs
index b03518de00a..883ee32bdec 100644
--- a/compiler/rustc_mir_transform/src/impossible_predicates.rs
+++ b/compiler/rustc_mir_transform/src/impossible_predicates.rs
@@ -28,6 +28,7 @@
 
 use rustc_middle::mir::{Body, START_BLOCK, TerminatorKind};
 use rustc_middle::ty::{TyCtxt, TypeFlags, TypeVisitableExt};
+use rustc_span::def_id::DefId;
 use rustc_trait_selection::traits;
 use tracing::trace;
 
@@ -35,23 +36,29 @@ use crate::pass_manager::MirPass;
 
 pub(crate) struct ImpossiblePredicates;
 
+fn has_impossible_predicates(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+    let predicates = tcx.predicates_of(def_id).instantiate_identity(tcx);
+    tracing::trace!(?predicates);
+    let predicates = predicates.predicates.into_iter().filter(|p| {
+        !p.has_type_flags(
+            // Only consider global clauses to simplify.
+            TypeFlags::HAS_FREE_LOCAL_NAMES
+                // Clauses that refer to unevaluated constants as they cause cycles.
+                | TypeFlags::HAS_CT_PROJECTION,
+        )
+    });
+    let predicates: Vec<_> = traits::elaborate(tcx, predicates).collect();
+    tracing::trace!(?predicates);
+    predicates.references_error() || traits::impossible_predicates(tcx, predicates)
+}
+
 impl<'tcx> MirPass<'tcx> for ImpossiblePredicates {
     #[tracing::instrument(level = "trace", skip(self, tcx, body))]
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         tracing::trace!(def_id = ?body.source.def_id());
-        let predicates = tcx.predicates_of(body.source.def_id()).instantiate_identity(tcx);
-        tracing::trace!(?predicates);
-        let predicates = predicates.predicates.into_iter().filter(|p| {
-            !p.has_type_flags(
-                // Only consider global clauses to simplify.
-                TypeFlags::HAS_FREE_LOCAL_NAMES
-                // Clauses that refer to unevaluated constants as they cause cycles.
-                | TypeFlags::HAS_CT_PROJECTION,
-            )
-        });
-        let predicates: Vec<_> = traits::elaborate(tcx, predicates).collect();
-        tracing::trace!(?predicates);
-        if predicates.references_error() || traits::impossible_predicates(tcx, predicates) {
+        let impossible = body.tainted_by_errors.is_some()
+            || has_impossible_predicates(tcx, body.source.def_id());
+        if impossible {
             trace!("found unsatisfiable predicates");
             // Clear the body to only contain a single `unreachable` statement.
             let bbs = body.basic_blocks.as_mut();
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index 6f61215cee2..b9d6e74ecae 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -195,10 +195,10 @@ fn compute_replacement<'tcx>(
     //   including DEF. This violates the DEF dominates USE condition, and so is impossible.
     let is_constant_place = |place: Place<'_>| {
         // We only allow `Deref` as the first projection, to avoid surprises.
-        if place.projection.first() == Some(&PlaceElem::Deref) {
+        if let Some((&PlaceElem::Deref, rest)) = place.projection.split_first() {
             // `place == (*some_local).xxx`, it is constant only if `some_local` is constant.
             // We approximate constness using SSAness.
-            ssa.is_ssa(place.local) && place.projection[1..].iter().all(PlaceElem::is_stable_offset)
+            ssa.is_ssa(place.local) && rest.iter().all(PlaceElem::is_stable_offset)
         } else {
             storage_live.has_single_storage(place.local)
                 && place.projection[..].iter().all(PlaceElem::is_stable_offset)
@@ -206,7 +206,7 @@ fn compute_replacement<'tcx>(
     };
 
     let mut can_perform_opt = |target: Place<'tcx>, loc: Location| {
-        if target.projection.first() == Some(&PlaceElem::Deref) {
+        if target.is_indirect_first_projection() {
             // We are creating a reborrow. As `place.local` is a reference, removing the storage
             // statements should not make it much harder for LLVM to optimize.
             storage_to_remove.insert(target.local);
@@ -266,7 +266,7 @@ fn compute_replacement<'tcx>(
             Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => {
                 let mut place = *place;
                 // Try to see through `place` in order to collapse reborrow chains.
-                if place.projection.first() == Some(&PlaceElem::Deref)
+                if let Some((&PlaceElem::Deref, rest)) = place.projection.split_first()
                     && let Value::Pointer(target, inner_needs_unique) = targets[place.local]
                     // Only see through immutable reference and pointers, as we do not know yet if
                     // mutable references are fully replaced.
@@ -274,7 +274,7 @@ fn compute_replacement<'tcx>(
                     // Only collapse chain if the pointee is definitely live.
                     && can_perform_opt(target, location)
                 {
-                    place = target.project_deeper(&place.projection[1..], tcx);
+                    place = target.project_deeper(rest, tcx);
                 }
                 assert_ne!(place.local, local);
                 if is_constant_place(place) {
@@ -323,7 +323,7 @@ fn compute_replacement<'tcx>(
                 return;
             }
 
-            if place.projection.first() != Some(&PlaceElem::Deref) {
+            if !place.is_indirect_first_projection() {
                 // This is not a dereference, nothing to do.
                 return;
             }
@@ -392,20 +392,15 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
     }
 
     fn visit_var_debug_info(&mut self, debuginfo: &mut VarDebugInfo<'tcx>) {
-        // If the debuginfo is a pointer to another place:
-        // - if it's a reborrow, see through it;
-        // - if it's a direct borrow, increase `debuginfo.references`.
+        // If the debuginfo is a pointer to another place
+        // and it's a reborrow: see through it
         while let VarDebugInfoContents::Place(ref mut place) = debuginfo.value
             && place.projection.is_empty()
             && let Value::Pointer(target, _) = self.targets[place.local]
-            && target.projection.iter().all(|p| p.can_use_in_debuginfo())
+            && let &[PlaceElem::Deref] = &target.projection[..]
         {
-            if let Some((&PlaceElem::Deref, rest)) = target.projection.split_last() {
-                *place = Place::from(target.local).project_deeper(rest, self.tcx);
-                self.any_replacement = true;
-            } else {
-                break;
-            }
+            *place = Place::from(target.local);
+            self.any_replacement = true;
         }
 
         // Simplify eventual projections left inside `debuginfo`.
@@ -414,9 +409,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
         loop {
-            if place.projection.first() != Some(&PlaceElem::Deref) {
-                return;
-            }
+            let Some((&PlaceElem::Deref, rest)) = place.projection.split_first() else { return };
 
             let Value::Pointer(target, _) = self.targets[place.local] else { return };
 
@@ -432,7 +425,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
                 return;
             }
 
-            *place = target.project_deeper(&place.projection[1..], self.tcx);
+            *place = target.project_deeper(rest, self.tcx);
             self.any_replacement = true;
         }
     }