Skip to content

Commit f745b34

Browse files
committed
Emit warnings for misplaced attributes used by some crates
1 parent 4efe97a commit f745b34

13 files changed

+691
-530
lines changed

compiler/rustc_passes/src/check_attr.rs

Lines changed: 100 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -66,22 +66,24 @@ impl CheckAttrVisitor<'tcx> {
6666
} else if self.tcx.sess.check_name(attr, sym::marker) {
6767
self.check_marker(attr, span, target)
6868
} else if self.tcx.sess.check_name(attr, sym::target_feature) {
69-
self.check_target_feature(attr, span, target)
69+
self.check_target_feature(hir_id, attr, span, target)
7070
} else if self.tcx.sess.check_name(attr, sym::track_caller) {
7171
self.check_track_caller(&attr.span, attrs, span, target)
7272
} else if self.tcx.sess.check_name(attr, sym::doc) {
7373
self.check_doc_alias(attr, hir_id, target)
74-
} else if self.tcx.sess.check_name(attr, sym::cold) {
75-
self.check_cold(&attr, span, target)
76-
} else if self.tcx.sess.check_name(attr, sym::link_name) {
77-
self.check_link_name(&attr, span, target)
7874
} else if self.tcx.sess.check_name(attr, sym::no_link) {
7975
self.check_no_link(&attr, span, target)
8076
} else if self.tcx.sess.check_name(attr, sym::export_name) {
8177
self.check_export_name(&attr, span, target)
82-
} else if self.tcx.sess.check_name(attr, sym::link_section) {
83-
self.check_link_section(&attr, span, target)
8478
} else {
79+
// lint-only checks
80+
if self.tcx.sess.check_name(attr, sym::cold) {
81+
self.check_cold(hir_id, attr, span, target);
82+
} else if self.tcx.sess.check_name(attr, sym::link_name) {
83+
self.check_link_name(hir_id, attr, span, target);
84+
} else if self.tcx.sess.check_name(attr, sym::link_section) {
85+
self.check_link_section(hir_id, attr, span, target);
86+
}
8587
true
8688
};
8789
}
@@ -212,10 +214,31 @@ impl CheckAttrVisitor<'tcx> {
212214
}
213215

214216
/// Checks if the `#[target_feature]` attribute on `item` is valid. Returns `true` if valid.
215-
fn check_target_feature(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
217+
fn check_target_feature(
218+
&self,
219+
hir_id: HirId,
220+
attr: &Attribute,
221+
span: &Span,
222+
target: Target,
223+
) -> bool {
216224
match target {
217225
Target::Fn
218226
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
227+
// FIXME: #[target_feature] was previously erroneously allowed on statements and some
228+
// crates used this, so only emit a warning.
229+
Target::Statement => {
230+
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
231+
lint.build("attribute should be applied to a function")
232+
.warn(
233+
"this was previously accepted by the compiler but is \
234+
being phased out; it will become a hard error in \
235+
a future release!",
236+
)
237+
.span_label(*span, "not a function")
238+
.emit();
239+
});
240+
true
241+
}
219242
_ => {
220243
self.tcx
221244
.sess
@@ -288,45 +311,58 @@ impl CheckAttrVisitor<'tcx> {
288311
}
289312

290313
/// Checks if `#[cold]` is applied to a non-function. Returns `true` if valid.
291-
fn check_cold(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
314+
fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) {
292315
match target {
293-
Target::Fn | Target::Method(..) | Target::ForeignFn => true,
316+
Target::Fn | Target::Method(..) | Target::ForeignFn => {}
294317
_ => {
295-
self.tcx
296-
.sess
297-
.struct_span_err(attr.span, "attribute should be applied to a function")
298-
.span_label(*span, "not a function")
299-
.emit();
300-
false
318+
// FIXME: #[cold] was previously allowed on non-functions and some crates used
319+
// this, so only emit a warning.
320+
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
321+
lint.build("attribute should be applied to a function")
322+
.warn(
323+
"this was previously accepted by the compiler but is \
324+
being phased out; it will become a hard error in \
325+
a future release!",
326+
)
327+
.span_label(*span, "not a function")
328+
.emit();
329+
});
301330
}
302331
}
303332
}
304333

