@@ -2198,45 +2198,46 @@ impl ClashingExternDeclarations {
21982198 debug ! ( "structurally_same_type_impl(cx, a = {:?}, b = {:?})" , a, b) ;
21992199 match seen_types. get ( a, b) {
22002200 // If we've already computed the result, just return the memoized result.
2201- SeenSetResult :: Computed ( result) => result,
2201+ SeenSetResult :: Computed ( result) => return result,
22022202 // We are already in the process of computing structural sameness for this type,
22032203 // meaning we've found a cycle. The types are structurally same, then.
2204- SeenSetResult :: Computing => true ,
2205- // We haven't seen this combination of types at all -- compute their sameness.
2206- SeenSetResult :: Unseen => {
2207- seen_types. mark_computing ( a, b) ;
2208- let tcx = cx. tcx ;
2209- let result = if a == b || rustc_middle:: ty:: TyS :: same_type ( a, b) {
2210- // All nominally-same types are structurally same, too.
2211- true
2212- } else {
2213- // Do a full, depth-first comparison between the two.
2214- use rustc_middle:: ty:: TyKind :: * ;
2215- let a_kind = & a. kind ;
2216- let b_kind = & b. kind ;
2217-
2218- let compare_layouts = |a, b| -> bool {
2219- let a_layout = & cx. layout_of ( a) . unwrap ( ) . layout . abi ;
2220- let b_layout = & cx. layout_of ( b) . unwrap ( ) . layout . abi ;
2221- debug ! ( "{:?} == {:?} = {}" , a_layout, b_layout, a_layout == b_layout) ;
2222- a_layout == b_layout
2223- } ;
2204+ SeenSetResult :: Computing => return true ,
2205+ // We haven't seen this combination of types at all -- continue on to computing
2206+ // their sameness.
2207+ SeenSetResult :: Unseen => ( ) ,
2208+ }
2209+ seen_types. mark_computing ( a, b) ;
2210+ let tcx = cx. tcx ;
2211+ let result = if a == b || rustc_middle:: ty:: TyS :: same_type ( a, b) {
2212+ // All nominally-same types are structurally same, too.
2213+ true
2214+ } else {
2215+ // Do a full, depth-first comparison between the two.
2216+ use rustc_middle:: ty:: TyKind :: * ;
2217+ let a_kind = & a. kind ;
2218+ let b_kind = & b. kind ;
2219+
2220+ let compare_layouts = |a, b| -> bool {
2221+ let a_layout = & cx. layout_of ( a) . unwrap ( ) . layout . abi ;
2222+ let b_layout = & cx. layout_of ( b) . unwrap ( ) . layout . abi ;
2223+ debug ! ( "{:?} == {:?} = {}" , a_layout, b_layout, a_layout == b_layout) ;
2224+ a_layout == b_layout
2225+ } ;
22242226
2225- #[ allow( rustc:: usage_of_ty_tykind) ]
2226- let is_primitive_or_pointer = |kind : & ty:: TyKind < ' _ > | {
2227- kind. is_primitive ( ) || matches ! ( kind, RawPtr ( ..) )
2228- } ;
2227+ #[ allow( rustc:: usage_of_ty_tykind) ]
2228+ let is_primitive_or_pointer =
2229+ |kind : & ty:: TyKind < ' _ > | kind. is_primitive ( ) || matches ! ( kind, RawPtr ( ..) ) ;
22292230
2230- match ( a_kind, b_kind) {
2231- ( Adt ( a_def, a_substs) , Adt ( b_def, b_substs) ) => {
2232- let a = a. subst ( cx. tcx , a_substs) ;
2233- let b = b. subst ( cx. tcx , b_substs) ;
2234- debug ! ( "Comparing {:?} and {:?}" , a, b) ;
2231+ match ( a_kind, b_kind) {
2232+ ( Adt ( a_def, a_substs) , Adt ( b_def, b_substs) ) => {
2233+ let a = a. subst ( cx. tcx , a_substs) ;
2234+ let b = b. subst ( cx. tcx , b_substs) ;
2235+ debug ! ( "Comparing {:?} and {:?}" , a, b) ;
22352236
2236- // Grab a flattened representation of all fields.
2237- let a_fields = a_def. variants . iter ( ) . flat_map ( |v| v. fields . iter ( ) ) ;
2238- let b_fields = b_def. variants . iter ( ) . flat_map ( |v| v. fields . iter ( ) ) ;
2239- compare_layouts ( a, b)
2237+ // Grab a flattened representation of all fields.
2238+ let a_fields = a_def. variants . iter ( ) . flat_map ( |v| v. fields . iter ( ) ) ;
2239+ let b_fields = b_def. variants . iter ( ) . flat_map ( |v| v. fields . iter ( ) ) ;
2240+ compare_layouts ( a, b)
22402241 && a_fields. eq_by (
22412242 b_fields,
22422243 |& ty:: FieldDef { did : a_did, .. } ,
@@ -2250,99 +2251,91 @@ impl ClashingExternDeclarations {
22502251 )
22512252 } ,
22522253 )
2253- }
2254- ( Array ( a_ty, a_const) , Array ( b_ty, b_const) ) => {
2255- // For arrays, we also check the constness of the type.
2256- a_const. val == b_const. val
2257- && structurally_same_type_impl (
2258- seen_types, cx, a_ty, b_ty, ckind,
2259- )
2260- }
2261- ( Slice ( a_ty) , Slice ( b_ty) ) => {
2262- structurally_same_type_impl ( seen_types, cx, a_ty, b_ty, ckind)
2263- }
2264- ( RawPtr ( a_tymut) , RawPtr ( b_tymut) ) => {
2265- a_tymut. mutbl == b_tymut. mutbl
2266- && structurally_same_type_impl (
2267- seen_types,
2268- cx,
2269- & a_tymut. ty ,
2270- & b_tymut. ty ,
2271- ckind,
2272- )
2273- }
2274- ( Ref ( _a_region, a_ty, a_mut) , Ref ( _b_region, b_ty, b_mut) ) => {
2275- // For structural sameness, we don't need the region to be same.
2276- a_mut == b_mut
2277- && structurally_same_type_impl (
2278- seen_types, cx, a_ty, b_ty, ckind,
2279- )
2280- }
2281- ( FnDef ( ..) , FnDef ( ..) ) => {
2282- let a_poly_sig = a. fn_sig ( tcx) ;
2283- let b_poly_sig = b. fn_sig ( tcx) ;
2284-
2285- // As we don't compare regions, skip_binder is fine.
2286- let a_sig = a_poly_sig. skip_binder ( ) ;
2287- let b_sig = b_poly_sig. skip_binder ( ) ;
2288-
2289- ( a_sig. abi , a_sig. unsafety , a_sig. c_variadic )
2290- == ( b_sig. abi , b_sig. unsafety , b_sig. c_variadic )
2291- && a_sig. inputs ( ) . iter ( ) . eq_by ( b_sig. inputs ( ) . iter ( ) , |a, b| {
2292- structurally_same_type_impl ( seen_types, cx, a, b, ckind)
2293- } )
2294- && structurally_same_type_impl (
2295- seen_types,
2296- cx,
2297- a_sig. output ( ) ,
2298- b_sig. output ( ) ,
2299- ckind,
2300- )
2301- }
2302- ( Tuple ( a_substs) , Tuple ( b_substs) ) => {
2303- a_substs. types ( ) . eq_by ( b_substs. types ( ) , |a_ty, b_ty| {
2304- structurally_same_type_impl ( seen_types, cx, a_ty, b_ty, ckind)
2305- } )
2306- }
2307- // For these, it's not quite as easy to define structural-sameness quite so easily.
2308- // For the purposes of this lint, take the conservative approach and mark them as
2309- // not structurally same.
2310- ( Dynamic ( ..) , Dynamic ( ..) )
2311- | ( Error ( ..) , Error ( ..) )
2312- | ( Closure ( ..) , Closure ( ..) )
2313- | ( Generator ( ..) , Generator ( ..) )
2314- | ( GeneratorWitness ( ..) , GeneratorWitness ( ..) )
2315- | ( Projection ( ..) , Projection ( ..) )
2316- | ( Opaque ( ..) , Opaque ( ..) ) => false ,
2317-
2318- // These definitely should have been caught above.
2319- ( Bool , Bool ) | ( Char , Char ) | ( Never , Never ) | ( Str , Str ) => {
2320- unreachable ! ( )
2321- }
2322-
2323- // An Adt and a primitive type. This can be FFI-safe is the ADT is an enum with a
2324- // non-null field.
2325- ( Adt ( ..) , other_kind) | ( other_kind, Adt ( ..) )
2326- if is_primitive_or_pointer ( other_kind) =>
2327- {
2328- let ( primitive, adt) =
2329- if is_primitive_or_pointer ( & a. kind ) { ( a, b) } else { ( b, a) } ;
2330- if let Some ( ty) = crate :: types:: repr_nullable_ptr ( cx, adt, ckind) {
2331- ty == primitive
2332- } else {
2333- compare_layouts ( a, b)
2334- }
2335- }
2336- // Otherwise, just compare the layouts. This may fail to lint for some
2337- // incompatible types, but at the very least, will stop reads into
2338- // uninitialised memory.
2339- _ => compare_layouts ( a, b) ,
2254+ }
2255+ ( Array ( a_ty, a_const) , Array ( b_ty, b_const) ) => {
2256+ // For arrays, we also check the constness of the type.
2257+ a_const. val == b_const. val
2258+ && structurally_same_type_impl ( seen_types, cx, a_ty, b_ty, ckind)
2259+ }
2260+ ( Slice ( a_ty) , Slice ( b_ty) ) => {
2261+ structurally_same_type_impl ( seen_types, cx, a_ty, b_ty, ckind)
2262+ }
2263+ ( RawPtr ( a_tymut) , RawPtr ( b_tymut) ) => {
2264+ a_tymut. mutbl == b_tymut. mutbl
2265+ && structurally_same_type_impl (
2266+ seen_types,
2267+ cx,
2268+ & a_tymut. ty ,
2269+ & b_tymut. ty ,
2270+ ckind,
2271+ )
2272+ }
2273+ ( Ref ( _a_region, a_ty, a_mut) , Ref ( _b_region, b_ty, b_mut) ) => {
2274+ // For structural sameness, we don't need the region to be same.
2275+ a_mut == b_mut
2276+ && structurally_same_type_impl ( seen_types, cx, a_ty, b_ty, ckind)
2277+ }
2278+ ( FnDef ( ..) , FnDef ( ..) ) => {
2279+ let a_poly_sig = a. fn_sig ( tcx) ;
2280+ let b_poly_sig = b. fn_sig ( tcx) ;
2281+
2282+ // As we don't compare regions, skip_binder is fine.
2283+ let a_sig = a_poly_sig. skip_binder ( ) ;
2284+ let b_sig = b_poly_sig. skip_binder ( ) ;
2285+
2286+ ( a_sig. abi , a_sig. unsafety , a_sig. c_variadic )
2287+ == ( b_sig. abi , b_sig. unsafety , b_sig. c_variadic )
2288+ && a_sig. inputs ( ) . iter ( ) . eq_by ( b_sig. inputs ( ) . iter ( ) , |a, b| {
2289+ structurally_same_type_impl ( seen_types, cx, a, b, ckind)
2290+ } )
2291+ && structurally_same_type_impl (
2292+ seen_types,
2293+ cx,
2294+ a_sig. output ( ) ,
2295+ b_sig. output ( ) ,
2296+ ckind,
2297+ )
2298+ }
2299+ ( Tuple ( a_substs) , Tuple ( b_substs) ) => {
2300+ a_substs. types ( ) . eq_by ( b_substs. types ( ) , |a_ty, b_ty| {
2301+ structurally_same_type_impl ( seen_types, cx, a_ty, b_ty, ckind)
2302+ } )
2303+ }
2304+ // For these, it's not quite as easy to define structural-sameness quite so easily.
2305+ // For the purposes of this lint, take the conservative approach and mark them as
2306+ // not structurally same.
2307+ ( Dynamic ( ..) , Dynamic ( ..) )
2308+ | ( Error ( ..) , Error ( ..) )
2309+ | ( Closure ( ..) , Closure ( ..) )
2310+ | ( Generator ( ..) , Generator ( ..) )
2311+ | ( GeneratorWitness ( ..) , GeneratorWitness ( ..) )
2312+ | ( Projection ( ..) , Projection ( ..) )
2313+ | ( Opaque ( ..) , Opaque ( ..) ) => false ,
2314+
2315+ // These definitely should have been caught above.
2316+ ( Bool , Bool ) | ( Char , Char ) | ( Never , Never ) | ( Str , Str ) => unreachable ! ( ) ,
2317+
2318+ // An Adt and a primitive type. This can be FFI-safe is the ADT is an enum with a
2319+ // non-null field.
2320+ ( Adt ( ..) , other_kind) | ( other_kind, Adt ( ..) )
2321+ if is_primitive_or_pointer ( other_kind) =>
2322+ {
2323+ let ( primitive, adt) =
2324+ if is_primitive_or_pointer ( & a. kind ) { ( a, b) } else { ( b, a) } ;
2325+ if let Some ( ty) = crate :: types:: repr_nullable_ptr ( cx, adt, ckind) {
2326+ ty == primitive
2327+ } else {
2328+ compare_layouts ( a, b)
23402329 }
2341- } ;
2342- seen_types. mark_computed ( a, b, result) ;
2343- result
2330+ }
2331+ // Otherwise, just compare the layouts. This may fail to lint for some
2332+ // incompatible types, but at the very least, will stop reads into
2333+ // uninitialised memory.
2334+ _ => compare_layouts ( a, b) ,
23442335 }
2345- }
2336+ } ;
2337+ seen_types. mark_computed ( a, b, result) ;
2338+ result
23462339 }
23472340 let mut seen_types = SeenSet :: new ( ) ;
23482341 structurally_same_type_impl ( & mut seen_types, cx, a, b, ckind)
0 commit comments