]> git.proxmox.com Git - rustc.git/blame - src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
New upstream version 1.76.0+dfsg1
[rustc.git] / src / tools / rust-analyzer / crates / hir-def / src / body / tests.rs
CommitLineData
064997fb
FG
1mod block;
2
3use base_db::{fixture::WithFixture, SourceDatabase};
781aab86 4use expect_test::{expect, Expect};
064997fb 5
add651ee 6use crate::{test_db::TestDB, ModuleDefId};
064997fb
FG
7
8use super::*;
9
781aab86 10fn lower(ra_fixture: &str) -> (TestDB, Arc<Body>, DefWithBodyId) {
add651ee 11 let db = TestDB::with_files(ra_fixture);
064997fb
FG
12
13 let krate = db.crate_graph().iter().next().unwrap();
14 let def_map = db.crate_def_map(krate);
15 let mut fn_def = None;
16 'outer: for (_, module) in def_map.modules() {
17 for decl in module.scope.declarations() {
18 if let ModuleDefId::FunctionId(it) = decl {
19 fn_def = Some(it);
20 break 'outer;
21 }
22 }
23 }
781aab86 24 let fn_def = fn_def.unwrap().into();
064997fb 25
781aab86
FG
26 let body = db.body(fn_def);
27 (db, body, fn_def)
064997fb
FG
28}
29
add651ee
FG
30fn def_map_at(ra_fixture: &str) -> String {
31 let (db, position) = TestDB::with_position(ra_fixture);
064997fb
FG
32
33 let module = db.module_at_position(position);
34 module.def_map(&db).dump(&db)
35}
36
37fn check_block_scopes_at(ra_fixture: &str, expect: Expect) {
add651ee 38 let (db, position) = TestDB::with_position(ra_fixture);
064997fb
FG
39
40 let module = db.module_at_position(position);
41 let actual = module.def_map(&db).dump_block_scopes(&db);
42 expect.assert_eq(&actual);
43}
44
45fn check_at(ra_fixture: &str, expect: Expect) {
add651ee 46 let actual = def_map_at(ra_fixture);
064997fb
FG
47 expect.assert_eq(&actual);
48}
49
50#[test]
51fn your_stack_belongs_to_me() {
52 cov_mark::check!(your_stack_belongs_to_me);
53 lower(
54 r#"
55macro_rules! n_nuple {
56 ($e:tt) => ();
57 ($($rest:tt)*) => {{
58 (n_nuple!($($rest)*)None,)
59 }};
60}
61fn main() { n_nuple!(1,2,3); }
62"#,
63 );
64}
65
9ffffee4
FG
66#[test]
67fn your_stack_belongs_to_me2() {
68 cov_mark::check!(overflow_but_not_me);
69 lower(
70 r#"
71macro_rules! foo {
72 () => {{ foo!(); foo!(); }}
73}
74fn main() { foo!(); }
75"#,
76 );
77}
78
064997fb
FG
79#[test]
80fn recursion_limit() {
81 cov_mark::check!(your_stack_belongs_to_me);
82
83 lower(
84 r#"
85#![recursion_limit = "2"]
86macro_rules! n_nuple {
87 ($e:tt) => ();
88 ($first:tt $($rest:tt)*) => {{
89 n_nuple!($($rest)*)
90 }};
91}
92fn main() { n_nuple!(1,2,3); }
93"#,
94 );
95}
96
97#[test]
98fn issue_3642_bad_macro_stackover() {
99 lower(
100 r#"
101#[macro_export]
102macro_rules! match_ast {
103 (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
104
105 (match ($node:expr) {
106 $( ast::$ast:ident($it:ident) => $res:expr, )*
107 _ => $catch_all:expr $(,)?
108 }) => {{
109 $( if let Some($it) = ast::$ast::cast($node.clone()) { $res } else )*
110 { $catch_all }
111 }};
112}
113
114fn main() {
115 let anchor = match_ast! {
116 match parent {
117 as => {},
118 _ => return None
119 }
120 };
121}"#,
122 );
123}
124
125#[test]
126fn macro_resolve() {
127 // Regression test for a path resolution bug introduced with inner item handling.
128 lower(
129 r#"
130macro_rules! vec {
131 () => { () };
132 ($elem:expr; $n:expr) => { () };
133 ($($x:expr),+ $(,)?) => { () };
134}
135mod m {
136 fn outer() {
137 let _ = vec![FileSet::default(); self.len()];
138 }
139}
140"#,
141 );
142}
781aab86
FG
143
144#[test]
145fn desugar_builtin_format_args() {
781aab86
FG
146 let (db, body, def) = lower(
147 r#"
148//- minicore: fmt
149fn main() {
150 let are = "are";
151 let count = 10;
152 builtin#format_args("hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!");
153}
154"#,
155 );
156
157 expect![[r#"
158 fn main() {
159 let are = "are";
160 let count = 10;
161 builtin#lang(Arguments::new_v1_formatted)(
162 &[
4b012472 163 "hello ", " ", " friends, we ", " ", "",
781aab86
FG
164 ],
165 &[
166 builtin#lang(Argument::new_display)(
167 &count,
168 ), builtin#lang(Argument::new_display)(
169 &"fancy",
170 ), builtin#lang(Argument::new_debug)(
171 &are,
172 ), builtin#lang(Argument::new_display)(
173 &"!",
174 ),
175 ],
176 &[
177 builtin#lang(Placeholder::new)(
178 0usize,
179 ' ',
180 builtin#lang(Alignment::Unknown),
181 8u32,
182 builtin#lang(Count::Implied),
183 builtin#lang(Count::Is)(
184 2usize,
185 ),
186 ), builtin#lang(Placeholder::new)(
187 1usize,
188 ' ',
189 builtin#lang(Alignment::Unknown),
190 0u32,
191 builtin#lang(Count::Implied),
192 builtin#lang(Count::Implied),
193 ), builtin#lang(Placeholder::new)(
194 2usize,
195 ' ',
196 builtin#lang(Alignment::Unknown),
197 0u32,
198 builtin#lang(Count::Implied),
199 builtin#lang(Count::Implied),
200 ), builtin#lang(Placeholder::new)(
201 1usize,
202 ' ',
203 builtin#lang(Alignment::Unknown),
204 0u32,
205 builtin#lang(Count::Implied),
206 builtin#lang(Count::Implied),
207 ), builtin#lang(Placeholder::new)(
208 3usize,
209 ' ',
210 builtin#lang(Alignment::Unknown),
211 0u32,
212 builtin#lang(Count::Implied),
213 builtin#lang(Count::Implied),
214 ),
215 ],
216 unsafe {
217 builtin#lang(UnsafeArg::new)()
218 },
219 );
220 }"#]]
221 .assert_eq(&body.pretty_print(&db, def))
222}
4b012472
FG
223
224#[test]
225fn test_macro_hygiene() {
226 let (db, body, def) = lower(
227 r##"
228//- minicore: fmt, from
229//- /main.rs
230mod error;
231
232use crate::error::error;
233
234fn main() {
235 // _ = forces body expansion instead of block def map expansion
236 _ = error!("Failed to resolve path `{}`", node.text());
237}
238//- /error.rs
239macro_rules! _error {
240 ($fmt:expr, $($arg:tt)+) => {$crate::error::intermediate!(format_args!($fmt, $($arg)+))}
241}
242pub(crate) use _error as error;
243macro_rules! _intermediate {
244 ($arg:expr) => {$crate::error::SsrError::new($arg)}
245}
246pub(crate) use _intermediate as intermediate;
247
248pub struct SsrError(pub(crate) core::fmt::Arguments);
249
250impl SsrError {
251 pub(crate) fn new(message: impl Into<core::fmt::Arguments>) -> SsrError {
252 SsrError(message.into())
253 }
254}
255"##,
256 );
257
258 assert_eq!(db.body_with_source_map(def.into()).1.diagnostics(), &[]);
259 expect![[r#"
260 fn main() {
261 _ = $crate::error::SsrError::new(
262 builtin#lang(Arguments::new_v1_formatted)(
263 &[
264 "Failed to resolve path `", "`",
265 ],
266 &[
267 builtin#lang(Argument::new_display)(
268 &node.text(),
269 ),
270 ],
271 &[
272 builtin#lang(Placeholder::new)(
273 0usize,
274 ' ',
275 builtin#lang(Alignment::Unknown),
276 0u32,
277 builtin#lang(Count::Implied),
278 builtin#lang(Count::Implied),
279 ),
280 ],
281 unsafe {
282 builtin#lang(UnsafeArg::new)()
283 },
284 ),
285 );
286 }"#]]
287 .assert_eq(&body.pretty_print(&db, def))
288}
289
290#[test]
291fn regression_10300() {
292 let (db, body, def) = lower(
293 r#"
294//- minicore: concat, panic
295mod private {
296 pub use core::concat;
297}
298
299macro_rules! m {
300 () => {
301 panic!(concat!($crate::private::concat!("cc")));
302 };
303}
304
305fn f() {
306 m!();
307}
308"#,
309 );
310
311 let (_, source_map) = db.body_with_source_map(def.into());
312 assert_eq!(source_map.diagnostics(), &[]);
313
314 for (_, def_map) in body.blocks(&db) {
315 assert_eq!(def_map.diagnostics(), &[]);
316 }
317
318 expect![[r#"
319 fn f() {
320 $crate::panicking::panic_fmt(
321 builtin#lang(Arguments::new_v1_formatted)(
322 &[
323 "cc",
324 ],
325 &[],
326 &[],
327 unsafe {
328 builtin#lang(UnsafeArg::new)()
329 },
330 ),
331 );
332 }"#]]
333 .assert_eq(&body.pretty_print(&db, def))
334}