@@ -29,6 +29,7 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree};
29
29
use rustc_ast:: visit:: { FnCtxt , FnKind } ;
30
30
use rustc_ast_pretty:: pprust:: { self , expr_to_string} ;
31
31
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
32
+ use rustc_data_structures:: stack:: ensure_sufficient_stack;
32
33
use rustc_errors:: { Applicability , DiagnosticBuilder , DiagnosticStyledString } ;
33
34
use rustc_feature:: { deprecated_attributes, AttributeGate , AttributeTemplate , AttributeType } ;
34
35
use rustc_feature:: { GateIssue , Stability } ;
@@ -2188,16 +2189,17 @@ impl ClashingExternDeclarations {
2188
2189
kind. is_primitive ( ) || matches ! ( kind, RawPtr ( ..) | Ref ( ..) )
2189
2190
} ;
2190
2191
2191
- match ( a_kind, b_kind) {
2192
- ( Adt ( a_def, a_substs) , Adt ( b_def, b_substs) ) => {
2193
- let a = a. subst ( cx. tcx , a_substs) ;
2194
- let b = b. subst ( cx. tcx , b_substs) ;
2195
- debug ! ( "Comparing {:?} and {:?}" , a, b) ;
2192
+ ensure_sufficient_stack ( || {
2193
+ match ( a_kind, b_kind) {
2194
+ ( Adt ( a_def, a_substs) , Adt ( b_def, b_substs) ) => {
2195
+ let a = a. subst ( cx. tcx , a_substs) ;
2196
+ let b = b. subst ( cx. tcx , b_substs) ;
2197
+ debug ! ( "Comparing {:?} and {:?}" , a, b) ;
2196
2198
2197
- // Grab a flattened representation of all fields.
2198
- let a_fields = a_def. variants . iter ( ) . flat_map ( |v| v. fields . iter ( ) ) ;
2199
- let b_fields = b_def. variants . iter ( ) . flat_map ( |v| v. fields . iter ( ) ) ;
2200
- compare_layouts ( a, b)
2199
+ // Grab a flattened representation of all fields.
2200
+ let a_fields = a_def. variants . iter ( ) . flat_map ( |v| v. fields . iter ( ) ) ;
2201
+ let b_fields = b_def. variants . iter ( ) . flat_map ( |v| v. fields . iter ( ) ) ;
2202
+ compare_layouts ( a, b)
2201
2203
&& a_fields. eq_by (
2202
2204
b_fields,
2203
2205
|& ty:: FieldDef { did : a_did, .. } ,
@@ -2211,88 +2213,89 @@ impl ClashingExternDeclarations {
2211
2213
)
2212
2214
} ,
2213
2215
)
2214
- }
2215
- ( Array ( a_ty, a_const) , Array ( b_ty, b_const) ) => {
2216
- // For arrays, we also check the constness of the type.
2217
- a_const. val == b_const. val
2218
- && structurally_same_type_impl ( seen_types, cx, a_ty, b_ty, ckind)
2219
- }
2220
- ( Slice ( a_ty) , Slice ( b_ty) ) => {
2221
- structurally_same_type_impl ( seen_types, cx, a_ty, b_ty, ckind)
2222
- }
2223
- ( RawPtr ( a_tymut) , RawPtr ( b_tymut) ) => {
2224
- a_tymut. mutbl == b_tymut. mutbl
2225
- && structurally_same_type_impl (
2226
- seen_types,
2227
- cx,
2228
- & a_tymut. ty ,
2229
- & b_tymut. ty ,
2230
- ckind,
2231
- )
2232
- }
2233
- ( Ref ( _a_region, a_ty, a_mut) , Ref ( _b_region, b_ty, b_mut) ) => {
2234
- // For structural sameness, we don't need the region to be same.
2235
- a_mut == b_mut
2236
- && structurally_same_type_impl ( seen_types, cx, a_ty, b_ty, ckind)
2237
- }
2238
- ( FnDef ( ..) , FnDef ( ..) ) => {
2239
- let a_poly_sig = a. fn_sig ( tcx) ;
2240
- let b_poly_sig = b. fn_sig ( tcx) ;
2241
-
2242
- // As we don't compare regions, skip_binder is fine.
2243
- let a_sig = a_poly_sig. skip_binder ( ) ;
2244
- let b_sig = b_poly_sig. skip_binder ( ) ;
2245
-
2246
- ( a_sig. abi , a_sig. unsafety , a_sig. c_variadic )
2247
- == ( b_sig. abi , b_sig. unsafety , b_sig. c_variadic )
2248
- && a_sig. inputs ( ) . iter ( ) . eq_by ( b_sig. inputs ( ) . iter ( ) , |a, b| {
2249
- structurally_same_type_impl ( seen_types, cx, a, b, ckind)
2250
- } )
2251
- && structurally_same_type_impl (
2252
- seen_types,
2253
- cx,
2254
- a_sig. output ( ) ,
2255
- b_sig. output ( ) ,
2256
- ckind,
2257
- )
2258
- }
2259
- ( Tuple ( a_substs) , Tuple ( b_substs) ) => {
2260
- a_substs. types ( ) . eq_by ( b_substs. types ( ) , |a_ty, b_ty| {
2216
+ }
2217
+ ( Array ( a_ty, a_const) , Array ( b_ty, b_const) ) => {
2218
+ // For arrays, we also check the constness of the type.
2219
+ a_const. val == b_const. val
2220
+ && structurally_same_type_impl ( seen_types, cx, a_ty, b_ty, ckind)
2221
+ }
2222
+ ( Slice ( a_ty) , Slice ( b_ty) ) => {
2261
2223
structurally_same_type_impl ( seen_types, cx, a_ty, b_ty, ckind)
2262
- } )
2263
- }
2264
- // For these, it's not quite as easy to define structural-sameness quite so easily.
2265
- // For the purposes of this lint, take the conservative approach and mark them as
2266
- // not structurally same.
2267
- ( Dynamic ( ..) , Dynamic ( ..) )
2268
- | ( Error ( ..) , Error ( ..) )
2269
- | ( Closure ( ..) , Closure ( ..) )
2270
- | ( Generator ( ..) , Generator ( ..) )
2271
- | ( GeneratorWitness ( ..) , GeneratorWitness ( ..) )
2272
- | ( Projection ( ..) , Projection ( ..) )
2273
- | ( Opaque ( ..) , Opaque ( ..) ) => false ,
2274
-
2275
- // These definitely should have been caught above.
2276
- ( Bool , Bool ) | ( Char , Char ) | ( Never , Never ) | ( Str , Str ) => unreachable ! ( ) ,
2277
-
2278
- // An Adt and a primitive or pointer type. This can be FFI-safe if non-null
2279
- // enum layout optimisation is being applied.
2280
- ( Adt ( ..) , other_kind) | ( other_kind, Adt ( ..) )
2281
- if is_primitive_or_pointer ( other_kind) =>
2282
- {
2283
- let ( primitive, adt) =
2284
- if is_primitive_or_pointer ( & a. kind ) { ( a, b) } else { ( b, a) } ;
2285
- if let Some ( ty) = crate :: types:: repr_nullable_ptr ( cx, adt, ckind) {
2286
- ty == primitive
2287
- } else {
2288
- compare_layouts ( a, b)
2289
2224
}
2225
+ ( RawPtr ( a_tymut) , RawPtr ( b_tymut) ) => {
2226
+ a_tymut. mutbl == b_tymut. mutbl
2227
+ && structurally_same_type_impl (
2228
+ seen_types,
2229
+ cx,
2230
+ & a_tymut. ty ,
2231
+ & b_tymut. ty ,
2232
+ ckind,
2233
+ )
2234
+ }
2235
+ ( Ref ( _a_region, a_ty, a_mut) , Ref ( _b_region, b_ty, b_mut) ) => {
2236
+ // For structural sameness, we don't need the region to be same.
2237
+ a_mut == b_mut
2238
+ && structurally_same_type_impl ( seen_types, cx, a_ty, b_ty, ckind)
2239
+ }
2240
+ ( FnDef ( ..) , FnDef ( ..) ) => {
2241
+ let a_poly_sig = a. fn_sig ( tcx) ;
2242
+ let b_poly_sig = b. fn_sig ( tcx) ;
2243
+
2244
+ // As we don't compare regions, skip_binder is fine.
2245
+ let a_sig = a_poly_sig. skip_binder ( ) ;
2246
+ let b_sig = b_poly_sig. skip_binder ( ) ;
2247
+
2248
+ ( a_sig. abi , a_sig. unsafety , a_sig. c_variadic )
2249
+ == ( b_sig. abi , b_sig. unsafety , b_sig. c_variadic )
2250
+ && a_sig. inputs ( ) . iter ( ) . eq_by ( b_sig. inputs ( ) . iter ( ) , |a, b| {
2251
+ structurally_same_type_impl ( seen_types, cx, a, b, ckind)
2252
+ } )
2253
+ && structurally_same_type_impl (
2254
+ seen_types,
2255
+ cx,
2256
+ a_sig. output ( ) ,
2257
+ b_sig. output ( ) ,
2258
+ ckind,
2259
+ )
2260
+ }
2261
+ ( Tuple ( a_substs) , Tuple ( b_substs) ) => {
2262
+ a_substs. types ( ) . eq_by ( b_substs. types ( ) , |a_ty, b_ty| {
2263
+ structurally_same_type_impl ( seen_types, cx, a_ty, b_ty, ckind)
2264
+ } )
2265
+ }
2266
+ // For these, it's not quite as easy to define structural-sameness quite so easily.
2267
+ // For the purposes of this lint, take the conservative approach and mark them as
2268
+ // not structurally same.
2269
+ ( Dynamic ( ..) , Dynamic ( ..) )
2270
+ | ( Error ( ..) , Error ( ..) )
2271
+ | ( Closure ( ..) , Closure ( ..) )
2272
+ | ( Generator ( ..) , Generator ( ..) )
2273
+ | ( GeneratorWitness ( ..) , GeneratorWitness ( ..) )
2274
+ | ( Projection ( ..) , Projection ( ..) )
2275
+ | ( Opaque ( ..) , Opaque ( ..) ) => false ,
2276
+
2277
+ // These definitely should have been caught above.
2278
+ ( Bool , Bool ) | ( Char , Char ) | ( Never , Never ) | ( Str , Str ) => unreachable ! ( ) ,
2279
+
2280
+ // An Adt and a primitive or pointer type. This can be FFI-safe if non-null
2281
+ // enum layout optimisation is being applied.
2282
+ ( Adt ( ..) , other_kind) | ( other_kind, Adt ( ..) )
2283
+ if is_primitive_or_pointer ( other_kind) =>
2284
+ {
2285
+ let ( primitive, adt) =
2286
+ if is_primitive_or_pointer ( & a. kind ) { ( a, b) } else { ( b, a) } ;
2287
+ if let Some ( ty) = crate :: types:: repr_nullable_ptr ( cx, adt, ckind) {
2288
+ ty == primitive
2289
+ } else {
2290
+ compare_layouts ( a, b)
2291
+ }
2292
+ }
2293
+ // Otherwise, just compare the layouts. This may fail to lint for some
2294
+ // incompatible types, but at the very least, will stop reads into
2295
+ // uninitialised memory.
2296
+ _ => compare_layouts ( a, b) ,
2290
2297
}
2291
- // Otherwise, just compare the layouts. This may fail to lint for some
2292
- // incompatible types, but at the very least, will stop reads into
2293
- // uninitialised memory.
2294
- _ => compare_layouts ( a, b) ,
2295
- }
2298
+ } )
2296
2299
}
2297
2300
}
2298
2301
let mut seen_types = FxHashSet :: default ( ) ;
0 commit comments