305-
/// Checks if `#[link_name]` is applied to an item other than a foreign function or static. Returns `true` if valid.
306-
fn check_link_name(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
307-
if target == Target::ForeignFn || target == Target::ForeignStatic {
308-
true
309-
} else {
310-
let mut err = self.tcx.sess.struct_span_err(
311-
attr.span,
312-
"attribute should be applied to a foreign function or static",
313-
);
314-
err.span_label(*span, "not a foreign function or static");
315-
316-
// See issue #47725
317-
if target == Target::ForeignMod {
318-
if let Some(value) = attr.value_str() {
319-
err.span_help(
320-
attr.span,
321-
&format!(r#"try `#[link(name = "{}")]` instead"#, value),
334+
/// Checks if `#[link_name]` is applied to an item other than a foreign function or static.
335+
fn check_link_name(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) {
336+
match target {
337+
Target::ForeignFn | Target::ForeignStatic => {}
338+
_ => {
339+
// FIXME: #[cold] was previously allowed on non-functions/statics and some crates
340+
// used this, so only emit a warning.
341+
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
342+
let mut diag =
343+
lint.build("attribute should be applied to a foreign function or static");
344+
diag.warn(
345+
"this was previously accepted by the compiler but is \
346+
being phased out; it will become a hard error in \
347+
a future release!",
322348
);
323-
} else {
324-
err.span_help(attr.span, r#"try `#[link(name = "...")]` instead"#);
325-
}
326-
}
327349

328-
err.emit();
329-
false
350+
// See issue #47725
351+
if let Target::ForeignMod = target {
352+
if let Some(value) = attr.value_str() {
353+
diag.span_help(
354+
attr.span,
355+
&format!(r#"try `#[link(name = "{}")]` instead"#, value),
356+
);
357+
} else {
358+
diag.span_help(attr.span, r#"try `#[link(name = "...")]` instead"#);
359+
}
360+
}
361+
362+
diag.span_label(*span, "not a foreign function or static");
363+
diag.emit();
364+
});
365+
}
330366
}
331367
}
332368

@@ -362,20 +398,23 @@ impl CheckAttrVisitor<'tcx> {
362398
}
363399
}
364400

365-
/// Checks if `#[link_section]` is applied to a function or static. Returns `true` if valid.
366-
fn check_link_section(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
401+
/// Checks if `#[link_section]` is applied to a function or static.
402+
fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) {
367403
match target {
368-
Target::Static | Target::Fn | Target::Method(..) => true,
404+
Target::Static | Target::Fn | Target::Method(..) => {}
369405
_ => {
370-
self.tcx
371-
.sess
372-
.struct_span_err(
373-
attr.span,
374-
"attribute should be applied to a function or static",
375-
)
376-
.span_label(*span, "not a function or static")
377-
.emit();
378-
false
406+
// FIXME: #[link_section] was previously allowed on non-functions/statics and some
407+
// crates used this, so only emit a warning.
408+
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
409+
lint.build("attribute should be applied to a function or static")
410+
.warn(
411+
"this was previously accepted by the compiler but is \
412+
being phased out; it will become a hard error in \
413+
a future release!",
414+
)
415+
.span_label(*span, "not a function or static")
416+
.emit();
417+
});
379418
}
380419
}
381420
}
@@ -424,7 +463,11 @@ impl CheckAttrVisitor<'tcx> {
424463
}
425464
sym::simd => {
426465
is_simd = true;
427-
if target != Target::Struct { ("a", "struct") } else { continue }
466+
if target != Target::Struct {
467+
("a", "struct")
468+
} else {
469+
continue;
470+
}
428471
}
429472
sym::transparent => {
430473
is_transparent = true;
@@ -461,7 +504,11 @@ impl CheckAttrVisitor<'tcx> {
461504
| sym::isize
462505
| sym::usize => {
463506
int_reprs += 1;
464-
if target != Target::Enum { ("an", "enum") } else { continue }
507+
if target != Target::Enum {
508+
("an", "enum")
509+
} else {
510+
continue;
511+
}
465512
}
466513
_ => continue,
467514
};

