@@ -3,8 +3,7 @@ use rustc_data_structures::unord::{UnordMap, UnordSet};
33use  rustc_hir as  hir; 
44use  rustc_hir:: def:: DefKind ; 
55use  rustc_middle:: query:: Providers ; 
6- use  rustc_middle:: ty:: layout:: LayoutError ; 
7- use  rustc_middle:: ty:: { self ,  Instance ,  Ty ,  TyCtxt } ; 
6+ use  rustc_middle:: ty:: { self ,  AdtDef ,  Instance ,  Ty ,  TyCtxt } ; 
87use  rustc_session:: declare_lint; 
98use  rustc_span:: { sym,  Span ,  Symbol } ; 
109use  rustc_target:: abi:: FIRST_VARIANT ; 
@@ -212,7 +211,17 @@ fn structurally_same_type<'tcx>(
212211    ckind :  types:: CItemKind , 
213212)  -> bool  { 
214213    let  mut  seen_types = UnordSet :: default ( ) ; 
215-     structurally_same_type_impl ( & mut  seen_types,  tcx,  param_env,  a,  b,  ckind) 
214+     let  result = structurally_same_type_impl ( & mut  seen_types,  tcx,  param_env,  a,  b,  ckind) ; 
215+     if  cfg ! ( debug_assertions)  && result { 
216+         // Sanity-check: must have same ABI, size and alignment. 
217+         // `extern` blocks cannot be generic, so we'll always get a layout here. 
218+         let  a_layout = tcx. layout_of ( param_env. and ( a) ) . unwrap ( ) ; 
219+         let  b_layout = tcx. layout_of ( param_env. and ( b) ) . unwrap ( ) ; 
220+         assert_eq ! ( a_layout. abi,  b_layout. abi) ; 
221+         assert_eq ! ( a_layout. size,  b_layout. size) ; 
222+         assert_eq ! ( a_layout. align,  b_layout. align) ; 
223+     } 
224+     result
216225} 
217226
218227fn  structurally_same_type_impl < ' tcx > ( 
@@ -266,30 +275,21 @@ fn structurally_same_type_impl<'tcx>(
266275        // Do a full, depth-first comparison between the two. 
267276        use  rustc_type_ir:: TyKind :: * ; 
268277
269-         let  compare_layouts = |a,  b| -> Result < bool ,  & ' tcx  LayoutError < ' tcx > >  { 
270-             debug ! ( "compare_layouts({:?}, {:?})" ,  a,  b) ; 
271-             let  a_layout = & tcx. layout_of ( param_env. and ( a) ) ?. layout . abi ( ) ; 
272-             let  b_layout = & tcx. layout_of ( param_env. and ( b) ) ?. layout . abi ( ) ; 
273-             debug ! ( 
274-                 "comparing layouts: {:?} == {:?} = {}" , 
275-                 a_layout, 
276-                 b_layout, 
277-                 a_layout == b_layout
278-             ) ; 
279-             Ok ( a_layout == b_layout) 
280-         } ; 
281- 
282278        let  is_primitive_or_pointer =
283279            |ty :  Ty < ' tcx > | ty. is_primitive ( )  || matches ! ( ty. kind( ) ,  RawPtr ( ..)  | Ref ( ..) ) ; 
284280
285281        ensure_sufficient_stack ( || { 
286282            match  ( a. kind ( ) ,  b. kind ( ) )  { 
287-                 ( Adt ( a_def,  _) ,  Adt ( b_def,  _) )  => { 
288-                     // We can immediately rule out these types as structurally same if 
289-                     // their layouts differ. 
290-                     match  compare_layouts ( a,  b)  { 
291-                         Ok ( false )  => return  false , 
292-                         _ => ( ) ,  // otherwise, continue onto the full, fields comparison 
283+                 ( & Adt ( a_def,  _) ,  & Adt ( b_def,  _) )  => { 
284+                     // Only `repr(C)` types can be compared structurally. 
285+                     if  !( a_def. repr ( ) . c ( )  && b_def. repr ( ) . c ( ) )  { 
286+                         return  false ; 
287+                     } 
288+                     // If the types differ in their packed-ness, align, or simd-ness they conflict. 
289+                     let  repr_characteristica =
290+                         |def :  AdtDef < ' tcx > | ( def. repr ( ) . pack ,  def. repr ( ) . align ,  def. repr ( ) . simd ( ) ) ; 
291+                     if  repr_characteristica ( a_def)  != repr_characteristica ( b_def)  { 
292+                         return  false ; 
293293                    } 
294294
295295                    // Grab a flattened representation of all fields. 
@@ -311,9 +311,9 @@ fn structurally_same_type_impl<'tcx>(
311311                        } , 
312312                    ) 
313313                } 
314-                 ( Array ( a_ty,  a_const ) ,  Array ( b_ty,  b_const ) )  => { 
315-                     // For arrays, we also check the constness of the type . 
316-                     a_const . kind ( )  == b_const . kind ( ) 
314+                 ( Array ( a_ty,  a_len ) ,  Array ( b_ty,  b_len ) )  => { 
315+                     // For arrays, we also check the length . 
316+                     a_len  == b_len 
317317                        && structurally_same_type_impl ( 
318318                            seen_types,  tcx,  param_env,  * a_ty,  * b_ty,  ckind, 
319319                        ) 
@@ -357,10 +357,9 @@ fn structurally_same_type_impl<'tcx>(
357357                            ckind, 
358358                        ) 
359359                } 
360-                 ( Tuple ( a_args) ,  Tuple ( b_args) )  => { 
361-                     a_args. iter ( ) . eq_by ( b_args. iter ( ) ,  |a_ty,  b_ty| { 
362-                         structurally_same_type_impl ( seen_types,  tcx,  param_env,  a_ty,  b_ty,  ckind) 
363-                     } ) 
360+                 ( Tuple ( ..) ,  Tuple ( ..) )  => { 
361+                     // Tuples are not `repr(C)` so these cannot be compared structurally. 
362+                     false 
364363                } 
365364                // For these, it's not quite as easy to define structural-sameness quite so easily. 
366365                // For the purposes of this lint, take the conservative approach and mark them as 
@@ -380,24 +379,21 @@ fn structurally_same_type_impl<'tcx>(
380379                // An Adt and a primitive or pointer type. This can be FFI-safe if non-null 
381380                // enum layout optimisation is being applied. 
382381                ( Adt ( ..) ,  _)  if  is_primitive_or_pointer ( b)  => { 
383-                     if  let  Some ( ty )  = types:: repr_nullable_ptr ( tcx,  param_env,  a,  ckind)  { 
384-                         ty  == b
382+                     if  let  Some ( a_inner )  = types:: repr_nullable_ptr ( tcx,  param_env,  a,  ckind)  { 
383+                         a_inner  == b
385384                    }  else  { 
386-                         compare_layouts ( a ,  b ) . unwrap_or ( false ) 
385+                         false 
387386                    } 
388387                } 
389388                ( _,  Adt ( ..) )  if  is_primitive_or_pointer ( a)  => { 
390-                     if  let  Some ( ty )  = types:: repr_nullable_ptr ( tcx,  param_env,  b,  ckind)  { 
391-                         ty  == a
389+                     if  let  Some ( b_inner )  = types:: repr_nullable_ptr ( tcx,  param_env,  b,  ckind)  { 
390+                         b_inner  == a
392391                    }  else  { 
393-                         compare_layouts ( a ,  b ) . unwrap_or ( false ) 
392+                         false 
394393                    } 
395394                } 
396395
397-                 // Otherwise, just compare the layouts. This may fail to lint for some 
398-                 // incompatible types, but at the very least, will stop reads into 
399-                 // uninitialised memory. 
400-                 _ => compare_layouts ( a,  b) . unwrap_or ( false ) , 
396+                 _ => false , 
401397            } 
402398        } ) 
403399    } 
0 commit comments