@@ -40,7 +40,7 @@ use rustc_hir::{ForeignItemKind, GenericParamKind, PatKind};
40
40
use rustc_hir:: { HirId , HirIdSet , Node } ;
41
41
use rustc_middle:: lint:: LintDiagnosticBuilder ;
42
42
use rustc_middle:: ty:: subst:: { GenericArgKind , Subst } ;
43
- use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
43
+ use rustc_middle:: ty:: { self , layout :: LayoutError , Ty , TyCtxt } ;
44
44
use rustc_session:: lint:: FutureIncompatibleInfo ;
45
45
use rustc_session:: Session ;
46
46
use rustc_span:: edition:: Edition ;
@@ -2177,11 +2177,17 @@ impl ClashingExternDeclarations {
2177
2177
let a_kind = & a. kind ;
2178
2178
let b_kind = & b. kind ;
2179
2179
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)
2185
2191
} ;
2186
2192
2187
2193
#[ allow( rustc:: usage_of_ty_tykind) ]
@@ -2196,11 +2202,19 @@ impl ClashingExternDeclarations {
2196
2202
let b = b. subst ( cx. tcx , b_substs) ;
2197
2203
debug ! ( "Comparing {:?} and {:?}" , a, b) ;
2198
2204
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
+
2199
2212
// Grab a flattened representation of all fields.
2200
2213
let a_fields = a_def. variants . iter ( ) . flat_map ( |v| v. fields . iter ( ) ) ;
2201
2214
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 (
2204
2218
b_fields,
2205
2219
|& ty:: FieldDef { did : a_did, .. } ,
2206
2220
& ty:: FieldDef { did : b_did, .. } | {
@@ -2287,13 +2301,13 @@ impl ClashingExternDeclarations {
2287
2301
if let Some ( ty) = crate :: types:: repr_nullable_ptr ( cx, adt, ckind) {
2288
2302
ty == primitive
2289
2303
} else {
2290
- compare_layouts ( a, b)
2304
+ compare_layouts ( a, b) . unwrap_or ( false )
2291
2305
}
2292
2306
}
2293
2307
// Otherwise, just compare the layouts. This may fail to lint for some
2294
2308
// incompatible types, but at the very least, will stop reads into
2295
2309
// uninitialised memory.
2296
- _ => compare_layouts ( a, b) ,
2310
+ _ => compare_layouts ( a, b) . unwrap_or ( false ) ,
2297
2311
}
2298
2312
} )
2299
2313
}
0 commit comments