Skip to content

Commit 0bb2ea6

Browse files
author
hyd-dev
committed
Adjust #[no_mangle]-related checks and lints for impl items
1 parent c84beef commit 0bb2ea6

13 files changed

+559
-42
lines changed

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14991499
}
15001500

15011501
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
1502+
if self.session.contains_name(&item.attrs, sym::no_mangle) {
1503+
self.check_nomangle_item_asciionly(item.ident, item.span);
1504+
}
1505+
15021506
if ctxt == AssocCtxt::Trait || !self.in_trait_impl {
15031507
self.check_defaultness(item.span, item.kind.defaultness());
15041508
}

compiler/rustc_lint/src/builtin.rs

Lines changed: 64 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,25 @@ impl EarlyLintPass for UnsafeCode {
417417
}
418418
}
419419

420+
fn check_impl_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
421+
if let ast::AssocItemKind::Fn(..) = it.kind {
422+
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) {
423+
self.report_overriden_symbol_name(
424+
cx,
425+
attr.span,
426+
"declaration of a `no_mangle` method",
427+
);
428+
}
429+
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) {
430+
self.report_overriden_symbol_name(
431+
cx,
432+
attr.span,
433+
"declaration of a method with `export_name`",
434+
);
435+
}
436+
}
437+
}
438+
420439
fn check_fn(&mut self, cx: &EarlyContext<'_>, fk: FnKind<'_>, span: Span, _: ast::NodeId) {
421440
if let FnKind::Fn(
422441
ctxt,
@@ -1115,31 +1134,37 @@ declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS, NO_MANGLE_GEN
11151134
impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
11161135
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
11171136
let attrs = cx.tcx.hir().attrs(it.hir_id());
1137+
let check_no_mangle_on_generic_fn = |no_mangle_attr: &ast::Attribute,
1138+
impl_generics: Option<&hir::Generics<'_>>,
1139+
generics: &hir::Generics<'_>,
1140+
span| {
1141+
for param in
1142+
generics.params.iter().chain(impl_generics.map(|g| g.params).into_iter().flatten())
1143+
{
1144+
match param.kind {
1145+
GenericParamKind::Lifetime { .. } => {}
1146+
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1147+
cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS, span, |lint| {
1148+
lint.build("functions generic over types or consts must be mangled")
1149+
.span_suggestion_short(
1150+
no_mangle_attr.span,
1151+
"remove this attribute",
1152+
String::new(),
1153+
// Use of `#[no_mangle]` suggests FFI intent; correct
1154+
// fix may be to monomorphize source by hand
1155+
Applicability::MaybeIncorrect,
1156+
)
1157+
.emit();
1158+
});
1159+
break;
1160+
}
1161+
}
1162+
}
1163+
};
11181164
match it.kind {
11191165
hir::ItemKind::Fn(.., ref generics, _) => {
11201166
if let Some(no_mangle_attr) = cx.sess().find_by_name(attrs, sym::no_mangle) {
1121-
for param in generics.params {
1122-
match param.kind {
1123-
GenericParamKind::Lifetime { .. } => {}
1124-
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1125-
cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS, it.span, |lint| {
1126-
lint.build(
1127-
"functions generic over types or consts must be mangled",
1128-
)
1129-
.span_suggestion_short(
1130-
no_mangle_attr.span,
1131-
"remove this attribute",
1132-
String::new(),
1133-
// Use of `#[no_mangle]` suggests FFI intent; correct
1134-
// fix may be to monomorphize source by hand
1135-
Applicability::MaybeIncorrect,
1136-
)
1137-
.emit();
1138-
});
1139-
break;
1140-
}
1141-
}
1142-
}
1167+
check_no_mangle_on_generic_fn(no_mangle_attr, None, generics, it.span);
11431168
}
11441169
}
11451170
hir::ItemKind::Const(..) => {
@@ -1170,6 +1195,23 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
11701195
});
11711196
}
11721197
}
1198+
hir::ItemKind::Impl(hir::Impl { ref generics, items, .. }) => {
1199+
for it in items {
1200+
if let hir::AssocItemKind::Fn { .. } = it.kind {
1201+
if let Some(no_mangle_attr) = cx
1202+
.sess()
1203+
.find_by_name(cx.tcx.hir().attrs(it.id.hir_id()), sym::no_mangle)
1204+
{
1205+
check_no_mangle_on_generic_fn(
1206+
no_mangle_attr,
1207+
Some(generics),
1208+
cx.tcx.hir().get_generics(it.id.def_id.to_def_id()).unwrap(),
1209+
it.span,
1210+
);
1211+
}
1212+
}
1213+
}
1214+
}
11731215
_ => {}
11741216
}
11751217
}

