@@ -40,7 +40,7 @@ use rustc_hir::{ForeignItemKind, GenericParamKind, PatKind};
4040use rustc_hir:: { HirId , HirIdSet , Node } ;
4141use rustc_middle:: lint:: LintDiagnosticBuilder ;
4242use rustc_middle:: ty:: subst:: { GenericArgKind , Subst } ;
43- use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
43+ use rustc_middle:: ty:: { self , layout :: LayoutError , Ty , TyCtxt } ;
4444use rustc_session:: lint:: FutureIncompatibleInfo ;
4545use rustc_session:: Session ;
4646use rustc_span:: edition:: Edition ;
@@ -2177,11 +2177,17 @@ impl ClashingExternDeclarations {
21772177 let a_kind = & a. kind ;
21782178 let b_kind = & b. kind ;
21792179
2180- let compare_layouts = |a, b| -> bool {
2181- let a_layout = & cx. layout_of ( a) . unwrap ( ) . layout . abi ;
2182- let b_layout = & cx. layout_of ( b) . unwrap ( ) . layout . abi ;
2183- debug ! ( "{:?} == {:?} = {}" , a_layout, b_layout, a_layout == b_layout) ;
2184- a_layout == b_layout
2180+ let compare_layouts = |a, b| -> Result < bool , LayoutError < ' tcx > > {
2181+ debug ! ( "compare_layouts({:?}, {:?})" , a, b) ;
2182+ let a_layout = & cx. layout_of ( a) ?. layout . abi ;
2183+ let b_layout = & cx. layout_of ( b) ?. layout . abi ;
2184+ debug ! (
2185+ "comparing layouts: {:?} == {:?} = {}" ,
2186+ a_layout,
2187+ b_layout,
2188+ a_layout == b_layout
2189+ ) ;
2190+ Ok ( a_layout == b_layout)
21852191 } ;
21862192
21872193 #[ allow( rustc:: usage_of_ty_tykind) ]
@@ -2196,11 +2202,19 @@ impl ClashingExternDeclarations {
21962202 let b = b. subst ( cx. tcx , b_substs) ;
21972203 debug ! ( "Comparing {:?} and {:?}" , a, b) ;
21982204
2205+ // We can immediately rule out these types as structurally same if
2206+ // their layouts differ.
2207+ match compare_layouts ( a, b) {
2208+ Ok ( false ) => return false ,
2209+ _ => ( ) , // otherwise, continue onto the full, fields comparison
2210+ }
2211+
21992212 // Grab a flattened representation of all fields.
22002213 let a_fields = a_def. variants . iter ( ) . flat_map ( |v| v. fields . iter ( ) ) ;
22012214 let b_fields = b_def. variants . iter ( ) . flat_map ( |v| v. fields . iter ( ) ) ;
2202- compare_layouts ( a, b)
2203- && a_fields. eq_by (
2215+
2216+ // Perform a structural comparison for each field.
2217+ a_fields. eq_by (
22042218 b_fields,
22052219 |& ty:: FieldDef { did : a_did, .. } ,
22062220 & ty:: FieldDef { did : b_did, .. } | {
@@ -2287,13 +2301,13 @@ impl ClashingExternDeclarations {
22872301 if let Some ( ty) = crate :: types:: repr_nullable_ptr ( cx, adt, ckind) {
22882302 ty == primitive
22892303 } else {
2290- compare_layouts ( a, b)
2304+ compare_layouts ( a, b) . unwrap_or ( false )
22912305 }
22922306 }
22932307 // Otherwise, just compare the layouts. This may fail to lint for some
22942308 // incompatible types, but at the very least, will stop reads into
22952309 // uninitialised memory.
2296- _ => compare_layouts ( a, b) ,
2310+ _ => compare_layouts ( a, b) . unwrap_or ( false ) ,
22972311 }
22982312 } )
22992313 }
0 commit comments