@@ -1718,11 +1718,11 @@ impl<'tcx> Debug for Statement<'tcx> {
1718
1718
#[ derive(
1719
1719
Clone , PartialEq , Eq , PartialOrd , Ord , Hash , RustcEncodable , RustcDecodable , HashStable ,
1720
1720
) ]
1721
- pub enum Place < ' tcx > {
1722
- Base ( PlaceBase < ' tcx > ) ,
1721
+ pub struct Place < ' tcx > {
1722
+ pub base : PlaceBase < ' tcx > ,
1723
1723
1724
1724
/// projection out of a place (access a field, deref a pointer, etc)
1725
- Projection ( Box < Projection < ' tcx > > ) ,
1725
+ pub projection : Option < Box < Projection < ' tcx > > > ,
1726
1726
}
1727
1727
1728
1728
#[ derive(
@@ -1761,7 +1761,7 @@ impl_stable_hash_for!(struct Static<'tcx> {
1761
1761
Clone , Debug , PartialEq , Eq , PartialOrd , Ord , Hash , RustcEncodable , RustcDecodable , HashStable ,
1762
1762
) ]
1763
1763
pub struct Projection < ' tcx > {
1764
- pub base : Place < ' tcx > ,
1764
+ pub base : Option < Box < Projection < ' tcx > > > ,
1765
1765
pub elem : PlaceElem < ' tcx > ,
1766
1766
}
1767
1767
@@ -1826,8 +1826,17 @@ newtype_index! {
1826
1826
}
1827
1827
}
1828
1828
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
+
1829
1835
impl < ' 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
+ } ;
1831
1840
1832
1841
pub fn field ( self , f : Field , ty : Ty < ' tcx > ) -> Place < ' tcx > {
1833
1842
self . elem ( ProjectionElem :: Field ( f, ty) )
@@ -1853,7 +1862,10 @@ impl<'tcx> Place<'tcx> {
1853
1862
}
1854
1863
1855
1864
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
+ }
1857
1869
}
1858
1870
1859
1871
/// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
@@ -1862,54 +1874,77 @@ impl<'tcx> Place<'tcx> {
1862
1874
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
1863
1875
pub fn local_or_deref_local ( & self ) -> Option < Local > {
1864
1876
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) ,
1870
1888
_ => None ,
1871
1889
}
1872
1890
}
1873
1891
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
-
1886
1892
/// Recursively "iterates" over place components, generating a `PlaceBase` and
1887
1893
/// `Projections` list and invoking `op` with a `ProjectionsIter`.
1888
1894
pub fn iterate < R > (
1889
1895
& self ,
1890
1896
op : impl FnOnce ( & PlaceBase < ' tcx > , ProjectionsIter < ' _ , ' tcx > ) -> R ,
1891
1897
) -> R {
1892
- self . iterate2 ( & Projections :: Empty , op)
1898
+ Place :: iterate_over ( & self . base , & self . projection , op)
1893
1899
}
1894
1900
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 > > > ,
1898
1904
op : impl FnOnce ( & PlaceBase < ' tcx > , ProjectionsIter < ' _ , ' tcx > ) -> R ,
1899
1905
) -> 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
+ }
1903
1928
}
1929
+ }
1904
1930
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 ,
1906
1938
}
1907
1939
}
1908
1940
}
1909
1941
1910
1942
impl From < Local > for Place < ' _ > {
1911
1943
fn from ( local : Local ) -> Self {
1912
- Place :: Base ( local. into ( ) )
1944
+ Place {
1945
+ base : local. into ( ) ,
1946
+ projection : None ,
1947
+ }
1913
1948
}
1914
1949
}
1915
1950
@@ -1919,6 +1954,36 @@ impl From<Local> for PlaceBase<'_> {
1919
1954
}
1920
1955
}
1921
1956
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
+
1922
1987
/// A linked list of projections running up the stack; begins with the
1923
1988
/// innermost projection and extends to the outermost (e.g., `a.b.c`
1924
1989
/// would have the place `b` with a "next" pointer to `b.c`).
@@ -3155,18 +3220,14 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
3155
3220
3156
3221
impl < ' tcx > TypeFoldable < ' tcx > for Place < ' tcx > {
3157
3222
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 ) ,
3161
3226
}
3162
3227
}
3163
3228
3164
3229
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)
3170
3231
}
3171
3232
}
3172
3233
0 commit comments