Skip to content

Commit 0080494

Browse files
committed
Handle static whose type is a function pointer
1 parent 856305b commit 0080494

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
}
@@ -163,7 +160,7 @@ fn check_fn(cx: &LateContext<'_>, symbol_name: &str, sig: FnSig<'_>, did: LocalD
163160
}
164161
}
165162

166-
fn check_static<'tcx>(cx: &LateContext<'tcx>, symbol_name: &str, static_ty: Ty<'tcx>, sp: Span) {
163+
fn check_static<'tcx>(cx: &LateContext<'tcx>, symbol_name: &str, did: LocalDefId, sp: Span) {
167164
let Some(expected_symbol) = EXPECTED_SYMBOLS.iter().find(|es| es.symbol == symbol_name) else {
168165
// The symbol name does not correspond to a runtime symbols, bail out
169166
return;
@@ -174,22 +171,35 @@ fn check_static<'tcx>(cx: &LateContext<'tcx>, symbol_name: &str, static_ty: Ty<'
174171
return;
175172
};
176173

177-
// Unconditionally report a mismatch, a static cannot ever be a function definition
174+
// Get the static type
175+
let static_ty = cx.tcx.type_of(did).instantiate_identity().skip_norm_wip();
178176

177+
// Peel Option<...> and get the inner type (see std weak! macro with #[linkage = "extern_weak"])
178+
let inner_static_ty: Ty<'_> = match static_ty.kind() {
179+
ty::Adt(def, args) if Some(def.did()) == cx.tcx.lang_items().option_type() => {
180+
args.type_at(0)
181+
}
182+
_ => static_ty,
183+
};
184+
185+
// Get the expected symbol function signature
179186
let lang_sig = cx.tcx.normalize_erasing_regions(
180187
cx.typing_env(),
181188
cx.tcx.fn_sig(expected_def_id).instantiate_identity(),
182189
);
183190

184191
let expected = Ty::new_fn_ptr(cx.tcx, lang_sig);
185192

186-
cx.emit_span_lint(
187-
INVALID_RUNTIME_SYMBOL_DEFINITIONS,
188-
sp,
189-
RedefiningRuntimeSymbolsDiag::Static {
190-
static_ty,
191-
symbol_name: symbol_name.to_string(),
192-
expected_fn_sig: expected,
193-
},
194-
);
193+
// Compare the expected function signature with the static type, report an error if they don't match
194+
if expected != inner_static_ty {
195+
cx.emit_span_lint(
196+
INVALID_RUNTIME_SYMBOL_DEFINITIONS,
197+
sp,
198+
RedefiningRuntimeSymbolsDiag::Static {
199+
static_ty,
200+
symbol_name: symbol_name.to_string(),
201+
expected_fn_sig: expected,
202+
},
203+
);
204+
}
195205
}

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)