Skip to content

Commit 0bd292d

Browse files
committed
Fix missed same-sized member clash in ClashingExternDeclarations.
1 parent 30a6f57 commit 0bd292d

File tree

3 files changed

+73
-12
lines changed

3 files changed

+73
-12
lines changed

src/librustc_lint/builtin.rs

+32-5
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ use rustc_hir::def_id::DefId;
3838
use rustc_hir::{ForeignItemKind, GenericParamKind, PatKind};
3939
use rustc_hir::{HirId, HirIdSet, Node};
4040
use rustc_middle::lint::LintDiagnosticBuilder;
41-
use rustc_middle::ty::subst::GenericArgKind;
41+
use rustc_middle::ty::subst::{GenericArgKind, Subst};
4242
use rustc_middle::ty::{self, Ty, TyCtxt};
4343
use rustc_session::lint::FutureIncompatibleInfo;
4444
use rustc_span::edition::Edition;
4545
use rustc_span::source_map::Spanned;
4646
use rustc_span::symbol::{kw, sym, Ident, Symbol};
4747
use rustc_span::{BytePos, Span};
48-
use rustc_target::abi::VariantIdx;
48+
use rustc_target::abi::{LayoutOf, VariantIdx};
4949
use rustc_trait_selection::traits::misc::can_type_implement_copy;
5050

