From 4ca56d28884678d89c753c03de9f0c7544d018e6 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 27 Jan 2022 21:25:51 +0300 Subject: [PATCH] Check that `#[rustc_must_implement_one_of]` is applied to a trait --- compiler/rustc_passes/src/check_attr.rs | 23 +++++++++++++++++++ .../rustc_must_implement_one_of_misuse.rs | 8 +++++++ .../rustc_must_implement_one_of_misuse.stderr | 20 +++++++++++++++- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c3d5bae32e681..ec4cefa3537f9 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -76,6 +76,9 @@ impl CheckAttrVisitor<'_> { sym::inline => self.check_inline(hir_id, attr, span, target), sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target), sym::marker => self.check_marker(hir_id, attr, span, target), + sym::rustc_must_implement_one_of => { + self.check_rustc_must_implement_one_of(attr, span, target) + } sym::target_feature => self.check_target_feature(hir_id, attr, span, target), sym::track_caller => { self.check_track_caller(hir_id, &attr.span, attrs, span, target) @@ -477,6 +480,26 @@ impl CheckAttrVisitor<'_> { } } + /// Checks if the `#[rustc_must_implement_one_of]` attribute on a `target` is valid. Returns `true` if valid. + fn check_rustc_must_implement_one_of( + &self, + attr: &Attribute, + span: &Span, + target: Target, + ) -> bool { + match target { + Target::Trait => true, + _ => { + self.tcx + .sess + .struct_span_err(attr.span, "attribute can only be applied to a trait") + .span_label(*span, "not a trait") + .emit(); + false + } + } + } + /// Checks if the `#[target_feature]` attribute on `item` is valid. Returns `true` if valid. fn check_target_feature( &self, diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs index 1089e5f9c4ab9..d9de6d5edb9b4 100644 --- a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs @@ -35,4 +35,12 @@ trait Tr5 { fn b(); //~ This function doesn't have a default implementation } +#[rustc_must_implement_one_of(abc, xyz)] +//~^ attribute can only be applied to a trait +fn function() {} + +#[rustc_must_implement_one_of(abc, xyz)] +//~^ attribute can only be applied to a trait +struct Struct {} + fn main() {} diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr index 74a6dc8fec97c..bc28dc2c4f40d 100644 --- a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr @@ -4,6 +4,24 @@ error: malformed `rustc_must_implement_one_of` attribute input LL | #[rustc_must_implement_one_of] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_must_implement_one_of(function1, function2, ...)]` +error: attribute can only be applied to a trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:38:1 + | +LL | #[rustc_must_implement_one_of(abc, xyz)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | fn function() {} + | ---------------- not a trait + +error: attribute can only be applied to a trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:42:1 + | +LL | #[rustc_must_implement_one_of(abc, xyz)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | struct Struct {} + | ---------------- not a trait + error: Function not found in this trait --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31 | @@ -78,5 +96,5 @@ note: required by this annotation LL | #[rustc_must_implement_one_of(a, b)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 9 previous errors +error: aborting due to 11 previous errors