about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCelina G. Val <celinval@amazon.com>2024-01-11 17:15:21 -0800
committerCelina G. Val <celinval@amazon.com>2024-01-11 17:15:21 -0800
commitefab0dcb2582fced369a3cc991660760f49a4712 (patch)
treec932babab437643fde3a8bd37986f81fde090acf
parent090d5eac722000906cc00d991f2bf052b0e388c3 (diff)
downloadrust-efab0dcb2582fced369a3cc991660760f49a4712.tar.gz
rust-efab0dcb2582fced369a3cc991660760f49a4712.zip
Add more information to `visit_projection_elem`
Without the starting place, it's hard to retrieve any useful information
from visiting a projection.
-rw-r--r--compiler/stable_mir/src/mir/body.rs33
-rw-r--r--compiler/stable_mir/src/mir/visit.rs24
2 files changed, 38 insertions, 19 deletions
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index 72227a04bf1..38877f7a77f 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -963,7 +963,7 @@ pub enum PointerCoercion {
     /// Go from a safe fn pointer to an unsafe fn pointer.
     UnsafeFnPointer,
 
-    /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
+    /// Go from a non-capturing closure to a fn pointer or an unsafe fn pointer.
     /// It cannot convert a closure that requires unsafe.
     ClosureFnPointer(Safety),
 
@@ -1037,21 +1037,24 @@ impl Place {
     /// locals from the function body where this place originates from.
     pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> {
         let start_ty = locals[self.local].ty;
-        self.projection.iter().fold(Ok(start_ty), |place_ty, elem| {
-            let ty = place_ty?;
-            match elem {
-                ProjectionElem::Deref => Self::deref_ty(ty),
-                ProjectionElem::Field(_idx, fty) => Ok(*fty),
-                ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
-                    Self::index_ty(ty)
-                }
-                ProjectionElem::Subslice { from, to, from_end } => {
-                    Self::subslice_ty(ty, from, to, from_end)
-                }
-                ProjectionElem::Downcast(_) => Ok(ty),
-                ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) => Ok(*ty),
+        self.projection.iter().fold(Ok(start_ty), |place_ty, elem| elem.ty(place_ty?))
+    }
+}
+
+impl ProjectionElem {
+    /// Get the expected type after applying this projection to a given place type.
+    pub fn ty(&self, place_ty: Ty) -> Result<Ty, Error> {
+        let ty = place_ty;
+        match &self {
+            ProjectionElem::Deref => Self::deref_ty(ty),
+            ProjectionElem::Field(_idx, fty) => Ok(*fty),
+            ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => Self::index_ty(ty),
+            ProjectionElem::Subslice { from, to, from_end } => {
+                Self::subslice_ty(ty, from, to, from_end)
             }
-        })
+            ProjectionElem::Downcast(_) => Ok(ty),
+            ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) => Ok(*ty),
+        }
     }
 
     fn index_ty(ty: Ty) -> Result<Ty, Error> {
diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs
index ab57ff0f8f5..24296e9e877 100644
--- a/compiler/stable_mir/src/mir/visit.rs
+++ b/compiler/stable_mir/src/mir/visit.rs
@@ -37,7 +37,7 @@
 
 use crate::mir::*;
 use crate::ty::{Const, GenericArgs, Region, Ty};
-use crate::{Opaque, Span};
+use crate::{Error, Opaque, Span};
 
 pub trait MirVisitor {
     fn visit_body(&mut self, body: &Body) {
@@ -76,12 +76,14 @@ pub trait MirVisitor {
         self.super_place(place, ptx, location)
     }
 
-    fn visit_projection_elem(
+    fn visit_projection_elem<'a>(
         &mut self,
+        place_ref: PlaceRef<'a>,
         elem: &ProjectionElem,
         ptx: PlaceContext,
         location: Location,
     ) {
+        let _ = place_ref;
         self.super_projection_elem(elem, ptx, location);
     }
 
@@ -284,8 +286,9 @@ pub trait MirVisitor {
         let _ = ptx;
         self.visit_local(&place.local, ptx, location);
 
-        for elem in &place.projection {
-            self.visit_projection_elem(elem, ptx, location);
+        for (idx, elem) in place.projection.iter().enumerate() {
+            let place_ref = PlaceRef { local: place.local, projection: &place.projection[..idx] };
+            self.visit_projection_elem(place_ref, elem, ptx, location);
         }
     }
 
@@ -453,6 +456,19 @@ impl Location {
     }
 }
 
+/// Reference to a place used to represent a partial projection.
+pub struct PlaceRef<'a> {
+    pub local: Local,
+    pub projection: &'a [ProjectionElem],
+}
+
+impl<'a> PlaceRef<'a> {
+    /// Get the type of this place.
+    pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> {
+        self.projection.iter().fold(Ok(locals[self.local].ty), |place_ty, elem| elem.ty(place_ty?))
+    }
+}
+
 /// Information about a place's usage.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct PlaceContext {