compiler/rustc_lint/src/nonstandard_style.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,14 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
391391
_: Span,
392392
id: hir::HirId,
393393
) {
394+
let attrs = cx.tcx.hir().attrs(id);
394395
match &fk {
395-
FnKind::Method(ident, ..) => match method_context(cx, id) {
396+
FnKind::Method(ident, sig, ..) => match method_context(cx, id) {
396397
MethodLateContext::PlainImpl => {
398+
if sig.header.abi != Abi::Rust && cx.sess().contains_name(attrs, sym::no_mangle)
399+
{
400+
return;
401+
}
397402
self.check_snake_case(cx, "method", ident);
398403
}
399404
MethodLateContext::TraitAutoImpl => {
@@ -402,7 +407,6 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
402407
_ => (),
403408
},
404409
FnKind::ItemFn(ident, _, header, _) => {
405-
let attrs = cx.tcx.hir().attrs(id);
406410
// Skip foreign-ABI #[no_mangle] functions (Issue #31924)
407411
if header.abi != Abi::Rust && cx.sess().contains_name(attrs, sym::no_mangle) {
408412
return;

src/test/ui/auxiliary/no-mangle-associated-fn.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,14 @@ impl Bar {
88
2
99
}
1010
}
11+
12+
trait Foo {
13+
fn baz() -> u8;
14+
}
15+
16+
impl Foo for Bar {
17+
#[no_mangle]
18+
fn baz() -> u8 {
19+
3
20+
}
21+
}

src/test/ui/generics/generic-no-mangle.fixed

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,119 @@ pub fn baz(x: &i32) -> &i32 { x }
1414
#[no_mangle]
1515
pub fn qux<'a>(x: &'a i32) -> &i32 { x }
1616

17+
pub struct Foo;
18+
19+
impl Foo {
20+
21+
pub fn foo<T>() {} //~ ERROR functions generic over types or consts must be mangled
22+
23+
24+
pub extern "C" fn bar<T>() {} //~ ERROR functions generic over types or consts must be mangled
25+
26+
#[no_mangle]
27+
pub fn baz(x: &i32) -> &i32 { x }
28+
29+
#[no_mangle]
30+
pub fn qux<'a>(x: &'a i32) -> &i32 { x }
31+
}
32+
33+
trait Trait1 {
34+
fn foo<T>();
35+
extern "C" fn bar<T>();
36+
fn baz(x: &i32) -> &i32;
37+
fn qux<'a>(x: &'a i32) -> &i32;
38+
}
39+
40+
impl Trait1 for Foo {
41+
42+
fn foo<T>() {} //~ ERROR functions generic over types or consts must be mangled
43+
44+
45+
extern "C" fn bar<T>() {} //~ ERROR functions generic over types or consts must be mangled
46+
47+
#[no_mangle]
48+
fn baz(x: &i32) -> &i32 { x }
49+
50+
#[no_mangle]
51+
fn qux<'a>(x: &'a i32) -> &i32 { x }
52+
}
53+
54+
trait Trait2<T> {
55+
fn foo();
56+
fn foo2<U>();
57+
extern "C" fn bar();
58+
fn baz(x: &i32) -> &i32;
59+
fn qux<'a>(x: &'a i32) -> &i32;
60+
}
61+
62+
impl<T> Trait2<T> for Foo {
63+
64+
fn foo() {} //~ ERROR functions generic over types or consts must be mangled
65+
66+
67+
fn foo2<U>() {} //~ ERROR functions generic over types or consts must be mangled
68+
69+
70+
extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled
71+
72+
73+
fn baz(x: &i32) -> &i32 { x } //~ ERROR functions generic over types or consts must be mangled
74+
75+
76+
fn qux<'a>(x: &'a i32) -> &i32 { x } //~ ERROR functions generic over types or consts must be mangled
77+
}
78+
79+
pub struct Bar<T>(T);
80+
81+
impl<T> Bar<T> {
82+
83+
pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled
84+
85+
86+
pub extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled
87+
88+
89+
pub fn baz<U>() {} //~ ERROR functions generic over types or consts must be mangled
90+
}
91+
92+
trait Trait3 {
93+
fn foo();
94+
extern "C" fn bar();
95+
fn baz<U>();
96+
}
97+
98+
impl<T> Trait3 for Bar<T> {
99+
100+
fn foo() {} //~ ERROR functions generic over types or consts must be mangled
101+
102+
103+
extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled
104+
105+
106+
fn baz<U>() {} //~ ERROR functions generic over types or consts must be mangled
107+
}
108+
109+
pub struct Baz<'a>(&'a i32);
110+
111+
impl<'a> Baz<'a> {
112+
#[no_mangle]
113+
pub fn foo() {}
114+
115+
#[no_mangle]
116+
pub fn bar<'b>(x: &'b i32) -> &i32 { x }
117+
}
118+
119+
trait Trait4 {
120+
fn foo();
121+
fn bar<'a>(x: &'a i32) -> &i32;
122+
}
123+
124+
impl<'a> Trait4 for Baz<'a> {
125+
#[no_mangle]
126+
fn foo() {}
127+
128+
#[no_mangle]
129+
fn bar<'b>(x: &'b i32) -> &i32 { x }
130+
}
131+
17132
fn main() {}

