@@ -29,6 +29,7 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree};
2929use rustc_ast:: visit:: { FnCtxt , FnKind } ;
3030use rustc_ast_pretty:: pprust:: { self , expr_to_string} ;
3131use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
32+ use rustc_data_structures:: stack:: ensure_sufficient_stack;
3233use rustc_errors:: { Applicability , DiagnosticBuilder , DiagnosticStyledString } ;
3334use rustc_feature:: { deprecated_attributes, AttributeGate , AttributeTemplate , AttributeType } ;
3435use rustc_feature:: { GateIssue , Stability } ;
@@ -2188,16 +2189,17 @@ impl ClashingExternDeclarations {
21882189 kind. is_primitive ( ) || matches ! ( kind, RawPtr ( ..) | Ref ( ..) )
21892190 } ;
21902191
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) ;
21962198
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)
22012203 && a_fields. eq_by (
22022204 b_fields,
22032205 |& ty:: FieldDef { did : a_did, .. } ,
@@ -2211,88 +2213,89 @@ impl ClashingExternDeclarations {
22112213 )
22122214 } ,
22132215 )
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) ) => {
22612223 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)
22892224 }
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) ,
22902297 }
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+ } )
22962299 }
22972300 }
22982301 let mut seen_types = FxHashSet :: default ( ) ;
0 commit comments