mirror of
https://github.com/rust-lang/rust
synced 2024-10-06 16:51:35 +00:00
Add a new trait to retrieve StableMir definition Ty
We implement the trait only for definitions that should have a type. It's possible that I missed a few definitions, but we can add them later if needed.
This commit is contained in:
parent
0285dab54f
commit
6d4a825714
|
@ -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::Span;
|
use crate::ty::{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.
|
||||||
|
@ -52,6 +52,23 @@ fn span(&self) -> Span {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A trait that can be used to retrieve a definition's type.
|
||||||
|
///
|
||||||
|
/// Note that not every CrateDef has a type `Ty`. They should not implement this trait.
|
||||||
|
pub trait CrateDefType: CrateDef {
|
||||||
|
/// Returns the type of this crate item.
|
||||||
|
fn ty(&self) -> Ty {
|
||||||
|
with(|cx| cx.def_ty(self.def_id()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve the type of this definition by instantiating and normalizing it with `args`.
|
||||||
|
///
|
||||||
|
/// This will panic if instantiation fails.
|
||||||
|
fn ty_with_args(&self, args: &GenericArgs) -> Ty {
|
||||||
|
with(|cx| cx.def_ty_with_args(self.def_id(), args))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! crate_def {
|
macro_rules! crate_def {
|
||||||
( $(#[$attr:meta])*
|
( $(#[$attr:meta])*
|
||||||
$vis:vis $name:ident $(;)?
|
$vis:vis $name:ident $(;)?
|
||||||
|
@ -67,3 +84,21 @@ fn def_id(&self) -> DefId {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! crate_def_with_ty {
|
||||||
|
( $(#[$attr:meta])*
|
||||||
|
$vis:vis $name:ident $(;)?
|
||||||
|
) => {
|
||||||
|
$(#[$attr])*
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||||
|
$vis struct $name(pub DefId);
|
||||||
|
|
||||||
|
impl CrateDef for $name {
|
||||||
|
fn def_id(&self) -> DefId {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CrateDefType for $name {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -22,8 +22,7 @@
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use crate::compiler_interface::with;
|
use crate::compiler_interface::with;
|
||||||
pub use crate::crate_def::CrateDef;
|
pub use crate::crate_def::{CrateDef, CrateDefType, DefId};
|
||||||
pub use crate::crate_def::DefId;
|
|
||||||
pub use crate::error::*;
|
pub use crate::error::*;
|
||||||
use crate::mir::Body;
|
use crate::mir::Body;
|
||||||
use crate::mir::Mutability;
|
use crate::mir::Mutability;
|
||||||
|
@ -115,12 +114,15 @@ pub enum CtorKind {
|
||||||
|
|
||||||
pub type Filename = String;
|
pub type Filename = String;
|
||||||
|
|
||||||
crate_def! {
|
crate_def_with_ty! {
|
||||||
/// Holds information about an item in a crate.
|
/// Holds information about an item in a crate.
|
||||||
pub CrateItem;
|
pub CrateItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrateItem {
|
impl CrateItem {
|
||||||
|
/// This will return the body of an item.
|
||||||
|
///
|
||||||
|
/// This will panic if no body is available.
|
||||||
pub fn body(&self) -> mir::Body {
|
pub fn body(&self) -> mir::Body {
|
||||||
with(|cx| cx.mir_body(self.0))
|
with(|cx| cx.mir_body(self.0))
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
with, DefId, Error, Symbol,
|
with, DefId, Error, Symbol,
|
||||||
};
|
};
|
||||||
use crate::abi::Layout;
|
use crate::abi::Layout;
|
||||||
|
use crate::crate_def::{CrateDef, CrateDefType};
|
||||||
use crate::mir::alloc::{read_target_int, read_target_uint, AllocId};
|
use crate::mir::alloc::{read_target_int, read_target_uint, AllocId};
|
||||||
|
use crate::mir::mono::StaticDef;
|
||||||
use crate::target::MachineInfo;
|
use crate::target::MachineInfo;
|
||||||
use crate::{crate_def::CrateDef, mir::mono::StaticDef};
|
|
||||||
use crate::{Filename, Opaque};
|
use crate::{Filename, Opaque};
|
||||||
use std::fmt::{self, Debug, Display, Formatter};
|
use std::fmt::{self, Debug, Display, Formatter};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
@ -504,6 +505,15 @@ pub fn fn_sig(&self) -> Option<PolyFnSig> {
|
||||||
pub fn discriminant_ty(&self) -> Option<Ty> {
|
pub fn discriminant_ty(&self) -> Option<Ty> {
|
||||||
self.rigid().map(|ty| with(|cx| cx.rigid_ty_discriminant_ty(ty)))
|
self.rigid().map(|ty| with(|cx| cx.rigid_ty_discriminant_ty(ty)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deconstruct a function type if this is one.
|
||||||
|
pub fn fn_def(&self) -> Option<(FnDef, &GenericArgs)> {
|
||||||
|
if let TyKind::RigidTy(RigidTy::FnDef(def, args)) = self {
|
||||||
|
Some((*def, args))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TypeAndMut {
|
pub struct TypeAndMut {
|
||||||
|
@ -629,7 +639,7 @@ pub fn items(&self) -> Vec<ForeignDef> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate_def! {
|
crate_def_with_ty! {
|
||||||
/// Hold information about a ForeignItem in a crate.
|
/// Hold information about a ForeignItem in a crate.
|
||||||
pub ForeignDef;
|
pub ForeignDef;
|
||||||
}
|
}
|
||||||
|
@ -647,7 +657,7 @@ pub enum ForeignItemKind {
|
||||||
Type(Ty),
|
Type(Ty),
|
||||||
}
|
}
|
||||||
|
|
||||||
crate_def! {
|
crate_def_with_ty! {
|
||||||
/// Hold information about a function definition in a crate.
|
/// Hold information about a function definition in a crate.
|
||||||
pub FnDef;
|
pub FnDef;
|
||||||
}
|
}
|
||||||
|
@ -668,9 +678,15 @@ pub fn as_intrinsic(&self) -> Option<IntrinsicDef> {
|
||||||
pub fn is_intrinsic(&self) -> bool {
|
pub fn is_intrinsic(&self) -> bool {
|
||||||
self.as_intrinsic().is_some()
|
self.as_intrinsic().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the function signature for this function definition.
|
||||||
|
pub fn fn_sig(&self) -> PolyFnSig {
|
||||||
|
let kind = self.ty().kind();
|
||||||
|
kind.fn_sig().unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate_def! {
|
crate_def_with_ty! {
|
||||||
pub IntrinsicDef;
|
pub IntrinsicDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,7 +726,7 @@ fn from(def: IntrinsicDef) -> Self {
|
||||||
pub BrNamedDef;
|
pub BrNamedDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
crate_def! {
|
crate_def_with_ty! {
|
||||||
pub AdtDef;
|
pub AdtDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -866,7 +882,7 @@ pub fn declaration(trait_def: &TraitDef) -> TraitDecl {
|
||||||
pub GenericDef;
|
pub GenericDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
crate_def! {
|
crate_def_with_ty! {
|
||||||
pub ConstDef;
|
pub ConstDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
114
tests/ui-fulldeps/stable-mir/check_def_ty.rs
Normal file
114
tests/ui-fulldeps/stable-mir/check_def_ty.rs
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
//@ run-pass
|
||||||
|
//! Test that users are able to use stable mir APIs to retrieve type information from a crate item
|
||||||
|
//! definition.
|
||||||
|
|
||||||
|
//@ ignore-stage1
|
||||||
|
//@ ignore-cross-compile
|
||||||
|
//@ ignore-remote
|
||||||
|
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||||
|
//@ edition: 2021
|
||||||
|
|
||||||
|
#![feature(rustc_private)]
|
||||||
|
#![feature(assert_matches)]
|
||||||
|
#![feature(control_flow_enum)]
|
||||||
|
|
||||||
|
#[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::ty::{Ty, ForeignItemKind};
|
||||||
|
use stable_mir::*;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
|
const CRATE_NAME: &str = "crate_def_ty";
|
||||||
|
|
||||||
|
/// Test if we can retrieve type information from different definitions.
|
||||||
|
fn test_def_tys() -> ControlFlow<()> {
|
||||||
|
let items = stable_mir::all_local_items();
|
||||||
|
for item in &items {
|
||||||
|
// Type from crate items.
|
||||||
|
let ty = item.ty();
|
||||||
|
match item.name().as_str() {
|
||||||
|
"STATIC_STR" => assert!(ty.kind().is_ref()),
|
||||||
|
"CONST_U32" => assert!(ty.kind().is_integral()),
|
||||||
|
"main" => { check_fn_def(ty) }
|
||||||
|
_ => unreachable!("Unexpected item: `{item:?}`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let foreign_items = stable_mir::local_crate().foreign_modules();
|
||||||
|
for item in foreign_items[0].module().items() {
|
||||||
|
// Type from foreign items.
|
||||||
|
let ty = item.ty();
|
||||||
|
let item_kind = item.kind();
|
||||||
|
let name = item.name();
|
||||||
|
match item_kind {
|
||||||
|
ForeignItemKind::Fn(fn_def) => {
|
||||||
|
assert_eq!(&name, "extern_fn");
|
||||||
|
assert_eq!(ty, fn_def.ty());
|
||||||
|
check_fn_def(ty)
|
||||||
|
}
|
||||||
|
ForeignItemKind::Static(def) => {
|
||||||
|
assert_eq!(&name, "EXT_STATIC");
|
||||||
|
assert_eq!(ty, def.ty());
|
||||||
|
assert!(ty.kind().is_integral())
|
||||||
|
}
|
||||||
|
_ => unreachable!("Unexpected kind: {item_kind:?}")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_fn_def(ty: Ty) {
|
||||||
|
let kind = ty.kind();
|
||||||
|
let (def, args) = kind.fn_def().expect(&format!("Expected function type, but found: {ty}"));
|
||||||
|
assert!(def.ty().kind().is_fn());
|
||||||
|
assert_eq!(def.ty_with_args(args), ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 = "defs_ty_input.rs";
|
||||||
|
generate_input(&path).unwrap();
|
||||||
|
let args = vec![
|
||||||
|
"rustc".to_string(),
|
||||||
|
"-Cpanic=abort".to_string(),
|
||||||
|
"--crate-name".to_string(),
|
||||||
|
CRATE_NAME.to_string(),
|
||||||
|
path.to_string(),
|
||||||
|
];
|
||||||
|
run!(args, test_def_tys).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_input(path: &str) -> std::io::Result<()> {
|
||||||
|
let mut file = std::fs::File::create(path)?;
|
||||||
|
write!(
|
||||||
|
file,
|
||||||
|
r#"
|
||||||
|
// We would like to check intrinsic definition.
|
||||||
|
#![feature(core_intrinsics)]
|
||||||
|
static STATIC_STR: &str = "foo";
|
||||||
|
const CONST_U32: u32 = 0u32;
|
||||||
|
|
||||||
|
fn main() {{
|
||||||
|
let _c = core::char::from_u32(99);
|
||||||
|
let _v = Vec::<u8>::new();
|
||||||
|
let _i = std::intrinsics::size_of::<u8>();
|
||||||
|
}}
|
||||||
|
|
||||||
|
extern "C" {{
|
||||||
|
fn extern_fn(x: i32) -> i32;
|
||||||
|
static EXT_STATIC: i32;
|
||||||
|
}}
|
||||||
|
"#
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in a new issue