@@ -12,6 +12,7 @@ use std::iter;
12
12
use std:: mem;
13
13
use std:: ops:: Bound ;
14
14
15
+ use hir;
15
16
use crate :: ich:: StableHashingContext ;
16
17
use rustc_data_structures:: indexed_vec:: { IndexVec , Idx } ;
17
18
use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher ,
@@ -1545,6 +1546,7 @@ impl<'gcx, 'tcx, T: HasTyCtxt<'gcx>> HasTyCtxt<'gcx> for LayoutCx<'tcx, T> {
1545
1546
pub trait MaybeResult < T > {
1546
1547
fn from_ok ( x : T ) -> Self ;
1547
1548
fn map_same < F : FnOnce ( T ) -> T > ( self , f : F ) -> Self ;
1549
+ fn ok ( self ) -> Option < T > ;
1548
1550
}
1549
1551
1550
1552
impl < T > MaybeResult < T > for T {
@@ -1554,6 +1556,9 @@ impl<T> MaybeResult<T> for T {
1554
1556
fn map_same < F : FnOnce ( T ) -> T > ( self , f : F ) -> Self {
1555
1557
f ( self )
1556
1558
}
1559
+ fn ok ( self ) -> Option < T > {
1560
+ Some ( self )
1561
+ }
1557
1562
}
1558
1563
1559
1564
impl < T , E > MaybeResult < T > for Result < T , E > {
@@ -1563,6 +1568,9 @@ impl<T, E> MaybeResult<T> for Result<T, E> {
1563
1568
fn map_same < F : FnOnce ( T ) -> T > ( self , f : F ) -> Self {
1564
1569
self . map ( f)
1565
1570
}
1571
+ fn ok ( self ) -> Option < T > {
1572
+ self . ok ( )
1573
+ }
1566
1574
}
1567
1575
1568
1576
pub type TyLayout < ' tcx > = :: rustc_target:: abi:: TyLayout < ' tcx , Ty < ' tcx > > ;
@@ -1824,6 +1832,125 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
1824
1832
}
1825
1833
} )
1826
1834
}
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
+
1827
1954
}
1828
1955
1829
1956
struct Niche {
0 commit comments