1 #![allow(unused_imports)]
2 // ignore-cross-compile
4 #![feature(rustc_private)]
11 use syntax::source_map::{FilePathMapping, FileName};
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;
18 use syntax::parse::attr::*;
19 use syntax::print::pprust;
22 // Copied out of syntax::util::parser_testing
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)
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>,
31 let mut p = string_to_parser(&ps, s);
34 if ps.span_diagnostic.has_errors() || p.token != token::Eof {
35 if let Err(mut e) = x {
38 return Err(p.fatal("parse error"));
44 fn expr<'a>(s: &str, ps: &'a ParseSess) -> PResult<'a, P<ast::Expr>> {
45 with_error_checking_parse(s.to_string(), ps, |p| {
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())
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)
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();
66 if expected != actual {
67 panic!("parsed `{}` as {:?}, expected {:?}", e, actual, expected);
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;
76 &expected.iter().map(|r| attr(r, &ps).unwrap()).collect::<Vec<_>>(),
78 pprust::attribute_to_string);
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();
86 &expected.iter().map(|r| attr(r, &ps).unwrap()).collect::<Vec<_>>(),
88 pprust::attribute_to_string);
91 fn reject_expr_parse(es: &str) {
92 let ps = ParseSess::new(FilePathMapping::empty());
94 Ok(_) => panic!("parser did not reject `{}`", es),
95 Err(mut e) => e.cancel(),
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(),
108 syntax::with_default_globals(|| run());
112 let both = &["#[attr]", "#![attr]"];
113 let outer = &["#[attr]"];
116 check_expr_attrs("#[attr] box 0", outer);
117 reject_expr_parse("box #![attr] 0");
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]]");
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()");
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);
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");
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");
149 check_expr_attrs("#[attr] false", outer);
150 check_expr_attrs("#[attr] 0", outer);
151 check_expr_attrs("#[attr] 'c'", outer);
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");
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]}");
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]}");
177 check_expr_attrs("#[attr] while true {#![attr]}", both);
179 check_expr_attrs("#[attr] while let Some(false) = true {#![attr]}", both);
181 check_expr_attrs("#[attr] for x in y {#![attr]}", both);
183 check_expr_attrs("#[attr] loop {#![attr]}", both);
185 check_expr_attrs("#[attr] match true {#![attr] #[attr] _ => false}", both);
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}");
198 check_expr_attrs("#[attr] { #![attr] }", both);
199 check_expr_attrs("#[attr] { #![attr] let _ = (); }", both);
200 check_expr_attrs("#[attr] { #![attr] let _ = (); foo }", both);
202 check_expr_attrs("#[attr] x = y", none);
203 check_expr_attrs("#[attr] (x = y)", outer);
205 check_expr_attrs("#[attr] x += y", none);
206 check_expr_attrs("#[attr] (x += y)", outer);
208 check_expr_attrs("#[attr] foo.bar", outer);
209 check_expr_attrs("(#[attr] foo).bar", none);
211 check_expr_attrs("#[attr] foo.0", outer);
212 check_expr_attrs("(#[attr] foo).0", none);
214 check_expr_attrs("#[attr] foo[bar]", outer);
215 check_expr_attrs("(#[attr] foo)[bar]", none);
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] ..");
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);
227 check_expr_attrs("#[attr] foo::bar::baz", outer);
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");
236 check_expr_attrs("#[attr] break", outer);
237 check_expr_attrs("#[attr] continue", outer);
238 check_expr_attrs("#[attr] return", outer);
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);
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);
251 check_expr_attrs("#[attr] (#![attr] 0)", both);
253 // Look at statements in their natural habitat...
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);
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!{}");
275 // FIXME: Allow attributes in pattern constexprs?
276 // note: requires parens in patterns to allow disambiguation
278 reject_expr_parse("match 0 {
281 reject_expr_parse("match 0 {
282 0..=#[attr] -10 => ()
284 reject_expr_parse("match 0 {
285 0..=-#[attr] 10 => ()
287 reject_expr_parse("match 0 {
288 0..=#[attr] FOO => ()
291 // make sure we don't catch this bug again...