@@ -36,14 +36,14 @@ use rustc_hir::def_id::DefId;
3636use rustc_hir:: { ForeignItemKind , GenericParamKind , PatKind } ;
3737use rustc_hir:: { HirId , HirIdSet , Node } ;
3838use rustc_middle:: lint:: LintDiagnosticBuilder ;
39- use rustc_middle:: ty:: subst:: GenericArgKind ;
39+ use rustc_middle:: ty:: subst:: { GenericArgKind , Subst } ;
4040use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
4141use rustc_session:: lint:: FutureIncompatibleInfo ;
4242use rustc_span:: edition:: Edition ;
4343use rustc_span:: source_map:: Spanned ;
4444use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
4545use rustc_span:: { BytePos , Span } ;
46- use rustc_target:: abi:: VariantIdx ;
46+ use rustc_target:: abi:: { LayoutOf , VariantIdx } ;
4747use rustc_trait_selection:: traits:: misc:: can_type_implement_copy;
4848
4949use crate :: nonstandard_style:: { method_context, MethodLateContext } ;
@@ -2131,6 +2131,7 @@ impl ClashingExternDeclarations {
21312131 /// clash. We need this so we don't emit a lint when two modules both declare an extern struct,
21322132 /// with the same members (as the declarations shouldn't clash).
21332133 fn structurally_same_type < ' tcx > ( cx : & LateContext < ' tcx > , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> bool {
2134+ debug ! ( "structurally_same_type(cx, a = {:?}, b = {:?})" , a, b) ;
21342135 let tcx = cx. tcx ;
21352136 if a == b || rustc_middle:: ty:: TyS :: same_type ( a, b) {
21362137 // All nominally-same types are structurally same, too.
@@ -2141,17 +2142,43 @@ impl ClashingExternDeclarations {
21412142 let a_kind = & a. kind ;
21422143 let b_kind = & b. kind ;
21432144
2144- use rustc_target:: abi:: LayoutOf ;
21452145 let compare_layouts = |a, b| -> bool {
2146- & cx. layout_of ( a) . unwrap ( ) . layout . abi == & cx. layout_of ( b) . unwrap ( ) . layout . abi
2146+ let a_layout = & cx. layout_of ( a) . unwrap ( ) . layout . abi ;
2147+ let b_layout = & cx. layout_of ( b) . unwrap ( ) . layout . abi ;
2148+ debug ! ( "{:?} == {:?} = {}" , a_layout, b_layout, a_layout == b_layout) ;
2149+ a_layout == b_layout
21472150 } ;
21482151
21492152 #[ allow( rustc:: usage_of_ty_tykind) ]
21502153 let is_primitive_or_pointer =
21512154 |kind : & ty:: TyKind < ' _ > | kind. is_primitive ( ) || matches ! ( kind, RawPtr ( ..) ) ;
21522155
21532156 match ( a_kind, b_kind) {
2154- ( Adt ( ..) , Adt ( ..) ) => compare_layouts ( a, b) ,
2157+ ( Adt ( _, a_substs) , Adt ( _, b_substs) ) => {
2158+ let a = a. subst ( cx. tcx , a_substs) ;
2159+ let b = b. subst ( cx. tcx , b_substs) ;
2160+ debug ! ( "Comparing {:?} and {:?}" , a, b) ;
2161+
2162+ if let ( Adt ( a_def, ..) , Adt ( b_def, ..) ) = ( & a. kind , & b. kind ) {
2163+ // Grab a flattened representation of all fields.
2164+ let a_fields = a_def. variants . iter ( ) . flat_map ( |v| v. fields . iter ( ) ) ;
2165+ let b_fields = b_def. variants . iter ( ) . flat_map ( |v| v. fields . iter ( ) ) ;
2166+ compare_layouts ( a, b)
2167+ && a_fields. eq_by (
2168+ b_fields,
2169+ |& ty:: FieldDef { did : a_did, .. } ,
2170+ & ty:: FieldDef { did : b_did, .. } | {
2171+ Self :: structurally_same_type (
2172+ cx,
2173+ tcx. type_of ( a_did) ,
2174+ tcx. type_of ( b_did) ,
2175+ )
2176+ } ,
2177+ )
2178+ } else {
2179+ unreachable ! ( )
2180+ }
2181+ }
21552182 ( Array ( a_ty, a_const) , Array ( b_ty, b_const) ) => {
21562183 // For arrays, we also check the constness of the type.
21572184 a_const. val == b_const. val
0 commit comments