Skip to content

Commit ffb72e9

Browse files
committed
add hir::Attribute
1 parent 0b7cffc commit ffb72e9

File tree

2 files changed

+174
-3
lines changed

2 files changed

+174
-3
lines changed

compiler/rustc_hir/src/arena.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ macro_rules! arena_types {
66
$macro!([
77
// HIR types
88
[] asm_template: rustc_ast::InlineAsmTemplatePiece,
9-
[] attribute: rustc_ast::Attribute,
9+
[] attribute: rustc_hir::Attribute,
1010
[] owner_info: rustc_hir::OwnerInfo<'tcx>,
1111
[] use_path: rustc_hir::UsePath<'tcx>,
1212
[] lit: rustc_hir::Lit,

compiler/rustc_hir/src/hir.rs

Lines changed: 173 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use std::fmt;
22

3+
use rustc_ast::attr::AttributeExt;
4+
use rustc_ast::token::CommentKind;
35
use rustc_ast::util::parser::ExprPrecedence;
46
use rustc_ast::{
5-
self as ast, Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label,
6-
LitKind, TraitObjectSyntax, UintTy,
7+
self as ast, AttrId, AttrStyle, DelimArgs, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece,
8+
IntTy, Label, LitKind, MetaItemLit, TraitObjectSyntax, UintTy,
79
};
810
pub use rustc_ast::{
911
BinOp, BinOpKind, BindingMode, BorrowKind, ByRef, CaptureBy, ImplPolarity, IsAuto, Movability,
@@ -21,6 +23,7 @@ use rustc_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Span};
2123
use rustc_target::asm::InlineAsmRegOrRegClass;
2224
use rustc_target::spec::abi::Abi;
2325
use smallvec::SmallVec;
26+
use thin_vec::ThinVec;
2427
use tracing::debug;
2528

2629
use crate::LangItem;
@@ -942,6 +945,174 @@ pub struct ParentedNode<'tcx> {
942945
pub node: Node<'tcx>,
943946
}
944947

948+
/// Arguments passed to an attribute macro.
949+
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable)]
950+
pub enum AttrArgs {
951+
/// No arguments: `#[attr]`.
952+
Empty,
953+
/// Delimited arguments: `#[attr()/[]/{}]`.
954+
Delimited(DelimArgs),
955+
/// Arguments of a key-value attribute: `#[attr = "value"]`.
956+
Eq(
957+
/// Span of the `=` token.
958+
Span,
959+
/// The "value".
960+
MetaItemLit,
961+
),
962+
}
963+
964+
#[derive(Clone, Debug, Encodable, Decodable)]
965+
pub enum AttrKind {
966+
/// A normal attribute.
967+
Normal(AttrItem),
968+
969+
/// A doc comment (e.g. `/// ...`, `//! ...`, `/** ... */`, `/*! ... */`).
970+
/// Doc attributes (e.g. `#[doc="..."]`) are represented with the `Normal`
971+
/// variant (which is much less compact and thus more expensive).
972+
DocComment(CommentKind, Symbol),
973+
}
974+
975+
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable)]
976+
pub struct AttrPath {
977+
pub segments: Box<[Ident]>,
978+
pub span: Span,
979+
}
980+
981+
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable)]
982+
pub struct AttrItem {
983+
pub unsafety: Safety,
984+
// Not lowered to hir::Path because we have no NodeId to resolve to.
985+
pub path: AttrPath,
986+
pub args: AttrArgs,
987+
}
988+
989+
#[derive(Clone, Debug, Encodable, Decodable)]
990+
pub struct Attribute {
991+
pub kind: AttrKind,
992+
pub id: AttrId,
993+
/// Denotes if the attribute decorates the following construct (outer)
994+
/// or the construct this attribute is contained within (inner).
995+
pub style: AttrStyle,
996+
pub span: Span,
997+
}
998+
999+
impl Attribute {
1000+
pub fn get_normal_item(&self) -> &AttrItem {
1001+
match &self.kind {
1002+
AttrKind::Normal(normal) => &normal,
1003+
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
1004+
}
1005+
}
1006+
1007+
pub fn unwrap_normal_item(self) -> AttrItem {
1008+
match self.kind {
1009+
AttrKind::Normal(normal) => normal,
1010+
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
1011+
}
1012+
}
1013+
1014+
pub fn value_lit(&self) -> Option<&MetaItemLit> {
1015+
match &self.kind {
1016+
AttrKind::Normal(AttrItem { args: AttrArgs::Eq(_, lit), .. }) => Some(lit),
1017+
_ => None,
1018+
}
1019+
}
1020+
}
1021+
1022+
impl AttributeExt for Attribute {
1023+
fn id(&self) -> AttrId {
1024+
self.id
1025+
}
1026+
1027+
fn meta_item_list(&self) -> Option<ThinVec<ast::MetaItemInner>> {
1028+
match &self.kind {
1029+
AttrKind::Normal(AttrItem { args: AttrArgs::Delimited(d), .. }) => {
1030+
ast::MetaItemKind::list_from_tokens(d.tokens.clone())
1031+
}
1032+
_ => None,
1033+
}
1034+
}
1035+
1036+
fn value_str(&self) -> Option<Symbol> {
1037+
self.value_lit().and_then(|x| x.value_str())
1038+
}
1039+
1040+
fn value_span(&self) -> Option<Span> {
1041+
self.value_lit().map(|i| i.span)
1042+
}
1043+
1044+
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
1045+
fn ident(&self) -> Option<Ident> {
1046+
match &self.kind {
1047+
AttrKind::Normal(AttrItem { path, .. }) => {
1048+
if let [ident] = path.segments.as_ref() {
1049+
Some(*ident)
1050+
} else {
1051+
None
1052+
}
1053+
}
1054+
AttrKind::DocComment(..) => None,
1055+
}
1056+
}
1057+
1058+
fn path_matches(&self, name: &[Symbol]) -> bool {
1059+
match &self.kind {
1060+
AttrKind::Normal(AttrItem { path, .. }) => {
1061+
path.segments.len() == name.len()
1062+
&& path.segments.iter().zip(name).all(|(s, n)| s.name == *n)
1063+
}
1064+
AttrKind::DocComment(..) => false,
1065+
}
1066+
}
1067+
1068+
fn is_doc_comment(&self) -> bool {
1069+
matches!(self.kind, AttrKind::DocComment(..))
1070+
}
1071+
1072+
fn span(&self) -> Span {
1073+
self.span
1074+
}
1075+
1076+
fn is_word(&self) -> bool {
1077+
match &self.kind {
1078+
AttrKind::Normal(AttrItem { args, .. }) => {
1079+
matches!(args, AttrArgs::Empty)
1080+
}
1081+
AttrKind::DocComment(..) => false,
1082+
}
1083+
}
1084+
1085+
fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
1086+
match &self.kind {
1087+
AttrKind::Normal(AttrItem { path, .. }) => {
1088+
Some(path.segments.iter().copied().collect())
1089+
}
1090+
AttrKind::DocComment(..) => None,
1091+
}
1092+
}
1093+
1094+
fn doc_str(&self) -> Option<Symbol> {
1095+
match &self.kind {
1096+
AttrKind::DocComment(.., data) => Some(*data),
1097+
AttrKind::Normal(_) if self.has_name(sym::doc) => self.value_str(),
1098+
_ => None,
1099+
}
1100+
}
1101+
fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
1102+
match &self.kind {
1103+
AttrKind::DocComment(kind, data) => Some((*data, *kind)),
1104+
AttrKind::Normal(_) if self.name_or_empty() == sym::doc => {
1105+
self.value_str().map(|s| (s, CommentKind::Line))
1106+
}
1107+
_ => None,
1108+
}
1109+
}
1110+
1111+
fn style(&self) -> AttrStyle {
1112+
self.style
1113+
}
1114+
}
1115+
9451116
/// Attributes owned by a HIR owner.
9461117
#[derive(Debug)]
9471118
pub struct AttributeMap<'tcx> {

0 commit comments

Comments
 (0)