]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs
Rollup merge of #56425 - scottmcm:redo-vec-set_len-docs, r=Centril
[rust.git] / src / test / run-pass-fulldeps / ast_stmt_expr_attr.rs
1 #![allow(unused_imports)]
2 // ignore-cross-compile
3
4 #![feature(rustc_private)]
5
6 extern crate syntax;
7
8 use syntax::ast::*;
9 use syntax::attr::*;
10 use syntax::ast;
11 use syntax::source_map::{FilePathMapping, FileName};
12 use syntax::parse;
13 use syntax::parse::{ParseSess, PResult};
14 use syntax::parse::new_parser_from_source_str;
15 use syntax::parse::parser::Parser;
16 use syntax::parse::token;
17 use syntax::ptr::P;
18 use syntax::parse::attr::*;
19 use syntax::print::pprust;
20 use std::fmt;
21
22 // Copied out of syntax::util::parser_testing
23
24 pub fn string_to_parser<'a>(ps: &'a ParseSess, source_str: String) -> Parser<'a> {
25     new_parser_from_source_str(ps, FileName::Custom(source_str.clone()), source_str)
26 }
27
28 fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) -> PResult<'a, T> where
29     F: FnOnce(&mut Parser<'a>) -> PResult<'a, T>,
30 {
31     let mut p = string_to_parser(&ps, s);
32     let x = f(&mut p);
33
34     if ps.span_diagnostic.has_errors() || p.token != token::Eof {
35         if let Err(mut e) = x {
36             e.cancel();
37         }
38         return Err(p.fatal("parse error"));
39     }
40
41     x
42 }
43
44 fn expr<'a>(s: &str, ps: &'a ParseSess) -> PResult<'a, P<ast::Expr>> {
45     with_error_checking_parse(s.to_string(), ps, |p| {
46         p.parse_expr()
47     })
48 }
49
50 fn stmt<'a>(s: &str, ps: &'a ParseSess) -> PResult<'a, ast::Stmt> {
51     with_error_checking_parse(s.to_string(), ps, |p| {
52         p.parse_stmt().map(|s| s.unwrap())
53     })
54 }
55
56 fn attr<'a>(s: &str, ps: &'a ParseSess) -> PResult<'a, ast::Attribute> {
57     with_error_checking_parse(s.to_string(), ps, |p| {
58         p.parse_attribute(true)
59     })
60 }
61
62 fn str_compare<T, F: Fn(&T) -> String>(e: &str, expected: &[T], actual: &[T], f: F) {
63     let expected: Vec<_> = expected.iter().map(|e| f(e)).collect();
64     let actual: Vec<_> = actual.iter().map(|e| f(e)).collect();
65
66     if expected != actual {
67         panic!("parsed `{}` as {:?}, expected {:?}", e, actual, expected);
68     }
69 }
70
71 fn check_expr_attrs(es: &str, expected: &[&str]) {
72     let ps = ParseSess::new(FilePathMapping::empty());
73     let e = expr(es, &ps).expect("parse error");
74     let actual = &e.attrs;
75     str_compare(es,
76                 &expected.iter().map(|r| attr(r, &ps).unwrap()).collect::<Vec<_>>(),
77                 &actual,
78                 pprust::attribute_to_string);
79 }
80
81 fn check_stmt_attrs(es: &str, expected: &[&str]) {
82     let ps = ParseSess::new(FilePathMapping::empty());
83     let e = stmt(es, &ps).expect("parse error");
84     let actual = e.node.attrs();
85     str_compare(es,
86                 &expected.iter().map(|r| attr(r, &ps).unwrap()).collect::<Vec<_>>(),
87                 actual,
88                 pprust::attribute_to_string);
89 }
90
91 fn reject_expr_parse(es: &str) {
92     let ps = ParseSess::new(FilePathMapping::empty());
93     match expr(es, &ps) {
94         Ok(_) => panic!("parser did not reject `{}`", es),
95         Err(mut e) => e.cancel(),
96     };
97 }
98
99 fn reject_stmt_parse(es: &str) {
100     let ps = ParseSess::new(FilePathMapping::empty());
101     match stmt(es, &ps) {
102         Ok(_) => panic!("parser did not reject `{}`", es),
103         Err(mut e) => e.cancel(),
104     };
105 }
106
107 fn main() {
108     syntax::with_globals(|| run());
109 }
110
111 fn run() {
112     let both = &["#[attr]", "#![attr]"];
113     let outer = &["#[attr]"];
114     let none = &[];
115
116     check_expr_attrs("#[attr] box 0", outer);
117     reject_expr_parse("box #![attr] 0");
118
119     check_expr_attrs("#[attr] [#![attr]]", both);
120     check_expr_attrs("#[attr] [#![attr] 0]", both);
121     check_expr_attrs("#[attr] [#![attr] 0; 0]", both);
122     check_expr_attrs("#[attr] [#![attr] 0, 0, 0]", both);
123     reject_expr_parse("[#[attr]]");
124
125     check_expr_attrs("#[attr] foo()", outer);
126     check_expr_attrs("#[attr] x.foo()", outer);
127     reject_expr_parse("foo#[attr]()");
128     reject_expr_parse("foo(#![attr])");
129     reject_expr_parse("x.foo(#![attr])");
130     reject_expr_parse("x.#[attr]foo()");
131     reject_expr_parse("x.#![attr]foo()");
132
133     check_expr_attrs("#[attr] (#![attr])", both);
134     check_expr_attrs("#[attr] (#![attr] #[attr] 0,)", both);
135     check_expr_attrs("#[attr] (#![attr] #[attr] 0, 0)", both);
136
137     check_expr_attrs("#[attr] 0 + #[attr] 0", none);
138     check_expr_attrs("#[attr] 0 / #[attr] 0", none);
139     check_expr_attrs("#[attr] 0 & #[attr] 0", none);
140     check_expr_attrs("#[attr] 0 % #[attr] 0", none);
141     check_expr_attrs("#[attr] (0 + 0)", outer);
142     reject_expr_parse("0 + #![attr] 0");
143
144     check_expr_attrs("#[attr] !0", outer);
145     check_expr_attrs("#[attr] -0", outer);
146     reject_expr_parse("!#![attr] 0");
147     reject_expr_parse("-#![attr] 0");
148
149     check_expr_attrs("#[attr] false", outer);
150     check_expr_attrs("#[attr] 0", outer);
151     check_expr_attrs("#[attr] 'c'", outer);
152
153     check_expr_attrs("#[attr] x as Y", none);
154     check_expr_attrs("#[attr] (x as Y)", outer);
155     reject_expr_parse("x #![attr] as Y");
156
157     reject_expr_parse("#[attr] if false {}");
158     reject_expr_parse("if false #[attr] {}");
159     reject_expr_parse("if false {#![attr]}");
160     reject_expr_parse("if false {} #[attr] else {}");
161     reject_expr_parse("if false {} else #[attr] {}");
162     reject_expr_parse("if false {} else {#![attr]}");
163     reject_expr_parse("if false {} else #[attr] if true {}");
164     reject_expr_parse("if false {} else if true #[attr] {}");
165     reject_expr_parse("if false {} else if true {#![attr]}");
166
167     reject_expr_parse("#[attr] if let Some(false) = false {}");
168     reject_expr_parse("if let Some(false) = false #[attr] {}");
169     reject_expr_parse("if let Some(false) = false {#![attr]}");
170     reject_expr_parse("if let Some(false) = false {} #[attr] else {}");
171     reject_expr_parse("if let Some(false) = false {} else #[attr] {}");
172     reject_expr_parse("if let Some(false) = false {} else {#![attr]}");
173     reject_expr_parse("if let Some(false) = false {} else #[attr] if let Some(false) = true {}");
174     reject_expr_parse("if let Some(false) = false {} else if let Some(false) = true #[attr] {}");
175     reject_expr_parse("if let Some(false) = false {} else if let Some(false) = true {#![attr]}");
176
177     check_expr_attrs("#[attr] while true {#![attr]}", both);
178
179     check_expr_attrs("#[attr] while let Some(false) = true {#![attr]}", both);
180
181     check_expr_attrs("#[attr] for x in y {#![attr]}", both);
182
183     check_expr_attrs("#[attr] loop {#![attr]}", both);
184
185     check_expr_attrs("#[attr] match true {#![attr] #[attr] _ => false}", both);
186
187     check_expr_attrs("#[attr]      || #[attr] foo", outer);
188     check_expr_attrs("#[attr] move || #[attr] foo", outer);
189     check_expr_attrs("#[attr]      || #[attr] { #![attr] foo }", outer);
190     check_expr_attrs("#[attr] move || #[attr] { #![attr] foo }", outer);
191     check_expr_attrs("#[attr]      || { #![attr] foo }", outer);
192     check_expr_attrs("#[attr] move || { #![attr] foo }", outer);
193     reject_expr_parse("|| #![attr] foo");
194     reject_expr_parse("move || #![attr] foo");
195     reject_expr_parse("|| #![attr] {foo}");
196     reject_expr_parse("move || #![attr] {foo}");
197
198     check_expr_attrs("#[attr] { #![attr] }", both);
199     check_expr_attrs("#[attr] { #![attr] let _ = (); }", both);
200     check_expr_attrs("#[attr] { #![attr] let _ = (); foo }", both);
201
202     check_expr_attrs("#[attr] x = y", none);
203     check_expr_attrs("#[attr] (x = y)", outer);
204
205     check_expr_attrs("#[attr] x += y", none);
206     check_expr_attrs("#[attr] (x += y)", outer);
207
208     check_expr_attrs("#[attr] foo.bar", outer);
209     check_expr_attrs("(#[attr] foo).bar", none);
210
211     check_expr_attrs("#[attr] foo.0", outer);
212     check_expr_attrs("(#[attr] foo).0", none);
213
214     check_expr_attrs("#[attr] foo[bar]", outer);
215     check_expr_attrs("(#[attr] foo)[bar]", none);
216
217     check_expr_attrs("#[attr] 0..#[attr] 0", none);
218     check_expr_attrs("#[attr] 0..", none);
219     reject_expr_parse("#[attr] ..#[attr] 0");
220     reject_expr_parse("#[attr] ..");
221
222     check_expr_attrs("#[attr] (0..0)", outer);
223     check_expr_attrs("#[attr] (0..)", outer);
224     check_expr_attrs("#[attr] (..0)", outer);
225     check_expr_attrs("#[attr] (..)", outer);
226
227     check_expr_attrs("#[attr] foo::bar::baz", outer);
228
229     check_expr_attrs("#[attr] &0", outer);
230     check_expr_attrs("#[attr] &mut 0", outer);
231     check_expr_attrs("#[attr] & #[attr] 0", outer);
232     check_expr_attrs("#[attr] &mut #[attr] 0", outer);
233     reject_expr_parse("#[attr] &#![attr] 0");
234     reject_expr_parse("#[attr] &mut #![attr] 0");
235
236     check_expr_attrs("#[attr] break", outer);
237     check_expr_attrs("#[attr] continue", outer);
238     check_expr_attrs("#[attr] return", outer);
239
240     check_expr_attrs("#[attr] foo!()", outer);
241     check_expr_attrs("#[attr] foo!(#![attr])", outer);
242     check_expr_attrs("#[attr] foo![]", outer);
243     check_expr_attrs("#[attr] foo![#![attr]]", outer);
244     check_expr_attrs("#[attr] foo!{}", outer);
245     check_expr_attrs("#[attr] foo!{#![attr]}", outer);
246
247     check_expr_attrs("#[attr] Foo { #![attr] bar: baz }", both);
248     check_expr_attrs("#[attr] Foo { #![attr] ..foo }", both);
249     check_expr_attrs("#[attr] Foo { #![attr] bar: baz, ..foo }", both);
250
251     check_expr_attrs("#[attr] (#![attr] 0)", both);
252
253     // Look at statements in their natural habitat...
254     check_expr_attrs("{
255         #[attr] let _ = 0;
256         #[attr] 0;
257         #[attr] foo!();
258         #[attr] foo!{}
259         #[attr] foo![];
260     }", none);
261
262     check_stmt_attrs("#[attr] let _ = 0", outer);
263     check_stmt_attrs("#[attr] 0",         outer);
264     check_stmt_attrs("#[attr] {#![attr]}", both);
265     check_stmt_attrs("#[attr] foo!()",    outer);
266     check_stmt_attrs("#[attr] foo![]",    outer);
267     check_stmt_attrs("#[attr] foo!{}",    outer);
268
269     reject_stmt_parse("#[attr] #![attr] let _ = 0");
270     reject_stmt_parse("#[attr] #![attr] 0");
271     reject_stmt_parse("#[attr] #![attr] foo!()");
272     reject_stmt_parse("#[attr] #![attr] foo![]");
273     reject_stmt_parse("#[attr] #![attr] foo!{}");
274
275     // FIXME: Allow attributes in pattern constexprs?
276     // note: requires parens in patterns to allow disambiguation
277
278     reject_expr_parse("match 0 {
279         0..=#[attr] 10 => ()
280     }");
281     reject_expr_parse("match 0 {
282         0..=#[attr] -10 => ()
283     }");
284     reject_expr_parse("match 0 {
285         0..=-#[attr] 10 => ()
286     }");
287     reject_expr_parse("match 0 {
288         0..=#[attr] FOO => ()
289     }");
290
291     // make sure we don't catch this bug again...
292     reject_expr_parse("{
293         fn foo() {
294             #[attr];
295         }
296     }");
297     reject_expr_parse("{
298         fn foo() {
299             #[attr]
300         }
301     }");
302 }