@@ -36,14 +36,14 @@ use rustc_hir::def_id::DefId;
36
36
use rustc_hir:: { ForeignItemKind , GenericParamKind , PatKind } ;
37
37
use rustc_hir:: { HirId , HirIdSet , Node } ;
38
38
use rustc_middle:: lint:: LintDiagnosticBuilder ;
39
- use rustc_middle:: ty:: subst:: GenericArgKind ;
39
+ use rustc_middle:: ty:: subst:: { GenericArgKind , Subst } ;
40
40
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
41
41
use rustc_session:: lint:: FutureIncompatibleInfo ;
42
42
use rustc_span:: edition:: Edition ;
43
43
use rustc_span:: source_map:: Spanned ;
44
44
use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
45
45
use rustc_span:: { BytePos , Span } ;
46
- use rustc_target:: abi:: VariantIdx ;
46
+ use rustc_target:: abi:: { LayoutOf , VariantIdx } ;
47
47
use rustc_trait_selection:: traits:: misc:: can_type_implement_copy;
48
48
49
49
use crate :: nonstandard_style:: { method_context, MethodLateContext } ;
@@ -2131,6 +2131,7 @@ impl ClashingExternDeclarations {
2131
2131
/// clash. We need this so we don't emit a lint when two modules both declare an extern struct,
2132
2132
/// with the same members (as the declarations shouldn't clash).
2133
2133
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) ;
2134
2135
let tcx = cx. tcx ;
2135
2136
if a == b || rustc_middle:: ty:: TyS :: same_type ( a, b) {
2136
2137
// All nominally-same types are structurally same, too.
@@ -2141,17 +2142,43 @@ impl ClashingExternDeclarations {
2141
2142
let a_kind = & a. kind ;
2142
2143
let b_kind = & b. kind ;
2143
2144
2144
- use rustc_target:: abi:: LayoutOf ;
2145
2145
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
2147
2150
} ;
2148
2151
2149
2152
#[ allow( rustc:: usage_of_ty_tykind) ]
2150
2153
let is_primitive_or_pointer =
2151
2154
|kind : & ty:: TyKind < ' _ > | kind. is_primitive ( ) || matches ! ( kind, RawPtr ( ..) ) ;
2152
2155
2153
2156
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
+ }
2155
2182
( Array ( a_ty, a_const) , Array ( b_ty, b_const) ) => {
2156
2183
// For arrays, we also check the constness of the type.
2157
2184
a_const. val == b_const. val
0 commit comments