authorbors <bors@rust-lang.org> 2026-06-26 18:28:45 UTC
committerbors <bors@rust-lang.org> 2026-06-26 18:28:45 UTC
logce9954c0cfc4bf26b82aef16e6fd8b020c237992
treec24ebfa039fba107ec21ef2eff5aaa5a62922622
parenteb6346c659ccb0468a1477c716ca5450a1fa9ba1
parent56d17c4d191feba4e4a016e1ffa74420f61a2703

Auto merge of #155521 - Urgau:runtime-symbols, r=davidtwco

Add lint against invalid runtime symbol definitions This PR adds a deny-by-default lint againts invalid runtime symbol definitions, those runtime symbols are assumed and used by `core`[^1] and `rustc` with a specific definition. We have had multiple reports of users tripping over `std` symbols (addressed in a future PR): - [Why does `#[no_mangle] fn open() {}` make `cargo t` hang?](https://users.rust-lang.org/t/why-does-no-mangle-fn-open-make-cargo-t-hang/103423) - [Pointer becomes misaligned in test with `no_mangle`](https://users.rust-lang.org/t/pointer-becomes-misaligned-in-test-with-no-mangle/126580) This PR is a second attempt after https://github.com/rust-lang/rust/pull/146505, where T-lang had [some reservations](https://github.com/rust-lang/rust/pull/146505#issuecomment-3492657109) about a blanket lint that does not check the signature, which is now done with this PR, and about linting of `std` runtime symbols when std is not linked, which this PR omits by not including any std runtime symbols (for now). ## `invalid_runtime_symbol_definitions` *(deny-by-default)* The `invalid_runtime_symbol_definitions` lint checks the signature of items whose symbol name is a runtime symbols expected by `core` differs significantly from the expected signature (like mismatch ABI, mismatch C variadics, mismatch argument count, missing return type, ...). ### Example ```rust,compile_fail #[unsafe(no_mangle)] pub fn memcmp() {} // invalid definition of the `memcmp` runtime symbol ``` ```text error: invalid definition of the runtime `memcmp` symbol used by the standard library --> a.rs:2:1 | 4 | fn memcmp() {} | ^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*const c_void, *const c_void, usize) -> i32` found `fn()` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "memcmp")]`, or `#[link_name = "memcmp"]` = note: `#[deny(invalid_runtime_symbol_definitions)]` on by default ``` ### Explanation Up-most care is required when defining runtime symbols assumed and used by the standard library. They must follow the C specification, not use any standard-library facility or undefined behavior may occur. The symbols currently checked are `memcpy`, `memmove`, `memset`, `memcmp`, `bcmp` and `strlen`. ## `suspicious_runtime_symbol_definitions` (warn-by-default, asked in [this comment](https://github.com/rust-lang/rust/pull/155521#issuecomment-4696528297)) The `suspicious_runtime_symbol_definitions` lint checks the signature of items whose symbol name is a runtime symbol expected by `core`. ### Example ```rust #[unsafe(no_mangle)] pub extern "C" fn strlen(ptr: *mut f32) -> usize { 0 } // suspicious definition of the `strlen` function // `ptr` should be `*const std::ffi::c_char` ``` ### Explanation Up-most care is required when defining runtime symbols assumed and used by the standard library. They must follow the C specification, not use any standard-library facility or undefined behavior may occur. [^1]: https://doc.rust-lang.org/core/index.html#how-to-use-the-core-library

20 files changed, 744 insertions(+), 56 deletions(-)

Cargo.lock+1
......@@ -4312,6 +4312,7 @@ dependencies = [
43124312 "rustc_parse_format",
43134313 "rustc_session",
43144314 "rustc_span",
4315 "rustc_symbol_mangling",
43154316 "rustc_target",
43164317 "rustc_trait_selection",
43174318 "smallvec",
compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs+3-1
......@@ -582,7 +582,7 @@ impl SingleAttributeParser for LangParser {
582582 // Only weak lang items may be applied to foreign items
583583 if [Target::ForeignFn, Target::ForeignStatic, Target::ForeignTy, Target::ForeignMod]
584584 .contains(&cx.target)
585 && !lang_item.is_weak()
585 && !(lang_item.is_weak() || lang_item.is_weak_only())
586586 {
587587 cx.emit_err(UnknownExternLangItem { span: cx.attr_span, lang_item: lang_item.name() });
588588 return None;
......@@ -591,6 +591,8 @@ impl SingleAttributeParser for LangParser {
591591 // Check the target
592592 let allowed_targets: &[_] = if lang_item == LangItem::PanicImpl {
593593 &[Allow(Target::Fn), Allow(Target::ForeignFn)]
594 } else if lang_item.is_weak_only() {
595 &[Allow(Target::ForeignFn)]
594596 } else {
595597 &[Allow(lang_item.target())]
596598 };
compiler/rustc_error_codes/src/error_codes/E0755.md+1-1
......@@ -20,7 +20,7 @@ side effects or infinite loops:
2020
2121extern "C" {
2222 #[unsafe(ffi_pure)] // ok!
23 pub fn strlen(s: *const i8) -> isize;
23 pub fn strlen(s: *const std::ffi::c_char) -> usize;
2424}
2525# fn main() {}
2626```
compiler/rustc_error_codes/src/error_codes/E0756.md+1-1
......@@ -21,7 +21,7 @@ which have no side effects except for their return value:
2121
2222extern "C" {
2323 #[unsafe(ffi_const)] // ok!
24 pub fn strlen(s: *const i8) -> i32;
24 pub fn strlen(s: *const std::ffi::c_char) -> usize;
2525}
2626# fn main() {}
2727```
compiler/rustc_hir/src/lang_items.rs+8
......@@ -447,6 +447,14 @@ language_item_table! {
447447
448448 // Used to fallback `{float}` to `f32` when `f32: From<{float}>`
449449 From, sym::From, from_trait, Target::Trait, GenericRequirement::Exact(1);
450
451 // Runtime symbols
452 MemCpy, sym::memcpy_fn, memcpy_fn, Target::Fn, GenericRequirement::None;
453 MemMove, sym::memmove_fn, memmove_fn, Target::Fn, GenericRequirement::None;
454 MemSet, sym::memset_fn, memset_fn, Target::Fn, GenericRequirement::None;
455 MemCmp, sym::memcmp_fn, memcmp_fn, Target::Fn, GenericRequirement::None;
456 Bcmp, sym::bcmp_fn, bcmp_fn, Target::Fn, GenericRequirement::None;
457 StrLen, sym::strlen_fn, strlen_fn, Target::Fn, GenericRequirement::None;
450458}
451459
452460/// The requirement imposed on the generics of a lang item
compiler/rustc_hir/src/weak_lang_items.rs+21
......@@ -23,7 +23,28 @@ macro_rules! weak_lang_items {
2323 }
2424}
2525
26macro_rules! weak_only_lang_items {
27 ($($item:ident,)*) => {
28 pub static WEAK_ONLY_LANG_ITEMS: &[LangItem] = &[$(LangItem::$item,)*];
29
30 impl LangItem {
31 pub fn is_weak_only(self) -> bool {
32 matches!(self, $(LangItem::$item)|*)
33 }
34 }
35 }
36}
37
2638weak_lang_items! {
2739 PanicImpl, rust_begin_unwind;
2840 EhPersonality, rust_eh_personality;
2941}
42
43weak_only_lang_items! {
44 MemCpy,
45 MemMove,
46 MemSet,
47 MemCmp,
48 Bcmp,
49 StrLen,
50}
compiler/rustc_lint/Cargo.toml+1
......@@ -22,6 +22,7 @@ rustc_middle = { path = "../rustc_middle" }
2222rustc_parse_format = { path = "../rustc_parse_format" }
2323rustc_session = { path = "../rustc_session" }
2424rustc_span = { path = "../rustc_span" }
25rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
2526rustc_target = { path = "../rustc_target" }
2627rustc_trait_selection = { path = "../rustc_trait_selection" }
2728smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
compiler/rustc_lint/src/lib.rs+3
......@@ -72,6 +72,7 @@ mod precedence;
7272mod ptr_nulls;
7373mod redundant_semicolon;
7474mod reference_casting;
75mod runtime_symbols;
7576mod shadowed_into_iter;
7677mod static_mut_refs;
7778mod traits;
......@@ -117,6 +118,7 @@ use precedence::*;
117118use ptr_nulls::*;
118119use redundant_semicolon::*;
119120use reference_casting::*;
121use runtime_symbols::*;
120122use rustc_data_structures::unord::UnordSet;
121123use rustc_hir::def_id::LocalModDefId;
122124use rustc_middle::query::Providers;
......@@ -259,6 +261,7 @@ late_lint_methods!(
259261 AsyncFnInTrait: AsyncFnInTrait,
260262 NonLocalDefinitions: NonLocalDefinitions::default(),
261263 InteriorMutableConsts: InteriorMutableConsts,
264 RuntimeSymbols: RuntimeSymbols,
262265 ImplTraitOvercaptures: ImplTraitOvercaptures,
263266 IfLetRescope: IfLetRescope::default(),
264267 StaticMutRefs: StaticMutRefs,
compiler/rustc_lint/src/lints.rs+39
......@@ -808,6 +808,45 @@ pub(crate) enum UseLetUnderscoreIgnoreSuggestion {
808808 },
809809}
810810
811// runtime_symbols.rs
812#[derive(Diagnostic)]
813pub(crate) enum RedefiningRuntimeSymbolsDiag<'tcx> {
814 #[diag(
815 "invalid definition of the runtime `{$symbol_name}` symbol used by the standard library"
816 )]
817 #[note(
818 "expected `{$expected_fn_sig}`
819 found `{$found_fn_sig}`"
820 )]
821 #[help(
822 "either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = \"{$symbol_name}\")]`, or `#[link_name = \"{$symbol_name}\"]`"
823 )]
824 FnDefInvalid { symbol_name: String, expected_fn_sig: Ty<'tcx>, found_fn_sig: Ty<'tcx> },
825 #[diag(
826 "suspicious definition of the runtime `{$symbol_name}` symbol used by the standard library"
827 )]
828 #[note(
829 "expected `{$expected_fn_sig}`
830 found `{$found_fn_sig}`"
831 )]
832 #[help(
833 "either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = \"{$symbol_name}\")]`, or `#[link_name = \"{$symbol_name}\"]`"
834 )]
835 #[help("allow this lint if the signature is compatible")]
836 FnDefSuspicious { symbol_name: String, expected_fn_sig: Ty<'tcx>, found_fn_sig: Ty<'tcx> },
837 #[diag(
838 "invalid definition of the runtime `{$symbol_name}` symbol used by the standard library"
839 )]
840 #[note(
841 "expected `{$expected_fn_sig}`
842 found `static {$symbol_name}: {$static_ty}`"
843 )]
844 #[help(
845 "either fix the signature or remove any attributes `#[unsafe(no_mangle)]` or `#[unsafe(export_name = \"{$symbol_name}\")]`"
846 )]
847 Static { symbol_name: String, static_ty: Ty<'tcx>, expected_fn_sig: Ty<'tcx> },
848}
849
811850// drop_forget_useless.rs
812851#[derive(Diagnostic)]
813852#[diag("calls to `std::mem::drop` with a reference instead of an owned value does nothing")]
compiler/rustc_lint/src/runtime_symbols.rs created+255
......@@ -0,0 +1,255 @@
1use rustc_hir::def_id::{DefId, LocalDefId};
2use rustc_hir::{self as hir, FnSig, ForeignItemKind, LanguageItems};
3use rustc_infer::infer::DefineOpaqueTypes;
4use rustc_middle::ty::{self, Instance, Ty};
5use rustc_session::{declare_lint, declare_lint_pass};
6use rustc_span::Span;
7use rustc_trait_selection::infer::TyCtxtInferExt;
8
9use crate::lints::RedefiningRuntimeSymbolsDiag;
10use crate::{LateContext, LateLintPass, LintContext};
11
12declare_lint! {
13 /// The `invalid_runtime_symbol_definitions` lint checks the signature of items whose
14 /// symbol name is a runtime symbol expected by `core` differs significantly from the
15 /// expected signature (like mismatch ABI, mismatch C variadics, mismatch argument count,
16 /// missing return type, ...).
17 ///
18 /// ### Example
19 ///
20 #[cfg_attr(bootstrap, doc = "```rust")]
21 #[cfg_attr(not(bootstrap), doc = "```rust,compile_fail")]
22 #[cfg_attr(not(bootstrap), doc = "#[unsafe(no_mangle)]")]
23 /// pub fn strlen() {} // invalid definition of the `strlen` function
24 #[doc = "```"]
25 ///
26 /// {{produces}}
27 ///
28 /// ### Explanation
29 ///
30 /// Up-most care is required when defining runtime symbols assumed and
31 /// used by the standard library. They must follow the C specification, not use any
32 /// standard-library facility or undefined behavior may occur.
33 ///
34 /// The symbols currently checked are `memcpy`, `memmove`, `memset`, `memcmp`,
35 /// `bcmp` and `strlen`.
36 ///
37 /// [^1]: https://doc.rust-lang.org/core/index.html#how-to-use-the-core-library
38 pub INVALID_RUNTIME_SYMBOL_DEFINITIONS,
39 Deny,
40 "invalid definition of a symbol used by the standard library"
41}
42
43declare_lint! {
44 /// The `suspicious_runtime_symbol_definitions` lint checks the signature of items whose
45 /// symbol name is a runtime symbol expected by `core`.
46 ///
47 /// ### Example
48 ///
49 /// ```rust,no_run,standalone_crate
50 #[cfg_attr(not(bootstrap), doc = "#[unsafe(no_mangle)]")]
51 /// pub extern "C" fn strlen(ptr: *mut f32) -> usize { 0 }
52 /// // suspicious definition of the `strlen` function
53 /// // `ptr` should be `*const std::ffi::c_char`
54 /// ```
55 ///
56 /// {{produces}}
57 ///
58 /// ### Explanation
59 ///
60 /// Up-most care is required when defining runtime symbols assumed and
61 /// used by the standard library. They must follow the C specification, not use any
62 /// standard-library facility or undefined behavior may occur.
63 ///
64 /// The symbols currently checked are `memcpy`, `memmove`, `memset`, `memcmp`,
65 /// `bcmp` and `strlen`.
66 ///
67 /// [^1]: https://doc.rust-lang.org/core/index.html#how-to-use-the-core-library
68 pub SUSPICIOUS_RUNTIME_SYMBOL_DEFINITIONS,
69 Warn,
70 "suspicious definition of a symbol used by the standard library"
71}
72
73declare_lint_pass!(RuntimeSymbols => [INVALID_RUNTIME_SYMBOL_DEFINITIONS, SUSPICIOUS_RUNTIME_SYMBOL_DEFINITIONS]);
74
75static EXPECTED_SYMBOLS: &[ExpectedSymbol] = &[
76 ExpectedSymbol { symbol: "memcpy", lang: LanguageItems::memcpy_fn },
77 ExpectedSymbol { symbol: "memmove", lang: LanguageItems::memmove_fn },
78 ExpectedSymbol { symbol: "memset", lang: LanguageItems::memset_fn },
79 ExpectedSymbol { symbol: "memcmp", lang: LanguageItems::memcmp_fn },
80 ExpectedSymbol { symbol: "bcmp", lang: LanguageItems::bcmp_fn },
81 ExpectedSymbol { symbol: "strlen", lang: LanguageItems::strlen_fn },
82];
83
84#[derive(Copy, Clone, Debug)]
85struct ExpectedSymbol {
86 symbol: &'static str,
87 lang: fn(&LanguageItems) -> Option<DefId>,
88}
89
90impl<'tcx> LateLintPass<'tcx> for RuntimeSymbols {
91 fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
92 // Bail-out if the item is not a function/method or static.
93 match item.kind {
94 hir::ItemKind::Fn { sig, ident: _, generics, body: _, has_body: _ } => {
95 // Generic functions cannot have the same runtime symbol as we do not allow
96 // any symbol attributes.
97 if !generics.params.is_empty() {
98 return;
99 }
100
101 // Try to get the overridden symbol name of this function (our mangling
102 // cannot ever conflict with runtime symbols, so no need to check for those).
103 let Some(symbol_name) = rustc_symbol_mangling::symbol_name_from_attrs(
104 cx.tcx,
105 rustc_middle::ty::InstanceKind::Item(item.owner_id.to_def_id()),
106 ) else {
107 return;
108 };
109
110 check_fn(cx, &symbol_name, sig, item.owner_id.def_id);
111 }
112 hir::ItemKind::Static(..) => {
113 // Compute the symbol name of this static (without mangling, as our mangling
114 // cannot ever conflict with runtime symbols).
115 let Some(symbol_name) = rustc_symbol_mangling::symbol_name_from_attrs(
116 cx.tcx,
117 rustc_middle::ty::InstanceKind::Item(item.owner_id.to_def_id()),
118 ) else {
119 return;
120 };
121
122 let def_id = item.owner_id.def_id;
123
124 check_static(cx, &symbol_name, def_id, item.span);
125 }
126 hir::ItemKind::ForeignMod { abi: _, items } => {
127 for item in items {
128 let item = cx.tcx.hir_foreign_item(*item);
129
130 let did = item.owner_id.def_id;
131 let instance = Instance::new_raw(
132 did.to_def_id(),
133 ty::List::identity_for_item(cx.tcx, did),
134 );
135 let symbol_name = cx.tcx.symbol_name(instance);
136
137 match item.kind {
138 ForeignItemKind::Fn(fn_sig, _idents, _generics) => {
139 check_fn(cx, &symbol_name.name, fn_sig, did);
140 }
141 ForeignItemKind::Static(..) => {
142 check_static(cx, &symbol_name.name, did, item.span);
143 }
144 ForeignItemKind::Type => return,
145 }
146 }
147 }
148 _ => return,
149 }
150 }
151}
152
153fn check_fn(cx: &LateContext<'_>, symbol_name: &str, sig: FnSig<'_>, did: LocalDefId) {
154 let Some(expected_symbol) = EXPECTED_SYMBOLS.iter().find(|es| es.symbol == symbol_name) else {
155 // The symbol name does not correspond to a runtime symbols, bail out
156 return;
157 };
158
159 let Some(expected_def_id) = (expected_symbol.lang)(&cx.tcx.lang_items()) else {
160 // Can't find the corresponding language item, bail out
161 return;
162 };
163
164 // Get the two function signatures
165 let lang_sig = cx.tcx.normalize_erasing_regions(
166 cx.typing_env(),
167 cx.tcx.fn_sig(expected_def_id).instantiate_identity(),
168 );
169 let user_sig = cx
170 .tcx
171 .normalize_erasing_regions(cx.typing_env(), cx.tcx.fn_sig(did).instantiate_identity());
172
173 // Compare the two signatures with an inference context
174 let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
175 let cause = rustc_middle::traits::ObligationCause::misc(sig.span, did);
176 let result = infcx.at(&cause, cx.param_env).eq(DefineOpaqueTypes::No, lang_sig, user_sig);
177
178 // If they don't match, emit our own mismatch signatures
179 if let Err(_terr) = result {
180 // Create fn pointers for diagnostics purpose
181 let expected = Ty::new_fn_ptr(cx.tcx, lang_sig);
182 let actual = Ty::new_fn_ptr(cx.tcx, user_sig);
183
184 if lang_sig.abi() != user_sig.abi()
185 || lang_sig.c_variadic() != user_sig.c_variadic()
186 || lang_sig.inputs().skip_binder().len() != user_sig.inputs().skip_binder().len()
187 || (!lang_sig.output().skip_binder().is_unit()
188 && user_sig.output().skip_binder().is_unit())
189 {
190 cx.emit_span_lint(
191 INVALID_RUNTIME_SYMBOL_DEFINITIONS,
192 sig.span,
193 RedefiningRuntimeSymbolsDiag::FnDefInvalid {
194 symbol_name: symbol_name.to_string(),
195 found_fn_sig: actual,
196 expected_fn_sig: expected,
197 },
198 );
199 } else {
200 cx.emit_span_lint(
201 SUSPICIOUS_RUNTIME_SYMBOL_DEFINITIONS,
202 sig.span,
203 RedefiningRuntimeSymbolsDiag::FnDefSuspicious {
204 symbol_name: symbol_name.to_string(),
205 found_fn_sig: actual,
206 expected_fn_sig: expected,
207 },
208 );
209 };
210 }
211}
212
213fn check_static<'tcx>(cx: &LateContext<'tcx>, symbol_name: &str, did: LocalDefId, sp: Span) {
214 let Some(expected_symbol) = EXPECTED_SYMBOLS.iter().find(|es| es.symbol == symbol_name) else {
215 // The symbol name does not correspond to a runtime symbols, bail out
216 return;
217 };
218
219 let Some(expected_def_id) = (expected_symbol.lang)(&cx.tcx.lang_items()) else {
220 // Can't find the corresponding language item, bail out
221 return;
222 };
223
224 // Get the static type
225 let static_ty = cx.tcx.type_of(did).instantiate_identity().skip_norm_wip();
226
227 // Peel Option<...> and get the inner type (see std weak! macro with #[linkage = "extern_weak"])
228 let inner_static_ty: Ty<'_> = match static_ty.kind() {
229 ty::Adt(def, args) if Some(def.did()) == cx.tcx.lang_items().option_type() => {
230 args.type_at(0)
231 }
232 _ => static_ty,
233 };
234
235 // Get the expected symbol function signature
236 let lang_sig = cx.tcx.normalize_erasing_regions(
237 cx.typing_env(),
238 cx.tcx.fn_sig(expected_def_id).instantiate_identity(),
239 );
240
241 let expected = Ty::new_fn_ptr(cx.tcx, lang_sig);
242
243 // Compare the expected function signature with the static type, report an error if they don't match
244 if expected != inner_static_ty {
245 cx.emit_span_lint(
246 INVALID_RUNTIME_SYMBOL_DEFINITIONS,
247 sp,
248 RedefiningRuntimeSymbolsDiag::Static {
249 static_ty,
250 symbol_name: symbol_name.to_string(),
251 expected_fn_sig: expected,
252 },
253 );
254 }
255}
compiler/rustc_passes/src/lang_items.rs+39-9
......@@ -27,6 +27,11 @@ pub(crate) enum Duplicate {
2727 CrateDepends,
2828}
2929
30enum CollectWeak {
31 Allowed,
32 Ignore,
33}
34
3035struct LanguageItemCollector<'ast, 'tcx> {
3136 items: LanguageItems,
3237 tcx: TyCtxt<'tcx>,
......@@ -58,6 +63,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> {
5863 attrs: &'ast [ast::Attribute],
5964 item_span: Span,
6065 generics: Option<&'ast ast::Generics>,
66 collect_weak: CollectWeak,
6167 ) {
6268 if let Some((name, attr_span)) = extract_ast(attrs) {
6369 match LangItem::from_name(name) {
......@@ -69,14 +75,18 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> {
6975 .delayed_bug("lang item target is checked in attribute parser");
7076 return;
7177 }
72 self.collect_item_extended(
73 lang_item,
74 def_id,
75 item_span,
76 attr_span,
77 generics,
78 actual_target,
79 );
78 // Weak lang items are handled separately
79 // Weak only lang items are always handled here
80 if !lang_item.is_weak() || matches!(collect_weak, CollectWeak::Allowed) {
81 self.collect_item_extended(
82 lang_item,
83 def_id,
84 item_span,
85 attr_span,
86 generics,
87 actual_target,
88 );
89 }
8090 }
8191 // Unknown lang item.
8292 _ => {
......@@ -295,6 +305,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
295305 &i.attrs,
296306 i.span,
297307 i.opt_generics(),
308 CollectWeak::Allowed,
298309 );
299310
300311 let parent_item = self.parent_item.replace(i);
......@@ -302,6 +313,17 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
302313 self.parent_item = parent_item;
303314 }
304315
316 fn visit_foreign_item(&mut self, i: &'ast ast::ForeignItem) {
317 self.check_for_lang(
318 Target::Fn,
319 self.resolver.owners[&i.id].def_id,
320 &i.attrs,
321 i.span,
322 None,
323 CollectWeak::Ignore,
324 );
325 }
326
305327 fn visit_variant(&mut self, variant: &'ast ast::Variant) {
306328 self.check_for_lang(
307329 Target::Variant,
......@@ -309,6 +331,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
309331 &variant.attrs,
310332 variant.span,
311333 None,
334 CollectWeak::Allowed,
312335 );
313336 }
314337
......@@ -342,7 +365,14 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
342365 }
343366 };
344367
345 self.check_for_lang(target, self.resolver.owners[&i.id].def_id, &i.attrs, i.span, generics);
368 self.check_for_lang(
369 target,
370 self.resolver.owners[&i.id].def_id,
371 &i.attrs,
372 i.span,
373 generics,
374 CollectWeak::Allowed,
375 );
346376
347377 visit::walk_assoc_item(self, i, ctxt);
348378 }
compiler/rustc_span/src/symbol.rs+6
......@@ -515,6 +515,7 @@ symbols! {
515515 await_macro,
516516 backchain,
517517 backend_repr,
518 bcmp_fn,
518519 begin_panic,
519520 bench,
520521 bevy_ecs,
......@@ -1280,7 +1281,11 @@ symbols! {
12801281 mem_variant_count,
12811282 mem_zeroed,
12821283 member_constraints,
1284 memcmp_fn,
1285 memcpy_fn,
1286 memmove_fn,
12831287 memory,
1288 memset_fn,
12841289 memtag,
12851290 message,
12861291 meta,
......@@ -2036,6 +2041,7 @@ symbols! {
20362041 strict_provenance_lints,
20372042 string_deref_patterns,
20382043 stringify,
2044 strlen_fn,
20392045 struct_field_attributes,
20402046 struct_inherit,
20412047 struct_variant,
compiler/rustc_symbol_mangling/src/lib.rs+30-17
......@@ -92,7 +92,7 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
9292use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
9393use rustc_middle::mono::{InstantiationMode, MonoItem};
9494use rustc_middle::query::Providers;
95use rustc_middle::ty::{self, Instance, TyCtxt};
95use rustc_middle::ty::{self, Instance, InstanceKind, TyCtxt};
9696use rustc_session::config::SymbolManglingVersion;
9797use tracing::debug;
9898
......@@ -149,29 +149,22 @@ pub fn typeid_for_trait_ref<'tcx>(
149149 v0::mangle_typeid_for_trait_ref(tcx, trait_ref)
150150}
151151
152/// Computes the symbol name for the given instance. This function will call
153/// `compute_instantiating_crate` if it needs to factor the instantiating crate
154/// into the symbol name.
155fn compute_symbol_name<'tcx>(
152pub fn symbol_name_from_attrs<'tcx>(
156153 tcx: TyCtxt<'tcx>,
157 instance: Instance<'tcx>,
158 compute_instantiating_crate: impl FnOnce() -> CrateNum,
159) -> String {
160 let def_id = instance.def_id();
161 let args = instance.args;
162
163 debug!("symbol_name(def_id={:?}, args={:?})", def_id, args);
154 instance_kind: InstanceKind<'tcx>,
155) -> Option<String> {
156 let def_id = instance_kind.def_id();
164157
165158 if let Some(def_id) = def_id.as_local() {
166159 if tcx.proc_macro_decls_static(()) == Some(def_id) {
167160 let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
168 return rustc_session::generate_proc_macro_decls_symbol(stable_crate_id);
161 return Some(rustc_session::generate_proc_macro_decls_symbol(stable_crate_id));
169162 }
170163 }
171164
172165 // FIXME(eddyb) Precompute a custom symbol name based on attributes.
173166 let attrs = if tcx.def_kind(def_id).has_codegen_attrs() {
174 &tcx.codegen_instance_attrs(instance.def)
167 &tcx.codegen_instance_attrs(instance_kind)
175168 } else {
176169 CodegenFnAttrs::EMPTY
177170 };
......@@ -197,7 +190,7 @@ fn compute_symbol_name<'tcx>(
197190 // legacy symbol mangling scheme.
198191 let name = if let Some(name) = attrs.symbol_name { name } else { tcx.item_name(def_id) };
199192
200 return v0::mangle_internal_symbol(tcx, name.as_str());
193 return Some(v0::mangle_internal_symbol(tcx, name.as_str()));
201194 }
202195
203196 let wasm_import_module_exception_force_mangling = {
......@@ -225,15 +218,35 @@ fn compute_symbol_name<'tcx>(
225218 if !wasm_import_module_exception_force_mangling {
226219 if let Some(name) = attrs.symbol_name {
227220 // Use provided name
228 return name.to_string();
221 return Some(name.to_string());
229222 }
230223
231224 if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) {
232225 // Don't mangle
233 return tcx.item_name(def_id).to_string();
226 return Some(tcx.item_name(def_id).to_string());
234227 }
235228 }
236229
230 None
231}
232
233/// Computes the symbol name for the given instance. This function will call
234/// `compute_instantiating_crate` if it needs to factor the instantiating crate
235/// into the symbol name.
236fn compute_symbol_name<'tcx>(
237 tcx: TyCtxt<'tcx>,
238 instance: Instance<'tcx>,
239 compute_instantiating_crate: impl FnOnce() -> CrateNum,
240) -> String {
241 let def_id = instance.def_id();
242 let args = instance.args;
243
244 debug!("symbol_name(def_id={:?}, args={:?})", def_id, args);
245
246 if let Some(symbol) = symbol_name_from_attrs(tcx, instance.def) {
247 return symbol;
248 }
249
237250 // If we're dealing with an instance of a function that's inlined from
238251 // another crate but we're marking it as globally shared to our
239252 // compilation (aka we're not making an internal copy in each of our
library/compiler-builtins/compiler-builtins/src/arm.rs+50-14
......@@ -84,7 +84,11 @@ intrinsics! {
8484 ///
8585 /// Usual `memcpy` requirements apply.
8686 #[cfg(not(target_vendor = "apple"))]
87 pub unsafe extern "aapcs" fn __aeabi_memcpy(dst: *mut u8, src: *const u8, n: usize) {
87 pub unsafe extern "aapcs" fn __aeabi_memcpy(
88 dst: *mut core::ffi::c_void,
89 src: *const core::ffi::c_void,
90 n: usize
91 ) {
8892 // SAFETY: memcpy preconditions apply.
8993 unsafe { crate::mem::memcpy(dst, src, n) };
9094 }
......@@ -96,7 +100,11 @@ intrinsics! {
96100 /// Usual `memcpy` requirements apply. Additionally, `dest` and `src` must be aligned to
97101 /// four bytes.
98102 #[cfg(not(target_vendor = "apple"))]
99 pub unsafe extern "aapcs" fn __aeabi_memcpy4(dst: *mut u8, src: *const u8, n: usize) {
103 pub unsafe extern "aapcs" fn __aeabi_memcpy4(
104 dst: *mut core::ffi::c_void,
105 src: *const core::ffi::c_void,
106 n: usize
107 ) {
100108 // We are guaranteed 4-alignment, so accessing at u32 is okay.
101109 let mut dst = dst.cast::<u32>();
102110 let mut src = src.cast::<u32>();
......@@ -121,7 +129,7 @@ intrinsics! {
121129 }
122130
123131 // SAFETY: `dst` and `src` will still be valid for `n` bytes
124 unsafe { __aeabi_memcpy(dst.cast::<u8>(), src.cast::<u8>(), n) };
132 unsafe { __aeabi_memcpy(dst.cast::<core::ffi::c_void>(), src.cast::<core::ffi::c_void>(), n) };
125133 }
126134
127135 /// `memcpy` for 8-byte alignment.
......@@ -131,7 +139,11 @@ intrinsics! {
131139 /// Usual `memcpy` requirements apply. Additionally, `dest` and `src` must be aligned to
132140 /// eight bytes.
133141 #[cfg(not(target_vendor = "apple"))]
134 pub unsafe extern "aapcs" fn __aeabi_memcpy8(dst: *mut u8, src: *const u8, n: usize) {
142 pub unsafe extern "aapcs" fn __aeabi_memcpy8(
143 dst: *mut core::ffi::c_void,
144 src: *const core::ffi::c_void,
145 n: usize
146 ) {
135147 debug_assert!(dst.addr().is_multiple_of(8));
136148 debug_assert!(src.addr().is_multiple_of(8));
137149
......@@ -145,7 +157,11 @@ intrinsics! {
145157 ///
146158 /// Usual `memmove` requirements apply.
147159 #[cfg(not(target_vendor = "apple"))]
148 pub unsafe extern "aapcs" fn __aeabi_memmove(dst: *mut u8, src: *const u8, n: usize) {
160 pub unsafe extern "aapcs" fn __aeabi_memmove(
161 dst: *mut core::ffi::c_void,
162 src: *const core::ffi::c_void,
163 n: usize
164 ) {
149165 // SAFETY: memmove preconditions apply.
150166 unsafe { crate::mem::memmove(dst, src, n) };
151167 }
......@@ -157,7 +173,11 @@ intrinsics! {
157173 /// Usual `memmove` requirements apply. Additionally, `dest` and `src` must be aligned to
158174 /// four bytes.
159175 #[cfg(not(any(target_vendor = "apple", target_env = "msvc")))]
160 pub unsafe extern "aapcs" fn __aeabi_memmove4(dst: *mut u8, src: *const u8, n: usize) {
176 pub unsafe extern "aapcs" fn __aeabi_memmove4(
177 dst: *mut core::ffi::c_void,
178 src: *const core::ffi::c_void,
179 n: usize
180 ) {
161181 debug_assert!(dst.addr().is_multiple_of(4));
162182 debug_assert!(src.addr().is_multiple_of(4));
163183
......@@ -172,7 +192,11 @@ intrinsics! {
172192 /// Usual `memmove` requirements apply. Additionally, `dst` and `src` must be aligned to
173193 /// eight bytes.
174194 #[cfg(not(any(target_vendor = "apple", target_env = "msvc")))]
175 pub unsafe extern "aapcs" fn __aeabi_memmove8(dst: *mut u8, src: *const u8, n: usize) {
195 pub unsafe extern "aapcs" fn __aeabi_memmove8(
196 dst: *mut core::ffi::c_void,
197 src: *const core::ffi::c_void,
198 n: usize
199 ) {
176200 debug_assert!(dst.addr().is_multiple_of(8));
177201 debug_assert!(src.addr().is_multiple_of(8));
178202
......@@ -186,7 +210,11 @@ intrinsics! {
186210 ///
187211 /// Usual `memset` requirements apply.
188212 #[cfg(not(target_vendor = "apple"))]
189 pub unsafe extern "aapcs" fn __aeabi_memset(dst: *mut u8, n: usize, c: i32) {
213 pub unsafe extern "aapcs" fn __aeabi_memset(
214 dst: *mut core::ffi::c_void,
215 n: usize,
216 c: i32
217 ) {
190218 // Note the different argument order
191219 // SAFETY: memset preconditions apply.
192220 unsafe { crate::mem::memset(dst, c, n) };
......@@ -199,7 +227,11 @@ intrinsics! {
199227 /// Usual `memset` requirements apply. Additionally, `dest` and `src` must be aligned to
200228 /// four bytes.
201229 #[cfg(not(target_vendor = "apple"))]
202 pub unsafe extern "aapcs" fn __aeabi_memset4(dst: *mut u8, n: usize, c: i32) {
230 pub unsafe extern "aapcs" fn __aeabi_memset4(
231 dst: *mut core::ffi::c_void,
232 n: usize,
233 c: i32
234 ) {
203235 let mut dst = dst.cast::<u32>();
204236 debug_assert!(dst.is_aligned());
205237 let mut n = n;
......@@ -222,7 +254,7 @@ intrinsics! {
222254 }
223255
224256 // SAFETY: `dst` will still be valid for `n` bytes
225 unsafe { __aeabi_memset(dst.cast::<u8>(), n, byte as i32) };
257 unsafe { __aeabi_memset(dst.cast::<core::ffi::c_void>(), n, byte as i32) };
226258 }
227259
228260 /// `memset` for 8-byte alignment.
......@@ -232,7 +264,11 @@ intrinsics! {
232264 /// Usual `memset` requirements apply. Additionally, `dst` and `src` must be aligned to
233265 /// eight bytes.
234266 #[cfg(not(target_vendor = "apple"))]
235 pub unsafe extern "aapcs" fn __aeabi_memset8(dst: *mut u8, n: usize, c: i32) {
267 pub unsafe extern "aapcs" fn __aeabi_memset8(
268 dst: *mut core::ffi::c_void,
269 n: usize,
270 c: i32
271 ) {
236272 debug_assert!(dst.addr().is_multiple_of(8));
237273
238274 // SAFETY: memset preconditions apply, less strict alignment.
......@@ -245,7 +281,7 @@ intrinsics! {
245281 ///
246282 /// Usual `memclr` requirements apply.
247283 #[cfg(not(target_vendor = "apple"))]
248 pub unsafe extern "aapcs" fn __aeabi_memclr(dst: *mut u8, n: usize) {
284 pub unsafe extern "aapcs" fn __aeabi_memclr(dst: *mut core::ffi::c_void, n: usize) {
249285 // SAFETY: memclr preconditions apply, less strict alignment.
250286 unsafe { __aeabi_memset(dst, n, 0) };
251287 }
......@@ -257,7 +293,7 @@ intrinsics! {
257293 /// Usual `memclr` requirements apply. Additionally, `dest` and `src` must be aligned to
258294 /// four bytes.
259295 #[cfg(not(any(target_vendor = "apple", target_env = "msvc")))]
260 pub unsafe extern "aapcs" fn __aeabi_memclr4(dst: *mut u8, n: usize) {
296 pub unsafe extern "aapcs" fn __aeabi_memclr4(dst: *mut core::ffi::c_void, n: usize) {
261297 debug_assert!(dst.addr().is_multiple_of(4));
262298
263299 // SAFETY: memclr preconditions apply, less strict alignment.
......@@ -271,7 +307,7 @@ intrinsics! {
271307 /// Usual `memclr` requirements apply. Additionally, `dst` and `src` must be aligned to
272308 /// eight bytes.
273309 #[cfg(not(any(target_vendor = "apple", target_env = "msvc")))]
274 pub unsafe extern "aapcs" fn __aeabi_memclr8(dst: *mut u8, n: usize) {
310 pub unsafe extern "aapcs" fn __aeabi_memclr8(dst: *mut core::ffi::c_void, n: usize) {
275311 debug_assert!(dst.addr().is_multiple_of(8));
276312
277313 // SAFETY: memclr preconditions apply, less strict alignment.
library/compiler-builtins/compiler-builtins/src/mem/mod.rs+30-10
......@@ -9,37 +9,57 @@ mod impls;
99
1010intrinsics! {
1111 #[mem_builtin]
12 pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
13 impls::copy_forward(dest, src, n);
12 pub unsafe extern "C" fn memcpy(
13 dest: *mut core::ffi::c_void,
14 src: *const core::ffi::c_void,
15 n: usize
16 ) -> *mut core::ffi::c_void {
17 impls::copy_forward(dest.cast(), src.cast(), n);
1418 dest
1519 }
1620
1721 #[mem_builtin]
18 pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
22 pub unsafe extern "C" fn memmove(
23 dest: *mut core::ffi::c_void,
24 src: *const core::ffi::c_void,
25 n: usize
26 ) -> *mut core::ffi::c_void {
1927 let delta = (dest as usize).wrapping_sub(src as usize);
2028 if delta >= n {
2129 // We can copy forwards because either dest is far enough ahead of src,
2230 // or src is ahead of dest (and delta overflowed).
23 impls::copy_forward(dest, src, n);
31 impls::copy_forward(dest.cast(), src.cast(), n);
2432 } else {
25 impls::copy_backward(dest, src, n);
33 impls::copy_backward(dest.cast(), src.cast(), n);
2634 }
2735 dest
2836 }
2937
3038 #[mem_builtin]
31 pub unsafe extern "C" fn memset(s: *mut u8, c: core::ffi::c_int, n: usize) -> *mut u8 {
32 impls::set_bytes(s, c as u8, n);
39 pub unsafe extern "C" fn memset(
40 s: *mut core::ffi::c_void,
41 c: core::ffi::c_int,
42 n: usize
43 ) -> *mut core::ffi::c_void {
44 impls::set_bytes(s.cast(), c as u8, n);
3345 s
3446 }
3547
3648 #[mem_builtin]
37 pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> core::ffi::c_int {
38 impls::compare_bytes(s1, s2, n)
49 pub unsafe extern "C" fn memcmp(
50 s1: *const core::ffi::c_void,
51 s2: *const core::ffi::c_void,
52 n: usize
53 ) -> core::ffi::c_int {
54 impls::compare_bytes(s1.cast(), s2.cast(), n)
3955 }
4056
4157 #[mem_builtin]
42 pub unsafe extern "C" fn bcmp(s1: *const u8, s2: *const u8, n: usize) -> core::ffi::c_int {
58 pub unsafe extern "C" fn bcmp(
59 s1: *const core::ffi::c_void,
60 s2: *const core::ffi::c_void,
61 n: usize
62 ) -> core::ffi::c_int {
4363 memcmp(s1, s2, n)
4464 }
4565
library/core/src/ffi/mod.rs+27
......@@ -85,3 +85,30 @@ impl fmt::Debug for c_void {
8585)]
8686#[link(name = "/defaultlib:libcmt", modifiers = "+verbatim", cfg(target_feature = "crt-static"))]
8787unsafe extern "C" {}
88
89// Used by rustc for checking the definitions of other function with the same symbol names
90//
91// See the `invalid_runtime_symbols_definitions` lint.
92mod runtime_symbols {
93 use crate::ffi::{c_char, c_int, c_void};
94
95 unsafe extern "C" {
96 #[lang = "memcpy_fn"]
97 fn memcpy(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void;
98
99 #[lang = "memmove_fn"]
100 fn memmove(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void;
101
102 #[lang = "memset_fn"]
103 fn memset(s: *mut c_void, c: c_int, n: usize) -> *mut c_void;
104
105 #[lang = "memcmp_fn"]
106 fn memcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int;
107
108 #[lang = "bcmp_fn"]
109 fn bcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int;
110
111 #[lang = "strlen_fn"]
112 fn strlen(s: *const c_char) -> usize;
113 }
114}
tests/codegen-llvm/no_builtins-at-crate.rs+4-2
......@@ -3,11 +3,13 @@
33#![no_builtins]
44#![crate_type = "lib"]
55
6use std::ffi::c_void;
7
68// CHECK: define
79// CHECK-SAME: @__aeabi_memcpy
810// CHECK-SAME: #0
911#[no_mangle]
10pub unsafe extern "C" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, size: usize) {
12pub unsafe extern "C" fn __aeabi_memcpy(dest: *mut c_void, src: *const c_void, size: usize) {
1113 // CHECK: call
1214 // CHECK-SAME: @memcpy(
1315 memcpy(dest, src, size);
......@@ -17,7 +19,7 @@ pub unsafe extern "C" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, size: usi
1719// CHECK-SAME: @memcpy
1820// CHECK-SAME: #0
1921extern "C" {
20 pub fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8;
22 pub fn memcpy(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void;
2123}
2224
2325// CHECK: attributes #0
tests/ui/foreign/foreign-int-types.rs+1-1
......@@ -4,7 +4,7 @@
44
55mod xx {
66 extern "C" {
7 pub fn strlen(str: *const u8) -> usize;
7 pub fn strlen2(str: *const u8) -> usize;
88 pub fn foo(x: isize, y: usize);
99 }
1010}
tests/ui/lint/runtime-symbols.rs created+95
......@@ -0,0 +1,95 @@
1// This test checks the runtime symbols lint.
2
3//@ edition: 2021
4//@ normalize-stderr: "\*const [iu]8" -> "*const U8"
5
6#![feature(c_variadic)]
7#![allow(clashing_extern_declarations)] // we are voluntarily testing different definitions
8
9use core::ffi::{c_char, c_int, c_void};
10
11fn invalid() {
12 #[no_mangle]
13 pub fn memmove() {}
14 //~^ ERROR invalid definition of the runtime `memmove` symbol
15
16 extern "C" {
17 pub fn memset();
18 //~^ ERROR invalid definition of the runtime `memset` symbol
19
20 pub fn memcmp();
21 //~^ ERROR invalid definition of the runtime `memcmp` symbol
22 }
23
24 #[no_mangle]
25 pub static strlen: () = ();
26 //~^ ERROR invalid definition of the runtime `strlen` symbol
27
28 // ABI mismatch: Rust ABI instead of C ABI
29 #[no_mangle]
30 pub fn memcpy(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void {
31 dest
32 }
33 //~^^^ ERROR invalid definition of the runtime `memcpy` symbol
34
35 // C-Variadic mismatch
36 #[no_mangle]
37 pub unsafe extern "C" fn bcmp(s1: *const c_void, s2: *const c_void, n: usize, _: ...) -> c_int {
38 0
39 }
40 //~^^^ ERROR invalid definition of the runtime `bcmp` symbol
41
42 // Return type is missing
43 #[export_name = "bcmp"]
44 pub extern "C" fn bcmp_(s1: *const c_void, s2: *const c_void, n: usize) {}
45 //~^ ERROR invalid definition of the runtime `bcmp` symbol
46}
47
48fn suspicious() {
49 #[no_mangle]
50 pub extern "C" fn memcpy(dest: *mut c_void, src: *const c_void, n: i64) -> *mut c_void {
51 std::ptr::null_mut()
52 }
53 //~^^^ WARN suspicious definition of the runtime `memcpy` symbol
54
55 #[no_mangle]
56 pub extern "C" fn memmove(dest: *mut c_void, src: *const c_void, n: i64) -> *mut c_void {
57 std::ptr::null_mut()
58 }
59 //~^^^ WARN suspicious definition of the runtime `memmove` symbol
60
61 extern "C" {
62 fn memset(s: *mut c_void, c: c_int, n: usize) -> f64;
63 //~^ WARN suspicious definition of the runtime `memset` symbol
64 }
65
66 #[export_name = "bcmp"]
67 pub extern "C" fn bcmp_(s1: *const u8, s2: *const u8, n: usize) -> c_int {
68 0
69 }
70 //~^^^ WARN suspicious definition of the runtime `bcmp` symbol
71
72 #[no_mangle]
73 pub extern "C" fn strlen(s: *const u64) -> usize {
74 0
75 }
76 //~^^^ WARN suspicious definition of the runtime `strlen` symbol
77}
78
79fn valid() {
80 extern "C" {
81 fn memcpy(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void;
82
83 fn memmove(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void;
84
85 fn memset(s: *mut c_void, c: c_int, n: usize) -> *mut c_void;
86
87 fn memcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int;
88
89 fn bcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int;
90
91 static strlen: Option<unsafe extern "C" fn(s: *const c_char) -> usize>;
92 }
93}
94
95fn main() {}
tests/ui/lint/runtime-symbols.stderr created+129
......@@ -0,0 +1,129 @@
1error: invalid definition of the runtime `memmove` symbol used by the standard library
2 --> $DIR/runtime-symbols.rs:13:5
3 |
4LL | pub fn memmove() {}
5 | ^^^^^^^^^^^^^^^^
6 |
7 = note: expected `unsafe extern "C" fn(*mut c_void, *const c_void, usize) -> *mut c_void`
8 found `fn()`
9 = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "memmove")]`, or `#[link_name = "memmove"]`
10 = note: `#[deny(invalid_runtime_symbol_definitions)]` on by default
11
12error: invalid definition of the runtime `memset` symbol used by the standard library
13 --> $DIR/runtime-symbols.rs:17:9
14 |
15LL | pub fn memset();
16 | ^^^^^^^^^^^^^^^^
17 |
18 = note: expected `unsafe extern "C" fn(*mut c_void, i32, usize) -> *mut c_void`
19 found `unsafe extern "C" fn()`
20 = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "memset")]`, or `#[link_name = "memset"]`
21
22error: invalid definition of the runtime `memcmp` symbol used by the standard library
23 --> $DIR/runtime-symbols.rs:20:9
24 |
25LL | pub fn memcmp();
26 | ^^^^^^^^^^^^^^^^
27 |
28 = note: expected `unsafe extern "C" fn(*const c_void, *const c_void, usize) -> i32`
29 found `unsafe extern "C" fn()`
30 = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "memcmp")]`, or `#[link_name = "memcmp"]`
31
32error: invalid definition of the runtime `strlen` symbol used by the standard library
33 --> $DIR/runtime-symbols.rs:25:5
34 |
35LL | pub static strlen: () = ();
36 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
37 |
38 = note: expected `unsafe extern "C" fn(*const U8) -> usize`
39 found `static strlen: ()`
40 = help: either fix the signature or remove any attributes `#[unsafe(no_mangle)]` or `#[unsafe(export_name = "strlen")]`
41
42error: invalid definition of the runtime `memcpy` symbol used by the standard library
43 --> $DIR/runtime-symbols.rs:30:5
44 |
45LL | pub fn memcpy(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void {
46 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47 |
48 = note: expected `unsafe extern "C" fn(*mut c_void, *const c_void, usize) -> *mut c_void`
49 found `fn(*mut c_void, *const c_void, usize) -> *mut c_void`
50 = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "memcpy")]`, or `#[link_name = "memcpy"]`
51
52error: invalid definition of the runtime `bcmp` symbol used by the standard library
53 --> $DIR/runtime-symbols.rs:37:5
54 |
55LL | pub unsafe extern "C" fn bcmp(s1: *const c_void, s2: *const c_void, n: usize, _: ...) -> c_int {
56 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
57 |
58 = note: expected `unsafe extern "C" fn(*const c_void, *const c_void, usize) -> i32`
59 found `unsafe extern "C" fn(*const c_void, *const c_void, usize, ...) -> i32`
60 = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "bcmp")]`, or `#[link_name = "bcmp"]`
61
62error: invalid definition of the runtime `bcmp` symbol used by the standard library
63 --> $DIR/runtime-symbols.rs:44:5
64 |
65LL | pub extern "C" fn bcmp_(s1: *const c_void, s2: *const c_void, n: usize) {}
66 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
67 |
68 = note: expected `unsafe extern "C" fn(*const c_void, *const c_void, usize) -> i32`
69 found `extern "C" fn(*const c_void, *const c_void, usize)`
70 = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "bcmp")]`, or `#[link_name = "bcmp"]`
71
72warning: suspicious definition of the runtime `memcpy` symbol used by the standard library
73 --> $DIR/runtime-symbols.rs:50:5
74 |
75LL | pub extern "C" fn memcpy(dest: *mut c_void, src: *const c_void, n: i64) -> *mut c_void {
76 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
77 |
78 = note: expected `unsafe extern "C" fn(*mut c_void, *const c_void, usize) -> *mut c_void`
79 found `extern "C" fn(*mut c_void, *const c_void, i64) -> *mut c_void`
80 = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "memcpy")]`, or `#[link_name = "memcpy"]`
81 = help: allow this lint if the signature is compatible
82 = note: `#[warn(suspicious_runtime_symbol_definitions)]` on by default
83
84warning: suspicious definition of the runtime `memmove` symbol used by the standard library
85 --> $DIR/runtime-symbols.rs:56:5
86 |
87LL | pub extern "C" fn memmove(dest: *mut c_void, src: *const c_void, n: i64) -> *mut c_void {
88 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
89 |
90 = note: expected `unsafe extern "C" fn(*mut c_void, *const c_void, usize) -> *mut c_void`
91 found `extern "C" fn(*mut c_void, *const c_void, i64) -> *mut c_void`
92 = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "memmove")]`, or `#[link_name = "memmove"]`
93 = help: allow this lint if the signature is compatible
94
95warning: suspicious definition of the runtime `memset` symbol used by the standard library
96 --> $DIR/runtime-symbols.rs:62:9
97 |
98LL | fn memset(s: *mut c_void, c: c_int, n: usize) -> f64;
99 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
100 |
101 = note: expected `unsafe extern "C" fn(*mut c_void, i32, usize) -> *mut c_void`
102 found `unsafe extern "C" fn(*mut c_void, i32, usize) -> f64`
103 = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "memset")]`, or `#[link_name = "memset"]`
104 = help: allow this lint if the signature is compatible
105
106warning: suspicious definition of the runtime `bcmp` symbol used by the standard library
107 --> $DIR/runtime-symbols.rs:67:5
108 |
109LL | pub extern "C" fn bcmp_(s1: *const U8, s2: *const U8, n: usize) -> c_int {
110 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
111 |
112 = note: expected `unsafe extern "C" fn(*const c_void, *const c_void, usize) -> i32`
113 found `extern "C" fn(*const U8, *const U8, usize) -> i32`
114 = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "bcmp")]`, or `#[link_name = "bcmp"]`
115 = help: allow this lint if the signature is compatible
116
117warning: suspicious definition of the runtime `strlen` symbol used by the standard library
118 --> $DIR/runtime-symbols.rs:73:5
119 |
120LL | pub extern "C" fn strlen(s: *const u64) -> usize {
121 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
122 |
123 = note: expected `unsafe extern "C" fn(*const U8) -> usize`
124 found `extern "C" fn(*const u64) -> usize`
125 = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "strlen")]`, or `#[link_name = "strlen"]`
126 = help: allow this lint if the signature is compatible
127
128error: aborting due to 7 previous errors; 5 warnings emitted
129