@@ -12,6 +12,7 @@ use std::iter;
1212use std:: mem;
1313use std:: ops:: Bound ;
1414
15+ use crate :: hir;
1516use crate :: ich:: StableHashingContext ;
1617use rustc_data_structures:: indexed_vec:: { IndexVec , Idx } ;
1718use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher ,
@@ -1518,6 +1519,10 @@ pub trait HasTyCtxt<'tcx>: HasDataLayout {
15181519 fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' a , ' tcx , ' tcx > ;
15191520}
15201521
1522+ pub trait HasParamEnv < ' tcx > {
1523+ fn param_env ( & self ) -> ty:: ParamEnv < ' tcx > ;
1524+ }
1525+
15211526impl < ' a , ' gcx , ' tcx > HasDataLayout for TyCtxt < ' a , ' gcx , ' tcx > {
15221527 fn data_layout ( & self ) -> & TargetDataLayout {
15231528 & self . data_layout
@@ -1530,6 +1535,12 @@ impl<'a, 'gcx, 'tcx> HasTyCtxt<'gcx> for TyCtxt<'a, 'gcx, 'tcx> {
15301535 }
15311536}
15321537
1538+ impl < ' tcx , C > HasParamEnv < ' tcx > for LayoutCx < ' tcx , C > {
1539+ fn param_env ( & self ) -> ty:: ParamEnv < ' tcx > {
1540+ self . param_env
1541+ }
1542+ }
1543+
15331544impl < ' tcx , T : HasDataLayout > HasDataLayout for LayoutCx < ' tcx , T > {
15341545 fn data_layout ( & self ) -> & TargetDataLayout {
15351546 self . tcx . data_layout ( )
@@ -1543,25 +1554,32 @@ impl<'gcx, 'tcx, T: HasTyCtxt<'gcx>> HasTyCtxt<'gcx> for LayoutCx<'tcx, T> {
15431554}
15441555
15451556pub trait MaybeResult < T > {
1546- fn from_ok ( x : T ) -> Self ;
1547- fn map_same < F : FnOnce ( T ) -> T > ( self , f : F ) -> Self ;
1557+ type Error ;
1558+
1559+ fn from ( x : Result < T , Self :: Error > ) -> Self ;
1560+ fn to_result ( self ) -> Result < T , Self :: Error > ;
15481561}
15491562
15501563impl < T > MaybeResult < T > for T {
1551- fn from_ok ( x : T ) -> Self {
1564+ type Error = !;
1565+
1566+ fn from ( x : Result < T , Self :: Error > ) -> Self {
1567+ let Ok ( x) = x;
15521568 x
15531569 }
1554- fn map_same < F : FnOnce ( T ) -> T > ( self , f : F ) -> Self {
1555- f ( self )
1570+ fn to_result ( self ) -> Result < T , Self :: Error > {
1571+ Ok ( self )
15561572 }
15571573}
15581574
15591575impl < T , E > MaybeResult < T > for Result < T , E > {
1560- fn from_ok ( x : T ) -> Self {
1561- Ok ( x)
1576+ type Error = E ;
1577+
1578+ fn from ( x : Result < T , Self :: Error > ) -> Self {
1579+ x
15621580 }
1563- fn map_same < F : FnOnce ( T ) -> T > ( self , f : F ) -> Self {
1564- self . map ( f )
1581+ fn to_result ( self ) -> Result < T , Self :: Error > {
1582+ self
15651583 }
15661584}
15671585
@@ -1656,18 +1674,18 @@ impl ty::query::TyCtxtAt<'a, 'tcx, '_> {
16561674
16571675impl < ' a , ' tcx , C > TyLayoutMethods < ' tcx , C > for Ty < ' tcx >
16581676 where C : LayoutOf < Ty = Ty < ' tcx > > + HasTyCtxt < ' tcx > ,
1659- C :: TyLayout : MaybeResult < TyLayout < ' tcx > >
1677+ C :: TyLayout : MaybeResult < TyLayout < ' tcx > > ,
1678+ C : HasParamEnv < ' tcx >
16601679{
16611680 fn for_variant ( this : TyLayout < ' tcx > , cx : & C , variant_index : VariantIdx ) -> TyLayout < ' tcx > {
16621681 let details = match this. variants {
16631682 Variants :: Single { index } if index == variant_index => this. details ,
16641683
16651684 Variants :: Single { index } => {
16661685 // Deny calling for_variant more than once for non-Single enums.
1667- cx. layout_of ( this. ty ) . map_same ( |layout| {
1686+ if let Ok ( layout ) = cx. layout_of ( this. ty ) . to_result ( ) {
16681687 assert_eq ! ( layout. variants, Variants :: Single { index } ) ;
1669- layout
1670- } ) ;
1688+ }
16711689
16721690 let fields = match this. ty . sty {
16731691 ty:: Adt ( def, _) => def. variants [ variant_index] . fields . len ( ) ,
@@ -1700,10 +1718,10 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
17001718 let tcx = cx. tcx ( ) ;
17011719 let discr_layout = |discr : & Scalar | -> C :: TyLayout {
17021720 let layout = LayoutDetails :: scalar ( cx, discr. clone ( ) ) ;
1703- MaybeResult :: from_ok ( TyLayout {
1721+ MaybeResult :: from ( Ok ( TyLayout {
17041722 details : tcx. intern_layout ( layout) ,
1705- ty : discr. value . to_ty ( tcx)
1706- } )
1723+ ty : discr. value . to_ty ( tcx) ,
1724+ } ) )
17071725 } ;
17081726
17091727 cx. layout_of ( match this. ty . sty {
@@ -1737,10 +1755,10 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
17371755 } else {
17381756 tcx. mk_mut_ref ( tcx. lifetimes . re_static , nil)
17391757 } ;
1740- return cx. layout_of ( ptr_ty) . map_same ( |mut ptr_layout| {
1758+ return MaybeResult :: from ( cx. layout_of ( ptr_ty) . to_result ( ) . map ( |mut ptr_layout| {
17411759 ptr_layout. ty = this. ty ;
17421760 ptr_layout
1743- } ) ;
1761+ } ) ) ;
17441762 }
17451763
17461764 match tcx. struct_tail ( pointee) . sty {
@@ -1824,6 +1842,130 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
18241842 }
18251843 } )
18261844 }
1845+
1846+ fn pointee_info_at (
1847+ this : TyLayout < ' tcx > ,
1848+ cx : & C ,
1849+ offset : Size ,
1850+ ) -> Option < PointeeInfo > {
1851+ match this. ty . sty {
1852+ ty:: RawPtr ( mt) if offset. bytes ( ) == 0 => {
1853+ cx. layout_of ( mt. ty ) . to_result ( ) . ok ( )
1854+ . map ( |layout| PointeeInfo {
1855+ size : layout. size ,
1856+ align : layout. align . abi ,
1857+ safe : None ,
1858+ } )
1859+ }
1860+
1861+ ty:: Ref ( _, ty, mt) if offset. bytes ( ) == 0 => {
1862+ let tcx = cx. tcx ( ) ;
1863+ let is_freeze = ty. is_freeze ( tcx, cx. param_env ( ) , DUMMY_SP ) ;
1864+ let kind = match mt {
1865+ hir:: MutImmutable => if is_freeze {
1866+ PointerKind :: Frozen
1867+ } else {
1868+ PointerKind :: Shared
1869+ } ,
1870+ hir:: MutMutable => {
1871+ // Previously we would only emit noalias annotations for LLVM >= 6 or in
1872+ // panic=abort mode. That was deemed right, as prior versions had many bugs
1873+ // in conjunction with unwinding, but later versions didn’t seem to have
1874+ // said issues. See issue #31681.
1875+ //
1876+ // Alas, later on we encountered a case where noalias would generate wrong
1877+ // code altogether even with recent versions of LLVM in *safe* code with no
1878+ // unwinding involved. See #54462.
1879+ //
1880+ // For now, do not enable mutable_noalias by default at all, while the
1881+ // issue is being figured out.
1882+ let mutable_noalias = tcx. sess . opts . debugging_opts . mutable_noalias
1883+ . unwrap_or ( false ) ;
1884+ if mutable_noalias {
1885+ PointerKind :: UniqueBorrowed
1886+ } else {
1887+ PointerKind :: Shared
1888+ }
1889+ }
1890+ } ;
1891+
1892+ cx. layout_of ( ty) . to_result ( ) . ok ( )
1893+ . map ( |layout| PointeeInfo {
1894+ size : layout. size ,
1895+ align : layout. align . abi ,
1896+ safe : Some ( kind) ,
1897+ } )
1898+ }
1899+
1900+ _ => {
1901+ let mut data_variant = match this. variants {
1902+ // Within the discriminant field, only the niche itself is
1903+ // always initialized, so we only check for a pointer at its
1904+ // offset.
1905+ //
1906+ // If the niche is a pointer, it's either valid (according
1907+ // to its type), or null (which the niche field's scalar
1908+ // validity range encodes). This allows using
1909+ // `dereferenceable_or_null` for e.g., `Option<&T>`, and
1910+ // this will continue to work as long as we don't start
1911+ // using more niches than just null (e.g., the first page of
1912+ // the address space, or unaligned pointers).
1913+ Variants :: Multiple {
1914+ discr_kind : DiscriminantKind :: Niche {
1915+ dataful_variant,
1916+ ..
1917+ } ,
1918+ discr_index,
1919+ ..
1920+ } if this. fields . offset ( discr_index) == offset =>
1921+ Some ( this. for_variant ( cx, dataful_variant) ) ,
1922+ _ => Some ( this) ,
1923+ } ;
1924+
1925+ if let Some ( variant) = data_variant {
1926+ // We're not interested in any unions.
1927+ if let FieldPlacement :: Union ( _) = variant. fields {
1928+ data_variant = None ;
1929+ }
1930+ }
1931+
1932+ let mut result = None ;
1933+
1934+ if let Some ( variant) = data_variant {
1935+ let ptr_end = offset + Pointer . size ( cx) ;
1936+ for i in 0 ..variant. fields . count ( ) {
1937+ let field_start = variant. fields . offset ( i) ;
1938+ if field_start <= offset {
1939+ let field = variant. field ( cx, i) ;
1940+ result = field. to_result ( ) . ok ( )
1941+ . and_then ( |field| {
1942+ if ptr_end <= field_start + field. size {
1943+ // We found the right field, look inside it.
1944+ field. pointee_info_at ( cx, offset - field_start)
1945+ } else {
1946+ None
1947+ }
1948+ } ) ;
1949+ if result. is_some ( ) {
1950+ break ;
1951+ }
1952+ }
1953+ }
1954+ }
1955+
1956+ // FIXME(eddyb) This should be for `ptr::Unique<T>`, not `Box<T>`.
1957+ if let Some ( ref mut pointee) = result {
1958+ if let ty:: Adt ( def, _) = this. ty . sty {
1959+ if def. is_box ( ) && offset. bytes ( ) == 0 {
1960+ pointee. safe = Some ( PointerKind :: UniqueOwned ) ;
1961+ }
1962+ }
1963+ }
1964+
1965+ result
1966+ }
1967+ }
1968+ }
18271969}
18281970
18291971struct Niche {
0 commit comments