Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC 2397] Deny incorrect locations #106716

Merged
merged 1 commit into from
Jan 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/passes.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
-passes_see_issue =
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 =
crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`

Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ impl CheckAttrVisitor<'_> {
let attrs = self.tcx.hir().attrs(hir_id);
for attr in attrs {
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::no_coverage => self.check_no_coverage(hir_id, attr, span, target),
sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target),
Expand Down Expand Up @@ -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.
fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
match target {
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ use rustc_span::{Span, Symbol, DUMMY_SP};

use crate::lang_items::Duplicate;

#[derive(Diagnostic)]
#[diag(passes_incorrect_do_not_recommend_location)]
pub struct IncorrectDoNotRecommendLocation {
#[primary_span]
pub span: Span,
}

#[derive(LintDiagnostic)]
#[diag(passes_outer_crate_level_attr)]
pub struct OuterCrateLevelAttr;
Expand Down
45 changes: 45 additions & 0 deletions tests/ui/rfc-2397-do-not-recommend/incorrect-locations.rs
Original file line number Diff line number Diff line change
@@ -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() {
}
50 changes: 50 additions & 0 deletions tests/ui/rfc-2397-do-not-recommend/incorrect-locations.stderr
Original file line number Diff line number Diff line change
@@ -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

5 changes: 4 additions & 1 deletion tests/ui/rfc-2397-do-not-recommend/unstable-feature.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
trait Foo {
}

#[do_not_recommend]
//~^ ERROR the `#[do_not_recommend]` attribute is an experimental feature
trait Foo {
impl Foo for i32 {
}

fn main() {
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/rfc-2397-do-not-recommend/unstable-feature.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
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]
| ^^^^^^^^^^^^^^^^^^^
Expand Down