Auto merge of #50307 - petrochenkov:keyhyg2, r=nikomatsakis

Implement edition hygiene for keywords

Determine "keywordness" of an identifier in its hygienic context.
cc https://github.com/rust-lang/rust/pull/49611

I've resurrected `proc` as an Edition-2015-only keyword for testing purposes, but it should probably be buried again. EDIT: `proc` is removed again.
This commit is contained in:
bors 2018-05-18 10:57:05 +00:00
commit df40e61382
58 changed files with 896 additions and 119 deletions

View file

@ -20,6 +20,7 @@ extern crate rustc_plugin;
use std::borrow::ToOwned;
use syntax::ast;
use syntax::ext::hygiene;
use syntax::ext::build::AstBuilder;
use syntax::ext::base::{TTMacroExpander, ExtCtxt, MacResult, MacEager, NormalTT};
use syntax::print::pprust;
@ -54,5 +55,6 @@ pub fn plugin_registrar(reg: &mut Registry) {
allow_internal_unstable: false,
allow_internal_unsafe: false,
unstable_feature: None,
edition: hygiene::default_edition(),
});
}

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.
// compile-flags: --edition=2015
#![feature(raw_identifiers)]
#[macro_export]
macro_rules! produces_async {
() => (pub fn async() {})
}
#[macro_export]
macro_rules! produces_async_raw {
() => (pub fn r#async() {})
}
#[macro_export]
macro_rules! consumes_async {
(async) => (1)
}
#[macro_export]
macro_rules! consumes_async_raw {
(r#async) => (1)
}
#[macro_export]
macro_rules! passes_ident {
($i: ident) => ($i)
}

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.
// compile-flags: --edition=2018
#![feature(raw_identifiers)]
#[macro_export]
macro_rules! produces_async {
() => (pub fn async() {})
}
#[macro_export]
macro_rules! produces_async_raw {
() => (pub fn r#async() {})
}
#[macro_export]
macro_rules! consumes_async {
(async) => (1)
}
#[macro_export]
macro_rules! consumes_async_raw {
(r#async) => (1)
}
#[macro_export]
macro_rules! passes_ident {
($i: ident) => ($i)
}

View file

@ -0,0 +1,43 @@
// 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.
// compile-flags: --edition=2015
// aux-build:edition-kw-macro-2015.rs
#![feature(raw_identifiers)]
#[macro_use]
extern crate edition_kw_macro_2015;
pub fn check_async() {
let mut async = 1; // OK
let mut r#async = 1; // OK
r#async = consumes_async!(async); // OK
// r#async = consumes_async!(r#async); // ERROR, not a match
// r#async = consumes_async_raw!(async); // ERROR, not a match
r#async = consumes_async_raw!(r#async); // OK
if passes_ident!(async) == 1 {} // OK
if passes_ident!(r#async) == 1 {} // OK
one_async::async(); // OK
one_async::r#async(); // OK
two_async::async(); // OK
two_async::r#async(); // OK
}
mod one_async {
produces_async! {} // OK
}
mod two_async {
produces_async_raw! {} // OK
}
fn main() {}

View file

@ -0,0 +1,43 @@
// 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.
// compile-flags: --edition=2015
// aux-build:edition-kw-macro-2018.rs
#![feature(raw_identifiers)]
#[macro_use]
extern crate edition_kw_macro_2018;
pub fn check_async() {
let mut async = 1; // OK
let mut r#async = 1; // OK
r#async = consumes_async!(async); // OK
// r#async = consumes_async!(r#async); // ERROR, not a match
// r#async = consumes_async_raw!(async); // ERROR, not a match
r#async = consumes_async_raw!(r#async); // OK
if passes_ident!(async) == 1 {} // OK
if passes_ident!(r#async) == 1 {} // OK
// one_async::async(); // ERROR, unresolved name
// one_async::r#async(); // ERROR, unresolved name
two_async::async(); // OK
two_async::r#async(); // OK
}
mod one_async {
// produces_async! {} // ERROR, reserved
}
mod two_async {
produces_async_raw! {} // OK
}
fn main() {}

View file

@ -0,0 +1,43 @@
// 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.
// compile-flags: --edition=2018
// aux-build:edition-kw-macro-2015.rs
#![feature(raw_identifiers)]
#[macro_use]
extern crate edition_kw_macro_2015;
pub fn check_async() {
// let mut async = 1; // ERROR, reserved
let mut r#async = 1; // OK
r#async = consumes_async!(async); // OK
// r#async = consumes_async!(r#async); // ERROR, not a match
// r#async = consumes_async_raw!(async); // ERROR, not a match
r#async = consumes_async_raw!(r#async); // OK
// if passes_ident!(async) == 1 {} // ERROR, reserved
if passes_ident!(r#async) == 1 {} // OK
// one_async::async(); // ERROR, reserved
one_async::r#async(); // OK
// two_async::async(); // ERROR, reserved
two_async::r#async(); // OK
}
mod one_async {
produces_async! {} // OK
}
mod two_async {
produces_async_raw! {} // OK
}
fn main() {}

View file

@ -0,0 +1,43 @@
// 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.
// compile-flags: --edition=2018
// aux-build:edition-kw-macro-2018.rs
#![feature(raw_identifiers)]
#[macro_use]
extern crate edition_kw_macro_2018;
pub fn check_async() {
// let mut async = 1; // ERROR, reserved
let mut r#async = 1; // OK
r#async = consumes_async!(async); // OK
// r#async = consumes_async!(r#async); // ERROR, not a match
// r#async = consumes_async_raw!(async); // ERROR, not a match
r#async = consumes_async_raw!(r#async); // OK
// if passes_ident!(async) == 1 {} // ERROR, reserved
if passes_ident!(r#async) == 1 {} // OK
// one_async::async(); // ERROR, reserved
// one_async::r#async(); // ERROR, unresolved name
// two_async::async(); // ERROR, reserved
two_async::r#async(); // OK
}
mod one_async {
// produces_async! {} // ERROR, reserved
}
mod two_async {
produces_async_raw! {} // OK
}
fn main() {}

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.
// compile-flags: --edition=2015
#![feature(raw_identifiers)]
#[macro_export]
macro_rules! produces_async {
() => (pub fn async() {})
}
#[macro_export]
macro_rules! produces_async_raw {
() => (pub fn r#async() {})
}
#[macro_export]
macro_rules! consumes_async {
(async) => (1)
}
#[macro_export]
macro_rules! consumes_async_raw {
(r#async) => (1)
}
#[macro_export]
macro_rules! passes_ident {
($i: ident) => ($i)
}

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.
// compile-flags: --edition=2018
#![feature(raw_identifiers)]
#[macro_export]
macro_rules! produces_async {
() => (pub fn async() {})
}
#[macro_export]
macro_rules! produces_async_raw {
() => (pub fn r#async() {})
}
#[macro_export]
macro_rules! consumes_async {
(async) => (1)
}
#[macro_export]
macro_rules! consumes_async_raw {
(r#async) => (1)
}
#[macro_export]
macro_rules! passes_ident {
($i: ident) => ($i)
}

View file

@ -0,0 +1,27 @@
// 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.
// compile-flags: --edition=2015
// aux-build:edition-kw-macro-2015.rs
// compile-pass
#![feature(raw_identifiers)]
#[macro_use]
extern crate edition_kw_macro_2015;
mod one_async {
produces_async! {} // OK
}
mod two_async {
produces_async_raw! {} // OK
}
fn main() {}

View file

@ -0,0 +1,32 @@
// 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.
// compile-flags: --edition=2015
// aux-build:edition-kw-macro-2015.rs
#![feature(raw_identifiers)]
#[macro_use]
extern crate edition_kw_macro_2015;
pub fn check_async() {
let mut async = 1; // OK
let mut r#async = 1; // OK
r#async = consumes_async!(async); // OK
r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
r#async = consumes_async_raw!(r#async); // OK
if passes_ident!(async) == 1 {} // OK
if passes_ident!(r#async) == 1 {} // OK
module::async(); // OK
module::r#async(); // OK
}

View file

@ -0,0 +1,14 @@
error: no rules expected the token `r#async`
--> $DIR/edition-keywords-2015-2015-parsing.rs:24:31
|
LL | r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
| ^^^^^^^
error: no rules expected the token `async`
--> $DIR/edition-keywords-2015-2015-parsing.rs:25:35
|
LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
| ^^^^^
error: aborting due to 2 previous errors

View file

@ -0,0 +1,24 @@
// 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.
// compile-flags: --edition=2015
// aux-build:edition-kw-macro-2018.rs
#![feature(raw_identifiers)]
#[macro_use]
extern crate edition_kw_macro_2018;
mod one_async {
produces_async! {} // ERROR expected identifier, found reserved keyword
}
mod two_async {
produces_async_raw! {} // OK
}

View file

@ -0,0 +1,10 @@
error: expected identifier, found reserved keyword `async`
--> $DIR/edition-keywords-2015-2018-expansion.rs:20:5
|
LL | produces_async! {} // ERROR expected identifier, found reserved keyword
| ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to previous error

View file

@ -0,0 +1,32 @@
// 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.
// compile-flags: --edition=2015
// aux-build:edition-kw-macro-2018.rs
#![feature(raw_identifiers)]
#[macro_use]
extern crate edition_kw_macro_2018;
pub fn check_async() {
let mut async = 1; // OK
let mut r#async = 1; // OK
r#async = consumes_async!(async); // OK
r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
r#async = consumes_async_raw!(r#async); // OK
if passes_ident!(async) == 1 {} // OK
if passes_ident!(r#async) == 1 {} // OK
module::async(); // OK
module::r#async(); // OK
}

View file

@ -0,0 +1,14 @@
error: no rules expected the token `r#async`
--> $DIR/edition-keywords-2015-2018-parsing.rs:24:31
|
LL | r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
| ^^^^^^^
error: no rules expected the token `async`
--> $DIR/edition-keywords-2015-2018-parsing.rs:25:35
|
LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
| ^^^^^
error: aborting due to 2 previous errors

View file

@ -0,0 +1,27 @@
// 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.
// compile-flags: --edition=2018
// aux-build:edition-kw-macro-2015.rs
// compile-pass
#![feature(raw_identifiers)]
#[macro_use]
extern crate edition_kw_macro_2015;
mod one_async {
produces_async! {} // OK
}
mod two_async {
produces_async_raw! {} // OK
}
fn main() {}

View file

@ -0,0 +1,32 @@
// 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.
// compile-flags: --edition=2018
// aux-build:edition-kw-macro-2015.rs
#![feature(raw_identifiers)]
#[macro_use]
extern crate edition_kw_macro_2015;
pub fn check_async() {
let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async`
let mut r#async = 1; // OK
r#async = consumes_async!(async); // OK
r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
r#async = consumes_async_raw!(r#async); // OK
if passes_ident!(async) == 1 {} //~ ERROR expected expression, found reserved keyword `async`
if passes_ident!(r#async) == 1 {} // OK
module::async(); //~ ERROR expected identifier, found reserved keyword `async`
module::r#async(); // OK
}

View file

@ -0,0 +1,32 @@
error: expected identifier, found reserved keyword `async`
--> $DIR/edition-keywords-2018-2015-parsing.rs:20:13
|
LL | let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async`
| ^^^^^ expected identifier, found reserved keyword
error: expected identifier, found reserved keyword `async`
--> $DIR/edition-keywords-2018-2015-parsing.rs:30:13
|
LL | module::async(); //~ ERROR expected identifier, found reserved keyword `async`
| ^^^^^ expected identifier, found reserved keyword
error: no rules expected the token `r#async`
--> $DIR/edition-keywords-2018-2015-parsing.rs:24:31
|
LL | r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
| ^^^^^^^
error: no rules expected the token `async`
--> $DIR/edition-keywords-2018-2015-parsing.rs:25:35
|
LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
| ^^^^^
error: expected expression, found reserved keyword `async`
--> $DIR/edition-keywords-2018-2015-parsing.rs:28:22
|
LL | if passes_ident!(async) == 1 {} //~ ERROR expected expression, found reserved keyword `async`
| ^^^^^ expected expression
error: aborting due to 5 previous errors

View file

@ -0,0 +1,24 @@
// 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.
// compile-flags: --edition=2018
// aux-build:edition-kw-macro-2018.rs
#![feature(raw_identifiers)]
#[macro_use]
extern crate edition_kw_macro_2018;
mod one_async {
produces_async! {} // ERROR expected identifier, found reserved keyword `async`
}
mod two_async {
produces_async_raw! {} // OK
}

View file

@ -0,0 +1,10 @@
error: expected identifier, found reserved keyword `async`
--> $DIR/edition-keywords-2018-2018-expansion.rs:20:5
|
LL | produces_async! {} // ERROR expected identifier, found reserved keyword `async`
| ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to previous error

View file

@ -0,0 +1,32 @@
// 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.
// compile-flags: --edition=2018
// aux-build:edition-kw-macro-2018.rs
#![feature(raw_identifiers)]
#[macro_use]
extern crate edition_kw_macro_2018;
pub fn check_async() {
let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async`
let mut r#async = 1; // OK
r#async = consumes_async!(async); // OK
r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
r#async = consumes_async_raw!(r#async); // OK
if passes_ident!(async) == 1 {} //~ ERROR expected expression, found reserved keyword `async`
if passes_ident!(r#async) == 1 {} // OK
module::async(); //~ ERROR expected identifier, found reserved keyword `async`
module::r#async(); // OK
}

View file

@ -0,0 +1,32 @@
error: expected identifier, found reserved keyword `async`
--> $DIR/edition-keywords-2018-2018-parsing.rs:20:13
|
LL | let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async`
| ^^^^^ expected identifier, found reserved keyword
error: expected identifier, found reserved keyword `async`
--> $DIR/edition-keywords-2018-2018-parsing.rs:30:13
|
LL | module::async(); //~ ERROR expected identifier, found reserved keyword `async`
| ^^^^^ expected identifier, found reserved keyword
error: no rules expected the token `r#async`
--> $DIR/edition-keywords-2018-2018-parsing.rs:24:31
|
LL | r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
| ^^^^^^^
error: no rules expected the token `async`
--> $DIR/edition-keywords-2018-2018-parsing.rs:25:35
|
LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
| ^^^^^
error: expected expression, found reserved keyword `async`
--> $DIR/edition-keywords-2018-2018-parsing.rs:28:22
|
LL | if passes_ident!(async) == 1 {} //~ ERROR expected expression, found reserved keyword `async`
| ^^^^^ expected expression
error: aborting due to 5 previous errors