@@ -12,6 +12,7 @@ use std::iter;
1212use std:: mem;
1313use std:: ops:: Bound ;
1414
15+ use hir;
1516use crate :: ich:: StableHashingContext ;
1617use rustc_data_structures:: indexed_vec:: { IndexVec , Idx } ;
1718use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher ,
@@ -1545,6 +1546,7 @@ impl<'gcx, 'tcx, T: HasTyCtxt<'gcx>> HasTyCtxt<'gcx> for LayoutCx<'tcx, T> {
15451546pub trait MaybeResult < T > {
15461547 fn from_ok ( x : T ) -> Self ;
15471548 fn map_same < F : FnOnce ( T ) -> T > ( self , f : F ) -> Self ;
1549+ fn ok ( self ) -> Option < T > ;
15481550}
15491551
15501552impl < T > MaybeResult < T > for T {
@@ -1554,6 +1556,9 @@ impl<T> MaybeResult<T> for T {
15541556 fn map_same < F : FnOnce ( T ) -> T > ( self , f : F ) -> Self {
15551557 f ( self )
15561558 }
1559+ fn ok ( self ) -> Option < T > {
1560+ Some ( self )
1561+ }
15571562}
15581563
15591564impl < T , E > MaybeResult < T > for Result < T , E > {
@@ -1563,6 +1568,9 @@ impl<T, E> MaybeResult<T> for Result<T, E> {
15631568 fn map_same < F : FnOnce ( T ) -> T > ( self , f : F ) -> Self {
15641569 self . map ( f)
15651570 }
1571+ fn ok ( self ) -> Option < T > {
1572+ self . ok ( )
1573+ }
15661574}
15671575
15681576pub type TyLayout < ' tcx > = :: rustc_target:: abi:: TyLayout < ' tcx , Ty < ' tcx > > ;
@@ -1824,6 +1832,125 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
18241832 }
18251833 } )
18261834 }
1835+
1836+ fn pointee_info_at ( this : TyLayout < ' tcx > , cx : & C , offset : Size
1837+ ) -> Option < PointeeInfo > {
1838+ let mut result = None ;
1839+ match this. ty . sty {
1840+ ty:: RawPtr ( mt) if offset. bytes ( ) == 0 => {
1841+ result = cx. layout_of ( mt. ty ) . ok ( )
1842+ . map ( |layout| PointeeInfo {
1843+ size : layout. size ,
1844+ align : layout. align . abi ,
1845+ safe : None ,
1846+ } ) ;
1847+ }
1848+
1849+ ty:: Ref ( _, ty, mt) if offset. bytes ( ) == 0 => {
1850+ let tcx = cx. tcx ( ) ;
1851+ let is_freeze = ty. is_freeze ( tcx, ty:: ParamEnv :: reveal_all ( ) , DUMMY_SP ) ;
1852+ let kind = match mt {
1853+ hir:: MutImmutable => if is_freeze {
1854+ PointerKind :: Frozen
1855+ } else {
1856+ PointerKind :: Shared
1857+ } ,
1858+ hir:: MutMutable => {
1859+ // Previously we would only emit noalias annotations for LLVM >= 6 or in
1860+ // panic=abort mode. That was deemed right, as prior versions had many bugs
1861+ // in conjunction with unwinding, but later versions didn’t seem to have
1862+ // said issues. See issue #31681.
1863+ //
1864+ // Alas, later on we encountered a case where noalias would generate wrong
1865+ // code altogether even with recent versions of LLVM in *safe* code with no
1866+ // unwinding involved. See #54462.
1867+ //
1868+ // For now, do not enable mutable_noalias by default at all, while the
1869+ // issue is being figured out.
1870+ let mutable_noalias = tcx. sess . opts . debugging_opts . mutable_noalias
1871+ . unwrap_or ( false ) ;
1872+ if mutable_noalias {
1873+ PointerKind :: UniqueBorrowed
1874+ } else {
1875+ PointerKind :: Shared
1876+ }
1877+ }
1878+ } ;
1879+
1880+ result = cx. layout_of ( ty) . ok ( )
1881+ . map ( |layout| PointeeInfo {
1882+ size : layout. size ,
1883+ align : layout. align . abi ,
1884+ safe : Some ( kind) ,
1885+ } ) ;
1886+ }
1887+
1888+ _ => {
1889+ let mut data_variant = match this. variants {
1890+ Variants :: NicheFilling { dataful_variant, .. } => {
1891+ // Only the niche itthis is always initialized,
1892+ // so only check for a pointer at its offset.
1893+ //
1894+ // If the niche is a pointer, it's either valid
1895+ // (according to its type), or null (which the
1896+ // niche field's scalar validity range encodes).
1897+ // This allows using `dereferenceable_or_null`
1898+ // for e.g., `Option<&T>`, and this will continue
1899+ // to work as long as we don't start using more
1900+ // niches than just null (e.g., the first page
1901+ // of the address space, or unaligned pointers).
1902+ if this. fields . offset ( 0 ) == offset {
1903+ Some ( this. for_variant ( cx, dataful_variant) )
1904+ } else {
1905+ None
1906+ }
1907+ }
1908+ _ => Some ( this)
1909+ } ;
1910+
1911+ if let Some ( variant) = data_variant {
1912+ // We're not interested in any unions.
1913+ if let FieldPlacement :: Union ( _) = variant. fields {
1914+ data_variant = None ;
1915+ }
1916+ }
1917+
1918+ if let Some ( variant) = data_variant {
1919+ let ptr_end = offset + Pointer . size ( cx) ;
1920+ for i in 0 ..variant. fields . count ( ) {
1921+ let field_start = variant. fields . offset ( i) ;
1922+ if field_start <= offset {
1923+ let field = variant. field ( cx, i) ;
1924+ result = field. ok ( )
1925+ . and_then ( |field| {
1926+ if ptr_end <= field_start + field. size {
1927+ // We found the right field, look inside it.
1928+ Self :: pointee_info_at ( field, cx, offset - field_start)
1929+ } else {
1930+ None
1931+ }
1932+ } ) ;
1933+ if result. is_some ( ) {
1934+ break ;
1935+ }
1936+ }
1937+ }
1938+ }
1939+
1940+ // FIXME(eddyb) This should be for `ptr::Unique<T>`, not `Box<T>`.
1941+ if let Some ( ref mut pointee) = result {
1942+ if let ty:: Adt ( def, _) = this. ty . sty {
1943+ if def. is_box ( ) && offset. bytes ( ) == 0 {
1944+ pointee. safe = Some ( PointerKind :: UniqueOwned ) ;
1945+ }
1946+ }
1947+ }
1948+ }
1949+ }
1950+
1951+ result
1952+ }
1953+
18271954}
18281955
18291956struct Niche {
0 commit comments