Rollup merge of #106716 - c410-f3r:rfc-2397-1, r=davidtwco

[RFC 2397] Deny incorrect locations

cc #51992

As declared in the RFC, `#[do_not_recommend]` should only be applicable on trait implementations.
This commit is contained in:
Yuki Okushi 2023-01-13 16:54:23 +09:00 committed by GitHub
commit f6f362c332
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 121 additions and 2 deletions

View File

@ -4,6 +4,9 @@
-passes_see_issue = -passes_see_issue =
see issue #{$issue} <https://github.com/rust-lang/rust/issues/{$issue}> for more information see issue #{$issue} <https://github.com/rust-lang/rust/issues/{$issue}> for more information
passes_incorrect_do_not_recommend_location =
`#[do_not_recommend]` can only be placed on trait implementations
passes_outer_crate_level_attr = passes_outer_crate_level_attr =
crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`

View File

@ -82,6 +82,7 @@ impl CheckAttrVisitor<'_> {
let attrs = self.tcx.hir().attrs(hir_id); let attrs = self.tcx.hir().attrs(hir_id);
for attr in attrs { for attr in attrs {
let attr_is_valid = match attr.name_or_empty() { let attr_is_valid = match attr.name_or_empty() {
sym::do_not_recommend => self.check_do_not_recommend(attr.span, target),
sym::inline => self.check_inline(hir_id, attr, span, target), sym::inline => self.check_inline(hir_id, attr, span, target),
sym::no_coverage => self.check_no_coverage(hir_id, attr, span, target), sym::no_coverage => self.check_no_coverage(hir_id, attr, span, target),
sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target), sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target),
@ -241,6 +242,16 @@ impl CheckAttrVisitor<'_> {
); );
} }
/// Checks if `#[do_not_recommend]` is applied on a trait impl.
fn check_do_not_recommend(&self, attr_span: Span, target: Target) -> bool {
if let Target::Impl = target {
true
} else {
self.tcx.sess.emit_err(errors::IncorrectDoNotRecommendLocation { span: attr_span });
false
}
}
/// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid. /// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool { fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
match target { match target {

View File

@ -14,6 +14,13 @@ use rustc_span::{Span, Symbol, DUMMY_SP};
use crate::lang_items::Duplicate; use crate::lang_items::Duplicate;
#[derive(Diagnostic)]
#[diag(passes_incorrect_do_not_recommend_location)]
pub struct IncorrectDoNotRecommendLocation {
#[primary_span]
pub span: Span,
}
#[derive(LintDiagnostic)] #[derive(LintDiagnostic)]
#[diag(passes_outer_crate_level_attr)] #[diag(passes_outer_crate_level_attr)]
pub struct OuterCrateLevelAttr; pub struct OuterCrateLevelAttr;

View File

@ -0,0 +1,45 @@
#![feature(do_not_recommend)]
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
const CONST: () = ();
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
static Static: () = ();
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
type Type = ();
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
enum Enum {
}
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
extern {
}
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
fn fun() {
}
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
struct Struct {
}
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
trait Trait {
}
#[do_not_recommend]
impl Trait for i32 {
}
fn main() {
}

View File

@ -0,0 +1,50 @@
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:3:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:7:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:11:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:15:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:20:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:25:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:30:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:35:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to 8 previous errors

View File

@ -1,6 +1,9 @@
trait Foo {
}
#[do_not_recommend] #[do_not_recommend]
//~^ ERROR the `#[do_not_recommend]` attribute is an experimental feature //~^ ERROR the `#[do_not_recommend]` attribute is an experimental feature
trait Foo { impl Foo for i32 {
} }
fn main() { fn main() {

View File

@ -1,5 +1,5 @@
error[E0658]: the `#[do_not_recommend]` attribute is an experimental feature error[E0658]: the `#[do_not_recommend]` attribute is an experimental feature
--> $DIR/unstable-feature.rs:1:1 --> $DIR/unstable-feature.rs:4:1
| |
LL | #[do_not_recommend] LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^