Auto merge of #49124 - abonander:attr-macro-stmt-expr, r=abonander

Expand Attributes on Statements and Expressions

This enables attribute-macro expansion on statements and expressions while retaining the `stmt_expr_attributes` feature requirement for attributes on expressions.

closes #41475
cc #38356  @petrochenkov @jseyfried
r? @nrc
This commit is contained in:
bors 2018-04-02 10:38:28 +00:00
commit 097efa9a99
16 changed files with 335 additions and 34 deletions

View file

@ -93,6 +93,8 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
}
})
}
// these are covered in proc_macro/attr-stmt-expr.rs
Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item")
}
}
@ -145,6 +147,8 @@ fn expand_duplicate(cx: &mut ExtCtxt,
new_it.ident = copy_name;
push(Annotatable::TraitItem(P(new_it)));
}
// covered in proc_macro/attr-stmt-expr.rs
Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item")
}
}

View file

@ -0,0 +1,38 @@
// Copyright 2018 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.
// aux-build:attr-stmt-expr.rs
// ignore-stage1
//! Attributes producing expressions in invalid locations
#![feature(proc_macro, stmt_expr_attributes)]
extern crate attr_stmt_expr;
use attr_stmt_expr::{duplicate, no_output};
fn main() {
let _ = #[no_output] "Hello, world!";
//~^ ERROR expected expression, found `<eof>`
let _ = #[duplicate] "Hello, world!";
//~^ ERROR macro expansion ignores token `,` and any following
let _ = {
#[no_output]
"Hello, world!"
};
let _ = {
#[duplicate]
//~^ ERROR macro expansion ignores token `,` and any following
"Hello, world!"
};
}

View file

@ -0,0 +1,38 @@
// Copyright 2018 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.
// aux-build:attr-stmt-expr.rs
// ignore-stage1
#![feature(proc_macro)]
extern crate attr_stmt_expr;
use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr};
fn print_str(string: &'static str) {
// macros are handled a bit differently
#[expect_print_expr]
//~^ ERROR attributes on expressions are experimental
//~| HELP add #![feature(stmt_expr_attributes)] to the crate attributes to enable
println!("{}", string)
}
fn main() {
#[expect_let]
let string = "Hello, world!";
#[expect_print_stmt]
println!("{}", string);
#[expect_expr]
//~^ ERROR attributes on expressions are experimental
//~| HELP add #![feature(stmt_expr_attributes)] to the crate attributes to enable
print_str("string")
}

View file

@ -0,0 +1,59 @@
// Copyright 2018 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.
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro_attribute]
pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "let string = \"Hello, world!\";");
item
}
#[proc_macro_attribute]
pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "println!(\"{}\" , string);");
item
}
#[proc_macro_attribute]
pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "print_str(\"string\")");
item
}
#[proc_macro_attribute]
pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "println!(\"{}\" , string)");
item
}
#[proc_macro_attribute]
pub fn duplicate(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
format!("{}, {}", item, item).parse().unwrap()
}
#[proc_macro_attribute]
pub fn no_output(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert!(!item.to_string().is_empty());
"".parse().unwrap()
}

View file

@ -96,6 +96,8 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
}
})
],
// these are covered in proc_macro/attr-stmt-expr.rs
Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item"),
}
}
@ -140,6 +142,8 @@ fn expand_duplicate(cx: &mut ExtCtxt,
new_it.ident = copy_name;
push(Annotatable::TraitItem(P(new_it)));
}
// these are covered in proc_macro/attr-stmt-expr.rs
Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item")
}
}

View file

@ -0,0 +1,34 @@
// Copyright 2018 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.
// aux-build:attr-stmt-expr.rs
// ignore-stage1
#![feature(proc_macro, stmt_expr_attributes)]
extern crate attr_stmt_expr;
use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr};
fn print_str(string: &'static str) {
// macros are handled a bit differently
#[expect_print_expr]
println!("{}", string)
}
fn main() {
#[expect_let]
let string = "Hello, world!";
#[expect_print_stmt]
println!("{}", string);
#[expect_expr]
print_str("string")
}

View file

@ -0,0 +1,46 @@
// Copyright 2018 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.
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro_attribute]
pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "let string = \"Hello, world!\";");
item
}
#[proc_macro_attribute]
pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "println!(\"{}\" , string);");
item
}
#[proc_macro_attribute]
pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "print_str(\"string\")");
item
}
#[proc_macro_attribute]
pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "println!(\"{}\" , string)");
item
}

View file

@ -9,6 +9,6 @@
// except according to those terms.
const X: i32 = #[allow(dead_code)] 8;
//~^ ERROR attributes on non-item statements and expressions are experimental. (see issue #15701)
//~^ ERROR attributes on expressions are experimental. (see issue #15701)
fn main() {}

View file

@ -1,4 +1,4 @@
error[E0658]: attributes on non-item statements and expressions are experimental. (see issue #15701)
error[E0658]: attributes on expressions are experimental. (see issue #15701)
--> $DIR/feature-gate-stmt_expr_attributes.rs:11:16
|
LL | const X: i32 = #[allow(dead_code)] 8;