Skip to content

Commit

Permalink
Add method to get all attributes on a definition
Browse files Browse the repository at this point in the history
  • Loading branch information
adwinwhite committed Jun 28, 2024
1 parent 84071e2 commit 9387b0b
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 30 deletions.
25 changes: 23 additions & 2 deletions compiler/rustc_smir/src/rustc_smir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
&self,
def_id: stable_mir::DefId,
attr: &[stable_mir::Symbol],
) -> Vec<stable_mir::ty::Attribute> {
) -> Vec<stable_mir::crate_def::Attribute> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let did = tables[def_id];
Expand All @@ -242,7 +242,28 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
.map(|attribute| {
let attr_str = rustc_ast_pretty::pprust::attribute_to_string(attribute);
let span = attribute.span;
stable_mir::ty::Attribute::new(attr_str, span.stable(&mut *tables))
stable_mir::crate_def::Attribute::new(attr_str, span.stable(&mut *tables))
})
.collect()
}

fn get_all_attrs(&self, def_id: stable_mir::DefId) -> Vec<stable_mir::crate_def::Attribute> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let did = tables[def_id];
let filter_fn = move |a: &&rustc_ast::ast::Attribute| {
matches!(a.kind, rustc_ast::ast::AttrKind::Normal(_))
};
let attrs_iter = if let Some(did) = did.as_local() {
tcx.hir().attrs(tcx.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
} else {
tcx.item_attrs(did).iter().filter(filter_fn)
};
attrs_iter
.map(|attribute| {
let attr_str = rustc_ast_pretty::pprust::attribute_to_string(attribute);
let span = attribute.span;
stable_mir::crate_def::Attribute::new(attr_str, span.stable(&mut *tables))
})
.collect()
}
Expand Down
11 changes: 9 additions & 2 deletions compiler/stable_mir/src/compiler_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
use std::cell::Cell;

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

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

/// Get all attributes of a definition.
fn get_all_attrs(&self, def_id: DefId) -> Vec<Attribute>;

/// Returns printable, human readable form of `Span`
fn span_to_string(&self, span: Span) -> String;

Expand Down
33 changes: 32 additions & 1 deletion compiler/stable_mir/src/crate_def.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Module that define a common trait for things that represent a crate definition,
//! such as, a function, a trait, an enum, and any other definitions.

use crate::ty::{Attribute, GenericArgs, Span, Ty};
use crate::ty::{GenericArgs, Span, Ty};
use crate::{with, Crate, Symbol};

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

/// Return attributes with the given attribute name.
///
/// Single segmented name like `#[inline]` is specified as `&["inline".to_string()]`.
/// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`.
fn attrs_by_path(&self, attr: &[Symbol]) -> Vec<Attribute> {
let def_id = self.def_id();
with(|cx| cx.get_attrs_by_path(def_id, attr))
}

/// Return all attributes of this definition.
fn all_attrs(&self) -> Vec<Attribute> {
let def_id = self.def_id();
with(|cx| cx.get_all_attrs(def_id))
}
}

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

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Attribute {
value: String,
span: Span,
}

impl Attribute {
pub fn new(value: String, span: Span) -> Attribute {
Attribute { value, span }
}

/// Get the span of this attribute.
pub fn span(&self) -> Span {
self.span
}

/// Get the string representation of this attribute.
pub fn as_str(&self) -> &str {
&self.value
}
}

macro_rules! crate_def {
( $(#[$attr:meta])*
$vis:vis $name:ident $(;)?
Expand Down
22 changes: 0 additions & 22 deletions compiler/stable_mir/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,28 +248,6 @@ pub struct Placeholder<T> {
pub bound: T,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Attribute {
value: String,
span: Span,
}

impl Attribute {
pub fn new(value: String, span: Span) -> Attribute {
Attribute { value, span }
}

/// Get the span of this attribute.
pub fn span(&self) -> Span {
self.span
}

/// Get the string representation of this attribute.
pub fn as_str(&self) -> &str {
&self.value
}
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Span(usize);

Expand Down
24 changes: 21 additions & 3 deletions tests/ui-fulldeps/stable-mir/check_attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ fn test_stable_mir() -> ControlFlow<()> {
test_builtins(&items);
test_derive(&items);
test_tool(&items);
test_all_attrs(&items);

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

fn test_all_attrs(items: &CrateItems) {
let target_fn = *get_item(&items, "many_attrs").unwrap();
let all_attrs = target_fn.all_attrs();
assert_eq!(all_attrs[0].as_str(), "#[inline]");
assert_eq!(all_attrs[1].as_str(), "#[allow(unused_variables)]");
assert_eq!(all_attrs[2].as_str(), "#[allow(dead_code)]");
assert_eq!(all_attrs[3].as_str(), "#[allow(unused_imports)]");
assert_eq!(all_attrs[4].as_str(), "#![allow(clippy::filter_map)]");
}


fn get_item<'a>(
items: &'a CrateItems,
name: &str,
) -> Option<&'a stable_mir::CrateItem> {
for item in items {
println!("{:?}", item);
}
items.iter().find(|crate_item| crate_item.name() == name)
}

Expand Down Expand Up @@ -131,6 +139,16 @@ fn generate_input(path: &str) -> std::io::Result<()> {
// A clippy tool attribute.
#[clippy::cyclomatic_complexity = "100"]
pub fn complex_fn() {{}}
// A function with many attributes.
#[inline]
#[allow(unused_variables)]
#[allow(dead_code)]
#[allow(unused_imports)]
fn many_attrs() {{
#![allow(clippy::filter_map)]
todo!()
}}
"#
)?;
Ok(())
Expand Down

0 comments on commit 9387b0b

Please sign in to comment.