forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcheck_crate_defs.rs
149 lines (129 loc) · 4.35 KB
/
check_crate_defs.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//@ run-pass
//! Test information about crate definitions (local and external).
//@ ignore-stage1
//@ ignore-cross-compile
//@ ignore-remote
#![feature(rustc_private)]
#![feature(assert_matches)]
extern crate rustc_hir;
extern crate rustc_middle;
#[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(())
}