diff --git a/compiler/rustc_attr_parsing/src/attributes/semantics.rs b/compiler/rustc_attr_parsing/src/attributes/semantics.rs index 74b2cc2ffd5a1..cdcb8e95da726 100644 --- a/compiler/rustc_attr_parsing/src/attributes/semantics.rs +++ b/compiler/rustc_attr_parsing/src/attributes/semantics.rs @@ -1,11 +1,17 @@ use rustc_feature::AttributeStability; +use rustc_hir::target::GenericParamKind; use super::prelude::*; pub(crate) struct MayDangleParser; impl NoArgsAttributeParser for MayDangleParser { const PATH: &[Symbol] = &[sym::may_dangle]; - const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ + Allow(Target::GenericParam { kind: GenericParamKind::Type, has_default: false }), + Allow(Target::GenericParam { kind: GenericParamKind::Type, has_default: true }), + Allow(Target::GenericParam { kind: GenericParamKind::Lifetime, has_default: false }), + Allow(Target::GenericParam { kind: GenericParamKind::Lifetime, has_default: true }), + ]); const STABILITY: AttributeStability = unstable!(dropck_eyepatch); const CREATE: fn(span: Span) -> AttributeKind = AttributeKind::MayDangle; } diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index 96737be04f5b2..03100381d23f3 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -416,6 +416,7 @@ pub(crate) fn allowed_targets_applied( // ensure a consistent order target_strings.sort(); + target_strings.dedup(); // If there is now only 1 target left, show that as the only possible target let only_target = target_strings.len() == 1; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 079fdd923ac0d..701f39e7c0e39 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -24,8 +24,9 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalModDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{ - self as hir, Attribute, CRATE_HIR_ID, Constness, FnSig, ForeignItem, GenericParamKind, HirId, - Item, ItemKind, MethodKind, Node, ParamName, Target, TraitItem, find_attr, + self as hir, Attribute, CRATE_HIR_ID, Constness, FnSig, ForeignItem, GenericParam, + GenericParamKind, HirId, Item, ItemKind, MethodKind, Node, ParamName, Target, TraitItem, + find_attr, }; use rustc_macros::Diagnostic; use rustc_middle::hir::nested_filter; @@ -1121,12 +1122,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Checks if `#[may_dangle]` is applied to a lifetime or type generic parameter in `Drop` impl. fn check_may_dangle(&self, hir_id: HirId, attr_span: Span) { - if let hir::Node::GenericParam(param) = self.tcx.hir_node(hir_id) - && matches!( - param.kind, - hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } - ) - && matches!(param.source, hir::GenericParamSource::Generics) + let hir::Node::GenericParam( + param @ GenericParam { + kind: hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. }, + .. + }, + ) = self.tcx.hir_node(hir_id) + else { + self.dcx().delayed_bug("Checked in attr parser"); + return; + }; + + if matches!(param.source, hir::GenericParamSource::Generics) && let parent_hir_id = self.tcx.parent_hir_id(hir_id) && let hir::Node::Item(item) = self.tcx.hir_node(parent_hir_id) && let hir::ItemKind::Impl(impl_) = item.kind diff --git a/tests/ui/attributes/may_dangle.rs b/tests/ui/attributes/may_dangle.rs index 209ba0e88ad18..401efce88851c 100644 --- a/tests/ui/attributes/may_dangle.rs +++ b/tests/ui/attributes/may_dangle.rs @@ -12,7 +12,7 @@ unsafe impl<'a, #[may_dangle] T, const N: usize> NotDrop for Implee2<'a, T, N> { //~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl unsafe impl<'a, T, #[may_dangle] const N: usize> Drop for Implee1<'a, T, N> { - //~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl + //~^ ERROR attribute cannot be used on fn drop(&mut self) {} } @@ -39,15 +39,15 @@ mod fake { } } -#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl +#[may_dangle] //~ ERROR attribute cannot be used on struct Dangling; -#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl +#[may_dangle] //~ ERROR attribute cannot be used on impl NotDrop for () { } -#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl +#[may_dangle] //~ ERROR attribute cannot be used on fn main() { - #[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl + #[may_dangle] //~ ERROR attribute cannot be used on let () = (); } diff --git a/tests/ui/attributes/may_dangle.stderr b/tests/ui/attributes/may_dangle.stderr index dc24f847f712f..596c44aa958e1 100644 --- a/tests/ui/attributes/may_dangle.stderr +++ b/tests/ui/attributes/may_dangle.stderr @@ -1,44 +1,54 @@ -error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl - --> $DIR/may_dangle.rs:8:13 - | -LL | unsafe impl<#[may_dangle] 'a, T, const N: usize> NotDrop for Implee1<'a, T, N> {} - | ^^^^^^^^^^^^^ - -error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl - --> $DIR/may_dangle.rs:11:17 - | -LL | unsafe impl<'a, #[may_dangle] T, const N: usize> NotDrop for Implee2<'a, T, N> {} - | ^^^^^^^^^^^^^ - -error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl +error: `#[may_dangle]` attribute cannot be used on const parameters --> $DIR/may_dangle.rs:14:20 | LL | unsafe impl<'a, T, #[may_dangle] const N: usize> Drop for Implee1<'a, T, N> { | ^^^^^^^^^^^^^ + | + = help: `#[may_dangle]` can be applied to lifetime parameters and type parameters -error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl +error: `#[may_dangle]` attribute cannot be used on structs --> $DIR/may_dangle.rs:42:1 | LL | #[may_dangle] | ^^^^^^^^^^^^^ + | + = help: `#[may_dangle]` can be applied to lifetime parameters and type parameters -error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl +error: `#[may_dangle]` attribute cannot be used on trait impl blocks --> $DIR/may_dangle.rs:45:1 | LL | #[may_dangle] | ^^^^^^^^^^^^^ + | + = help: `#[may_dangle]` can be applied to lifetime parameters and type parameters -error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl +error: `#[may_dangle]` attribute cannot be used on functions --> $DIR/may_dangle.rs:49:1 | LL | #[may_dangle] | ^^^^^^^^^^^^^ + | + = help: `#[may_dangle]` can be applied to lifetime parameters and type parameters -error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl +error: `#[may_dangle]` attribute cannot be used on statements --> $DIR/may_dangle.rs:51:5 | LL | #[may_dangle] | ^^^^^^^^^^^^^ + | + = help: `#[may_dangle]` can be applied to lifetime parameters and type parameters + +error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl + --> $DIR/may_dangle.rs:8:13 + | +LL | unsafe impl<#[may_dangle] 'a, T, const N: usize> NotDrop for Implee1<'a, T, N> {} + | ^^^^^^^^^^^^^ + +error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl + --> $DIR/may_dangle.rs:11:17 + | +LL | unsafe impl<'a, #[may_dangle] T, const N: usize> NotDrop for Implee2<'a, T, N> {} + | ^^^^^^^^^^^^^ error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl --> $DIR/may_dangle.rs:36:17