diff options
| author | Dylan MacKenzie <ecstaticmorse@gmail.com> | 2019-08-29 13:22:16 -0700 |
|---|---|---|
| committer | Dylan MacKenzie <ecstaticmorse@gmail.com> | 2019-08-29 13:40:28 -0700 |
| commit | 86487329bb385f74bed67718f2358436ddca1aa4 (patch) | |
| tree | 7c12cc5ecf7a9865e35fa65a7bf7a89be2264edf /src/librustc | |
| parent | 555d7a2fd6165b614cfc01136d8e3f5c465a1582 (diff) | |
| download | rust-86487329bb385f74bed67718f2358436ddca1aa4.tar.gz rust-86487329bb385f74bed67718f2358436ddca1aa4.zip | |
Add `Place::is_indirect`
This returns whether a `Place` references the same region of memory as its base, or equivalently whether it contains a `Deref` projection. This is helpful for analyses that must track state for locals, since an assignment to `x` or `x.field` is fundamentally different than one to `*x`, which may mutate any memory region.
Diffstat (limited to 'src/librustc')
| -rw-r--r-- | src/librustc/mir/mod.rs | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 858b77af804..a07f12cd9c5 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1801,6 +1801,23 @@ pub enum ProjectionElem<V, T> { Downcast(Option<Symbol>, VariantIdx), } +impl<V, T> ProjectionElem<V, T> { + /// Returns `true` if the target of this projection may refer to a different region of memory + /// than the base. + fn is_indirect(&self) -> bool { + match self { + Self::Deref => true, + + | Self::Field(_, _) + | Self::Index(_) + | Self::ConstantIndex { .. } + | Self::Subslice { .. } + | Self::Downcast(_, _) + => false + } + } +} + /// Alias for projections as they appear in places, where the base is a place /// and the index is a local. pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>; @@ -1862,6 +1879,14 @@ impl<'tcx> Place<'tcx> { } } + /// Returns `true` if this `Place` contains a `Deref` projection. + /// + /// If `Place::is_indirect` returns false, the caller knows that the `Place` refers to the + /// same region of memory as its base. + pub fn is_indirect(&self) -> bool { + self.iterate(|_, mut projections| projections.any(|proj| proj.elem.is_indirect())) + } + /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or /// a single deref of a local. // |
