1
Fork 0

Enforce crate level attributes checks

This commit is contained in:
Guillaume Gomez 2020-10-03 20:45:39 +02:00
parent 6ec2474622
commit 3641a37455
10 changed files with 377 additions and 372 deletions

View file

@ -19,8 +19,8 @@ use rustc_hir::{
use rustc_hir::{MethodKind, Target}; use rustc_hir::{MethodKind, Target};
use rustc_session::lint::builtin::{CONFLICTING_REPR_HINTS, UNUSED_ATTRIBUTES}; use rustc_session::lint::builtin::{CONFLICTING_REPR_HINTS, UNUSED_ATTRIBUTES};
use rustc_session::parse::feature_err; use rustc_session::parse::feature_err;
use rustc_span::symbol::sym; use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span; use rustc_span::{Span, DUMMY_SP};
pub(crate) fn target_from_impl_item<'tcx>( pub(crate) fn target_from_impl_item<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
@ -821,6 +821,33 @@ fn is_c_like_enum(item: &Item<'_>) -> bool {
} }
} }
fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
const ATTRS_TO_CHECK: &[Symbol] = &[
sym::macro_export,
sym::repr,
sym::path,
sym::automatically_derived,
sym::start,
sym::main,
];
for attr in attrs {
for attr_to_check in ATTRS_TO_CHECK {
if tcx.sess.check_name(attr, *attr_to_check) {
tcx.sess
.struct_span_err(
attr.span,
&format!(
"`{}` attribute cannot be used at crate level",
attr_to_check.to_ident_string()
),
)
.emit();
}
}
}
}
fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
tcx.hir() tcx.hir()
.visit_item_likes_in_module(module_def_id, &mut CheckAttrVisitor { tcx }.as_deep_visitor()); .visit_item_likes_in_module(module_def_id, &mut CheckAttrVisitor { tcx }.as_deep_visitor());
@ -828,10 +855,11 @@ fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
CheckAttrVisitor { tcx }.check_attributes( CheckAttrVisitor { tcx }.check_attributes(
CRATE_HIR_ID, CRATE_HIR_ID,
tcx.hir().krate_attrs(), tcx.hir().krate_attrs(),
&tcx.hir().span(CRATE_HIR_ID), &DUMMY_SP,
Target::Mod, Target::Mod,
None, None,
); );
check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs());
} }
} }

View file

@ -78,29 +78,38 @@ fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType)
// Beware, this is duplicated in `librustc_builtin_macros/test_harness.rs` // Beware, this is duplicated in `librustc_builtin_macros/test_harness.rs`
// (with `ast::Item`), so make sure to keep them in sync. // (with `ast::Item`), so make sure to keep them in sync.
fn entry_point_type(sess: &Session, item: &Item<'_>, at_root: bool) -> EntryPointType { fn entry_point_type(sess: &Session, item: &Item<'_>, at_root: bool) -> EntryPointType {
match item.kind { if sess.contains_name(&item.attrs, sym::start) {
ItemKind::Fn(..) => { EntryPointType::Start
if sess.contains_name(&item.attrs, sym::start) { } else if sess.contains_name(&item.attrs, sym::main) {
EntryPointType::Start EntryPointType::MainAttr
} else if sess.contains_name(&item.attrs, sym::main) { } else if item.ident.name == sym::main {
EntryPointType::MainAttr if at_root {
} else if item.ident.name == sym::main { // This is a top-level function so can be `main`.
if at_root { EntryPointType::MainNamed
// This is a top-level function so can be `main`. } else {
EntryPointType::MainNamed EntryPointType::OtherMain
} else {
EntryPointType::OtherMain
}
} else {
EntryPointType::None
}
} }
_ => EntryPointType::None, } else {
EntryPointType::None
} }
} }
fn throw_attr_err(sess: &Session, span: Span, attr: &str) {
sess.struct_span_err(span, &format!("`{}` attribute can only be used on functions", attr))
.emit();
}
fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) { fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
match entry_point_type(&ctxt.session, item, at_root) { match entry_point_type(&ctxt.session, item, at_root) {
EntryPointType::None => (),
_ if !matches!(item.kind, ItemKind::Fn(..)) => {
if let Some(attr) = ctxt.session.find_by_name(item.attrs, sym::start) {
throw_attr_err(&ctxt.session, attr.span, "start");
}
if let Some(attr) = ctxt.session.find_by_name(item.attrs, sym::main) {
throw_attr_err(&ctxt.session, attr.span, "main");
}
}
EntryPointType::MainNamed => { EntryPointType::MainNamed => {
if ctxt.main_fn.is_none() { if ctxt.main_fn.is_none() {
ctxt.main_fn = Some((item.hir_id, item.span)); ctxt.main_fn = Some((item.hir_id, item.span));
@ -137,7 +146,6 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
.emit(); .emit();
} }
} }
EntryPointType::None => (),
} }
} }

