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
58 changed files with 896 additions and 119 deletions
+1 -1
View File
@@ -818,7 +818,7 @@ pub fn new(string: &str, span: Span) -> Ident {
pub fn new_raw(string: &str, span: Span) -> Ident {
let mut ident = Ident::new(string, span);
if ident.sym == keywords::Underscore.name() ||
token::is_path_segment_keyword(ast::Ident::with_empty_ctxt(ident.sym)) {
ast::Ident::with_empty_ctxt(ident.sym).is_path_segment_keyword() {
panic!("`{:?}` is not a valid raw identifier", string)
}
ident.is_raw = true;
+1
View File
@@ -593,6 +593,7 @@ fn allow_internal_unstable(&self, reason: CompilerDesugaringKind, span: Span) ->
span: Some(span),
allow_internal_unstable: true,
allow_internal_unsafe: false,
edition: codemap::hygiene::default_edition(),
},
});
span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
+2 -2
View File
@@ -13,7 +13,7 @@
use rustc_target::spec::abi::Abi;
use syntax::ast;
use syntax::codemap::{CodeMap, Spanned};
use syntax::parse::{token, ParseSess};
use syntax::parse::ParseSess;
use syntax::parse::lexer::comments;
use syntax::print::pp::{self, Breaks};
use syntax::print::pp::Breaks::{Consistent, Inconsistent};
@@ -1559,7 +1559,7 @@ pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
}
pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> {
if token::is_raw_guess(ast::Ident::with_empty_ctxt(name)) {
if name.to_ident().is_raw_guess() {
self.s.word(&format!("r#{}", name))?;
} else {
self.s.word(&name.as_str())?;
+10
View File
@@ -131,6 +131,15 @@ fn to_stable_hash_key(&self,
rustc_const_unstable
});
impl<'a> HashStable<StableHashingContext<'a>>
for ::syntax::edition::Edition {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
}
}
impl<'a> HashStable<StableHashingContext<'a>>
for ::syntax::attr::StabilityLevel {
fn hash_stable<W: StableHasherResult>(&self,
@@ -389,6 +398,7 @@ fn hash_token<'a, 'gcx, W: StableHasherResult>(
format,
allow_internal_unstable,
allow_internal_unsafe,
edition,
span
});
+3
View File
@@ -34,6 +34,7 @@
use std::any::Any;
use std::path::{Path, PathBuf};
use syntax::ast;
use syntax::edition::Edition;
use syntax::ext::base::SyntaxExtension;
use syntax::symbol::Symbol;
use syntax_pos::Span;
@@ -235,6 +236,7 @@ pub trait CrateStore {
fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;
fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition;
fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name>;
fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec<def::Export>;
fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro;
@@ -309,6 +311,7 @@ fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator {
bug!("crate_disambiguator")
}
fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh { bug!("crate_hash") }
fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition { bug!("crate_edition_untracked") }
// resolve
fn def_key(&self, def: DefId) -> DefKey { bug!("def_key") }
+2 -1
View File
@@ -21,7 +21,7 @@
use syntax::ext::base::Resolver;
use syntax::ext::build::AstBuilder;
use syntax::ext::expand::ExpansionConfig;
use syntax::ext::hygiene::{Mark, SyntaxContext};
use syntax::ext::hygiene::{self, Mark, SyntaxContext};
use syntax::fold::{self, Folder};
use syntax::parse::ParseSess;
use syntax::ptr::P;
@@ -86,6 +86,7 @@ fn fold_item(&mut self, item: P<Item>) -> SmallVector<P<Item>> {
span: None,
allow_internal_unstable: true,
allow_internal_unsafe: false,
edition: hygiene::default_edition(),
},
});
let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark));
+2 -1
View File
@@ -108,7 +108,7 @@
use syntax::codemap::{CodeMap, FileLoader, RealFileLoader};
use syntax::feature_gate::{GatedCfg, UnstableFeatures};
use syntax::parse::{self, PResult};
use syntax_pos::{DUMMY_SP, MultiSpan, FileName};
use syntax_pos::{hygiene, DUMMY_SP, MultiSpan, FileName};
#[cfg(test)]
mod test;
@@ -466,6 +466,7 @@ pub fn run_compiler<'a>(args: &[String],
};
let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
hygiene::set_default_edition(sopts.edition);
driver::spawn_thread_pool(sopts, |sopts| {
run_compiler_with_pool(matches, sopts, cfg, callbacks, file_loader, emitter_dest)
+15 -9
View File
@@ -35,6 +35,7 @@
use syntax::ast;
use syntax::attr;
use syntax::edition::Edition;
use syntax::ext::base::SyntaxExtension;
use syntax::symbol::Symbol;
use syntax::visit;
@@ -535,7 +536,10 @@ fn load_derive_macros(&mut self, root: &CrateRoot, dylib: Option<PathBuf>, span:
mem::transmute::<*mut u8, fn(&mut Registry)>(sym)
};
struct MyRegistrar(Vec<(ast::Name, Lrc<SyntaxExtension>)>);
struct MyRegistrar {
extensions: Vec<(ast::Name, Lrc<SyntaxExtension>)>,
edition: Edition,
}
impl Registry for MyRegistrar {
fn register_custom_derive(&mut self,
@@ -544,36 +548,38 @@ fn register_custom_derive(&mut self,
attributes: &[&'static str]) {
let attrs = attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
let derive = ProcMacroDerive::new(expand, attrs.clone());
let derive = SyntaxExtension::ProcMacroDerive(Box::new(derive), attrs);
self.0.push((Symbol::intern(trait_name), Lrc::new(derive)));
let derive = SyntaxExtension::ProcMacroDerive(
Box::new(derive), attrs, self.edition
);
self.extensions.push((Symbol::intern(trait_name), Lrc::new(derive)));
}
fn register_attr_proc_macro(&mut self,
name: &str,
expand: fn(TokenStream, TokenStream) -> TokenStream) {
let expand = SyntaxExtension::AttrProcMacro(
Box::new(AttrProcMacro { inner: expand })
Box::new(AttrProcMacro { inner: expand }), self.edition
);
self.0.push((Symbol::intern(name), Lrc::new(expand)));
self.extensions.push((Symbol::intern(name), Lrc::new(expand)));
}
fn register_bang_proc_macro(&mut self,
name: &str,
expand: fn(TokenStream) -> TokenStream) {
let expand = SyntaxExtension::ProcMacro(
Box::new(BangProcMacro { inner: expand })
Box::new(BangProcMacro { inner: expand }), self.edition
);
self.0.push((Symbol::intern(name), Lrc::new(expand)));
self.extensions.push((Symbol::intern(name), Lrc::new(expand)));
}
}
let mut my_registrar = MyRegistrar(Vec::new());
let mut my_registrar = MyRegistrar { extensions: Vec::new(), edition: root.edition };
registrar(&mut my_registrar);
// Intentionally leak the dynamic library. We can't ever unload it
// since the library can make things that will live arbitrarily long.
mem::forget(lib);
my_registrar.0
my_registrar.extensions
}
/// Look for a plugin registrar. Returns library path, crate
+5
View File
@@ -24,6 +24,7 @@
use rustc_data_structures::sync::{Lrc, RwLock, Lock};
use syntax::{ast, attr};
use syntax::edition::Edition;
use syntax::ext::base::SyntaxExtension;
use syntax::symbol::Symbol;
use syntax_pos;
@@ -234,4 +235,8 @@ pub fn is_no_builtins(&self, sess: &Session) -> bool {
pub fn panic_strategy(&self) -> PanicStrategy {
self.root.panic_strategy.clone()
}
pub fn edition(&self) -> Edition {
self.root.edition
}
}
+8 -1
View File
@@ -38,6 +38,7 @@
use syntax::ast;
use syntax::attr;
use syntax::codemap;
use syntax::edition::Edition;
use syntax::ext::base::SyntaxExtension;
use syntax::parse::filemap_to_stream;
use syntax::symbol::Symbol;
@@ -464,6 +465,11 @@ fn crate_hash_untracked(&self, cnum: CrateNum) -> hir::svh::Svh
self.get_crate_data(cnum).hash()
}
fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition
{
self.get_crate_data(cnum).edition()
}
/// Returns the `DefKey` for a given `DefId`. This indicates the
/// parent `DefId` as well as some idea of what kind of data the
/// `DefId` refers to.
@@ -512,7 +518,8 @@ fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone());
} else if data.name == "proc_macro" &&
self.get_crate_data(id.krate).item_name(id.index) == "quote" {
let ext = SyntaxExtension::ProcMacro(Box::new(::proc_macro::__internal::Quoter));
let ext = SyntaxExtension::ProcMacro(Box::new(::proc_macro::__internal::Quoter),
data.edition());
return LoadedMacro::ProcMacro(Lrc::new(ext));
}
+2 -1
View File
@@ -44,7 +44,7 @@
use syntax::codemap::Spanned;
use syntax::attr;
use syntax::symbol::Symbol;
use syntax_pos::{self, FileName, FileMap, Span, DUMMY_SP};
use syntax_pos::{self, hygiene, FileName, FileMap, Span, DUMMY_SP};
use rustc::hir::{self, PatKind};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
@@ -496,6 +496,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
hash: link_meta.crate_hash,
disambiguator: tcx.sess.local_crate_disambiguator(),
panic_strategy: tcx.sess.panic_strategy(),
edition: hygiene::default_edition(),
has_global_allocator: has_global_allocator,
has_default_lib_allocator: has_default_lib_allocator,
plugin_registrar_fn: tcx.sess
+2
View File
@@ -23,6 +23,7 @@
use rustc_serialize as serialize;
use syntax::{ast, attr};
use syntax::edition::Edition;
use syntax::symbol::Symbol;
use syntax_pos::{self, Span};
@@ -189,6 +190,7 @@ pub struct CrateRoot {
pub hash: hir::svh::Svh,
pub disambiguator: CrateDisambiguator,
pub panic_strategy: PanicStrategy,
pub edition: Edition,
pub has_global_allocator: bool,
pub has_default_lib_allocator: bool,
pub plugin_registrar_fn: Option<DefIndex>,
+2 -4
View File
@@ -21,7 +21,6 @@
use syntax::ast::*;
use syntax::attr;
use syntax::codemap::Spanned;
use syntax::parse::token;
use syntax::symbol::keywords;
use syntax::visit::{self, Visitor};
use syntax_pos::Span;
@@ -40,14 +39,13 @@ fn check_lifetime(&self, ident: Ident) {
let valid_names = [keywords::UnderscoreLifetime.name(),
keywords::StaticLifetime.name(),
keywords::Invalid.name()];
if !valid_names.contains(&ident.name) &&
token::is_reserved_ident(ident.without_first_quote()) {
if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names");
}
}
fn check_label(&self, ident: Ident) {
if token::is_reserved_ident(ident.without_first_quote()) {
if ident.without_first_quote().is_reserved() {
self.err_handler()
.span_err(ident.span, &format!("invalid label name `{}`", ident.name));
}
+6 -2
View File
@@ -15,6 +15,7 @@
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT, IdentTT};
use syntax::ext::base::MacroExpanderFn;
use syntax::ext::hygiene;
use syntax::symbol::Symbol;
use syntax::ast;
use syntax::feature_gate::AttributeType;
@@ -107,7 +108,8 @@ pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxEx
def_info: _,
allow_internal_unstable,
allow_internal_unsafe,
unstable_feature
unstable_feature,
edition,
} => {
let nid = ast::CRATE_NODE_ID;
NormalTT {
@@ -115,7 +117,8 @@ pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxEx
def_info: Some((nid, self.krate_span)),
allow_internal_unstable,
allow_internal_unsafe,
unstable_feature
unstable_feature,
edition,
}
}
IdentTT(ext, _, allow_internal_unstable) => {
@@ -150,6 +153,7 @@ pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) {
allow_internal_unstable: false,
allow_internal_unsafe: false,
unstable_feature: None,
edition: hygiene::default_edition(),
});
}
+2 -1
View File
@@ -588,7 +588,8 @@ pub fn get_macro(&mut self, def: Def) -> Lrc<SyntaxExtension> {
let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
&self.session.features_untracked(),
&macro_def));
&macro_def,
self.cstore.crate_edition_untracked(def_id.krate)));
self.macro_map.insert(def_id, ext.clone());
ext
}
+1 -2
View File
@@ -58,7 +58,6 @@
use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path};
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
use syntax::feature_gate::{feature_err, GateIssue};
use syntax::parse::token;
use syntax::ptr::P;
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
@@ -3274,7 +3273,7 @@ fn resolve_path(&mut self,
// `$crate::a::b`
module = Some(self.resolve_crate_root(ident.span.ctxt(), true));
continue
} else if i == 1 && !token::is_path_segment_keyword(ident) {
} else if i == 1 && !ident.is_path_segment_keyword() {
let prev_name = path[0].name;
if prev_name == keywords::Extern.name() ||
prev_name == keywords::CrateRoot.name() &&
+9 -8
View File
@@ -24,7 +24,7 @@
use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator};
use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
use syntax::ext::expand::{Expansion, ExpansionKind, Invocation, InvocationKind, find_attr_invoc};
use syntax::ext::hygiene::{Mark, MarkKind};
use syntax::ext::hygiene::{self, Mark, MarkKind};
use syntax::ext::placeholders::placeholder;
use syntax::ext::tt::macro_rules;
use syntax::feature_gate::{self, emit_feature_err, GateIssue};
@@ -328,7 +328,7 @@ fn check_unused_macros(&self) {
for did in self.unused_macros.iter() {
let id_span = match *self.macro_map[did] {
SyntaxExtension::NormalTT { def_info, .. } => def_info,
SyntaxExtension::DeclMacro(.., osp) => osp,
SyntaxExtension::DeclMacro(.., osp, _) => osp,
_ => None,
};
if let Some((id, span)) = id_span {
@@ -371,7 +371,7 @@ fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: b
};
for path in traits {
match self.resolve_macro(scope, path, MacroKind::Derive, force) {
Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs) = *ext {
Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs, _) = *ext {
if inert_attrs.contains(&attr_name) {
// FIXME(jseyfried) Avoid `mem::replace` here.
let dummy_item = placeholder(ExpansionKind::Items, ast::DUMMY_NODE_ID)
@@ -755,7 +755,7 @@ pub fn define_macro(&mut self,
let def_id = self.definitions.local_def_id(item.id);
let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
&self.session.features_untracked(),
item));
item, hygiene::default_edition()));
self.macro_map.insert(def_id, ext);
let def = match item.node { ast::ItemKind::MacroDef(ref def) => def, _ => unreachable!() };
@@ -803,14 +803,15 @@ fn err_if_macro_use_proc_macro(&mut self, name: Name, use_span: Span,
match *ext {
// If `ext` is a procedural macro, check if we've already warned about it
AttrProcMacro(_) | ProcMacro(_) => if !self.warned_proc_macros.insert(name) { return; },
AttrProcMacro(..) | ProcMacro(..) =>
if !self.warned_proc_macros.insert(name) { return; },
_ => return,
}
let warn_msg = match *ext {
AttrProcMacro(_) => "attribute procedural macros cannot be \
imported with `#[macro_use]`",
ProcMacro(_) => "procedural macros cannot be imported with `#[macro_use]`",
AttrProcMacro(..) => "attribute procedural macros cannot be \
imported with `#[macro_use]`",
ProcMacro(..) => "procedural macros cannot be imported with `#[macro_use]`",
_ => return,
};
+3 -4
View File
@@ -27,7 +27,6 @@
use syntax::ast::{Ident, Name, NodeId};
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
use syntax::ext::hygiene::Mark;
use syntax::parse::token;
use syntax::symbol::keywords;
use syntax::util::lev_distance::find_best_match_for_name;
use syntax_pos::Span;
@@ -667,7 +666,7 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
} else {
Some(self.resolve_crate_root(source.span.ctxt().modern(), false))
}
} else if is_extern && !token::is_path_segment_keyword(source) {
} else if is_extern && !source.is_path_segment_keyword() {
let crate_id =
self.resolver.crate_loader.process_use_extern(
source.name,
@@ -715,8 +714,8 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
}
PathResult::Failed(span, msg, true) => {
let (mut self_path, mut self_result) = (module_path.clone(), None);
let is_special = |ident| token::is_path_segment_keyword(ident) &&
ident.name != keywords::CrateRoot.name();
let is_special = |ident: Ident| ident.is_path_segment_keyword() &&
ident.name != keywords::CrateRoot.name();
if !self_path.is_empty() && !is_special(self_path[0]) &&
!(self_path.len() > 1 && is_special(self_path[1])) {
self_path[0].name = keywords::SelfValue.name();
+1 -2
View File
@@ -107,8 +107,7 @@ pub fn from_ident(ident: Ident) -> Path {
// or starts with something like `self`/`super`/`$crate`/etc.
pub fn make_root(&self) -> Option<PathSegment> {
if let Some(ident) = self.segments.get(0).map(|seg| seg.ident) {
if ::parse::token::is_path_segment_keyword(ident) &&
ident.name != keywords::Crate.name() {
if ident.is_path_segment_keyword() && ident.name != keywords::Crate.name() {
return None;
}
}
+24 -7
View File
@@ -14,9 +14,10 @@
use attr::HasAttrs;
use codemap::{self, CodeMap, Spanned, respan};
use syntax_pos::{Span, MultiSpan, DUMMY_SP};
use edition::Edition;
use errors::{DiagnosticBuilder, DiagnosticId};
use ext::expand::{self, Expansion, Invocation};
use ext::hygiene::{Mark, SyntaxContext};
use ext::hygiene::{self, Mark, SyntaxContext};
use fold::{self, Folder};
use parse::{self, parser, DirectoryOwnership};
use parse::token;
@@ -586,13 +587,13 @@ pub enum SyntaxExtension {
MultiModifier(Box<MultiItemModifier + sync::Sync + sync::Send>),
/// A function-like procedural macro. TokenStream -> TokenStream.
ProcMacro(Box<ProcMacro + sync::Sync + sync::Send>),
ProcMacro(Box<ProcMacro + sync::Sync + sync::Send>, Edition),
/// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
/// The first TokenSteam is the attribute, the second is the annotated item.
/// Allows modification of the input items and adding new items, similar to
/// MultiModifier, but uses TokenStreams, rather than AST nodes.
AttrProcMacro(Box<AttrProcMacro + sync::Sync + sync::Send>),
AttrProcMacro(Box<AttrProcMacro + sync::Sync + sync::Send>, Edition),
/// A normal, function-like syntax extension.
///
@@ -608,6 +609,8 @@ pub enum SyntaxExtension {
allow_internal_unsafe: bool,
/// The macro's feature name if it is unstable, and the stability feature
unstable_feature: Option<(Symbol, u32)>,
/// Edition of the crate in which the macro is defined
edition: Edition,
},
/// A function-like syntax extension that has an extra ident before
@@ -619,9 +622,8 @@ pub enum SyntaxExtension {
/// The input is the annotated item.
/// Allows generating code to implement a Trait for a given struct
/// or enum item.
ProcMacroDerive(Box<MultiItemModifier +
sync::Sync +
sync::Send>, Vec<Symbol> /* inert attribute names */),
ProcMacroDerive(Box<MultiItemModifier + sync::Sync + sync::Send>,
Vec<Symbol> /* inert attribute names */, Edition),
/// An attribute-like procedural macro that derives a builtin trait.
BuiltinDerive(BuiltinDeriveFn),
@@ -629,7 +631,7 @@ pub enum SyntaxExtension {
/// A declarative macro, e.g. `macro m() {}`.
///
/// The second element is the definition site span.
DeclMacro(Box<TTMacroExpander + sync::Sync + sync::Send>, Option<(ast::NodeId, Span)>),
DeclMacro(Box<TTMacroExpander + sync::Sync + sync::Send>, Option<(ast::NodeId, Span)>, Edition),
}
impl SyntaxExtension {
@@ -660,6 +662,21 @@ pub fn is_modern(&self) -> bool {
_ => false,
}
}
pub fn edition(&self) -> Edition {
match *self {
SyntaxExtension::NormalTT { edition, .. } |
SyntaxExtension::DeclMacro(.., edition) |
SyntaxExtension::ProcMacro(.., edition) |
SyntaxExtension::AttrProcMacro(.., edition) |
SyntaxExtension::ProcMacroDerive(.., edition) => edition,
// Unstable legacy stuff
SyntaxExtension::IdentTT(..) |
SyntaxExtension::MultiDecorator(..) |
SyntaxExtension::MultiModifier(..) |
SyntaxExtension::BuiltinDerive(..) => hygiene::default_edition(),
}
}
}
pub type NamedSyntaxExtension = (Name, SyntaxExtension);
+2 -1
View File
@@ -10,7 +10,7 @@
use attr::HasAttrs;
use ast;
use codemap::{ExpnInfo, NameAndSpan, ExpnFormat};
use codemap::{hygiene, ExpnInfo, NameAndSpan, ExpnFormat};
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use parse::parser::PathStyle;
@@ -65,6 +65,7 @@ pub fn add_derived_markers<T>(cx: &mut ExtCtxt, span: Span, traits: &[ast::Path]
span: None,
allow_internal_unstable: true,
allow_internal_unsafe: false,
edition: hygiene::default_edition(),
},
});
+17 -8
View File
@@ -16,7 +16,7 @@
use errors::FatalError;
use ext::base::*;
use ext::derive::{add_derived_markers, collect_derives};
use ext::hygiene::{Mark, SyntaxContext};
use ext::hygiene::{self, Mark, SyntaxContext};
use ext::placeholders::{placeholder, PlaceholderExpander};
use feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
use fold;
@@ -502,6 +502,7 @@ fn expand_attr_invoc(&mut self,
span: None,
allow_internal_unstable: false,
allow_internal_unsafe: false,
edition: ext.edition(),
}
});
@@ -520,7 +521,7 @@ fn expand_attr_invoc(&mut self,
items.push(item);
Some(kind.expect_from_annotatables(items))
}
AttrProcMacro(ref mac) => {
AttrProcMacro(ref mac, ..) => {
self.gate_proc_macro_attr_item(attr.span, &item);
let item_tok = TokenTree::Token(DUMMY_SP, Token::interpolated(match item {
Annotatable::Item(item) => token::NtItem(item),
@@ -609,7 +610,8 @@ fn expand_bang_invoc(&mut self,
allow_internal_unstable,
allow_internal_unsafe,
// can't infer this type
unstable_feature: Option<(Symbol, u32)>| {
unstable_feature: Option<(Symbol, u32)>,
edition| {
// feature-gate the macro invocation
if let Some((feature, issue)) = unstable_feature {
@@ -642,15 +644,17 @@ fn expand_bang_invoc(&mut self,
span: def_site_span,
allow_internal_unstable,
allow_internal_unsafe,
edition,
},
});
Ok(())
};
let opt_expanded = match *ext {
DeclMacro(ref expand, def_span) => {
DeclMacro(ref expand, def_span, edition) => {
if let Err(dummy_span) = validate_and_set_expn_info(self, def_span.map(|(_, s)| s),
false, false, None) {
false, false, None,
edition) {
dummy_span
} else {
kind.make_from(expand.expand(self.cx, span, mac.node.stream()))
@@ -663,11 +667,13 @@ fn expand_bang_invoc(&mut self,
allow_internal_unstable,
allow_internal_unsafe,
unstable_feature,
edition,
} => {
if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
allow_internal_unstable,
allow_internal_unsafe,
unstable_feature) {
unstable_feature,
edition) {
dummy_span
} else {
kind.make_from(expander.expand(self.cx, span, mac.node.stream()))
@@ -688,6 +694,7 @@ fn expand_bang_invoc(&mut self,
span: tt_span,
allow_internal_unstable,
allow_internal_unsafe: false,
edition: hygiene::default_edition(),
}
});
@@ -709,7 +716,7 @@ fn expand_bang_invoc(&mut self,
kind.dummy(span)
}
ProcMacro(ref expandfun) => {
ProcMacro(ref expandfun, edition) => {
if ident.name != keywords::Invalid.name() {
let msg =
format!("macro {}! expects no ident argument, given '{}'", path, ident);
@@ -728,6 +735,7 @@ fn expand_bang_invoc(&mut self,
// FIXME probably want to follow macro_rules macros here.
allow_internal_unstable: false,
allow_internal_unsafe: false,
edition,
},
});
@@ -802,11 +810,12 @@ fn expand_derive_invoc(&mut self,
span: None,
allow_internal_unstable: false,
allow_internal_unsafe: false,
edition: ext.edition(),
}
};
match *ext {
ProcMacroDerive(ref ext, _) => {
ProcMacroDerive(ref ext, ..) => {
invoc.expansion_data.mark.set_expn_info(expn_info);
let span = span.with_ctxt(self.cx.backtrace());
let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
+6 -3
View File
@@ -10,6 +10,7 @@
use {ast, attr};
use syntax_pos::{Span, DUMMY_SP};
use edition::Edition;
use ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension};
use ext::base::{NormalTT, TTMacroExpander};
use ext::expand::{Expansion, ExpansionKind};
@@ -183,7 +184,8 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt,
// Holy self-referential!
/// Converts a `macro_rules!` invocation into a syntax extension.
pub fn compile(sess: &ParseSess, features: &Features, def: &ast::Item) -> SyntaxExtension {
pub fn compile(sess: &ParseSess, features: &Features, def: &ast::Item, edition: Edition)
-> SyntaxExtension {
let lhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("lhs"));
let rhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("rhs"));
@@ -298,10 +300,11 @@ pub fn compile(sess: &ParseSess, features: &Features, def: &ast::Item) -> Syntax
def_info: Some((def.id, def.span)),
allow_internal_unstable,
allow_internal_unsafe,
unstable_feature
unstable_feature,
edition,
}
} else {
SyntaxExtension::DeclMacro(expander, Some((def.id, def.span)))
SyntaxExtension::DeclMacro(expander, Some((def.id, def.span)), edition)
}
}
+1 -2
View File
@@ -22,7 +22,6 @@
#![feature(unicode_internals)]
#![feature(rustc_diagnostic_macros)]
#![feature(slice_sort_by_cached_key)]
#![feature(non_exhaustive)]
#![feature(const_atomic_usize_new)]
#![feature(rustc_attrs)]
#![feature(str_escape)]
@@ -142,7 +141,6 @@ pub mod syntax {
#[macro_use]
pub mod config;
pub mod entry;
pub mod edition;
pub mod feature_gate;
pub mod fold;
pub mod parse;
@@ -150,6 +148,7 @@ pub mod syntax {
pub mod show_span;
pub mod std_inject;
pub mod str;
pub use syntax_pos::edition;
pub use syntax_pos::symbol;
pub mod test;
pub mod tokenstream;
+1 -1
View File
@@ -1128,7 +1128,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
return Ok(self.with_str_from(start, |string| {
// FIXME: perform NFKC normalization here. (Issue #2253)
let ident = self.mk_ident(string);
if is_raw_ident && (token::is_path_segment_keyword(ident) ||
if is_raw_ident && (ident.is_path_segment_keyword() ||
ident.name == keywords::Underscore.name()) {
self.fatal_span_(raw_start, self.pos,
&format!("`r#{}` is not currently supported.", ident.name)
+6 -44
View File
@@ -138,44 +138,6 @@ fn ident_can_begin_type(ident: ast::Ident, is_raw: bool) -> bool {
].contains(&ident.name)
}
pub fn is_path_segment_keyword(id: ast::Ident) -> bool {
id.name == keywords::Super.name() ||
id.name == keywords::SelfValue.name() ||
id.name == keywords::SelfType.name() ||
id.name == keywords::Extern.name() ||
id.name == keywords::Crate.name() ||
id.name == keywords::CrateRoot.name() ||
id.name == keywords::DollarCrate.name()
}
// We see this identifier in a normal identifier position, like variable name or a type.
// How was it written originally? Did it use the raw form? Let's try to guess.
pub fn is_raw_guess(ident: ast::Ident) -> bool {
ident.name != keywords::Invalid.name() &&
is_reserved_ident(ident) && !is_path_segment_keyword(ident)
}
// Returns true for reserved identifiers used internally for elided lifetimes,
// unnamed method parameters, crate root module, error recovery etc.
pub fn is_special_ident(id: ast::Ident) -> bool {
id.name <= keywords::Underscore.name()
}
/// Returns `true` if the token is a keyword used in the language.
pub fn is_used_keyword(id: ast::Ident) -> bool {
id.name >= keywords::As.name() && id.name <= keywords::While.name()
}
/// Returns `true` if the token is a keyword reserved for possible future use.
pub fn is_unused_keyword(id: ast::Ident) -> bool {
id.name >= keywords::Abstract.name() && id.name <= keywords::Yield.name()
}
/// Returns `true` if the token is either a special identifier or a keyword.
pub fn is_reserved_ident(id: ast::Ident) -> bool {
is_special_ident(id) || is_used_keyword(id) || is_unused_keyword(id)
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug)]
pub enum Token {
/* Expression-operator symbols. */
@@ -251,7 +213,7 @@ pub fn interpolated(nt: Nonterminal) -> Token {
/// Recovers a `Token` from an `ast::Ident`. This creates a raw identifier if necessary.
pub fn from_ast_ident(ident: ast::Ident) -> Token {
Ident(ident, is_raw_guess(ident))
Ident(ident, ident.is_raw_guess())
}
/// Returns `true` if the token starts with '>'.
@@ -431,7 +393,7 @@ pub fn is_keyword(&self, kw: keywords::Keyword) -> bool {
pub fn is_path_segment_keyword(&self) -> bool {
match self.ident() {
Some((id, false)) => is_path_segment_keyword(id),
Some((id, false)) => id.is_path_segment_keyword(),
_ => false,
}
}
@@ -440,7 +402,7 @@ pub fn is_path_segment_keyword(&self) -> bool {
// unnamed method parameters, crate root module, error recovery etc.
pub fn is_special_ident(&self) -> bool {
match self.ident() {
Some((id, false)) => is_special_ident(id),
Some((id, false)) => id.is_special(),
_ => false,
}
}
@@ -448,7 +410,7 @@ pub fn is_special_ident(&self) -> bool {
/// Returns `true` if the token is a keyword used in the language.
pub fn is_used_keyword(&self) -> bool {
match self.ident() {
Some((id, false)) => is_used_keyword(id),
Some((id, false)) => id.is_used_keyword(),
_ => false,
}
}
@@ -456,7 +418,7 @@ pub fn is_used_keyword(&self) -> bool {
/// Returns `true` if the token is a keyword reserved for possible future use.
pub fn is_unused_keyword(&self) -> bool {
match self.ident() {
Some((id, false)) => is_unused_keyword(id),
Some((id, false)) => id.is_unused_keyword(),
_ => false,
}
}
@@ -464,7 +426,7 @@ pub fn is_unused_keyword(&self) -> bool {
/// Returns `true` if the token is either a special identifier or a keyword.
pub fn is_reserved_ident(&self) -> bool {
match self.ident() {
Some((id, false)) => is_reserved_ident(id),
Some((id, false)) => id.is_reserved(),
_ => false,
}
}
+1 -1
View File
@@ -2374,7 +2374,7 @@ pub fn print_local_decl(&mut self, loc: &ast::Local) -> io::Result<()> {
}
pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
if token::is_raw_guess(ident) {
if ident.is_raw_guess() {
self.s.word(&format!("r#{}", ident))?;
} else {
self.s.word(&ident.name.as_str())?;
+2 -1
View File
@@ -14,7 +14,7 @@
use ext::hygiene::{Mark, SyntaxContext};
use symbol::{Symbol, keywords};
use syntax_pos::{DUMMY_SP, Span};
use codemap::{ExpnInfo, NameAndSpan, MacroAttribute, dummy_spanned, respan};
use codemap::{ExpnInfo, NameAndSpan, MacroAttribute, dummy_spanned, hygiene, respan};
use ptr::P;
use tokenstream::TokenStream;
@@ -30,6 +30,7 @@ fn ignored_span(sp: Span) -> Span {
span: None,
allow_internal_unstable: true,
allow_internal_unsafe: false,
edition: hygiene::default_edition(),
}
});
sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))
+2 -1
View File
@@ -29,7 +29,7 @@
use ext::base::{ExtCtxt, Resolver};
use ext::build::AstBuilder;
use ext::expand::ExpansionConfig;
use ext::hygiene::{Mark, SyntaxContext};
use ext::hygiene::{self, Mark, SyntaxContext};
use fold::Folder;
use feature_gate::Features;
use util::move_map::MoveMap;
@@ -300,6 +300,7 @@ fn generate_test_harness(sess: &ParseSess,
span: None,
allow_internal_unstable: true,
allow_internal_unsafe: false,
edition: hygiene::default_edition(),
}
});
+4 -1
View File
@@ -54,6 +54,7 @@
use rustc_data_structures::sync::Lrc;
use syntax::ast;
use syntax::ext::base::{MacroExpanderFn, NormalTT, NamedSyntaxExtension};
use syntax::ext::hygiene;
use syntax::symbol::Symbol;
pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
@@ -74,6 +75,7 @@ macro_rules! register {
allow_internal_unstable: false,
allow_internal_unsafe: false,
unstable_feature: None,
edition: hygiene::default_edition(),
});
)* }
}
@@ -128,7 +130,8 @@ macro_rules! register {
def_info: None,
allow_internal_unstable: true,
allow_internal_unsafe: false,
unstable_feature: None
unstable_feature: None,
edition: hygiene::default_edition(),
});
for (name, ext) in user_exts {
+2 -1
View File
@@ -14,7 +14,7 @@
use syntax::ast::{self, Ident, NodeId};
use syntax::attr;
use syntax::codemap::{ExpnInfo, NameAndSpan, MacroAttribute, respan};
use syntax::codemap::{ExpnInfo, NameAndSpan, MacroAttribute, hygiene, respan};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ext::expand::ExpansionConfig;
@@ -369,6 +369,7 @@ fn mk_registrar(cx: &mut ExtCtxt,
span: None,
allow_internal_unstable: true,
allow_internal_unsafe: false,
edition: hygiene::default_edition(),
}
});
let span = DUMMY_SP.apply_mark(mark);
@@ -12,7 +12,7 @@
use std::str::FromStr;
/// The edition of the compiler (RFC 2052)
#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq, Debug)]
#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq, Debug, RustcEncodable, RustcDecodable)]
#[non_exhaustive]
pub enum Edition {
// editions must be kept in order, newest to oldest
+13
View File
@@ -17,6 +17,7 @@
use GLOBALS;
use Span;
use edition::Edition;
use symbol::{Ident, Symbol};
use serialize::{Encodable, Decodable, Encoder, Decoder};
@@ -151,6 +152,7 @@ pub struct HygieneData {
syntax_contexts: Vec<SyntaxContextData>,
markings: HashMap<(SyntaxContext, Mark), SyntaxContext>,
gensym_to_ctxt: HashMap<Symbol, Span>,
default_edition: Edition,
}
impl HygieneData {
@@ -168,6 +170,7 @@ pub fn new() -> Self {
}],
markings: HashMap::new(),
gensym_to_ctxt: HashMap::new(),
default_edition: Edition::Edition2015,
}
}
@@ -176,6 +179,14 @@ fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
}
}
pub fn default_edition() -> Edition {
HygieneData::with(|data| data.default_edition)
}
pub fn set_default_edition(edition: Edition) {
HygieneData::with(|data| data.default_edition = edition);
}
pub fn clear_markings() {
HygieneData::with(|data| data.markings = HashMap::new());
}
@@ -443,6 +454,8 @@ pub struct NameAndSpan {
/// Whether the macro is allowed to use `unsafe` internally
/// even if the user crate has `#![forbid(unsafe_code)]`.
pub allow_internal_unsafe: bool,
/// Edition of the crate in which the macro is defined.
pub edition: Edition,
/// The span of the macro definition itself. The macro may not
/// have a sensible definition span (e.g. something defined
/// completely inside libsyntax) in which case this is None.
+8
View File
@@ -20,6 +20,7 @@
#![feature(const_fn)]
#![feature(custom_attribute)]
#![feature(non_exhaustive)]
#![feature(optin_builtin_traits)]
#![allow(unused_attributes)]
#![feature(specialization)]
@@ -48,6 +49,7 @@
extern crate unicode_width;
pub mod edition;
pub mod hygiene;
pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan, CompilerDesugaringKind};
@@ -298,6 +300,12 @@ pub fn parent(self) -> Option<Span> {
self.ctxt().outer().expn_info().map(|i| i.call_site)
}
/// Edition of the crate from which this span came.
pub fn edition(self) -> edition::Edition {
self.ctxt().outer().expn_info().map_or_else(|| hygiene::default_edition(),
|einfo| einfo.callee.edition)
}
/// Return the source callee.
///
/// Returns None if the supplied span has no expansion trace,
+61 -8
View File
@@ -12,6 +12,7 @@
//! allows bidirectional lookup; i.e. given a value, one can easily find the
//! type, and vice versa.
use edition::Edition;
use hygiene::SyntaxContext;
use {Span, DUMMY_SP, GLOBALS};
@@ -318,7 +319,7 @@ pub fn fresh() -> Self {
// NB: leaving holes in the ident table is bad! a different ident will get
// interned with the id from the hole, but it will be between the min and max
// of the reserved words, and thus tagged as "reserved".
// After modifying this list adjust `is_special_ident`, `is_used_keyword`/`is_unused_keyword`,
// After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`,
// this should be rarely necessary though if the keywords are kept in alphabetic order.
declare_keywords! {
// Special reserved identifiers used internally for elided lifetimes,
@@ -383,16 +384,68 @@ pub fn fresh() -> Self {
(53, Virtual, "virtual")
(54, Yield, "yield")
// Edition-specific keywords reserved for future use.
(55, Async, "async") // >= 2018 Edition Only
// Special lifetime names
(55, UnderscoreLifetime, "'_")
(56, StaticLifetime, "'static")
(56, UnderscoreLifetime, "'_")
(57, StaticLifetime, "'static")
// Weak keywords, have special meaning only in specific contexts.
(57, Auto, "auto")
(58, Catch, "catch")
(59, Default, "default")
(60, Dyn, "dyn")
(61, Union, "union")
(58, Auto, "auto")
(59, Catch, "catch")
(60, Default, "default")
(61, Dyn, "dyn")
(62, Union, "union")
}
impl Symbol {
fn is_unused_keyword_2018(self) -> bool {
self == keywords::Async.name()
}
}
impl Ident {
// Returns true for reserved identifiers used internally for elided lifetimes,
// unnamed method parameters, crate root module, error recovery etc.
pub fn is_special(self) -> bool {
self.name <= keywords::Underscore.name()
}
/// Returns `true` if the token is a keyword used in the language.
pub fn is_used_keyword(self) -> bool {
self.name >= keywords::As.name() && self.name <= keywords::While.name()
}
/// Returns `true` if the token is a keyword reserved for possible future use.
pub fn is_unused_keyword(self) -> bool {
// Note: `span.edition()` is relatively expensive, don't call it unless necessary.
self.name >= keywords::Abstract.name() && self.name <= keywords::Yield.name() ||
self.name.is_unused_keyword_2018() && self.span.edition() == Edition::Edition2018
}
/// Returns `true` if the token is either a special identifier or a keyword.
pub fn is_reserved(self) -> bool {
self.is_special() || self.is_used_keyword() || self.is_unused_keyword()
}
/// A keyword or reserved identifier that can be used as a path segment.
pub fn is_path_segment_keyword(self) -> bool {
self.name == keywords::Super.name() ||
self.name == keywords::SelfValue.name() ||
self.name == keywords::SelfType.name() ||
self.name == keywords::Extern.name() ||
self.name == keywords::Crate.name() ||
self.name == keywords::CrateRoot.name() ||
self.name == keywords::DollarCrate.name()
}
// We see this identifier in a normal identifier position, like variable name or a type.
// How was it written originally? Did it use the raw form? Let's try to guess.
pub fn is_raw_guess(self) -> bool {
self.name != keywords::Invalid.name() &&
self.is_reserved() && !self.is_path_segment_keyword()
}
}
// If an interner exists, return it. Otherwise, prepare a fresh one.
@@ -20,6 +20,7 @@
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(),
});
}
@@ -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)
}
@@ -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)
}
@@ -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() {}
@@ -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() {}
@@ -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() {}
@@ -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() {}
@@ -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)
}
@@ -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)
}
@@ -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() {}
@@ -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
}
@@ -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
@@ -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
}
@@ -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
@@ -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
}
@@ -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
@@ -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() {}
@@ -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
}
@@ -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
@@ -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
}
@@ -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
@@ -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
}
@@ -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