@@ -1718,11 +1718,11 @@ impl<'tcx> Debug for Statement<'tcx> {
17181718#[ derive(
17191719 Clone , PartialEq , Eq , PartialOrd , Ord , Hash , RustcEncodable , RustcDecodable , HashStable ,
17201720) ]
1721- pub enum Place < ' tcx > {
1722- Base ( PlaceBase < ' tcx > ) ,
1721+ pub struct Place < ' tcx > {
1722+ pub base : PlaceBase < ' tcx > ,
17231723
17241724 /// projection out of a place (access a field, deref a pointer, etc)
1725- Projection ( Box < Projection < ' tcx > > ) ,
1725+ pub projection : Option < Box < Projection < ' tcx > > > ,
17261726}
17271727
17281728#[ derive(
@@ -1761,7 +1761,7 @@ impl_stable_hash_for!(struct Static<'tcx> {
17611761 Clone , Debug , PartialEq , Eq , PartialOrd , Ord , Hash , RustcEncodable , RustcDecodable , HashStable ,
17621762) ]
17631763pub struct Projection < ' tcx > {
1764- pub base : Place < ' tcx > ,
1764+ pub base : Option < Box < Projection < ' tcx > > > ,
17651765 pub elem : PlaceElem < ' tcx > ,
17661766}
17671767
@@ -1826,8 +1826,17 @@ newtype_index! {
18261826 }
18271827}
18281828
1829+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
1830+ pub struct PlaceRef < ' a , ' tcx > {
1831+ pub base : & ' a PlaceBase < ' tcx > ,
1832+ pub projection : & ' a Option < Box < Projection < ' tcx > > > ,
1833+ }
1834+
18291835impl < ' tcx > Place < ' tcx > {
1830- pub const RETURN_PLACE : Place < ' tcx > = Place :: Base ( PlaceBase :: Local ( RETURN_PLACE ) ) ;
1836+ pub const RETURN_PLACE : Place < ' tcx > = Place {
1837+ base : PlaceBase :: Local ( RETURN_PLACE ) ,
1838+ projection : None ,
1839+ } ;
18311840
18321841 pub fn field ( self , f : Field , ty : Ty < ' tcx > ) -> Place < ' tcx > {
18331842 self . elem ( ProjectionElem :: Field ( f, ty) )
@@ -1853,7 +1862,10 @@ impl<'tcx> Place<'tcx> {
18531862 }
18541863
18551864 pub fn elem ( self , elem : PlaceElem < ' tcx > ) -> Place < ' tcx > {
1856- Place :: Projection ( Box :: new ( Projection { base : self , elem } ) )
1865+ Place {
1866+ base : self . base ,
1867+ projection : Some ( Box :: new ( Projection { base : self . projection , elem } ) ) ,
1868+ }
18571869 }
18581870
18591871 /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
@@ -1862,54 +1874,77 @@ impl<'tcx> Place<'tcx> {
18621874 // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
18631875 pub fn local_or_deref_local ( & self ) -> Option < Local > {
18641876 match self {
1865- Place :: Base ( PlaceBase :: Local ( local) )
1866- | Place :: Projection ( box Projection {
1867- base : Place :: Base ( PlaceBase :: Local ( local) ) ,
1868- elem : ProjectionElem :: Deref ,
1869- } ) => Some ( * local) ,
1877+ Place {
1878+ base : PlaceBase :: Local ( local) ,
1879+ projection : None ,
1880+ } |
1881+ Place {
1882+ base : PlaceBase :: Local ( local) ,
1883+ projection : Some ( box Projection {
1884+ base : None ,
1885+ elem : ProjectionElem :: Deref ,
1886+ } ) ,
1887+ } => Some ( * local) ,
18701888 _ => None ,
18711889 }
18721890 }
18731891
1874- /// Finds the innermost `Local` from this `Place`.
1875- pub fn base_local ( & self ) -> Option < Local > {
1876- let mut place = self ;
1877- loop {
1878- match place {
1879- Place :: Projection ( proj) => place = & proj. base ,
1880- Place :: Base ( PlaceBase :: Static ( _) ) => return None ,
1881- Place :: Base ( PlaceBase :: Local ( local) ) => return Some ( * local) ,
1882- }
1883- }
1884- }
1885-
18861892 /// Recursively "iterates" over place components, generating a `PlaceBase` and
18871893 /// `Projections` list and invoking `op` with a `ProjectionsIter`.
18881894 pub fn iterate < R > (
18891895 & self ,
18901896 op : impl FnOnce ( & PlaceBase < ' tcx > , ProjectionsIter < ' _ , ' tcx > ) -> R ,
18911897 ) -> R {
1892- self . iterate2 ( & Projections :: Empty , op)
1898+ Place :: iterate_over ( & self . base , & self . projection , op)
18931899 }
18941900
1895- fn iterate2 < R > (
1896- & self ,
1897- next : & Projections < ' _ , ' tcx > ,
1901+ pub fn iterate_over < R > (
1902+ place_base : & PlaceBase < ' tcx > ,
1903+ place_projection : & Option < Box < Projection < ' tcx > > > ,
18981904 op : impl FnOnce ( & PlaceBase < ' tcx > , ProjectionsIter < ' _ , ' tcx > ) -> R ,
18991905 ) -> R {
1900- match self {
1901- Place :: Projection ( interior) => {
1902- interior. base . iterate2 ( & Projections :: List { projection : interior, next } , op)
1906+ fn iterate_over2 < ' tcx , R > (
1907+ place_base : & PlaceBase < ' tcx > ,
1908+ place_projection : & Option < Box < Projection < ' tcx > > > ,
1909+ next : & Projections < ' _ , ' tcx > ,
1910+ op : impl FnOnce ( & PlaceBase < ' tcx > , ProjectionsIter < ' _ , ' tcx > ) -> R ,
1911+ ) -> R {
1912+ match place_projection {
1913+ None => {
1914+ op ( place_base, next. iter ( ) )
1915+ }
1916+
1917+ Some ( interior) => {
1918+ iterate_over2 (
1919+ place_base,
1920+ & interior. base ,
1921+ & Projections :: List {
1922+ projection : interior,
1923+ next,
1924+ } ,
1925+ op,
1926+ )
1927+ }
19031928 }
1929+ }
19041930
1905- Place :: Base ( base) => op ( base, next. iter ( ) ) ,
1931+ iterate_over2 ( place_base, place_projection, & Projections :: Empty , op)
1932+ }
1933+
1934+ pub fn as_place_ref ( & self ) -> PlaceRef < ' _ , ' tcx > {
1935+ PlaceRef {
1936+ base : & self . base ,
1937+ projection : & self . projection ,
19061938 }
19071939 }
19081940}
19091941
19101942impl From < Local > for Place < ' _ > {
19111943 fn from ( local : Local ) -> Self {
1912- Place :: Base ( local. into ( ) )
1944+ Place {
1945+ base : local. into ( ) ,
1946+ projection : None ,
1947+ }
19131948 }
19141949}
19151950
@@ -1919,6 +1954,36 @@ impl From<Local> for PlaceBase<'_> {
19191954 }
19201955}
19211956
1957+ impl < ' a , ' tcx > PlaceRef < ' a , ' tcx > {
1958+ pub fn iterate < R > (
1959+ & self ,
1960+ op : impl FnOnce ( & PlaceBase < ' tcx > , ProjectionsIter < ' _ , ' tcx > ) -> R ,
1961+ ) -> R {
1962+ Place :: iterate_over ( self . base , self . projection , op)
1963+ }
1964+
1965+ /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
1966+ /// a single deref of a local.
1967+ //
1968+ // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
1969+ pub fn local_or_deref_local ( & self ) -> Option < Local > {
1970+ match self {
1971+ PlaceRef {
1972+ base : PlaceBase :: Local ( local) ,
1973+ projection : None ,
1974+ } |
1975+ PlaceRef {
1976+ base : PlaceBase :: Local ( local) ,
1977+ projection : Some ( box Projection {
1978+ base : None ,
1979+ elem : ProjectionElem :: Deref ,
1980+ } ) ,
1981+ } => Some ( * local) ,
1982+ _ => None ,
1983+ }
1984+ }
1985+ }
1986+
19221987/// A linked list of projections running up the stack; begins with the
19231988/// innermost projection and extends to the outermost (e.g., `a.b.c`
19241989/// would have the place `b` with a "next" pointer to `b.c`).
@@ -3155,18 +3220,14 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
31553220
31563221impl < ' tcx > TypeFoldable < ' tcx > for Place < ' tcx > {
31573222 fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
3158- match self {
3159- & Place :: Projection ( ref p ) => Place :: Projection ( p . fold_with ( folder ) ) ,
3160- _ => self . clone ( ) ,
3223+ Place {
3224+ base : self . base . clone ( ) ,
3225+ projection : self . projection . fold_with ( folder ) ,
31613226 }
31623227 }
31633228
31643229 fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
3165- if let & Place :: Projection ( ref p) = self {
3166- p. visit_with ( visitor)
3167- } else {
3168- false
3169- }
3230+ self . projection . visit_with ( visitor)
31703231 }
31713232}
31723233
0 commit comments