mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 00:03:43 +00:00
Support fetching Attribute
of items.
This commit is contained in:
parent
9c3bc805dd
commit
84071e2662
@ -4675,6 +4675,8 @@ name = "rustc_smir"
|
|||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc_abi",
|
"rustc_abi",
|
||||||
|
"rustc_ast",
|
||||||
|
"rustc_ast_pretty",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
"rustc_hir",
|
"rustc_hir",
|
||||||
"rustc_middle",
|
"rustc_middle",
|
||||||
|
@ -6,6 +6,8 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
# tidy-alphabetical-start
|
# tidy-alphabetical-start
|
||||||
rustc_abi = { path = "../rustc_abi" }
|
rustc_abi = { path = "../rustc_abi" }
|
||||||
|
rustc_ast = { path = "../rustc_ast" }
|
||||||
|
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||||
rustc_hir = { path = "../rustc_hir" }
|
rustc_hir = { path = "../rustc_hir" }
|
||||||
rustc_middle = { path = "../rustc_middle" }
|
rustc_middle = { path = "../rustc_middle" }
|
||||||
|
@ -228,6 +228,25 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_attrs_by_path(
|
||||||
|
&self,
|
||||||
|
def_id: stable_mir::DefId,
|
||||||
|
attr: &[stable_mir::Symbol],
|
||||||
|
) -> Vec<stable_mir::ty::Attribute> {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let tcx = tables.tcx;
|
||||||
|
let did = tables[def_id];
|
||||||
|
let attr_name: Vec<_> =
|
||||||
|
attr.iter().map(|seg| rustc_span::symbol::Symbol::intern(&seg)).collect();
|
||||||
|
tcx.get_attrs_by_path(did, &attr_name)
|
||||||
|
.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))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
fn span_to_string(&self, span: stable_mir::ty::Span) -> String {
|
fn span_to_string(&self, span: stable_mir::ty::Span) -> String {
|
||||||
let tables = self.0.borrow();
|
let tables = self.0.borrow();
|
||||||
tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span])
|
tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span])
|
||||||
|
@ -11,7 +11,7 @@ use crate::mir::mono::{Instance, InstanceDef, StaticDef};
|
|||||||
use crate::mir::{BinOp, Body, Place, UnOp};
|
use crate::mir::{BinOp, Body, Place, UnOp};
|
||||||
use crate::target::MachineInfo;
|
use crate::target::MachineInfo;
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef,
|
AdtDef, AdtKind, Allocation, Attribute, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef,
|
||||||
ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics,
|
ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics,
|
||||||
ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, TraitDecl,
|
ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, TraitDecl,
|
||||||
TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef,
|
TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef,
|
||||||
@ -55,6 +55,9 @@ pub trait Context {
|
|||||||
/// Returns the name of given `DefId`
|
/// Returns the name of given `DefId`
|
||||||
fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol;
|
fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol;
|
||||||
|
|
||||||
|
/// Get all attributes with the given attribute name.
|
||||||
|
fn get_attrs_by_path(&self, def_id: DefId, attr: &[Symbol]) -> Vec<Attribute>;
|
||||||
|
|
||||||
/// Returns printable, human readable form of `Span`
|
/// Returns printable, human readable form of `Span`
|
||||||
fn span_to_string(&self, span: Span) -> String;
|
fn span_to_string(&self, span: Span) -> String;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Module that define a common trait for things that represent a crate definition,
|
//! 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.
|
//! such as, a function, a trait, an enum, and any other definitions.
|
||||||
|
|
||||||
use crate::ty::{GenericArgs, Span, Ty};
|
use crate::ty::{Attribute, GenericArgs, Span, Ty};
|
||||||
use crate::{with, Crate, Symbol};
|
use crate::{with, Crate, Symbol};
|
||||||
|
|
||||||
/// A unique identification number for each item accessible for the current compilation unit.
|
/// A unique identification number for each item accessible for the current compilation unit.
|
||||||
@ -50,6 +50,12 @@ pub trait CrateDef {
|
|||||||
let def_id = self.def_id();
|
let def_id = self.def_id();
|
||||||
with(|cx| cx.span_of_an_item(def_id))
|
with(|cx| cx.span_of_an_item(def_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return attributes with the given attribute name.
|
||||||
|
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))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait that can be used to retrieve a definition's type.
|
/// A trait that can be used to retrieve a definition's type.
|
||||||
|
@ -248,6 +248,28 @@ pub struct Placeholder<T> {
|
|||||||
pub bound: 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)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct Span(usize);
|
pub struct Span(usize);
|
||||||
|
|
||||||
|
137
tests/ui-fulldeps/stable-mir/check_attribute.rs
Normal file
137
tests/ui-fulldeps/stable-mir/check_attribute.rs
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
//@ run-pass
|
||||||
|
//! Test information regarding type layout.
|
||||||
|
|
||||||
|
//@ ignore-stage1
|
||||||
|
//@ ignore-cross-compile
|
||||||
|
//@ ignore-remote
|
||||||
|
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||||
|
|
||||||
|
#![feature(rustc_private)]
|
||||||
|
#![feature(control_flow_enum)]
|
||||||
|
|
||||||
|
extern crate rustc_hir;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate rustc_smir;
|
||||||
|
extern crate rustc_driver;
|
||||||
|
extern crate rustc_interface;
|
||||||
|
extern crate stable_mir;
|
||||||
|
|
||||||
|
use rustc_smir::rustc_internal;
|
||||||
|
use stable_mir::{CrateDef, CrateItems};
|
||||||
|
use std::io::Write;
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
|
const CRATE_NAME: &str = "input";
|
||||||
|
|
||||||
|
/// This function uses the Stable MIR APIs to get information about the test crate.
|
||||||
|
fn test_stable_mir() -> ControlFlow<()> {
|
||||||
|
// Find items in the local crate.
|
||||||
|
let items = stable_mir::all_local_items();
|
||||||
|
|
||||||
|
test_builtins(&items);
|
||||||
|
test_derive(&items);
|
||||||
|
test_tool(&items);
|
||||||
|
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test built-in attributes.
|
||||||
|
fn test_builtins(items: &CrateItems) {
|
||||||
|
let target_fn = *get_item(&items, "builtins_fn").unwrap();
|
||||||
|
let allow_attrs = target_fn.attrs_by_path(&["allow".to_string()]);
|
||||||
|
assert_eq!(allow_attrs[0].as_str(), "#![allow(unused_variables)]");
|
||||||
|
|
||||||
|
let inline_attrs = target_fn.attrs_by_path(&["inline".to_string()]);
|
||||||
|
assert_eq!(inline_attrs[0].as_str(), "#[inline]");
|
||||||
|
|
||||||
|
let deprecated_attrs = target_fn.attrs_by_path(&["deprecated".to_string()]);
|
||||||
|
assert_eq!(deprecated_attrs[0].as_str(), "#[deprecated(since = \"5.2.0\")]");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test derive attribute.
|
||||||
|
fn test_derive(items: &CrateItems) {
|
||||||
|
let target_struct = *get_item(&items, "Foo").unwrap();
|
||||||
|
let attrs = target_struct.attrs_by_path(&["derive".to_string()]);
|
||||||
|
// No `derive` attribute since it's expanded before MIR.
|
||||||
|
assert_eq!(attrs.len(), 0);
|
||||||
|
|
||||||
|
// Check derived trait method's attributes.
|
||||||
|
let derived_fmt = *get_item(&items, "<Foo as std::fmt::Debug>::fmt").unwrap();
|
||||||
|
// The Rust reference lies about this attribute. It doesn't show up in `clone` or `fmt` impl.
|
||||||
|
let _fmt_attrs = derived_fmt.attrs_by_path(&["automatically_derived".to_string()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test tool attributes.
|
||||||
|
fn test_tool(items: &CrateItems) {
|
||||||
|
let rustfmt_fn = *get_item(&items, "do_not_format").unwrap();
|
||||||
|
let rustfmt_attrs = rustfmt_fn.attrs_by_path(&["rustfmt".to_string(), "skip".to_string()]);
|
||||||
|
assert_eq!(rustfmt_attrs[0].as_str(), "#[rustfmt::skip]");
|
||||||
|
|
||||||
|
let clippy_fn = *get_item(&items, "complex_fn").unwrap();
|
||||||
|
let clippy_attrs = clippy_fn.attrs_by_path(&["clippy".to_string(),
|
||||||
|
"cyclomatic_complexity".to_string()]);
|
||||||
|
assert_eq!(clippy_attrs[0].as_str(), "#[clippy::cyclomatic_complexity = \"100\"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This test will generate and analyze a dummy crate using the stable mir.
|
||||||
|
/// For that, it will first write the dummy crate into a file.
|
||||||
|
/// Then it will create a `StableMir` using custom arguments and then
|
||||||
|
/// it will run the compiler.
|
||||||
|
fn main() {
|
||||||
|
let path = "attribute_input.rs";
|
||||||
|
generate_input(&path).unwrap();
|
||||||
|
let args = vec![
|
||||||
|
"rustc".to_string(),
|
||||||
|
"--crate-type=lib".to_string(),
|
||||||
|
"--crate-name".to_string(),
|
||||||
|
CRATE_NAME.to_string(),
|
||||||
|
path.to_string(),
|
||||||
|
];
|
||||||
|
run!(args, test_stable_mir).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_input(path: &str) -> std::io::Result<()> {
|
||||||
|
let mut file = std::fs::File::create(path)?;
|
||||||
|
write!(
|
||||||
|
file,
|
||||||
|
r#"
|
||||||
|
// General metadata applied to the enclosing module or crate.
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
// Mixed inner and outer attributes.
|
||||||
|
#[inline]
|
||||||
|
#[deprecated(since = "5.2.0")]
|
||||||
|
fn builtins_fn() {{
|
||||||
|
#![allow(unused_variables)]
|
||||||
|
|
||||||
|
let x = ();
|
||||||
|
let y = ();
|
||||||
|
let z = ();
|
||||||
|
}}
|
||||||
|
|
||||||
|
// A derive attribute to automatically implement a trait.
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct Foo(u32);
|
||||||
|
|
||||||
|
// A rustfmt tool attribute.
|
||||||
|
#[rustfmt::skip]
|
||||||
|
fn do_not_format() {{}}
|
||||||
|
|
||||||
|
// A clippy tool attribute.
|
||||||
|
#[clippy::cyclomatic_complexity = "100"]
|
||||||
|
pub fn complex_fn() {{}}
|
||||||
|
"#
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user