Skip to content

Commit 9387b0b

Browse files
committed
Add method to get all attributes on a definition
1 parent 84071e2 commit 9387b0b

File tree

5 files changed

+85
-30
lines changed

5 files changed

+85
-30
lines changed

compiler/rustc_smir/src/rustc_smir/context.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
232232
&self,
233233
def_id: stable_mir::DefId,
234234
attr: &[stable_mir::Symbol],
235-
) -> Vec<stable_mir::ty::Attribute> {
235+
) -> Vec<stable_mir::crate_def::Attribute> {
236236
let mut tables = self.0.borrow_mut();
237237
let tcx = tables.tcx;
238238
let did = tables[def_id];
@@ -242,7 +242,28 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
242242
.map(|attribute| {
243243
let attr_str = rustc_ast_pretty::pprust::attribute_to_string(attribute);
244244
let span = attribute.span;
245-
stable_mir::ty::Attribute::new(attr_str, span.stable(&mut *tables))
245+
stable_mir::crate_def::Attribute::new(attr_str, span.stable(&mut *tables))
246+
})
247+
.collect()
248+
}
249+
250+
fn get_all_attrs(&self, def_id: stable_mir::DefId) -> Vec<stable_mir::crate_def::Attribute> {
251+
let mut tables = self.0.borrow_mut();
252+
let tcx = tables.tcx;
253+
let did = tables[def_id];
254+
let filter_fn = move |a: &&rustc_ast::ast::Attribute| {
255+
matches!(a.kind, rustc_ast::ast::AttrKind::Normal(_))
256+
};
257+
let attrs_iter = if let Some(did) = did.as_local() {
258+
tcx.hir().attrs(tcx.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
259+
} else {
260+
tcx.item_attrs(did).iter().filter(filter_fn)
261+
};
262+
attrs_iter
263+
.map(|attribute| {
264+
let attr_str = rustc_ast_pretty::pprust::attribute_to_string(attribute);
265+
let span = attribute.span;
266+
stable_mir::crate_def::Attribute::new(attr_str, span.stable(&mut *tables))
246267
})
247268
.collect()
248269
}

compiler/stable_mir/src/compiler_interface.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
use std::cell::Cell;
77

88
use crate::abi::{FnAbi, Layout, LayoutShape};
9+
use crate::crate_def::Attribute;
910
use crate::mir::alloc::{AllocId, GlobalAlloc};
1011
use crate::mir::mono::{Instance, InstanceDef, StaticDef};
1112
use crate::mir::{BinOp, Body, Place, UnOp};
1213
use crate::target::MachineInfo;
1314
use crate::ty::{
14-
AdtDef, AdtKind, Allocation, Attribute, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef,
15+
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef,
1516
ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics,
1617
ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, TraitDecl,
1718
TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef,
@@ -55,9 +56,15 @@ pub trait Context {
5556
/// Returns the name of given `DefId`
5657
fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol;
5758

58-
/// Get all attributes with the given attribute name.
59+
/// Return attributes with the given attribute name.
60+
///
61+
/// Single segmented name like `#[inline]` is specified as `&["inline".to_string()]`.
62+
/// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`.
5963
fn get_attrs_by_path(&self, def_id: DefId, attr: &[Symbol]) -> Vec<Attribute>;
6064

65+
/// Get all attributes of a definition.
66+
fn get_all_attrs(&self, def_id: DefId) -> Vec<Attribute>;
67+
6168
/// Returns printable, human readable form of `Span`
6269
fn span_to_string(&self, span: Span) -> String;
6370

compiler/stable_mir/src/crate_def.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Module that define a common trait for things that represent a crate definition,
22
//! such as, a function, a trait, an enum, and any other definitions.
33
4-
use crate::ty::{Attribute, GenericArgs, Span, Ty};
4+
use crate::ty::{GenericArgs, Span, Ty};
55
use crate::{with, Crate, Symbol};
66

77
/// A unique identification number for each item accessible for the current compilation unit.
@@ -52,10 +52,19 @@ pub trait CrateDef {
5252
}
5353

5454
/// Return attributes with the given attribute name.
55+
///
56+
/// Single segmented name like `#[inline]` is specified as `&["inline".to_string()]`.
57+
/// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`.
5558
fn attrs_by_path(&self, attr: &[Symbol]) -> Vec<Attribute> {
5659
let def_id = self.def_id();
5760
with(|cx| cx.get_attrs_by_path(def_id, attr))
5861
}
62+
63+
/// Return all attributes of this definition.
64+
fn all_attrs(&self) -> Vec<Attribute> {
65+
let def_id = self.def_id();
66+
with(|cx| cx.get_all_attrs(def_id))
67+
}
5968
}
6069

6170
/// A trait that can be used to retrieve a definition's type.
@@ -75,6 +84,28 @@ pub trait CrateDefType: CrateDef {
7584
}
7685
}
7786

87+
#[derive(Clone, Debug, PartialEq, Eq)]
88+
pub struct Attribute {
89+
value: String,
90+
span: Span,
91+
}
92+
93+
impl Attribute {
94+
pub fn new(value: String, span: Span) -> Attribute {
95+
Attribute { value, span }
96+
}
97+
98+
/// Get the span of this attribute.
99+
pub fn span(&self) -> Span {
100+
self.span
101+
}
102+
103+
/// Get the string representation of this attribute.
104+
pub fn as_str(&self) -> &str {
105+
&self.value
106+
}
107+
}
108+
78109
macro_rules! crate_def {
79110
( $(#[$attr:meta])*
80111
$vis:vis $name:ident $(;)?

compiler/stable_mir/src/ty.rs

-22
Original file line numberDiff line numberDiff line change
@@ -248,28 +248,6 @@ pub struct Placeholder<T> {
248248
pub bound: T,
249249
}
250250

251-
#[derive(Clone, Debug, PartialEq, Eq)]
252-
pub struct Attribute {
253-
value: String,
254-
span: Span,
255-
}
256-
257-
impl Attribute {
258-
pub fn new(value: String, span: Span) -> Attribute {
259-
Attribute { value, span }
260-
}
261-
262-
/// Get the span of this attribute.
263-
pub fn span(&self) -> Span {
264-
self.span
265-
}
266-
267-
/// Get the string representation of this attribute.
268-
pub fn as_str(&self) -> &str {
269-
&self.value
270-
}
271-
}
272-
273251
#[derive(Clone, Copy, PartialEq, Eq)]
274252
pub struct Span(usize);
275253

tests/ui-fulldeps/stable-mir/check_attribute.rs

+21-3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ fn test_stable_mir() -> ControlFlow<()> {
3131
test_builtins(&items);
3232
test_derive(&items);
3333
test_tool(&items);
34+
test_all_attrs(&items);
3435

3536
ControlFlow::Continue(())
3637
}
@@ -73,14 +74,21 @@ fn test_tool(items: &CrateItems) {
7374
assert_eq!(clippy_attrs[0].as_str(), "#[clippy::cyclomatic_complexity = \"100\"]");
7475
}
7576

77+
fn test_all_attrs(items: &CrateItems) {
78+
let target_fn = *get_item(&items, "many_attrs").unwrap();
79+
let all_attrs = target_fn.all_attrs();
80+
assert_eq!(all_attrs[0].as_str(), "#[inline]");
81+
assert_eq!(all_attrs[1].as_str(), "#[allow(unused_variables)]");
82+
assert_eq!(all_attrs[2].as_str(), "#[allow(dead_code)]");
83+
assert_eq!(all_attrs[3].as_str(), "#[allow(unused_imports)]");
84+
assert_eq!(all_attrs[4].as_str(), "#![allow(clippy::filter_map)]");
85+
}
86+
7687

7788
fn get_item<'a>(
7889
items: &'a CrateItems,
7990
name: &str,
8091
) -> Option<&'a stable_mir::CrateItem> {
81-
for item in items {
82-
println!("{:?}", item);
83-
}
8492
items.iter().find(|crate_item| crate_item.name() == name)
8593
}
8694

@@ -131,6 +139,16 @@ fn generate_input(path: &str) -> std::io::Result<()> {
131139
// A clippy tool attribute.
132140
#[clippy::cyclomatic_complexity = "100"]
133141
pub fn complex_fn() {{}}
142+
143+
// A function with many attributes.
144+
#[inline]
145+
#[allow(unused_variables)]
146+
#[allow(dead_code)]
147+
#[allow(unused_imports)]
148+
fn many_attrs() {{
149+
#![allow(clippy::filter_map)]
150+
todo!()
151+
}}
134152
"#
135153
)?;
136154
Ok(())

0 commit comments

Comments
 (0)