@@ -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