5151
use crate::nonstandard_style::{method_context, MethodLateContext};
@@ -2163,17 +2163,44 @@ impl ClashingExternDeclarations {
21632163
let a_kind = &a.kind;
21642164
let b_kind = &b.kind;
21652165

2166-
use rustc_target::abi::LayoutOf;
21672166
let compare_layouts = |a, b| -> bool {
2168-
&cx.layout_of(a).unwrap().layout.abi == &cx.layout_of(b).unwrap().layout.abi
2167+
let a_layout = &cx.layout_of(a).unwrap().layout.abi;
2168+
let b_layout = &cx.layout_of(b).unwrap().layout.abi;
2169+
debug!("{:?} == {:?} = {}", a_layout, b_layout, a_layout == b_layout);
2170+
a_layout == b_layout
21692171
};
21702172

21712173
#[allow(rustc::usage_of_ty_tykind)]
21722174
let is_primitive_or_pointer =
21732175
|kind: &ty::TyKind<'_>| kind.is_primitive() || matches!(kind, RawPtr(..));
21742176

21752177
match (a_kind, b_kind) {
2176-
(Adt(..), Adt(..)) => compare_layouts(a, b),
2178+
(Adt(_, a_substs), Adt(_, b_substs)) => {
2179+
let a = a.subst(cx.tcx, a_substs);
2180+
let b = b.subst(cx.tcx, b_substs);
2181+
debug!("Comparing {:?} and {:?}", a, b);
2182+
2183+
if let (Adt(a_def, ..), Adt(b_def, ..)) = (&a.kind, &b.kind) {
2184+
// Grab a flattened representation of all fields.
2185+
let a_fields = a_def.variants.iter().flat_map(|v| v.fields.iter());
2186+
let b_fields = b_def.variants.iter().flat_map(|v| v.fields.iter());
2187+
compare_layouts(a, b)
2188+
&& a_fields.eq_by(
2189+
b_fields,
2190+
|&ty::FieldDef { did: a_did, .. },
2191+
&ty::FieldDef { did: b_did, .. }| {
2192+
Self::structurally_same_type(
2193+
cx,
2194+
tcx.type_of(a_did),
2195+
tcx.type_of(b_did),
2196+
ckind,
2197+
)
2198+
},
2199+
)
2200+
} else {
2201+
unreachable!()
2202+
}
2203+
}
21772204
(Array(a_ty, a_const), Array(b_ty, b_const)) => {
21782205
// For arrays, we also check the constness of the type.
21792206
a_const.val == b_const.val

src/test/ui/lint/clashing-extern-fn.rs

+22
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,28 @@ mod sameish_members {
174174
}
175175
}
176176

177+
mod same_sized_members_clash {
178+
mod a {
179+
#[repr(C)]
180+
struct Point3 {
181+
x: f32,
182+
y: f32,
183+
z: f32,
184+
}
185+
extern "C" { fn origin() -> Point3; }
186+
}
187+
mod b {
188+
#[repr(C)]
189+
struct Point3 {
190+
x: i32,
191+
y: i32,
192+
z: i32, // NOTE: Incorrectly redeclared as i32
193+
}
194+
extern "C" { fn origin() -> Point3; }
195+
//~^ WARN `origin` redeclared with a different signature
196+
}
197+
}
198+
177199
mod transparent {
178200
#[repr(transparent)]
179201
struct T(usize);

src/test/ui/lint/clashing-extern-fn.stderr

+19-7
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,20 @@ LL | fn draw_point(p: Point);
105105
= note: expected `unsafe extern "C" fn(sameish_members::a::Point)`
106106
found `unsafe extern "C" fn(sameish_members::b::Point)`
107107

108+
warning: `origin` redeclared with a different signature
109+
--> $DIR/clashing-extern-fn.rs:194:22
110+
|
111+
LL | extern "C" { fn origin() -> Point3; }
112+
| ---------------------- `origin` previously declared here
113+
...
114+
LL | extern "C" { fn origin() -> Point3; }
115+
| ^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
116+
|
117+
= note: expected `unsafe extern "C" fn() -> same_sized_members_clash::a::Point3`
118+
found `unsafe extern "C" fn() -> same_sized_members_clash::b::Point3`
119+
108120
warning: `transparent_incorrect` redeclared with a different signature
109-
--> $DIR/clashing-extern-fn.rs:195:13
121+
--> $DIR/clashing-extern-fn.rs:217:13
110122
|
111123
LL | fn transparent_incorrect() -> T;
112124
| -------------------------------- `transparent_incorrect` previously declared here
@@ -118,7 +130,7 @@ LL | fn transparent_incorrect() -> isize;
118130
found `unsafe extern "C" fn() -> isize`
119131

120132
warning: `missing_return_type` redeclared with a different signature
121-
--> $DIR/clashing-extern-fn.rs:213:13
133+
--> $DIR/clashing-extern-fn.rs:235:13
122134
|
123135
LL | fn missing_return_type() -> usize;
124136
| ---------------------------------- `missing_return_type` previously declared here
@@ -130,7 +142,7 @@ LL | fn missing_return_type();
130142
found `unsafe extern "C" fn()`
131143

132144
warning: `non_zero_usize` redeclared with a different signature
133-
--> $DIR/clashing-extern-fn.rs:231:13
145+
--> $DIR/clashing-extern-fn.rs:253:13
134146
|
135147
LL | fn non_zero_usize() -> core::num::NonZeroUsize;
136148
| ----------------------------------------------- `non_zero_usize` previously declared here
@@ -142,7 +154,7 @@ LL | fn non_zero_usize() -> usize;
142154
found `unsafe extern "C" fn() -> usize`
143155

144156
warning: `non_null_ptr` redeclared with a different signature
145-
--> $DIR/clashing-extern-fn.rs:233:13
157+
--> $DIR/clashing-extern-fn.rs:255:13
146158
|
147159
LL | fn non_null_ptr() -> core::ptr::NonNull<usize>;
148160
| ----------------------------------------------- `non_null_ptr` previously declared here
@@ -154,7 +166,7 @@ LL | fn non_null_ptr() -> *const usize;
154166
found `unsafe extern "C" fn() -> *const usize`
155167

156168
warning: `option_non_zero_usize_incorrect` redeclared with a different signature
157-
--> $DIR/clashing-extern-fn.rs:259:13
169+
--> $DIR/clashing-extern-fn.rs:281:13
158170
|
159171
LL | fn option_non_zero_usize_incorrect() -> usize;
160172
| ---------------------------------------------- `option_non_zero_usize_incorrect` previously declared here
@@ -166,7 +178,7 @@ LL | fn option_non_zero_usize_incorrect() -> isize;
166178
found `unsafe extern "C" fn() -> isize`
167179

168180
warning: `option_non_null_ptr_incorrect` redeclared with a different signature
169-
--> $DIR/clashing-extern-fn.rs:261:13
181+
--> $DIR/clashing-extern-fn.rs:283:13
170182
|
171183
LL | fn option_non_null_ptr_incorrect() -> *const usize;
172184
| --------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here
@@ -177,5 +189,5 @@ LL | fn option_non_null_ptr_incorrect() -> *const isize;
177189
= note: expected `unsafe extern "C" fn() -> *const usize`
178190
found `unsafe extern "C" fn() -> *const isize`
179191

180-
warning: 14 warnings emitted
192+
warning: 15 warnings emitted
181193

0 commit comments

Comments
 (0)