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:
commit
df40e61382
@ -818,7 +818,7 @@ impl 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;
|
||||
|
@ -593,6 +593,7 @@ impl<'a> LoweringContext<'a> {
|
||||
span: Some(span),
|
||||
allow_internal_unstable: true,
|
||||
allow_internal_unsafe: false,
|
||||
edition: codemap::hygiene::default_edition(),
|
||||
},
|
||||
});
|
||||
span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
|
||||
|
@ -13,7 +13,7 @@ pub use self::AnnNode::*;
|
||||
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 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
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())?;
|
||||
|
@ -131,6 +131,15 @@ impl_stable_hash_for!(struct ::syntax::attr::Stability {
|
||||
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 @@ impl_stable_hash_for!(struct ::syntax_pos::hygiene::NameAndSpan {
|
||||
format,
|
||||
allow_internal_unstable,
|
||||
allow_internal_unsafe,
|
||||
edition,
|
||||
span
|
||||
});
|
||||
|
||||
|
@ -34,6 +34,7 @@ use session::search_paths::PathKind;
|
||||
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 @@ impl CrateStore for DummyCrateStore {
|
||||
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") }
|
||||
|
@ -21,7 +21,7 @@ use syntax::ext::base::ExtCtxt;
|
||||
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 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
|
||||
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));
|
||||
|
@ -108,7 +108,7 @@ use syntax::ast;
|
||||
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)
|
||||
|
@ -35,6 +35,7 @@ use std::{cmp, fs};
|
||||
|
||||
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 @@ impl<'a> CrateLoader<'a> {
|
||||
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 @@ impl<'a> CrateLoader<'a> {
|
||||
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
|
||||
|
@ -24,6 +24,7 @@ use rustc::util::nodemap::{FxHashMap, NodeMap};
|
||||
|
||||
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 @@ impl CrateMetadata {
|
||||
pub fn panic_strategy(&self) -> PanicStrategy {
|
||||
self.root.panic_strategy.clone()
|
||||
}
|
||||
|
||||
pub fn edition(&self) -> Edition {
|
||||
self.root.edition
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ use std::sync::Arc;
|
||||
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 @@ impl CrateStore for cstore::CStore {
|
||||
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 @@ impl CrateStore for cstore::CStore {
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ use syntax::ast::{self, CRATE_NODE_ID};
|
||||
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 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
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
|
||||
|
@ -23,6 +23,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple};
|
||||
|
||||
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>,
|
||||
|
@ -21,7 +21,6 @@ use rustc::session::Session;
|
||||
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 @@ impl<'a> AstValidator<'a> {
|
||||
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));
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ use rustc::session::Session;
|
||||
|
||||
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 @@ impl<'a> Registry<'a> {
|
||||
def_info: _,
|
||||
allow_internal_unstable,
|
||||
allow_internal_unsafe,
|
||||
unstable_feature
|
||||
unstable_feature,
|
||||
edition,
|
||||
} => {
|
||||
let nid = ast::CRATE_NODE_ID;
|
||||
NormalTT {
|
||||
@ -115,7 +117,8 @@ impl<'a> Registry<'a> {
|
||||
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 @@ impl<'a> Registry<'a> {
|
||||
allow_internal_unstable: false,
|
||||
allow_internal_unsafe: false,
|
||||
unstable_feature: None,
|
||||
edition: hygiene::default_edition(),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -588,7 +588,8 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
|
||||
&self.session.features_untracked(),
|
||||
¯o_def));
|
||||
¯o_def,
|
||||
self.cstore.crate_edition_untracked(def_id.krate)));
|
||||
self.macro_map.insert(def_id, ext.clone());
|
||||
ext
|
||||
}
|
||||
|
@ -58,7 +58,6 @@ use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
// `$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() &&
|
||||
|
@ -24,7 +24,7 @@ use syntax::errors::DiagnosticBuilder;
|
||||
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 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
};
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
|
@ -27,7 +27,6 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
||||
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 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
} 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 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
}
|
||||
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();
|
||||
|
@ -107,8 +107,7 @@ impl 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;
|
||||
}
|
||||
}
|
||||
|
@ -14,9 +14,10 @@ use ast::{self, Attribute, Name, PatKind, MetaItem};
|
||||
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 @@ impl SyntaxExtension {
|
||||
_ => 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);
|
||||
|
@ -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(),
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -16,7 +16,7 @@ use config::{is_test_or_bench, StripUnconfigured};
|
||||
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 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
span: None,
|
||||
allow_internal_unstable: false,
|
||||
allow_internal_unsafe: false,
|
||||
edition: ext.edition(),
|
||||
}
|
||||
});
|
||||
|
||||
@ -520,7 +521,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
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 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
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 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
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 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
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 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
span: tt_span,
|
||||
allow_internal_unstable,
|
||||
allow_internal_unsafe: false,
|
||||
edition: hygiene::default_edition(),
|
||||
}
|
||||
});
|
||||
|
||||
@ -709,7 +716,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
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 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
// FIXME probably want to follow macro_rules macros here.
|
||||
allow_internal_unstable: false,
|
||||
allow_internal_unsafe: false,
|
||||
edition,
|
||||
},
|
||||
});
|
||||
|
||||
@ -802,11 +810,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 codemap;
|
||||
#[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 ptr;
|
||||
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;
|
||||
|
@ -1128,7 +1128,7 @@ impl<'a> StringReader<'a> {
|
||||
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)
|
||||
|
@ -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 @@ impl 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 @@ impl Token {
|
||||
|
||||
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 @@ impl Token {
|
||||
// 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 @@ impl Token {
|
||||
/// 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 @@ impl Token {
|
||||
/// 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 @@ impl Token {
|
||||
/// 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,
|
||||
}
|
||||
}
|
||||
|
@ -2374,7 +2374,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
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())?;
|
||||
|
@ -14,7 +14,7 @@ use std::cell::Cell;
|
||||
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))
|
||||
|
@ -29,7 +29,7 @@ use entry::{self, EntryPointType};
|
||||
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(),
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -54,6 +54,7 @@ pub mod proc_macro_impl;
|
||||
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 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
|
||||
allow_internal_unstable: false,
|
||||
allow_internal_unsafe: false,
|
||||
unstable_feature: None,
|
||||
edition: hygiene::default_edition(),
|
||||
});
|
||||
)* }
|
||||
}
|
||||
@ -128,7 +130,8 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
|
||||
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 {
|
||||
|
@ -14,7 +14,7 @@ use errors;
|
||||
|
||||
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::fmt;
|
||||
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
|
@ -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 @@ impl HygieneData {
|
||||
}],
|
||||
markings: HashMap::new(),
|
||||
gensym_to_ctxt: HashMap::new(),
|
||||
default_edition: Edition::Edition2015,
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,6 +179,14 @@ impl HygieneData {
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -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 serialize as rustc_serialize; // used by deriving
|
||||
|
||||
extern crate unicode_width;
|
||||
|
||||
pub mod edition;
|
||||
pub mod hygiene;
|
||||
pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan, CompilerDesugaringKind};
|
||||
|
||||
@ -298,6 +300,12 @@ impl 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,
|
||||
|
@ -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 @@ macro_rules! declare_keywords {(
|
||||
// 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 @@ declare_keywords! {
|
||||
(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 @@ 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(),
|
||||
});
|
||||
}
|
||||
|
38
src/test/run-pass/auxiliary/edition-kw-macro-2015.rs
Normal file
38
src/test/run-pass/auxiliary/edition-kw-macro-2015.rs
Normal 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)
|
||||
}
|
38
src/test/run-pass/auxiliary/edition-kw-macro-2018.rs
Normal file
38
src/test/run-pass/auxiliary/edition-kw-macro-2018.rs
Normal 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)
|
||||
}
|
43
src/test/run-pass/edition-keywords-2015-2015.rs
Normal file
43
src/test/run-pass/edition-keywords-2015-2015.rs
Normal 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() {}
|
43
src/test/run-pass/edition-keywords-2015-2018.rs
Normal file
43
src/test/run-pass/edition-keywords-2015-2018.rs
Normal 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() {}
|
43
src/test/run-pass/edition-keywords-2018-2015.rs
Normal file
43
src/test/run-pass/edition-keywords-2018-2015.rs
Normal 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() {}
|
43
src/test/run-pass/edition-keywords-2018-2018.rs
Normal file
43
src/test/run-pass/edition-keywords-2018-2018.rs
Normal 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() {}
|
38
src/test/ui/auxiliary/edition-kw-macro-2015.rs
Normal file
38
src/test/ui/auxiliary/edition-kw-macro-2015.rs
Normal 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)
|
||||
}
|
38
src/test/ui/auxiliary/edition-kw-macro-2018.rs
Normal file
38
src/test/ui/auxiliary/edition-kw-macro-2018.rs
Normal 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)
|
||||
}
|
27
src/test/ui/edition-keywords-2015-2015-expansion.rs
Normal file
27
src/test/ui/edition-keywords-2015-2015-expansion.rs
Normal 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() {}
|
32
src/test/ui/edition-keywords-2015-2015-parsing.rs
Normal file
32
src/test/ui/edition-keywords-2015-2015-parsing.rs
Normal 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
|
||||
}
|
14
src/test/ui/edition-keywords-2015-2015-parsing.stderr
Normal file
14
src/test/ui/edition-keywords-2015-2015-parsing.stderr
Normal 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
|
||||
|
24
src/test/ui/edition-keywords-2015-2018-expansion.rs
Normal file
24
src/test/ui/edition-keywords-2015-2018-expansion.rs
Normal 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
|
||||
}
|
10
src/test/ui/edition-keywords-2015-2018-expansion.stderr
Normal file
10
src/test/ui/edition-keywords-2015-2018-expansion.stderr
Normal 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
|
||||
|
32
src/test/ui/edition-keywords-2015-2018-parsing.rs
Normal file
32
src/test/ui/edition-keywords-2015-2018-parsing.rs
Normal 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
|
||||
}
|
14
src/test/ui/edition-keywords-2015-2018-parsing.stderr
Normal file
14
src/test/ui/edition-keywords-2015-2018-parsing.stderr
Normal 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
|
||||
|
27
src/test/ui/edition-keywords-2018-2015-expansion.rs
Normal file
27
src/test/ui/edition-keywords-2018-2015-expansion.rs
Normal 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() {}
|
32
src/test/ui/edition-keywords-2018-2015-parsing.rs
Normal file
32
src/test/ui/edition-keywords-2018-2015-parsing.rs
Normal 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
|
||||
}
|
32
src/test/ui/edition-keywords-2018-2015-parsing.stderr
Normal file
32
src/test/ui/edition-keywords-2018-2015-parsing.stderr
Normal 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
|
||||
|
24
src/test/ui/edition-keywords-2018-2018-expansion.rs
Normal file
24
src/test/ui/edition-keywords-2018-2018-expansion.rs
Normal 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
|
||||
}
|
10
src/test/ui/edition-keywords-2018-2018-expansion.stderr
Normal file
10
src/test/ui/edition-keywords-2018-2018-expansion.stderr
Normal 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
|
||||
|
32
src/test/ui/edition-keywords-2018-2018-parsing.rs
Normal file
32
src/test/ui/edition-keywords-2018-2018-parsing.rs
Normal 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
|
||||
}
|
32
src/test/ui/edition-keywords-2018-2018-parsing.stderr
Normal file
32
src/test/ui/edition-keywords-2018-2018-parsing.stderr
Normal 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
|
||||
|
Loading…
Reference in New Issue
Block a user