forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of rust-lang#132131 - celinval:smir-crate-defs, r=compiler-errors [StableMIR] API to retrieve definitions from crates Add functions to retrieve function definitions and static items from all crates (local and external). For external crates, we're still missing items from trait implementation and primitives. r? ````@compiler-errors:```` Do you know what is the best way to retrieve the associated items for primitives and trait implementations for external crates? Thanks!
- Loading branch information
Showing
7 changed files
with
225 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
//@ run-pass | ||
//! Test information about crate definitions (local and external). | ||
|
||
//@ 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(assert_matches)] | ||
|
||
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; | ||
use std::collections::HashSet; | ||
use std::io::Write; | ||
use std::ops::ControlFlow; | ||
|
||
const CRATE_NAME: &str = "crate_defs"; | ||
|
||
/// 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 local = stable_mir::local_crate(); | ||
check_items(&local.statics(), &["PRIVATE_STATIC", "dummy::PUBLIC_STATIC"]); | ||
check_items( | ||
&local.fn_defs(), | ||
&[ | ||
"top_level", | ||
"dummy::public_fn", | ||
"dummy::private_fn", | ||
"dummy::PrivateStruct::new", | ||
"<dummy::PrivateStruct as std::ops::Drop>::drop", | ||
"DummyTrait::method", | ||
"<T as DummyTrait>::method", | ||
], | ||
); | ||
|
||
// Find items inside core crate. | ||
// FIXME: We are currently missing primitive type methods and trait implementations for external | ||
// crates. | ||
let core = stable_mir::find_crates("core").pop().expect("Cannot find `core` crate"); | ||
contains( | ||
&core.fn_defs(), | ||
&[ | ||
"std::fmt::Debug::fmt", | ||
"std::option::Option::<T>::is_some", | ||
"std::ptr::swap", | ||
"<std::slice::Iter<'a, T> as std::iter::Iterator>::next", | ||
"core::num::<impl u8>::abs_diff", | ||
], | ||
); | ||
// Ensure nothing crashes. There is no public static in core that we can test here. | ||
let _ = core.statics(); | ||
|
||
ControlFlow::Continue(()) | ||
} | ||
|
||
/// Check if the list of definitions matches the expected list. | ||
/// Note that order doesn't matter. | ||
fn check_items<T: CrateDef>(items: &[T], expected: &[&str]) { | ||
let expected: HashSet<_> = expected.iter().map(|s| s.to_string()).collect(); | ||
let item_names: HashSet<_> = items.iter().map(|item| item.name()).collect(); | ||
assert_eq!(item_names, expected); | ||
} | ||
|
||
/// Check that the list contains the expected items. | ||
fn contains<T: CrateDef + std::fmt::Debug>(items: &[T], expected: &[&str]) { | ||
let expected: HashSet<_> = expected.iter().map(|s| s.to_string()).collect(); | ||
let item_names = items.iter().map(|item| item.name()).collect(); | ||
let not_found: Vec<_> = expected.difference(&item_names).collect(); | ||
assert!(not_found.is_empty(), "Missing items: {:?}", not_found); | ||
} | ||
|
||
/// 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 = "crate_definitions.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#" | ||
#![allow(dead_code, unused_variables)] | ||
static PRIVATE_STATIC: u8 = 0; | ||
fn top_level() -> &'static str {{ | ||
"hello" | ||
}} | ||
pub trait DummyTrait {{ | ||
fn method(&self) -> Self; | ||
}} | ||
impl<T: Copy> DummyTrait for T {{ | ||
fn method(&self) -> T {{ | ||
*self | ||
}} | ||
}} | ||
pub mod dummy {{ | ||
pub static mut PUBLIC_STATIC: Option<char> = None; | ||
pub fn public_fn(input: bool) -> bool {{ | ||
private_fn(!input) | ||
}} | ||
fn private_fn(input: bool) -> bool {{ | ||
todo!() | ||
}} | ||
struct PrivateStruct {{ | ||
field: u32, | ||
}} | ||
impl PrivateStruct {{ | ||
fn new() -> Self {{ | ||
Self {{ field: 42 }} | ||
}} | ||
}} | ||
impl Drop for PrivateStruct {{ | ||
fn drop(&mut self) {{ | ||
println!("Dropping PrivateStruct"); | ||
}} | ||
}} | ||
}} | ||
"# | ||
)?; | ||
Ok(()) | ||
} |