Skip to content

Commit 058c0e4

Browse files
committed
Handle static whose type is a function pointer
1 parent de45224 commit 058c0e4

2 files changed

Lines changed: 27 additions & 17 deletions

File tree

compiler/rustc_lint/src/runtime_symbols.rs

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,8 @@ impl<'tcx> LateLintPass<'tcx> for RuntimeSymbols {
8787
};
8888

8989
let def_id = item.owner_id.def_id;
90-
let static_ty = cx.tcx.type_of(def_id).instantiate_identity();
9190

92-
check_static(cx, &symbol_name, static_ty, item.span);
91+
check_static(cx, &symbol_name, def_id, item.span);
9392
}
9493
hir::ItemKind::ForeignMod { abi: _, items } => {
9594
for item in items {
@@ -107,9 +106,7 @@ impl<'tcx> LateLintPass<'tcx> for RuntimeSymbols {
107106
check_fn(cx, &symbol_name.name, fn_sig, did);
108107
}
109108
ForeignItemKind::Static(..) => {
110-
let def_id = item.owner_id.def_id;
111-
let static_ty = cx.tcx.type_of(def_id).instantiate_identity();
112-
check_static(cx, &symbol_name.name, static_ty, item.span);
109+
check_static(cx, &symbol_name.name, did, item.span);
113110
}
114111
ForeignItemKind::Type => return,
115112
}
@@ -159,7 +156,7 @@ fn check_fn(cx: &LateContext<'_>, symbol_name: &str, sig: FnSig<'_>, did: LocalD
159156
}
160157
}
161158

162-
fn check_static<'tcx>(cx: &LateContext<'tcx>, symbol_name: &str, static_ty: Ty<'tcx>, sp: Span) {
159+
fn check_static<'tcx>(cx: &LateContext<'tcx>, symbol_name: &str, did: LocalDefId, sp: Span) {
163160
let Some(expected_symbol) = EXPECTED_SYMBOLS.iter().find(|es| es.symbol == symbol_name) else {
164161
// The symbol name does not correspond to a runtime symbols, bail out
165162
return;
@@ -170,19 +167,32 @@ fn check_static<'tcx>(cx: &LateContext<'tcx>, symbol_name: &str, static_ty: Ty<'
170167
return;
171168
};
172169

173-
// Unconditionally report a mismatch, a static cannot ever be a function definition
170+
// Get the static type
171+
let static_ty = cx.tcx.type_of(did).instantiate_identity();
174172

173+
// Peel Option<...> and get the inner type (see std weak! macro with #[linkage = "extern_weak"])
174+
let inner_static_ty: Ty<'_> = match static_ty.kind() {
175+
ty::Adt(def, args) if Some(def.did()) == cx.tcx.lang_items().option_type() => {
176+
args.type_at(0)
177+
}
178+
_ => static_ty,
179+
};
180+
181+
// Get the expected symbol function signature
175182
let lang_sig =
176183
cx.tcx.erase_and_anonymize_regions(cx.tcx.fn_sig(expected_def_id).instantiate_identity());
177184
let expected = Ty::new_fn_ptr(cx.tcx, lang_sig);
178185

179-
cx.emit_span_lint(
180-
INVALID_RUNTIME_SYMBOL_DEFINITIONS,
181-
sp,
182-
RedefiningRuntimeSymbolsDiag::Static {
183-
static_ty,
184-
symbol_name: symbol_name.to_string(),
185-
expected_fn_sig: expected,
186-
},
187-
);
186+
// Compare the expected function signature with the static type, report an error if they don't match
187+
if expected != inner_static_ty {
188+
cx.emit_span_lint(
189+
INVALID_RUNTIME_SYMBOL_DEFINITIONS,
190+
sp,
191+
RedefiningRuntimeSymbolsDiag::Static {
192+
static_ty,
193+
symbol_name: symbol_name.to_string(),
194+
expected_fn_sig: expected,
195+
},
196+
);
197+
}
188198
}

tests/ui/lint/runtime-symbols.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ fn valid() {
4747

4848
fn bcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int;
4949

50-
fn strlen(s: *const c_char) -> usize;
50+
static strlen: Option<unsafe extern "C" fn(s: *const c_char) -> usize>;
5151
}
5252
}
5353

0 commit comments

Comments
 (0)