Add syntax support for attributes on expressions and all syntax
nodes in statement position. Extended #[cfg] folder to allow removal of statements, and of expressions in optional positions like expression lists and trailing block expressions. Extended lint checker to recognize lint levels on expressions and locals.
This commit is contained in:
parent
6ef02eff89
commit
2a8f358de7
34 changed files with 1602 additions and 416 deletions
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
|
||||
fn main() {
|
||||
#[attr] //~ ERROR expected item after attributes
|
||||
println!("hi");
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
|
||||
fn main() {
|
||||
#[attr] //~ ERROR expected item
|
||||
let __isize = 0;
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
|
||||
// error-pattern:expected item
|
||||
|
||||
fn f() {
|
||||
#[foo = "bar"]
|
||||
let x = 10;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
// compile-flags: -Z parse-only
|
||||
|
||||
// error-pattern:expected item
|
||||
// error-pattern:expected statement
|
||||
|
||||
fn f() {
|
||||
#[foo = "bar"]
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
|
||||
fn main() {
|
||||
/// hi
|
||||
println!("hi");
|
||||
//~^^ ERROR expected item after doc comment
|
||||
}
|
||||
|
|
@ -12,5 +12,5 @@
|
|||
|
||||
fn main() {
|
||||
println!("Hi"); /// hi
|
||||
//~^ ERROR expected item after doc comment
|
||||
}
|
||||
//~^ ERROR expected statement
|
||||
|
|
|
|||
|
|
@ -13,5 +13,5 @@
|
|||
fn main() {
|
||||
/// hi
|
||||
;
|
||||
//~^^ ERROR expected item after doc comment
|
||||
//~^ ERROR expected statement
|
||||
}
|
||||
|
|
|
|||
281
src/test/pretty/stmt_expr_attributes.rs
Normal file
281
src/test/pretty/stmt_expr_attributes.rs
Normal file
|
|
@ -0,0 +1,281 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// pp-exact
|
||||
|
||||
#![feature(custom_attribute)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(placement_in_syntax)]
|
||||
|
||||
fn main() { }
|
||||
|
||||
fn _0() {
|
||||
|
||||
#[attr]
|
||||
foo();
|
||||
}
|
||||
|
||||
fn _1() {
|
||||
|
||||
#[attr]
|
||||
unsafe {
|
||||
// code
|
||||
}
|
||||
}
|
||||
|
||||
fn _2() {
|
||||
|
||||
#[attr]
|
||||
{ foo(); }
|
||||
|
||||
{
|
||||
#![attr]
|
||||
|
||||
foo()
|
||||
}
|
||||
}
|
||||
|
||||
fn _3() {
|
||||
|
||||
#[attr]
|
||||
match () { _ => { } }
|
||||
}
|
||||
|
||||
fn _4() {
|
||||
|
||||
#[attr]
|
||||
match () {
|
||||
#![attr]
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let _ =
|
||||
#[attr] match () {
|
||||
#![attr]
|
||||
() => (),
|
||||
};
|
||||
}
|
||||
|
||||
fn _5() {
|
||||
|
||||
#[attr]
|
||||
let x = 1;
|
||||
|
||||
let x = #[attr] 1;
|
||||
|
||||
let y = ();
|
||||
let z = ();
|
||||
|
||||
foo3(x, #[attr] y, z);
|
||||
|
||||
qux(3 + #[attr] 2);
|
||||
}
|
||||
|
||||
fn _6() {
|
||||
|
||||
#[attr]
|
||||
[#![attr] 1, 2, 3];
|
||||
|
||||
let _ = #[attr] [#![attr] 1, 2, 3];
|
||||
|
||||
#[attr]
|
||||
[#![attr] 1; 4];
|
||||
|
||||
let _ = #[attr] [#![attr] 1; 4];
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
data: (),
|
||||
}
|
||||
|
||||
struct Bar(());
|
||||
|
||||
fn _7() {
|
||||
|
||||
#[attr]
|
||||
Foo{#![attr] data: (),};
|
||||
|
||||
let _ = #[attr] Foo{#![attr] data: (),};
|
||||
}
|
||||
|
||||
fn _8() {
|
||||
|
||||
#[attr]
|
||||
(#![attr] );
|
||||
|
||||
#[attr]
|
||||
(#![attr] 0);
|
||||
|
||||
#[attr]
|
||||
(#![attr] 0,);
|
||||
|
||||
#[attr]
|
||||
(#![attr] 0, 1);
|
||||
}
|
||||
|
||||
fn _9() {
|
||||
macro_rules! stmt_mac(( ) => { let _ = ( ) ; });
|
||||
|
||||
#[attr]
|
||||
stmt_mac!();
|
||||
|
||||
/*
|
||||
// pre existing pp bug: delimiter styles gets lost:
|
||||
|
||||
#[attr]
|
||||
stmt_mac!{ };
|
||||
|
||||
#[attr]
|
||||
stmt_mac![];
|
||||
|
||||
#[attr]
|
||||
stmt_mac!{ } // pre-existing pp bug: compiler ICEs with a None unwrap
|
||||
*/
|
||||
|
||||
let _ = ();
|
||||
}
|
||||
|
||||
macro_rules! expr_mac(( ) => { ( ) });
|
||||
|
||||
fn _10() {
|
||||
|
||||
let _ = #[attr] expr_mac!();
|
||||
|
||||
/*
|
||||
// pre existing pp bug: delimiter styles gets lost:
|
||||
let _ = #[attr] expr_mac![];
|
||||
let _ = #[attr] expr_mac!{};
|
||||
*/
|
||||
}
|
||||
|
||||
fn _11() {
|
||||
let _ = #[attr] box 0;
|
||||
let _: [(); 0] = #[attr] [#![attr] ];
|
||||
let _ = #[attr] [#![attr] 0, 0];
|
||||
let _ = #[attr] [#![attr] 0; 0];
|
||||
let _ = #[attr] foo();
|
||||
let _ = #[attr] 1i32.clone();
|
||||
let _ = #[attr] (#![attr] );
|
||||
let _ = #[attr] (#![attr] 0);
|
||||
let _ = #[attr] (#![attr] 0,);
|
||||
let _ = #[attr] (#![attr] 0, 0);
|
||||
let _ = #[attr] 0 + #[attr] 0;
|
||||
let _ = #[attr] !0;
|
||||
let _ = #[attr] -0i32;
|
||||
let _ = #[attr] false;
|
||||
let _ = #[attr] 'c';
|
||||
let _ = #[attr] 0;
|
||||
let _ = #[attr] 0 as usize;
|
||||
let _ =
|
||||
#[attr] while false {
|
||||
#![attr]
|
||||
};
|
||||
let _ =
|
||||
#[attr] while let None = Some(()) {
|
||||
#![attr]
|
||||
};
|
||||
let _ =
|
||||
#[attr] for _ in 0..0 {
|
||||
#![attr]
|
||||
};
|
||||
// FIXME: pp bug, two spaces after the loop
|
||||
let _ =
|
||||
#[attr] loop {
|
||||
#![attr]
|
||||
};
|
||||
let _ =
|
||||
#[attr] match false {
|
||||
#![attr]
|
||||
_ => (),
|
||||
};
|
||||
let _ = #[attr] || #[attr] ();
|
||||
let _ = #[attr] move || #[attr] ();
|
||||
let _ = #[attr] || {
|
||||
#![attr]
|
||||
#[attr]
|
||||
() };
|
||||
let _ = #[attr] move || {
|
||||
#![attr]
|
||||
#[attr]
|
||||
() };
|
||||
let _ =
|
||||
#[attr] {
|
||||
#![attr]
|
||||
};
|
||||
let _ =
|
||||
#[attr] {
|
||||
#![attr]
|
||||
let _ = ();
|
||||
};
|
||||
let _ =
|
||||
#[attr] {
|
||||
#![attr]
|
||||
let _ = ();
|
||||
()
|
||||
};
|
||||
let mut x = 0;
|
||||
let _ = #[attr] x = 15;
|
||||
let _ = #[attr] x += 15;
|
||||
let s = Foo{data: (),};
|
||||
let _ = #[attr] s.data;
|
||||
let _ = (#[attr] s).data;
|
||||
let t = Bar(());
|
||||
let _ = #[attr] t.0;
|
||||
let _ = (#[attr] t).0;
|
||||
let v = vec!(0);
|
||||
let _ = #[attr] v[0];
|
||||
let _ = (#[attr] v)[0];
|
||||
let _ = #[attr] 0..#[attr] 0;
|
||||
let _ = #[attr] 0..;
|
||||
let _ = #[attr] (0..0);
|
||||
let _ = #[attr] (0..);
|
||||
let _ = #[attr] (..0);
|
||||
let _ = #[attr] (..);
|
||||
let _: fn(&u32) -> u32 = #[attr] std::clone::Clone::clone;
|
||||
let _ = #[attr] &0;
|
||||
let _ = #[attr] &mut 0;
|
||||
let _ = #[attr] &#[attr] 0;
|
||||
let _ = #[attr] &mut #[attr] 0;
|
||||
// FIXME: pp bug, extra space after keyword?
|
||||
while false { let _ = #[attr] continue ; }
|
||||
while true { let _ = #[attr] break ; }
|
||||
|| #[attr] return;
|
||||
let _ = #[attr] expr_mac!();
|
||||
/* FIXME: pp bug, loosing delimiter styles
|
||||
let _ = #[attr] expr_mac![];
|
||||
let _ = #[attr] expr_mac!{};
|
||||
*/
|
||||
let _ = #[attr] Foo{#![attr] data: (),};
|
||||
let _ = #[attr] Foo{#![attr] ..s};
|
||||
let _ = #[attr] Foo{#![attr] data: (), ..s};
|
||||
let _ = #[attr] (#![attr] 0);
|
||||
}
|
||||
|
||||
fn _12() {
|
||||
#[attr]
|
||||
let _ = 0;
|
||||
|
||||
#[attr]
|
||||
0;
|
||||
|
||||
#[attr]
|
||||
expr_mac!();
|
||||
|
||||
#[attr]
|
||||
{
|
||||
#![attr]
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////
|
||||
|
||||
fn foo() { }
|
||||
fn foo3(_: i32, _: (), _: ()) { }
|
||||
fn qux(_: i32) { }
|
||||
306
src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs
Normal file
306
src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate syntax;
|
||||
|
||||
use syntax::ast::*;
|
||||
use syntax::ast;
|
||||
use syntax::parse;
|
||||
use syntax::parse::{ParseSess,filemap_to_tts, PResult};
|
||||
use syntax::parse::new_parser_from_source_str;
|
||||
use syntax::parse::parser::Parser;
|
||||
use syntax::parse::token;
|
||||
use syntax::ptr::P;
|
||||
use syntax::str::char_at;
|
||||
use syntax::parse::attr::*;
|
||||
use syntax::print::pprust;
|
||||
use std::fmt;
|
||||
|
||||
|
||||
// Copied out of syntax::util::parser_testing
|
||||
|
||||
pub fn string_to_parser<'a>(ps: &'a ParseSess, source_str: String) -> Parser<'a> {
|
||||
new_parser_from_source_str(ps,
|
||||
Vec::new(),
|
||||
"bogofile".to_string(),
|
||||
source_str)
|
||||
}
|
||||
|
||||
fn with_error_checking_parse<T, F>(s: String, f: F) -> PResult<T> where
|
||||
F: FnOnce(&mut Parser) -> PResult<T>,
|
||||
{
|
||||
let ps = ParseSess::new();
|
||||
let mut p = string_to_parser(&ps, s);
|
||||
let x = f(&mut p);
|
||||
|
||||
if ps.span_diagnostic.handler().has_errors() || p.token != token::Eof {
|
||||
return Err(p.fatal("parse error"));
|
||||
}
|
||||
|
||||
x
|
||||
}
|
||||
|
||||
fn expr(s: &str) -> PResult<P<ast::Expr>> {
|
||||
with_error_checking_parse(s.to_string(), |p| {
|
||||
p.parse_expr_nopanic()
|
||||
})
|
||||
}
|
||||
|
||||
fn stmt(s: &str) -> PResult<P<ast::Stmt>> {
|
||||
with_error_checking_parse(s.to_string(), |p| {
|
||||
p.parse_stmt_nopanic().map(|s| s.unwrap())
|
||||
})
|
||||
}
|
||||
|
||||
fn attr(s: &str) -> PResult<ast::Attribute> {
|
||||
with_error_checking_parse(s.to_string(), |p| {
|
||||
p.parse_attribute(true)
|
||||
})
|
||||
}
|
||||
|
||||
fn str_compare<T, F: Fn(&T) -> String>(e: &str, expected: &[T], actual: &[T], f: F) {
|
||||
let expected: Vec<_> = expected.iter().map(|e| f(e)).collect();
|
||||
let actual: Vec<_> = actual.iter().map(|e| f(e)).collect();
|
||||
|
||||
if expected != actual {
|
||||
panic!("parsed `{}` as {:?}, expected {:?}", e, actual, expected);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_expr_attrs(es: &str, expected: &[&str]) {
|
||||
let e = expr(es).expect("parse error");
|
||||
let actual = &e.attrs;
|
||||
str_compare(es,
|
||||
&expected.iter().map(|r| attr(r).unwrap()).collect::<Vec<_>>(),
|
||||
actual.as_attrs(),
|
||||
pprust::attribute_to_string);
|
||||
}
|
||||
|
||||
fn check_stmt_attrs(es: &str, expected: &[&str]) {
|
||||
let e = stmt(es).expect("parse error");
|
||||
let actual = e.node.attrs();
|
||||
str_compare(es,
|
||||
&expected.iter().map(|r| attr(r).unwrap()).collect::<Vec<_>>(),
|
||||
actual,
|
||||
pprust::attribute_to_string);
|
||||
}
|
||||
|
||||
fn reject_expr_parse(es: &str) {
|
||||
assert!(expr(es).is_err(), "parser did not reject `{}`", es);
|
||||
}
|
||||
|
||||
fn reject_stmt_parse(es: &str) {
|
||||
assert!(stmt(es).is_err(), "parser did not reject `{}`", es);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let both = &["#[attr]", "#![attr]"];
|
||||
let outer = &["#[attr]"];
|
||||
let none = &[];
|
||||
|
||||
check_expr_attrs("#[attr] box 0", outer);
|
||||
reject_expr_parse("box #![attr] 0");
|
||||
|
||||
check_expr_attrs("#[attr] 0 <- #[attr] 0", none);
|
||||
check_expr_attrs("#[attr] (0 <- 0)", outer);
|
||||
reject_expr_parse("0 #[attr] <- 0");
|
||||
reject_expr_parse("0 <- #![attr] 0");
|
||||
|
||||
check_expr_attrs("in #[attr] 0 {#[attr] 0}", none);
|
||||
check_expr_attrs("#[attr] (in 0 {0})", outer);
|
||||
reject_expr_parse("in 0 #[attr] {0}");
|
||||
reject_expr_parse("in 0 {#![attr] 0}");
|
||||
|
||||
check_expr_attrs("#[attr] [#![attr]]", both);
|
||||
check_expr_attrs("#[attr] [#![attr] 0]", both);
|
||||
check_expr_attrs("#[attr] [#![attr] 0; 0]", both);
|
||||
check_expr_attrs("#[attr] [#![attr] 0, 0, 0]", both);
|
||||
reject_expr_parse("[#[attr]]");
|
||||
|
||||
check_expr_attrs("#[attr] foo()", outer);
|
||||
check_expr_attrs("#[attr] x.foo()", outer);
|
||||
reject_expr_parse("foo#[attr]()");
|
||||
reject_expr_parse("foo(#![attr])");
|
||||
reject_expr_parse("x.foo(#![attr])");
|
||||
reject_expr_parse("x.#[attr]foo()");
|
||||
reject_expr_parse("x.#![attr]foo()");
|
||||
|
||||
check_expr_attrs("#[attr] (#![attr])", both);
|
||||
check_expr_attrs("#[attr] (#![attr] #[attr] 0,)", both);
|
||||
check_expr_attrs("#[attr] (#![attr] #[attr] 0, 0)", both);
|
||||
|
||||
check_expr_attrs("#[attr] 0 + #[attr] 0", none);
|
||||
check_expr_attrs("#[attr] 0 / #[attr] 0", none);
|
||||
check_expr_attrs("#[attr] 0 & #[attr] 0", none);
|
||||
check_expr_attrs("#[attr] 0 % #[attr] 0", none);
|
||||
check_expr_attrs("#[attr] (0 + 0)", outer);
|
||||
reject_expr_parse("0 + #![attr] 0");
|
||||
|
||||
check_expr_attrs("#[attr] !0", outer);
|
||||
check_expr_attrs("#[attr] -0", outer);
|
||||
reject_expr_parse("!#![attr] 0");
|
||||
reject_expr_parse("-#![attr] 0");
|
||||
|
||||
check_expr_attrs("#[attr] false", outer);
|
||||
check_expr_attrs("#[attr] 0", outer);
|
||||
check_expr_attrs("#[attr] 'c'", outer);
|
||||
|
||||
check_expr_attrs("#[attr] x as Y", none);
|
||||
check_expr_attrs("#[attr] (x as Y)", outer);
|
||||
reject_expr_parse("x #![attr] as Y");
|
||||
|
||||
reject_expr_parse("#[attr] if false {}");
|
||||
reject_expr_parse("if false #[attr] {}");
|
||||
reject_expr_parse("if false {#![attr]}");
|
||||
reject_expr_parse("if false {} #[attr] else {}");
|
||||
reject_expr_parse("if false {} else #[attr] {}");
|
||||
reject_expr_parse("if false {} else {#![attr]}");
|
||||
reject_expr_parse("if false {} else #[attr] if true {}");
|
||||
reject_expr_parse("if false {} else if true #[attr] {}");
|
||||
reject_expr_parse("if false {} else if true {#![attr]}");
|
||||
|
||||
reject_expr_parse("#[attr] if let Some(false) = false {}");
|
||||
reject_expr_parse("if let Some(false) = false #[attr] {}");
|
||||
reject_expr_parse("if let Some(false) = false {#![attr]}");
|
||||
reject_expr_parse("if let Some(false) = false {} #[attr] else {}");
|
||||
reject_expr_parse("if let Some(false) = false {} else #[attr] {}");
|
||||
reject_expr_parse("if let Some(false) = false {} else {#![attr]}");
|
||||
reject_expr_parse("if let Some(false) = false {} else #[attr] if let Some(false) = true {}");
|
||||
reject_expr_parse("if let Some(false) = false {} else if let Some(false) = true #[attr] {}");
|
||||
reject_expr_parse("if let Some(false) = false {} else if let Some(false) = true {#![attr]}");
|
||||
|
||||
check_expr_attrs("#[attr] while true {#![attr]}", both);
|
||||
|
||||
check_expr_attrs("#[attr] while let Some(false) = true {#![attr]}", both);
|
||||
|
||||
check_expr_attrs("#[attr] for x in y {#![attr]}", both);
|
||||
|
||||
check_expr_attrs("#[attr] loop {#![attr]}", both);
|
||||
|
||||
check_expr_attrs("#[attr] match true {#![attr] #[attr] _ => false}", both);
|
||||
|
||||
check_expr_attrs("#[attr] || #[attr] foo", outer);
|
||||
check_expr_attrs("#[attr] move || #[attr] foo", outer);
|
||||
check_expr_attrs("#[attr] || #[attr] { #![attr] foo }", outer);
|
||||
check_expr_attrs("#[attr] move || #[attr] { #![attr] foo }", outer);
|
||||
check_expr_attrs("#[attr] || { #![attr] foo }", outer);
|
||||
check_expr_attrs("#[attr] move || { #![attr] foo }", outer);
|
||||
reject_expr_parse("|| #![attr] foo");
|
||||
reject_expr_parse("move || #![attr] foo");
|
||||
reject_expr_parse("|| #![attr] {foo}");
|
||||
reject_expr_parse("move || #![attr] {foo}");
|
||||
|
||||
check_expr_attrs("#[attr] { #![attr] }", both);
|
||||
check_expr_attrs("#[attr] { #![attr] let _ = (); }", both);
|
||||
check_expr_attrs("#[attr] { #![attr] let _ = (); foo }", both);
|
||||
|
||||
check_expr_attrs("#[attr] x = y", none);
|
||||
check_expr_attrs("#[attr] (x = y)", outer);
|
||||
|
||||
check_expr_attrs("#[attr] x += y", none);
|
||||
check_expr_attrs("#[attr] (x += y)", outer);
|
||||
|
||||
check_expr_attrs("#[attr] foo.bar", outer);
|
||||
check_expr_attrs("(#[attr] foo).bar", none);
|
||||
|
||||
check_expr_attrs("#[attr] foo.0", outer);
|
||||
check_expr_attrs("(#[attr] foo).0", none);
|
||||
|
||||
check_expr_attrs("#[attr] foo[bar]", outer);
|
||||
check_expr_attrs("(#[attr] foo)[bar]", none);
|
||||
|
||||
check_expr_attrs("#[attr] 0..#[attr] 0", none);
|
||||
check_expr_attrs("#[attr] 0..", none);
|
||||
reject_expr_parse("#[attr] ..#[attr] 0");
|
||||
reject_expr_parse("#[attr] ..");
|
||||
|
||||
check_expr_attrs("#[attr] (0..0)", outer);
|
||||
check_expr_attrs("#[attr] (0..)", outer);
|
||||
check_expr_attrs("#[attr] (..0)", outer);
|
||||
check_expr_attrs("#[attr] (..)", outer);
|
||||
|
||||
check_expr_attrs("#[attr] foo::bar::baz", outer);
|
||||
|
||||
check_expr_attrs("#[attr] &0", outer);
|
||||
check_expr_attrs("#[attr] &mut 0", outer);
|
||||
check_expr_attrs("#[attr] & #[attr] 0", outer);
|
||||
check_expr_attrs("#[attr] &mut #[attr] 0", outer);
|
||||
reject_expr_parse("#[attr] &#![attr] 0");
|
||||
reject_expr_parse("#[attr] &mut #![attr] 0");
|
||||
|
||||
check_expr_attrs("#[attr] break", outer);
|
||||
check_expr_attrs("#[attr] continue", outer);
|
||||
check_expr_attrs("#[attr] return", outer);
|
||||
|
||||
check_expr_attrs("#[attr] foo!()", outer);
|
||||
check_expr_attrs("#[attr] foo!(#![attr])", outer);
|
||||
check_expr_attrs("#[attr] foo![]", outer);
|
||||
check_expr_attrs("#[attr] foo![#![attr]]", outer);
|
||||
check_expr_attrs("#[attr] foo!{}", outer);
|
||||
check_expr_attrs("#[attr] foo!{#![attr]}", outer);
|
||||
|
||||
check_expr_attrs("#[attr] Foo { #![attr] bar: baz }", both);
|
||||
check_expr_attrs("#[attr] Foo { #![attr] ..foo }", both);
|
||||
check_expr_attrs("#[attr] Foo { #![attr] bar: baz, ..foo }", both);
|
||||
|
||||
check_expr_attrs("#[attr] (#![attr] 0)", both);
|
||||
|
||||
// Look at statements in their natural habitat...
|
||||
check_expr_attrs("{
|
||||
#[attr] let _ = 0;
|
||||
#[attr] 0;
|
||||
#[attr] foo!();
|
||||
#[attr] foo!{}
|
||||
#[attr] foo![];
|
||||
}", none);
|
||||
|
||||
check_stmt_attrs("#[attr] let _ = 0", outer);
|
||||
check_stmt_attrs("#[attr] 0", outer);
|
||||
check_stmt_attrs("#[attr] {#![attr]}", both);
|
||||
check_stmt_attrs("#[attr] foo!()", outer);
|
||||
check_stmt_attrs("#[attr] foo![]", outer);
|
||||
check_stmt_attrs("#[attr] foo!{}", outer);
|
||||
|
||||
reject_stmt_parse("#[attr] #![attr] let _ = 0");
|
||||
reject_stmt_parse("#[attr] #![attr] 0");
|
||||
reject_stmt_parse("#[attr] #![attr] foo!()");
|
||||
reject_stmt_parse("#[attr] #![attr] foo![]");
|
||||
reject_stmt_parse("#[attr] #![attr] foo!{}");
|
||||
|
||||
// FIXME: Allow attributes in pattern constexprs?
|
||||
// would require parens in patterns to allow disambiguation...
|
||||
|
||||
reject_expr_parse("match 0 {
|
||||
0...#[attr] 10 => ()
|
||||
}");
|
||||
reject_expr_parse("match 0 {
|
||||
0...#[attr] -10 => ()
|
||||
}");
|
||||
reject_expr_parse("match 0 {
|
||||
0...-#[attr] 10 => ()
|
||||
}");
|
||||
reject_expr_parse("match 0 {
|
||||
0...#[attr] FOO => ()
|
||||
}");
|
||||
|
||||
// make sure we don't catch this bug again...
|
||||
reject_expr_parse("{
|
||||
fn foo() {
|
||||
#[attr];
|
||||
}
|
||||
}");
|
||||
reject_expr_parse("{
|
||||
fn foo() {
|
||||
#[attr]
|
||||
}
|
||||
}");
|
||||
}
|
||||
97
src/test/run-pass/cfg_stmt_expr.rs
Normal file
97
src/test/run-pass/cfg_stmt_expr.rs
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![deny(non_snake_case)]
|
||||
|
||||
fn main() {
|
||||
let a = 413;
|
||||
#[cfg(unset)]
|
||||
let a = ();
|
||||
assert_eq!(a, 413);
|
||||
|
||||
let mut b = 612;
|
||||
#[cfg(unset)]
|
||||
{
|
||||
b = 1111;
|
||||
}
|
||||
assert_eq!(b, 612);
|
||||
|
||||
#[cfg(unset)]
|
||||
undefined_fn();
|
||||
|
||||
#[cfg(unset)]
|
||||
undefined_macro!();
|
||||
#[cfg(unset)]
|
||||
undefined_macro![];
|
||||
#[cfg(unset)]
|
||||
undefined_macro!{};
|
||||
|
||||
// pretty printer bug...
|
||||
// #[cfg(unset)]
|
||||
// undefined_macro!{}
|
||||
|
||||
let () = (#[cfg(unset)] 341,); // Should this also work on parens?
|
||||
let t = (1, #[cfg(unset)] 3, 4);
|
||||
assert_eq!(t, (1, 4));
|
||||
|
||||
let f = |_: u32, _: u32| ();
|
||||
f(2, 1, #[cfg(unset)] 6);
|
||||
|
||||
let _: u32 = a.clone(#[cfg(unset)] undefined);
|
||||
|
||||
let _: [(); 0] = [#[cfg(unset)] 126];
|
||||
let t = [#[cfg(unset)] 1, 2, 6];
|
||||
assert_eq!(t, [2, 6]);
|
||||
|
||||
{
|
||||
let r;
|
||||
#[cfg(unset)]
|
||||
(r = 5);
|
||||
#[cfg(not(unset))]
|
||||
(r = 10);
|
||||
assert_eq!(r, 10);
|
||||
}
|
||||
|
||||
// check that macro expanded code works
|
||||
|
||||
macro_rules! if_cfg {
|
||||
($cfg:meta $ib:block else $eb:block) => {
|
||||
{
|
||||
let r;
|
||||
#[cfg($cfg)]
|
||||
(r = $ib);
|
||||
#[cfg(not($cfg))]
|
||||
(r = $eb);
|
||||
r
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let n = if_cfg!(unset {
|
||||
413
|
||||
} else {
|
||||
612
|
||||
});
|
||||
|
||||
assert_eq!((#[cfg(unset)] 1, #[cfg(not(unset))] 2), (2,));
|
||||
assert_eq!(n, 612);
|
||||
|
||||
// check that lints work
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
let FOOBAR = {
|
||||
fn SYLADEX() {}
|
||||
};
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
{
|
||||
fn CRUXTRUDER() {}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue