Skip to content

Commit 903b6ad

Browse files
committed
Add weak-only lang items for core runtime symbols
1 parent 620f3eb commit 903b6ad

8 files changed

Lines changed: 120 additions & 17 deletions

File tree

compiler/rustc_hir/src/lang_items.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,14 @@ language_item_table! {
448448

449449
// Used to fallback `{float}` to `f32` when `f32: From<{float}>`
450450
From, sym::From, from_trait, Target::Trait, GenericRequirement::Exact(1);
451+
452+
// Runtime symbols
453+
MemCpy, sym::memcpy_fn, memcpy_fn, Target::Fn, GenericRequirement::None;
454+
MemMove, sym::memmove_fn, memmove_fn, Target::Fn, GenericRequirement::None;
455+
MemSet, sym::memset_fn, memset_fn, Target::Fn, GenericRequirement::None;
456+
MemCmp, sym::memcmp_fn, memcmp_fn, Target::Fn, GenericRequirement::None;
457+
Bcmp, sym::bcmp_fn, bcmp_fn, Target::Fn, GenericRequirement::None;
458+
StrLen, sym::strlen_fn, strlen_fn, Target::Fn, GenericRequirement::None;
451459
}
452460

453461
/// The requirement imposed on the generics of a lang item

compiler/rustc_hir/src/weak_lang_items.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,29 @@ macro_rules! weak_lang_items {
2323
}
2424
}
2525

26+
macro_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+
2638
weak_lang_items! {
2739
PanicImpl, rust_begin_unwind;
2840
EhPersonality, rust_eh_personality;
2941
EhCatchTypeinfo, rust_eh_catch_typeinfo;
3042
}
43+
44+
weak_only_lang_items! {
45+
MemCpy,
46+
MemMove,
47+
MemSet,
48+
MemCmp,
49+
Bcmp,
50+
StrLen,
51+
}

compiler/rustc_passes/src/lang_items.rs

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ pub(crate) enum Duplicate {
2929
CrateDepends,
3030
}
3131

32+
enum CollectWeak {
33+
Allowed,
34+
Ignore,
35+
}
36+
3237
struct LanguageItemCollector<'ast, 'tcx> {
3338
items: LanguageItems,
3439
tcx: TyCtxt<'tcx>,
@@ -60,19 +65,24 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> {
6065
attrs: &'ast [ast::Attribute],
6166
item_span: Span,
6267
generics: Option<&'ast ast::Generics>,
68+
collect_weak: CollectWeak,
6369
) {
6470
if let Some((name, attr_span)) = extract_ast(attrs) {
6571
match LangItem::from_name(name) {
6672
// Known lang item with attribute on correct target.
6773
Some(lang_item) if actual_target == lang_item.target() => {
68-
self.collect_item_extended(
69-
lang_item,
70-
def_id,
71-
item_span,
72-
attr_span,
73-
generics,
74-
actual_target,
75-
);
74+
// Weak lang items are handled separately
75+
// Weak only lang items are always handled here
76+
if !lang_item.is_weak() || matches!(collect_weak, CollectWeak::Allowed) {
77+
self.collect_item_extended(
78+
lang_item,
79+
def_id,
80+
item_span,
81+
attr_span,
82+
generics,
83+
actual_target,
84+
);
85+
}
7686
}
7787
// Known lang item with attribute on incorrect target.
7888
Some(lang_item) => {
@@ -299,20 +309,33 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
299309
&i.attrs,
300310
i.span,
301311
i.opt_generics(),
312+
CollectWeak::Allowed,
302313
);
303314

304315
let parent_item = self.parent_item.replace(i);
305316
visit::walk_item(self, i);
306317
self.parent_item = parent_item;
307318
}
308319

320+
fn visit_foreign_item(&mut self, i: &'ast ast::ForeignItem) {
321+
self.check_for_lang(
322+
Target::Fn,
323+
self.resolver.owners[&i.id].def_id,
324+
&i.attrs,
325+
i.span,
326+
None,
327+
CollectWeak::Ignore,
328+
);
329+
}
330+
309331
fn visit_variant(&mut self, variant: &'ast ast::Variant) {
310332
self.check_for_lang(
311333
Target::Variant,
312334
self.resolver.owners[&self.parent_item.unwrap().id].node_id_to_def_id[&variant.id],
313335
&variant.attrs,
314336
variant.span,
315337
None,
338+
CollectWeak::Allowed,
316339
);
317340
}
318341

@@ -346,7 +369,14 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
346369
}
347370
};
348371

349-
self.check_for_lang(target, self.resolver.owners[&i.id].def_id, &i.attrs, i.span, generics);
372+
self.check_for_lang(
373+
target,
374+
self.resolver.owners[&i.id].def_id,
375+
&i.attrs,
376+
i.span,
377+
generics,
378+
CollectWeak::Allowed,
379+
);
350380

351381
visit::walk_assoc_item(self, i, ctxt);
352382
}

