Skip to content

Commit

Permalink
Add more information to visit_projection_elem
Browse files Browse the repository at this point in the history
Without the starting place, it's hard to retrieve any useful information
from visiting a projection.
  • Loading branch information
celinval committed Jan 12, 2024
1 parent 090d5ea commit efab0dc
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 19 deletions.
33 changes: 18 additions & 15 deletions compiler/stable_mir/src/mir/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),

Expand Down Expand Up @@ -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> {
Expand Down
24 changes: 20 additions & 4 deletions compiler/stable_mir/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit efab0dc

Please sign in to comment.