View file

@ -518,7 +518,7 @@ declare_lint! {
/// ### Example /// ### Example
/// ///
/// ```rust /// ```rust
/// #![macro_export] /// #![ignore]
/// ``` /// ```
/// ///
/// {{produces}} /// {{produces}}

View file

@ -1,3 +1,6 @@
#![feature(doc_alias)] #![feature(doc_alias)]
#![doc(alias = "shouldn't work!")] //~ ERROR #![doc(alias = "crate-level-not-working")] //~ ERROR
#[doc(alias = "shouldn't work!")] //~ ERROR
pub fn foo() {}

View file

@ -1,8 +1,14 @@
error: '\'' character isn't allowed in `#[doc(alias = "...")]`
--> $DIR/doc-alias-crate-level.rs:5:7
|
LL | #[doc(alias = "shouldn't work!")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: `#![doc(alias = "...")]` isn't allowed as a crate level attribute error: `#![doc(alias = "...")]` isn't allowed as a crate level attribute
--> $DIR/doc-alias-crate-level.rs:3:8 --> $DIR/doc-alias-crate-level.rs:3:8
| |
LL | #![doc(alias = "shouldn't work!")] LL | #![doc(alias = "crate-level-not-working")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error error: aborting due to 2 previous errors

View file

@ -1,4 +1,4 @@
error: `#![doc(alias = "...")]` isn't allowed as a crate level attribute error: '\'' character isn't allowed in `#[doc(alias = "...")]`
--> $DIR/doc-alias-crate-level.rs:7:8 --> $DIR/doc-alias-crate-level.rs:7:8
| |
LL | #![doc(alias = "shouldn't work!")] LL | #![doc(alias = "shouldn't work!")]

View file

@ -1,3 +1,6 @@
//~ NOTE: not an `extern crate` item
//~^ NOTE: not a function or static
//~^^ NOTE: not a function or closure
// This is testing whether various builtin attributes signals an // This is testing whether various builtin attributes signals an
// error or warning when put in "weird" places. // error or warning when put in "weird" places.
// //
@ -7,22 +10,19 @@
// ignore-tidy-linelength // ignore-tidy-linelength
#![deny(unused_attributes)]
//~^ NOTE not a function or static
//~^^ NOTE the lint level is defined here
//~^^^ NOTE not an `extern crate` item
//~^^^^ NOTE not a function or static
//~^^^^^ NOTE not a function or closure
#![macro_export] #![macro_export]
//~^ ERROR: `macro_export` attribute cannot be used at crate level
#![main] #![main]
//~^ ERROR: `main` attribute cannot be used at crate level
#![start] #![start]
//~^ ERROR: `start` attribute cannot be used at crate level
#![repr()] #![repr()]
//~^ ERROR: `repr` attribute cannot be used at crate level
#![path = "3800"] #![path = "3800"]
//~^ ERROR: `path` attribute cannot be used at crate level
#![automatically_derived] #![automatically_derived]
//~^ ERROR: `automatically_derived` attribute cannot be used at crate level
#![no_mangle] #![no_mangle]
//~^ ERROR attribute should be applied to a function or static
//~^^ WARN
#![no_link] #![no_link]
//~^ ERROR: attribute should be applied to an `extern crate` item //~^ ERROR: attribute should be applied to an `extern crate` item
#![export_name = "2200"] #![export_name = "2200"]
@ -107,4 +107,40 @@ mod export_name {
//~| NOTE not a function or static //~| NOTE not a function or static
} }
#[main]
//~^ ERROR: `main` attribute can only be used on functions
mod main {
mod inner { #![main] }
//~^ ERROR: `main` attribute can only be used on functions
// for `fn f()` case, see feature-gate-main.rs
#[main] struct S;
//~^ ERROR: `main` attribute can only be used on functions
#[main] type T = S;
//~^ ERROR: `main` attribute can only be used on functions
#[main] impl S { }
//~^ ERROR: `main` attribute can only be used on functions
}
#[start]
//~^ ERROR: `start` attribute can only be used on functions
mod start {
mod inner { #![start] }
//~^ ERROR: `start` attribute can only be used on functions
// for `fn f()` case, see feature-gate-start.rs
#[start] struct S;
//~^ ERROR: `start` attribute can only be used on functions
#[start] type T = S;
//~^ ERROR: `start` attribute can only be used on functions
#[start] impl S { }
//~^ ERROR: `start` attribute can only be used on functions
}
fn main() {} fn main() {}

View file

@ -8,6 +8,66 @@ LL | #[inline = "2100"] fn f() { }
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
error: `main` attribute can only be used on functions
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:110:1
|
LL | #[main]
| ^^^^^^^
error: `main` attribute can only be used on functions
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:113:17
|
LL | mod inner { #![main] }
| ^^^^^^^^
error: `main` attribute can only be used on functions
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:118:5
|
LL | #[main] struct S;
| ^^^^^^^
error: `main` attribute can only be used on functions
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:121:5
|
LL | #[main] type T = S;
| ^^^^^^^
error: `main` attribute can only be used on functions
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:124:5
|
LL | #[main] impl S { }
| ^^^^^^^
error: `start` attribute can only be used on functions
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:128:1
|
LL | #[start]
| ^^^^^^^^
error: `start` attribute can only be used on functions
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:131:17
|
LL | mod inner { #![start] }
| ^^^^^^^^^
error: `start` attribute can only be used on functions
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:136:5
|
LL | #[start] struct S;
| ^^^^^^^^
error: `start` attribute can only be used on functions
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:139:5
|
LL | #[start] type T = S;
| ^^^^^^^^
error: `start` attribute can only be used on functions
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:142:5
|
LL | #[start] impl S { }
| ^^^^^^^^
error[E0518]: attribute should be applied to function or closure error[E0518]: attribute should be applied to function or closure
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:32:1 --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:32:1
| |
@ -53,72 +113,59 @@ LL | |
LL | | } LL | | }
| |_- not a function or static | |_- not a function or static
error: attribute should be applied to a function or static
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:23:1
|
LL | / #![deny(unused_attributes)]
LL | |
LL | |
LL | |
... |
LL | | #![no_mangle]
| | ^^^^^^^^^^^^^
... |
LL | |
LL | | fn main() {}
| |____________- not a function or static
|
note: the lint level is defined here
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:10:9
|
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
error: attribute should be applied to an `extern crate` item error: attribute should be applied to an `extern crate` item
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:26:1 --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:26:1
| |
LL | / #![deny(unused_attributes)] LL | #![no_link]
LL | | | ^^^^^^^^^^^
LL | |
LL | |
... |
LL | | #![no_link]
| | ^^^^^^^^^^^
... |
LL | |
LL | | fn main() {}
| |____________- not an `extern crate` item
error: attribute should be applied to a function or static error: attribute should be applied to a function or static
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:28:1 --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:28:1
| |
LL | / #![deny(unused_attributes)] LL | #![export_name = "2200"]
LL | | | ^^^^^^^^^^^^^^^^^^^^^^^^
LL | |
LL | |
... |
LL | | #![export_name = "2200"]
| | ^^^^^^^^^^^^^^^^^^^^^^^^
... |
LL | |
LL | | fn main() {}
| |____________- not a function or static
error[E0518]: attribute should be applied to function or closure error[E0518]: attribute should be applied to function or closure
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:30:1 --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:30:1
| |
LL | / #![deny(unused_attributes)] LL | #![inline]
LL | | | ^^^^^^^^^^
LL | |
LL | | error: `macro_export` attribute cannot be used at crate level
... | --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:13:1
LL | | #![inline] |
| | ^^^^^^^^^^ LL | #![macro_export]
... | | ^^^^^^^^^^^^^^^^
LL | |
LL | | fn main() {} error: `main` attribute cannot be used at crate level
| |____________- not a function or closure --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:15:1
|
LL | #![main]
| ^^^^^^^^
error: `start` attribute cannot be used at crate level
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:17:1
|
LL | #![start]
| ^^^^^^^^^
error: `repr` attribute cannot be used at crate level
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:19:1
|
LL | #![repr()]
| ^^^^^^^^^^
error: `path` attribute cannot be used at crate level
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1
|
LL | #![path = "3800"]
| ^^^^^^^^^^^^^^^^^
error: `automatically_derived` attribute cannot be used at crate level
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:23:1
|
LL | #![automatically_derived]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0518]: attribute should be applied to function or closure error[E0518]: attribute should be applied to function or closure
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:37:17 --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:37:17
@ -198,6 +245,6 @@ error: attribute should be applied to a function or static
LL | #[export_name = "2200"] impl S { } LL | #[export_name = "2200"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static | ^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static
error: aborting due to 21 previous errors error: aborting due to 36 previous errors
For more information about this error, try `rustc --explain E0518`. For more information about this error, try `rustc --explain E0518`.

View file

@ -1,3 +1,6 @@
//~ NOTE not a function
//~^ NOTE not a foreign function or static
//~^^ NOTE not a function or static
// This test enumerates as many compiler-builtin ungated attributes as // This test enumerates as many compiler-builtin ungated attributes as
// possible (that is, all the mutually compatible ones), and checks // possible (that is, all the mutually compatible ones), and checks
// that we get "expected" (*) warnings for each in the various weird // that we get "expected" (*) warnings for each in the various weird
@ -34,9 +37,6 @@
// ignore-tidy-linelength // ignore-tidy-linelength
#![feature(test, plugin_registrar)] #![feature(test, plugin_registrar)]
//~^ NOTE not a function
//~^^ NOTE not a foreign function or static
//~^^^ NOTE not a function or static
#![warn(unused_attributes, unknown_lints)] #![warn(unused_attributes, unknown_lints)]
//~^ NOTE the lint level is defined here //~^ NOTE the lint level is defined here
//~| NOTE the lint level is defined here //~| NOTE the lint level is defined here
@ -249,42 +249,6 @@ mod plugin_registrar {
//~| HELP may be removed in a future compiler version //~| HELP may be removed in a future compiler version
} }
#[main]
//~^ WARN unused attribute
mod main {
mod inner { #![main] }
//~^ WARN unused attribute
// for `fn f()` case, see feature-gate-main.rs
#[main] struct S;
//~^ WARN unused attribute
#[main] type T = S;
//~^ WARN unused attribute
#[main] impl S { }
//~^ WARN unused attribute
}
#[start]
//~^ WARN unused attribute
mod start {
mod inner { #![start] }
//~^ WARN unused attribute
// for `fn f()` case, see feature-gate-start.rs
#[start] struct S;
//~^ WARN unused attribute
#[start] type T = S;
//~^ WARN unused attribute
#[start] impl S { }
//~^ WARN unused attribute
}
// At time of unit test authorship, if compiling without `--test` then // At time of unit test authorship, if compiling without `--test` then
// non-crate-level #[test] attributes seem to be ignored. // non-crate-level #[test] attributes seem to be ignored.