Skip to content

Commit 1ddede1

Browse files
committed
Port #[may_dangle] to the new attribute system
1 parent 6f935a0 commit 1ddede1

File tree

6 files changed

+47
-22
lines changed

6 files changed

+47
-22
lines changed

compiler/rustc_attr_data_structures/src/attributes.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,9 @@ pub enum AttributeKind {
227227
/// Represents `#[rustc_macro_transparency]`.
228228
MacroTransparency(Transparency),
229229

230+
/// Represents [`#[may_dangle]`](https://std-dev-guide.rust-lang.org/tricky/may-dangle.html).
231+
MayDangle(Span),
232+
230233
/// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
231234
Repr(ThinVec<(ReprAttr, Span)>),
232235

compiler/rustc_attr_parsing/src/attributes/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub(crate) mod deprecation;
3333
pub(crate) mod inline;
3434
pub(crate) mod lint_helpers;
3535
pub(crate) mod repr;
36+
pub(crate) mod semantics;
3637
pub(crate) mod stability;
3738
pub(crate) mod transparency;
3839
pub(crate) mod util;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use rustc_attr_data_structures::AttributeKind;
2+
use rustc_feature::{AttributeTemplate, template};
3+
use rustc_span::{Symbol, sym};
4+
5+
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
6+
use crate::context::{AcceptContext, Stage};
7+
use crate::parser::ArgParser;
8+
9+
pub(crate) struct MayDangleParser;
10+
impl<S: Stage> SingleAttributeParser<S> for MayDangleParser {
11+
const PATH: &[Symbol] = &[sym::may_dangle];
12+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
13+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
14+
const TEMPLATE: AttributeTemplate = template!(Word);
15+
16+
fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
17+
Some(AttributeKind::MayDangle(cx.attr_span))
18+
}
19+
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::attributes::deprecation::DeprecationParser;
2020
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
2121
use crate::attributes::lint_helpers::AsPtrParser;
2222
use crate::attributes::repr::ReprParser;
23+
use crate::attributes::semantics::MayDangleParser;
2324
use crate::attributes::stability::{
2425
BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
2526
};
@@ -107,6 +108,7 @@ attribute_parsers!(
107108
Single<ConstStabilityIndirectParser>,
108109
Single<DeprecationParser>,
109110
Single<InlineParser>,
111+
Single<MayDangleParser>,
110112
Single<RustcForceInlineParser>,
111113
Single<TransparencyParser>,
112114
// tidy-alphabetical-end

compiler/rustc_hir/src/hir.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,6 +1302,7 @@ impl AttributeExt for Attribute {
13021302
// FIXME: should not be needed anymore when all attrs are parsed
13031303
Attribute::Parsed(AttributeKind::Deprecation { span, .. }) => *span,
13041304
Attribute::Parsed(AttributeKind::DocComment { span, .. }) => *span,
1305+
Attribute::Parsed(AttributeKind::MayDangle(span)) => *span,
13051306
a => panic!("can't get the span of an arbitrary parsed attribute: {a:?}"),
13061307
}
13071308
}

compiler/rustc_passes/src/check_attr.rs

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,27 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
154154
Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => {
155155
self.check_applied_to_fn_or_method(hir_id, *attr_span, span, target)
156156
}
157+
&Attribute::Parsed(AttributeKind::MayDangle(attr_span)) => {
158+
// Check if `#[may_dangle]` is applied to a lifetime or type generic parameter in `Drop` impl.
159+
if let hir::Node::GenericParam(param) = self.tcx.hir_node(hir_id)
160+
&& matches!(
161+
param.kind,
162+
hir::GenericParamKind::Lifetime { .. }
163+
| hir::GenericParamKind::Type { .. }
164+
)
165+
&& matches!(param.source, hir::GenericParamSource::Generics)
166+
&& let parent_hir_id = self.tcx.parent_hir_id(hir_id)
167+
&& let hir::Node::Item(item) = self.tcx.hir_node(parent_hir_id)
168+
&& let hir::ItemKind::Impl(impl_) = item.kind
169+
&& let Some(trait_) = impl_.of_trait
170+
&& let Some(def_id) = trait_.trait_def_id()
171+
&& self.tcx.is_lang_item(def_id, hir::LangItem::Drop)
172+
{
173+
// OK
174+
} else {
175+
self.dcx().emit_err(errors::InvalidMayDangle { attr_span });
176+
}
177+
}
157178
Attribute::Unparsed(_) => {
158179
match attr.path().as_slice() {
159180
[sym::diagnostic, sym::do_not_recommend, ..] => {
@@ -228,7 +249,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
228249
[sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
229250
[sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
230251
[sym::must_use, ..] => self.check_must_use(hir_id, attr, target),
231-
[sym::may_dangle, ..] => self.check_may_dangle(hir_id, attr),
232252
[sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target),
233253
[sym::rustc_allow_incoherent_impl, ..] => {
234254
self.check_allow_incoherent_impl(attr, span, target)
@@ -1606,27 +1626,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
16061626
}
16071627
}
16081628

1609-
/// Checks if `#[may_dangle]` is applied to a lifetime or type generic parameter in `Drop` impl.
1610-
fn check_may_dangle(&self, hir_id: HirId, attr: &Attribute) {
1611-
if let hir::Node::GenericParam(param) = self.tcx.hir_node(hir_id)
1612-
&& matches!(
1613-
param.kind,
1614-
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. }
1615-
)
1616-
&& matches!(param.source, hir::GenericParamSource::Generics)
1617-
&& let parent_hir_id = self.tcx.parent_hir_id(hir_id)
1618-
&& let hir::Node::Item(item) = self.tcx.hir_node(parent_hir_id)
1619-
&& let hir::ItemKind::Impl(impl_) = item.kind
1620-
&& let Some(trait_) = impl_.of_trait
1621-
&& let Some(def_id) = trait_.trait_def_id()
1622-
&& self.tcx.is_lang_item(def_id, hir::LangItem::Drop)
1623-
{
1624-
return;
1625-
}
1626-
1627-
self.dcx().emit_err(errors::InvalidMayDangle { attr_span: attr.span() });
1628-
}
1629-
16301629
/// Checks if `#[cold]` is applied to a non-function.
16311630
fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
16321631
match target {

0 commit comments

Comments
 (0)