src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs-error.rs

Lines changed: 0 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -64,30 +64,6 @@ mod no_link {
6464
//~| NOTE not an `extern crate` item
6565
}
6666

67-
#[cold]
68-
//~^ ERROR attribute should be applied to a function
69-
mod cold {
70-
//~^ NOTE not a function
71-
72-
mod inner { #![cold] }
73-
//~^ ERROR attribute should be applied to a function
74-
//~| NOTE not a function
75-
76-
#[cold] fn f() { }
77-
78-
#[cold] struct S;
79-
//~^ ERROR attribute should be applied to a function
80-
//~| NOTE not a function
81-
82-
#[cold] type T = S;
83-
//~^ ERROR attribute should be applied to a function
84-
//~| NOTE not a function
85-
86-
#[cold] impl S { }
87-
//~^ ERROR attribute should be applied to a function
88-
//~| NOTE not a function
89-
}
90-
9167
#[export_name = "2200"]
9268
//~^ ERROR attribute should be applied to a function or static
9369
mod export_name {
@@ -112,60 +88,4 @@ mod export_name {
11288
//~| NOTE not a function or static
11389
}
11490

115-
#[link_name = "1900"]
116-
//~^ ERROR attribute should be applied to a foreign function or static
117-
mod link_name {
118-
//~^ NOTE not a foreign function or static
119-
120-
#[link_name = "1900"]
121-
//~^ ERROR attribute should be applied to a foreign function or static
122-
//~| HELP try `#[link(name = "1900")]` instead
123-
extern { }
124-
//~^ NOTE not a foreign function or static
125-
126-
mod inner { #![link_name="1900"] }
127-
//~^ ERROR attribute should be applied to a foreign function or static
128-
//~| NOTE not a foreign function or static
129-
130-
#[link_name = "1900"] fn f() { }
131-
//~^ ERROR attribute should be applied to a foreign function or static
132-
//~| NOTE not a foreign function or static
133-
134-
#[link_name = "1900"] struct S;
135-
//~^ ERROR attribute should be applied to a foreign function or static
136-
//~| NOTE not a foreign function or static
137-
138-
#[link_name = "1900"] type T = S;
139-
//~^ ERROR attribute should be applied to a foreign function or static
140-
//~| NOTE not a foreign function or static
141-
142-
#[link_name = "1900"] impl S { }
143-
//~^ ERROR attribute should be applied to a foreign function or static
144-
//~| NOTE not a foreign function or static
145-
}
146-
147-
#[link_section = "1800"]
148-
//~^ ERROR attribute should be applied to a function or static
149-
mod link_section {
150-
//~^ NOTE not a function or static
151-
152-
mod inner { #![link_section="1800"] }
153-
//~^ ERROR attribute should be applied to a function or static
154-
//~| NOTE not a function or static
155-
156-
#[link_section = "1800"] fn f() { }
157-
158-
#[link_section = "1800"] struct S;
159-
//~^ ERROR attribute should be applied to a function or static
160-
//~| NOTE not a function or static
161-
162-
#[link_section = "1800"] type T = S;
163-
//~^ ERROR attribute should be applied to a function or static
164-
//~| NOTE not a function or static
165-
166-
#[link_section = "1800"] impl S { }
167-
//~^ ERROR attribute should be applied to a function or static
168-
//~| NOTE not a function or static
169-
}
170-
17191
fn main() {}

0 commit comments

Comments
 (0)