2020//! If you define a new `LateLintPass`, you will also need to add it to the
2121//! `late_lint_methods!` invocation in `lib.rs`.
2222
23- use crate :: { EarlyContext , EarlyLintPass , LateContext , LateLintPass , LintContext } ;
23+ use crate :: {
24+ types:: CItemKind , EarlyContext , EarlyLintPass , LateContext , LateLintPass , LintContext ,
25+ } ;
2426use rustc_ast:: ast:: { self , Expr } ;
2527use rustc_ast:: attr:: { self , HasAttrs } ;
2628use rustc_ast:: tokenstream:: { TokenStream , TokenTree } ;
@@ -2144,7 +2146,13 @@ impl ClashingExternDeclarations {
21442146 /// Checks whether two types are structurally the same enough that the declarations shouldn't
21452147 /// clash. We need this so we don't emit a lint when two modules both declare an extern struct,
21462148 /// with the same members (as the declarations shouldn't clash).
2147- fn structurally_same_type < ' tcx > ( cx : & LateContext < ' tcx > , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> bool {
2149+ fn structurally_same_type < ' tcx > (
2150+ cx : & LateContext < ' tcx > ,
2151+ a : Ty < ' tcx > ,
2152+ b : Ty < ' tcx > ,
2153+ ckind : CItemKind ,
2154+ ) -> bool {
2155+ debug ! ( "structurally_same_type(cx, a = {:?}, b = {:?})" , a, b) ;
21482156 let tcx = cx. tcx ;
21492157 if a == b || rustc_middle:: ty:: TyS :: same_type ( a, b) {
21502158 // All nominally-same types are structurally same, too.
@@ -2156,29 +2164,30 @@ impl ClashingExternDeclarations {
21562164 let b_kind = & b. kind ;
21572165
21582166 use rustc_target:: abi:: LayoutOf ;
2159- let compare_layouts = |a, b| {
2160- let a_layout = & cx. layout_of ( a) . unwrap ( ) . layout . abi ;
2161- let b_layout = & cx. layout_of ( b) . unwrap ( ) . layout . abi ;
2162- let result = a_layout == b_layout;
2163- result
2167+ let compare_layouts = |a, b| -> bool {
2168+ & cx. layout_of ( a) . unwrap ( ) . layout . abi == & cx. layout_of ( b) . unwrap ( ) . layout . abi
21642169 } ;
21652170
2171+ #[ allow( rustc:: usage_of_ty_tykind) ]
2172+ let is_primitive_or_pointer =
2173+ |kind : & ty:: TyKind < ' _ > | kind. is_primitive ( ) || matches ! ( kind, RawPtr ( ..) ) ;
2174+
21662175 match ( a_kind, b_kind) {
21672176 ( Adt ( ..) , Adt ( ..) ) => compare_layouts ( a, b) ,
21682177 ( Array ( a_ty, a_const) , Array ( b_ty, b_const) ) => {
21692178 // For arrays, we also check the constness of the type.
21702179 a_const. val == b_const. val
2171- && Self :: structurally_same_type ( cx, a_const. ty , b_const. ty )
2172- && Self :: structurally_same_type ( cx, a_ty, b_ty)
2180+ && Self :: structurally_same_type ( cx, a_const. ty , b_const. ty , ckind )
2181+ && Self :: structurally_same_type ( cx, a_ty, b_ty, ckind )
21732182 }
2174- ( Slice ( a_ty) , Slice ( b_ty) ) => Self :: structurally_same_type ( cx, a_ty, b_ty) ,
2183+ ( Slice ( a_ty) , Slice ( b_ty) ) => Self :: structurally_same_type ( cx, a_ty, b_ty, ckind ) ,
21752184 ( RawPtr ( a_tymut) , RawPtr ( b_tymut) ) => {
21762185 a_tymut. mutbl == a_tymut. mutbl
2177- && Self :: structurally_same_type ( cx, & a_tymut. ty , & b_tymut. ty )
2186+ && Self :: structurally_same_type ( cx, & a_tymut. ty , & b_tymut. ty , ckind )
21782187 }
21792188 ( Ref ( _a_region, a_ty, a_mut) , Ref ( _b_region, b_ty, b_mut) ) => {
21802189 // For structural sameness, we don't need the region to be same.
2181- a_mut == b_mut && Self :: structurally_same_type ( cx, a_ty, b_ty)
2190+ a_mut == b_mut && Self :: structurally_same_type ( cx, a_ty, b_ty, ckind )
21822191 }
21832192 ( FnDef ( ..) , FnDef ( ..) ) => {
21842193 let a_poly_sig = a. fn_sig ( tcx) ;
@@ -2191,13 +2200,13 @@ impl ClashingExternDeclarations {
21912200 ( a_sig. abi , a_sig. unsafety , a_sig. c_variadic )
21922201 == ( b_sig. abi , b_sig. unsafety , b_sig. c_variadic )
21932202 && a_sig. inputs ( ) . iter ( ) . eq_by ( b_sig. inputs ( ) . iter ( ) , |a, b| {
2194- Self :: structurally_same_type ( cx, a, b)
2203+ Self :: structurally_same_type ( cx, a, b, ckind )
21952204 } )
2196- && Self :: structurally_same_type ( cx, a_sig. output ( ) , b_sig. output ( ) )
2205+ && Self :: structurally_same_type ( cx, a_sig. output ( ) , b_sig. output ( ) , ckind )
21972206 }
21982207 ( Tuple ( a_substs) , Tuple ( b_substs) ) => {
21992208 a_substs. types ( ) . eq_by ( b_substs. types ( ) , |a_ty, b_ty| {
2200- Self :: structurally_same_type ( cx, a_ty, b_ty)
2209+ Self :: structurally_same_type ( cx, a_ty, b_ty, ckind )
22012210 } )
22022211 }
22032212 // For these, it's not quite as easy to define structural-sameness quite so easily.
@@ -2210,58 +2219,27 @@ impl ClashingExternDeclarations {
22102219 | ( GeneratorWitness ( ..) , GeneratorWitness ( ..) )
22112220 | ( Projection ( ..) , Projection ( ..) )
22122221 | ( Opaque ( ..) , Opaque ( ..) ) => false ,
2222+
22132223 // These definitely should have been caught above.
22142224 ( Bool , Bool ) | ( Char , Char ) | ( Never , Never ) | ( Str , Str ) => unreachable ! ( ) ,
22152225
2216- // Disjoint kinds.
2217- ( _, _) => {
2218- // First, check if the conversion is FFI-safe. This can happen if the type is an
2219- // enum with a non-null field (see improper_ctypes).
2220- let is_primitive_or_pointer =
2221- |ty : Ty < ' tcx > | ty. is_primitive ( ) || matches ! ( ty. kind, RawPtr ( ..) ) ;
2222- if ( is_primitive_or_pointer ( a) || is_primitive_or_pointer ( b) )
2223- && !( is_primitive_or_pointer ( a) && is_primitive_or_pointer ( b) )
2224- && ( matches ! ( a_kind, Adt ( ..) ) || matches ! ( b_kind, Adt ( ..) ) )
2225- /* ie, 1 adt and 1 primitive */
2226- {
2227- let ( primitive_ty, adt_ty) =
2228- if is_primitive_or_pointer ( a) { ( a, b) } else { ( b, a) } ;
2229- // First, check that the Adt is FFI-safe to use.
2230- use crate :: types:: { ImproperCTypesMode , ImproperCTypesVisitor } ;
2231- let vis =
2232- ImproperCTypesVisitor { cx, mode : ImproperCTypesMode :: Declarations } ;
2233-
2234- if let Adt ( def, substs) = adt_ty. kind {
2235- let repr_nullable = vis. is_repr_nullable_ptr ( adt_ty, def, substs) ;
2236- if let Some ( safe_ty) = repr_nullable {
2237- let safe_ty_layout = & cx. layout_of ( safe_ty) . unwrap ( ) ;
2238- let primitive_ty_layout = & cx. layout_of ( primitive_ty) . unwrap ( ) ;
2239-
2240- use rustc_target:: abi:: Abi :: * ;
2241- match ( & safe_ty_layout. abi , & primitive_ty_layout. abi ) {
2242- ( Scalar ( safe) , Scalar ( primitive) ) => {
2243- // The two types are safe to convert between if `safe` is
2244- // the non-zero version of `primitive`.
2245- use std:: ops:: RangeInclusive ;
2246-
2247- let safe_range: & RangeInclusive < _ > = & safe. valid_range ;
2248- let primitive_range: & RangeInclusive < _ > =
2249- & primitive. valid_range ;
2250-
2251- return primitive_range. end ( ) == safe_range. end ( )
2252- // This check works for both signed and unsigned types due to wraparound.
2253- && * safe_range. start ( ) == 1
2254- && * primitive_range. start ( ) == 0 ;
2255- }
2256- _ => { }
2257- }
2258- }
2259- }
2226+ // An Adt and a primitive type. This can be FFI-safe is the ADT is an enum with a
2227+ // non-null field.
2228+ ( Adt ( ..) , other_kind) | ( other_kind, Adt ( ..) )
2229+ if is_primitive_or_pointer ( other_kind) =>
2230+ {
2231+ let ( primitive, adt) =
2232+ if is_primitive_or_pointer ( & a. kind ) { ( a, b) } else { ( b, a) } ;
2233+ if let Some ( ty) = crate :: types:: repr_nullable_ptr ( cx, adt, ckind) {
2234+ ty == primitive
2235+ } else {
2236+ compare_layouts ( a, b)
22602237 }
2261- // Otherwise, just compare the layouts. This may be underapproximate, but at
2262- // the very least, will stop reads into uninitialised memory.
2263- compare_layouts ( a, b)
22642238 }
2239+ // Otherwise, just compare the layouts. This may fail to lint for some
2240+ // incompatible types, but at the very least, will stop reads into
2241+ // uninitialised memory.
2242+ _ => compare_layouts ( a, b) ,
22652243 }
22662244 }
22672245 }
@@ -2282,7 +2260,12 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
22822260 existing_hid, existing_decl_ty, this_fi. hir_id, this_decl_ty
22832261 ) ;
22842262 // Check that the declarations match.
2285- if !Self :: structurally_same_type ( cx, existing_decl_ty, this_decl_ty) {
2263+ if !Self :: structurally_same_type (
2264+ cx,
2265+ existing_decl_ty,
2266+ this_decl_ty,
2267+ CItemKind :: Declaration ,
2268+ ) {
22862269 let orig_fi = tcx. hir ( ) . expect_foreign_item ( existing_hid) ;
22872270 let orig = Self :: name_of_extern_decl ( tcx, orig_fi) ;
22882271
0 commit comments