src/test/ui/generics/generic-no-mangle.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,119 @@ pub fn baz(x: &i32) -> &i32 { x }
1414
#[no_mangle]
1515
pub fn qux<'a>(x: &'a i32) -> &i32 { x }
1616

17+
pub struct Foo;
18+
19+
impl Foo {
20+
#[no_mangle]
21+
pub fn foo<T>() {} //~ ERROR functions generic over types or consts must be mangled
22+
23+
#[no_mangle]
24+
pub extern "C" fn bar<T>() {} //~ ERROR functions generic over types or consts must be mangled
25+
26+
#[no_mangle]
27+
pub fn baz(x: &i32) -> &i32 { x }
28+
29+
#[no_mangle]
30+
pub fn qux<'a>(x: &'a i32) -> &i32 { x }
31+
}
32+
33+
trait Trait1 {
34+
fn foo<T>();
35+
extern "C" fn bar<T>();
36+
fn baz(x: &i32) -> &i32;
37+
fn qux<'a>(x: &'a i32) -> &i32;
38+
}
39+
40+
impl Trait1 for Foo {
41+
#[no_mangle]
42+
fn foo<T>() {} //~ ERROR functions generic over types or consts must be mangled
43+
44+
#[no_mangle]
45+
extern "C" fn bar<T>() {} //~ ERROR functions generic over types or consts must be mangled
46+
47+
#[no_mangle]
48+
fn baz(x: &i32) -> &i32 { x }
49+
50+
#[no_mangle]
51+
fn qux<'a>(x: &'a i32) -> &i32 { x }
52+
}
53+
54+
trait Trait2<T> {
55+
fn foo();
56+
fn foo2<U>();
57+
extern "C" fn bar();
58+
fn baz(x: &i32) -> &i32;
59+
fn qux<'a>(x: &'a i32) -> &i32;
60+
}
61+
62+
impl<T> Trait2<T> for Foo {
63+
#[no_mangle]
64+
fn foo() {} //~ ERROR functions generic over types or consts must be mangled
65+
66+
#[no_mangle]
67+
fn foo2<U>() {} //~ ERROR functions generic over types or consts must be mangled
68+
69+
#[no_mangle]
70+
extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled
71+
72+
#[no_mangle]
73+
fn baz(x: &i32) -> &i32 { x } //~ ERROR functions generic over types or consts must be mangled
74+
75+
#[no_mangle]
76+
fn qux<'a>(x: &'a i32) -> &i32 { x } //~ ERROR functions generic over types or consts must be mangled
77+
}
78+
79+
pub struct Bar<T>(T);
80+
81+
impl<T> Bar<T> {
82+
#[no_mangle]
83+
pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled
84+
85+
#[no_mangle]
86+
pub extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled
87+
88+
#[no_mangle]
89+
pub fn baz<U>() {} //~ ERROR functions generic over types or consts must be mangled
90+
}
91+
92+
trait Trait3 {
93+
fn foo();
94+
extern "C" fn bar();
95+
fn baz<U>();
96+
}
97+
98+
impl<T> Trait3 for Bar<T> {
99+
#[no_mangle]
100+
fn foo() {} //~ ERROR functions generic over types or consts must be mangled
101+
102+
#[no_mangle]
103+
extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled
104+
105+
#[no_mangle]
106+
fn baz<U>() {} //~ ERROR functions generic over types or consts must be mangled
107+
}
108+
109+
pub struct Baz<'a>(&'a i32);
110+
111+
impl<'a> Baz<'a> {
112+
#[no_mangle]
113+
pub fn foo() {}
114+
115+
#[no_mangle]
116+
pub fn bar<'b>(x: &'b i32) -> &i32 { x }
117+
}
118+
119+
trait Trait4 {
120+
fn foo();
121+
fn bar<'a>(x: &'a i32) -> &i32;
122+
}
123+
124+
impl<'a> Trait4 for Baz<'a> {
125+
#[no_mangle]
126+
fn foo() {}
127+
128+
#[no_mangle]
129+
fn bar<'b>(x: &'b i32) -> &i32 { x }
130+
}
131+
17132
fn main() {}

0 commit comments

Comments
 (0)