compiler/rustc_passes/src/weak_lang_items.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,15 @@ struct WeakLangItemVisitor<'a, 'tcx> {
4848
impl<'ast> visit::Visitor<'ast> for WeakLangItemVisitor<'_, '_> {
4949
fn visit_foreign_item(&mut self, i: &'ast ast::ForeignItem) {
5050
if let Some((lang_item, _)) = extract_ast(&i.attrs) {
51-
if let Some(item) = LangItem::from_name(lang_item)
52-
&& item.is_weak()
53-
{
54-
if self.items.get(item).is_none() {
55-
self.items.missing.push(item);
51+
if let Some(item) = LangItem::from_name(lang_item) {
52+
if item.is_weak() {
53+
if self.items.get(item).is_none() {
54+
self.items.missing.push(item);
55+
}
56+
} else if item.is_weak_only() {
57+
// weak only lang items are handled directly in lang_items.rs
58+
} else {
59+
self.tcx.dcx().emit_err(UnknownExternLangItem { span: i.span, lang_item });
5660
}
5761
} else {
5862
self.tcx.dcx().emit_err(UnknownExternLangItem { span: i.span, lang_item });

compiler/rustc_span/src/symbol.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,7 @@ symbols! {
509509
backchain,
510510
backend_repr,
511511
bang,
512+
bcmp_fn,
512513
begin_panic,
513514
bench,
514515
bevy_ecs,
@@ -1258,7 +1259,11 @@ symbols! {
12581259
mem_variant_count,
12591260
mem_zeroed,
12601261
member_constraints,
1262+
memcmp_fn,
1263+
memcpy_fn,
1264+
memmove_fn,
12611265
memory,
1266+
memset_fn,
12621267
memtag,
12631268
message,
12641269
meta,
@@ -1997,6 +2002,7 @@ symbols! {
19972002
strict_provenance_lints,
19982003
string_deref_patterns,
19992004
stringify,
2005+
strlen_fn,
20002006
struct_field_attributes,
20012007
struct_inherit,
20022008
struct_variant,

library/core/src/ffi/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,30 @@ impl fmt::Debug for c_void {
8585
)]
8686
#[link(name = "/defaultlib:libcmt", modifiers = "+verbatim", cfg(target_feature = "crt-static"))]
8787
unsafe 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.
92+
mod 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/ui/error-codes/E0264.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![feature(lang_items)]
22

33
extern "C" {
4-
#[lang = "copy"]
4+
#[lang = "copy"] //~ ERROR E0718
55
fn copy(); //~ ERROR E0264
66
}
77

tests/ui/error-codes/E0264.stderr

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1+
error[E0718]: `copy` lang item must be applied to a trait
2+
--> $DIR/E0264.rs:4:5
3+
|
4+
LL | #[lang = "copy"]
5+
| ^^^^^^^^^^^^^^^^ attribute should be applied to a trait, not a function
6+
17
error[E0264]: unknown external lang item: `copy`
28
--> $DIR/E0264.rs:5:5
39
|
410
LL | fn copy();
511
| ^^^^^^^^^^
612

7-
error: aborting due to 1 previous error
13+
error: aborting due to 2 previous errors
814

9-
For more information about this error, try `rustc --explain E0264`.
15+
Some errors have detailed explanations: E0264, E0718.
16+
For more information about an error, try `rustc --explain E0264`.

0 commit comments

Comments
 (0)