Pound => op!('#'),
Dollar => op!('$'),
Question => op!('?'),
- Underscore => op!('_'),
Ident(ident) | Lifetime(ident) => TokenNode::Term(Term(ident.name)),
Literal(..) | DocComment(..) => TokenNode::Literal(self::Literal(token)),
'#' => Pound,
'$' => Dollar,
'?' => Question,
- '_' => Underscore,
_ => panic!("unsupported character {}", op),
};
use self::LifetimeName::*;
match *self {
Implicit => keywords::Invalid.name(),
- Underscore => Symbol::intern("'_"),
+ Underscore => keywords::UnderscoreLifetime.name(),
Static => keywords::StaticLifetime.name(),
Name(name) => name,
}
token::Token::Pound |
token::Token::Dollar |
token::Token::Question |
- token::Token::Underscore |
token::Token::Whitespace |
token::Token::Comment |
token::Token::Eof => {}
use locator::{self, CratePaths};
use native_libs::relevant_lib;
use schema::CrateRoot;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, RwLock, Lock};
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX};
use rustc::hir::svh::Svh;
use rustc::util::nodemap::FxHashSet;
use rustc::hir::map::Definitions;
-use std::cell::{RefCell, Cell};
use std::ops::Deref;
use std::path::PathBuf;
use std::{cmp, fs};
info!(" name: {}", data.name());
info!(" cnum: {}", data.cnum);
info!(" hash: {}", data.hash());
- info!(" reqd: {:?}", data.dep_kind.get());
+ info!(" reqd: {:?}", *data.dep_kind.lock());
let CrateSource { dylib, rlib, rmeta } = data.source.clone();
dylib.map(|dl| info!(" dylib: {}", dl.0.display()));
rlib.map(|rl| info!(" rlib: {}", rl.0.display()));
let mut cmeta = cstore::CrateMetadata {
name,
- extern_crate: Cell::new(None),
+ extern_crate: Lock::new(None),
def_path_table: Lrc::new(def_path_table),
trait_impls,
proc_macros: crate_root.macro_derive_registrar.map(|_| {
}),
root: crate_root,
blob: metadata,
- cnum_map: RefCell::new(cnum_map),
+ cnum_map: Lock::new(cnum_map),
cnum,
- codemap_import_info: RefCell::new(vec![]),
- attribute_cache: RefCell::new([Vec::new(), Vec::new()]),
- dep_kind: Cell::new(dep_kind),
+ codemap_import_info: RwLock::new(vec![]),
+ attribute_cache: Lock::new([Vec::new(), Vec::new()]),
+ dep_kind: Lock::new(dep_kind),
source: cstore::CrateSource {
dylib,
rlib,
if data.root.macro_derive_registrar.is_some() {
dep_kind = DepKind::UnexportedMacrosOnly;
}
- data.dep_kind.set(cmp::max(data.dep_kind.get(), dep_kind));
+ data.dep_kind.with_lock(|data_dep_kind| {
+ *data_dep_kind = cmp::max(*data_dep_kind, dep_kind);
+ });
(cnum, data)
}
LoadResult::Loaded(library) => {
if !visited.insert((cnum, extern_crate.direct)) { return }
let cmeta = self.cstore.get_crate_data(cnum);
- let old_extern_crate = cmeta.extern_crate.get();
+ let mut old_extern_crate = cmeta.extern_crate.borrow_mut();
// Prefer:
// - something over nothing (tuple.0);
// - direct extern crate to indirect (tuple.1);
// - shorter paths to longer (tuple.2).
let new_rank = (true, extern_crate.direct, !extern_crate.path_len);
- let old_rank = match old_extern_crate {
+ let old_rank = match *old_extern_crate {
None => (false, false, !0),
Some(ref c) => (true, c.direct, !c.path_len),
};
return; // no change needed
}
- cmeta.extern_crate.set(Some(extern_crate));
+ *old_extern_crate = Some(extern_crate);
+ drop(old_extern_crate);
+
// Propagate the extern crate info to dependencies.
extern_crate.direct = false;
for &dep_cnum in cmeta.cnum_map.borrow().iter() {
// #![panic_runtime] crate.
self.inject_dependency_if(cnum, "a panic runtime",
&|data| data.needs_panic_runtime(sess));
- runtime_found = runtime_found || data.dep_kind.get() == DepKind::Explicit;
+ runtime_found = runtime_found || *data.dep_kind.lock() == DepKind::Explicit;
}
});
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap};
-use std::cell::{RefCell, Cell};
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, RwLock, Lock};
use syntax::{ast, attr};
use syntax::ext::base::SyntaxExtension;
use syntax::symbol::Symbol;
/// Information about the extern crate that caused this crate to
/// be loaded. If this is `None`, then the crate was injected
/// (e.g., by the allocator)
- pub extern_crate: Cell<Option<ExternCrate>>,
+ pub extern_crate: Lock<Option<ExternCrate>>,
pub blob: MetadataBlob,
- pub cnum_map: RefCell<CrateNumMap>,
+ pub cnum_map: Lock<CrateNumMap>,
pub cnum: CrateNum,
- pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
- pub attribute_cache: RefCell<[Vec<Option<Lrc<[ast::Attribute]>>>; 2]>,
+ pub codemap_import_info: RwLock<Vec<ImportedFileMap>>,
+ pub attribute_cache: Lock<[Vec<Option<Lrc<[ast::Attribute]>>>; 2]>,
pub root: schema::CrateRoot,
pub trait_impls: FxHashMap<(u32, DefIndex), schema::LazySeq<DefIndex>>,
- pub dep_kind: Cell<DepKind>,
+ pub dep_kind: Lock<DepKind>,
pub source: CrateSource,
pub proc_macros: Option<Vec<(ast::Name, Lrc<SyntaxExtension>)>>,
}
pub struct CStore {
- metas: RefCell<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
+ metas: RwLock<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
/// Map from NodeId's of local extern crate statements to crate numbers
- extern_mod_crate_map: RefCell<NodeMap<CrateNum>>,
- pub metadata_loader: Box<MetadataLoader>,
+ extern_mod_crate_map: Lock<NodeMap<CrateNum>>,
+ pub metadata_loader: Box<MetadataLoader + Sync>,
}
impl CStore {
- pub fn new(metadata_loader: Box<MetadataLoader>) -> CStore {
+ pub fn new(metadata_loader: Box<MetadataLoader + Sync>) -> CStore {
CStore {
- metas: RefCell::new(IndexVec::new()),
- extern_mod_crate_map: RefCell::new(FxHashMap()),
+ metas: RwLock::new(IndexVec::new()),
+ extern_mod_crate_map: Lock::new(FxHashMap()),
metadata_loader,
}
}
+ /// You cannot use this function to allocate a CrateNum in a thread-safe manner.
+ /// It is currently only used in CrateLoader which is single-threaded code.
pub fn next_crate_num(&self) -> CrateNum {
CrateNum::new(self.metas.borrow().len() + 1)
}
is_sanitizer_runtime => { cdata.is_sanitizer_runtime(tcx.sess) }
is_profiler_runtime => { cdata.is_profiler_runtime(tcx.sess) }
panic_strategy => { cdata.panic_strategy() }
- extern_crate => { Lrc::new(cdata.extern_crate.get()) }
+ extern_crate => {
+ let r = Lrc::new(*cdata.extern_crate.lock());
+ r
+ }
is_no_builtins => { cdata.is_no_builtins(tcx.sess) }
impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
reachable_non_generics => {
cdata.is_dllimport_foreign_item(def_id.index)
}
visibility => { cdata.get_visibility(def_id.index) }
- dep_kind => { cdata.dep_kind.get() }
+ dep_kind => {
+ let r = *cdata.dep_kind.lock();
+ r
+ }
crate_name => { cdata.name }
item_children => {
let mut result = vec![];
}
missing_extern_crate_item => {
- match cdata.extern_crate.get() {
+ let r = match *cdata.extern_crate.borrow() {
Some(extern_crate) if !extern_crate.direct => true,
_ => false,
- }
+ };
+ r
}
used_crate_source => { Lrc::new(cdata.source.clone()) }
fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind
{
- self.get_crate_data(cnum).dep_kind.get()
+ let data = self.get_crate_data(cnum);
+ let r = *data.dep_kind.lock();
+ r
}
fn export_macros_untracked(&self, cnum: CrateNum) {
let data = self.get_crate_data(cnum);
- if data.dep_kind.get() == DepKind::UnexportedMacrosOnly {
- data.dep_kind.set(DepKind::MacrosOnly)
+ let mut dep_kind = data.dep_kind.lock();
+ if *dep_kind == DepKind::UnexportedMacrosOnly {
+ *dep_kind = DepKind::MacrosOnly;
}
}
use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary};
use schema::*;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, ReadGuard};
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
use rustc::hir;
use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
use rustc::mir::Mir;
use rustc::util::nodemap::FxHashMap;
-use std::cell::Ref;
use std::collections::BTreeMap;
use std::io;
use std::mem;
};
// Iterate over all children.
- let macros_only = self.dep_kind.get().macros_only();
+ let macros_only = self.dep_kind.lock().macros_only();
for child_index in item.children.decode((self, sess)) {
if macros_only {
continue
if vec_.len() < node_index + 1 {
vec_.resize(node_index + 1, None);
}
+ // This can overwrite the result produced by another thread, but the value
+ // written should be the same
vec_[node_index] = Some(result.clone());
result
}
/// for items inlined from other crates.
pub fn imported_filemaps(&'a self,
local_codemap: &codemap::CodeMap)
- -> Ref<'a, Vec<cstore::ImportedFileMap>> {
+ -> ReadGuard<'a, Vec<cstore::ImportedFileMap>> {
{
let filemaps = self.codemap_import_info.borrow();
if !filemaps.is_empty() {
}
}
+ // Lock the codemap_import_info to ensure this only happens once
+ let mut codemap_import_info = self.codemap_import_info.borrow_mut();
+
+ if !codemap_import_info.is_empty() {
+ drop(codemap_import_info);
+ return self.codemap_import_info.borrow();
+ }
+
let external_codemap = self.root.codemap.decode(self);
let imported_filemaps = external_codemap.map(|filemap_to_import| {
}
}).collect();
+ *codemap_import_info = imported_filemaps;
+ drop(codemap_import_info);
+
// This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref.
- *self.codemap_import_info.borrow_mut() = imported_filemaps;
self.codemap_import_info.borrow()
}
}
}
fn check_lifetime(&self, lifetime: &Lifetime) {
- let valid_names = [keywords::StaticLifetime.name(), keywords::Invalid.name()];
+ let valid_names = [keywords::UnderscoreLifetime.name(),
+ keywords::StaticLifetime.name(),
+ keywords::Invalid.name()];
if !valid_names.contains(&lifetime.ident.name) &&
token::Ident(lifetime.ident.without_first_quote()).is_reserved_ident() {
self.err_handler().span_err(lifetime.span, "lifetimes cannot use keyword names");
}
fn check_label(&self, label: Ident, span: Span) {
- if token::Ident(label.without_first_quote()).is_reserved_ident() || label.name == "'_" {
+ if token::Ident(label.without_first_quote()).is_reserved_ident() {
self.err_handler().span_err(span, &format!("invalid label name `{}`", label.name));
}
}
target_features(sess)
}
- fn metadata_loader(&self) -> Box<MetadataLoader> {
+ fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
box metadata::LlvmMetadataLoader
}
fn print_version(&self) {}
fn diagnostics(&self) -> &[(&'static str, &'static str)] { &[] }
- fn metadata_loader(&self) -> Box<MetadataLoader>;
+ fn metadata_loader(&self) -> Box<MetadataLoader + Sync>;
fn provide(&self, _providers: &mut Providers);
fn provide_extern(&self, _providers: &mut Providers);
fn trans_crate<'a, 'tcx>(
pub struct DummyTransCrate;
impl TransCrate for DummyTransCrate {
- fn metadata_loader(&self) -> Box<MetadataLoader> {
+ fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
box DummyMetadataLoader(())
}
}
}
- fn metadata_loader(&self) -> Box<MetadataLoader> {
+ fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
box NoLlvmMetadataLoader
}
token::Lifetime(..) => Class::Lifetime,
- token::Underscore | token::Eof | token::Interpolated(..) |
+ token::Eof | token::Interpolated(..) |
token::Tilde | token::At | token::DotEq => Class::None,
};
use ext::build::AstBuilder;
use parse::token;
use ptr::P;
-use symbol::Symbol;
+use symbol::{keywords, Symbol};
use tokenstream::{TokenTree};
use util::small_vector::SmallVector;
(descriptions.len(), ecx.expr_vec(span, descriptions))
});
- let static_ = ecx.lifetime(span, Ident::from_str("'static"));
+ let static_ = ecx.lifetime(span, keywords::StaticLifetime.ident());
let ty_str = ecx.ty_rptr(
span,
ecx.ty_ident(span, ecx.ident_of("str")),
token::Pound => "Pound",
token::Dollar => "Dollar",
token::Question => "Question",
- token::Underscore => "Underscore",
token::Eof => "Eof",
token::Whitespace | token::Comment | token::Shebang(_) => {
use ast::Ident;
use syntax_pos::{self, BytePos, Span};
-use codemap::Spanned;
+use codemap::respan;
use errors::FatalError;
use ext::tt::quoted::{self, TokenTree};
use parse::{Directory, ParseSess};
}
}
+/// The token is an identifier, but not `_`.
+/// We prohibit passing `_` to macros expecting `ident` for now.
+fn get_macro_ident(token: &Token) -> Option<Ident> {
+ match *token {
+ token::Ident(ident) if ident.name != keywords::Underscore.name() => Some(ident),
+ _ => None,
+ }
+}
+
/// Checks whether a non-terminal may begin with a particular token.
///
/// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
match name {
"expr" => token.can_begin_expr(),
"ty" => token.can_begin_type(),
- "ident" => token.is_ident(),
+ "ident" => get_macro_ident(token).is_some(),
"vis" => match *token {
// The follow-set of :vis + "priv" keyword + interpolated
Token::Comma | Token::Ident(_) | Token::Interpolated(_) => true,
Token::DotDotDot | // range pattern (future compat)
Token::ModSep | // path
Token::Lt | // path (UFCS constant)
- Token::BinOp(token::Shl) | // path (double UFCS)
- Token::Underscore => true, // placeholder
+ Token::BinOp(token::Shl) => true, // path (double UFCS)
Token::Interpolated(ref nt) => may_be_ident(&nt.0),
_ => false,
},
"expr" => token::NtExpr(panictry!(p.parse_expr())),
"ty" => token::NtTy(panictry!(p.parse_ty())),
// this could be handled like a token, since it is one
- "ident" => match p.token {
- token::Ident(sn) => {
- p.bump();
- token::NtIdent(Spanned::<Ident> {
- node: sn,
- span: p.prev_span,
- })
- }
- _ => {
- let token_str = pprust::token_to_string(&p.token);
- p.fatal(&format!("expected ident, found {}", &token_str[..]))
- .emit();
- FatalError.raise()
- }
- },
+ "ident" => if let Some(ident) = get_macro_ident(&p.token) {
+ p.bump();
+ token::NtIdent(respan(p.prev_span, ident))
+ } else {
+ let token_str = pprust::token_to_string(&p.token);
+ p.fatal(&format!("expected ident, found {}", &token_str)).emit();
+ FatalError.raise()
+ }
"path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),
"meta" => token::NtMeta(panictry!(p.parse_meta_item())),
"vis" => token::NtVis(panictry!(p.parse_visibility(true))),
}
fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) {
- if lt.ident.name == "'_" {
+ if lt.ident.name == keywords::UnderscoreLifetime.name() {
gate_feature_post!(&self, underscore_lifetimes, lt.span,
"underscore lifetimes are unstable");
}
impl Default for TokenAndSpan {
fn default() -> Self {
- TokenAndSpan { tok: token::Underscore, sp: syntax_pos::DUMMY_SP }
+ TokenAndSpan { tok: token::Whitespace, sp: syntax_pos::DUMMY_SP }
}
}
pub fn try_next_token(&mut self) -> Result<TokenAndSpan, ()> {
assert!(self.fatal_errs.is_empty());
let ret_val = TokenAndSpan {
- tok: replace(&mut self.peek_tok, token::Underscore),
+ tok: replace(&mut self.peek_tok, token::Whitespace),
sp: self.peek_span,
};
self.advance_token()?;
self.bump();
}
- return Ok(self.with_str_from(start, |string| {
- if string == "_" {
- token::Underscore
- } else {
- // FIXME: perform NFKC normalization here. (Issue #2253)
- token::Ident(self.mk_ident(string))
- }
- }));
+ // FIXME: perform NFKC normalization here. (Issue #2253)
+ return Ok(self.with_str_from(start, |string| token::Ident(self.mk_ident(string))));
}
if is_dec_digit(c) {
-> Self {
let mut parser = Parser {
sess,
- token: token::Underscore,
+ token: token::Whitespace,
span: syntax_pos::DUMMY_SP,
prev_span: syntax_pos::DUMMY_SP,
meta_var_span: None,
Err(if self.prev_token_kind == PrevTokenKind::DocComment {
self.span_fatal_err(self.prev_span, Error::UselessDocComment)
} else {
- let mut err = self.expected_ident_found();
- if self.token == token::Underscore {
- err.note("`_` is a wildcard pattern, not an identifier");
- }
- err
+ self.expected_ident_found()
})
}
}
let e = self.parse_expr()?;
self.expect(&token::CloseDelim(token::Paren))?;
TyKind::Typeof(e)
- } else if self.eat(&token::Underscore) {
+ } else if self.eat_keyword(keywords::Underscore) {
// A type to be inferred `_`
TyKind::Infer
} else if self.token_is_bare_fn_keyword() {
_ => 0,
};
- self.look_ahead(offset, |t| t.is_ident() || t == &token::Underscore) &&
+ self.look_ahead(offset, |t| t.is_ident()) &&
self.look_ahead(offset + 1, |t| t == &token::Colon)
}
},
token::CloseDelim(_) | token::Eof => unreachable!(),
_ => {
- let (token, span) = (mem::replace(&mut self.token, token::Underscore), self.span);
+ let (token, span) = (mem::replace(&mut self.token, token::Whitespace), self.span);
self.bump();
TokenTree::Token(span, token)
}
let lo = self.span;
let pat;
match self.token {
- token::Underscore => {
- // Parse _
- self.bump();
- pat = PatKind::Wild;
- }
token::BinOp(token::And) | token::AndAnd => {
// Parse &pat / &mut pat
self.expect_and()?;
self.expect(&token::CloseDelim(token::Bracket))?;
pat = PatKind::Slice(before, slice, after);
}
- // At this point, token != _, &, &&, (, [
- _ => if self.eat_keyword(keywords::Mut) {
+ // At this point, token != &, &&, (, [
+ _ => if self.eat_keyword(keywords::Underscore) {
+ // Parse _
+ pat = PatKind::Wild;
+ } else if self.eat_keyword(keywords::Mut) {
// Parse mut ident @ pat / mut ref ident @ pat
let mutref_span = self.prev_span.to(self.span);
let binding_mode = if self.eat_keyword(keywords::Ref) {
fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
if self.eat_keyword(keywords::As) {
- if self.eat(&token::Underscore) {
- Ok(Some(Ident::with_empty_ctxt(Symbol::gensym("_"))))
- } else {
- self.parse_ident().map(Some)
+ match self.token {
+ token::Ident(ident) if ident.name == keywords::Underscore.name() => {
+ self.bump(); // `_`
+ Ok(Some(Ident { name: ident.name.gensymed(), ..ident }))
+ }
+ _ => self.parse_ident().map(Some),
}
} else {
Ok(None)
!ident_token.is_reserved_ident() ||
ident_token.is_path_segment_keyword() ||
[
+ keywords::Underscore.name(),
keywords::For.name(),
keywords::Impl.name(),
keywords::Fn.name(),
/* Name components */
Ident(ast::Ident),
- Underscore,
Lifetime(ast::Ident),
// The `LazyTokenStream` is a pure function of the `Nonterminal`,
Ident(ident) => ident_can_begin_type(ident), // type name or keyword
OpenDelim(Paren) | // tuple
OpenDelim(Bracket) | // array
- Underscore | // placeholder
Not | // never
BinOp(Star) | // raw pointer
BinOp(And) | // reference
// unnamed method parameters, crate root module, error recovery etc.
pub fn is_special_ident(&self) -> bool {
match self.ident() {
- Some(id) => id.name <= keywords::DollarCrate.name(),
+ Some(id) => id.name <= keywords::Underscore.name(),
_ => false,
}
}
Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | DotEq |
DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar |
- Question | OpenDelim(..) | CloseDelim(..) | Underscore => return None,
+ Question | OpenDelim(..) | CloseDelim(..) => return None,
Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) |
Whitespace | Comment | Shebang(..) | Eof => return None,
pub fn is_op(tok: &Token) -> bool {
match *tok {
OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) |
- Ident(..) | Underscore | Lifetime(..) | Interpolated(..) |
+ Ident(..) | Lifetime(..) | Interpolated(..) |
Whitespace | Comment | Shebang(..) | Eof => false,
_ => true,
}
/* Name components */
token::Ident(s) => s.to_string(),
token::Lifetime(s) => s.to_string(),
- token::Underscore => "_".to_string(),
/* Other */
token::DocComment(s) => s.to_string(),
use syntax::ext::base::*;
use syntax::ext::base;
use syntax::ext::build::AstBuilder;
-use syntax::symbol::Symbol;
+use syntax::symbol::{keywords, Symbol};
use syntax_pos::Span;
use syntax::tokenstream;
let sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark));
let e = match env::var(&*var.as_str()) {
Err(..) => {
+ let lt = cx.lifetime(sp, keywords::StaticLifetime.ident());
cx.expr_path(cx.path_all(sp,
true,
cx.std_path(&["option", "Option", "None"]),
Vec::new(),
vec![cx.ty_rptr(sp,
cx.ty_ident(sp, Ident::from_str("str")),
- Some(cx.lifetime(sp,
- Ident::from_str("'static"))),
+ Some(lt),
ast::Mutability::Immutable)],
Vec::new()))
}
declare_keywords! {
// Special reserved identifiers used internally for elided lifetimes,
// unnamed method parameters, crate root module, error recovery etc.
- (0, Invalid, "")
- (1, CrateRoot, "{{root}}")
- (2, DollarCrate, "$crate")
+ (0, Invalid, "")
+ (1, CrateRoot, "{{root}}")
+ (2, DollarCrate, "$crate")
+ (3, Underscore, "_")
// Keywords used in the language.
- (3, As, "as")
- (4, Box, "box")
- (5, Break, "break")
- (6, Const, "const")
- (7, Continue, "continue")
- (8, Crate, "crate")
- (9, Else, "else")
- (10, Enum, "enum")
- (11, Extern, "extern")
- (12, False, "false")
- (13, Fn, "fn")
- (14, For, "for")
- (15, If, "if")
- (16, Impl, "impl")
- (17, In, "in")
- (18, Let, "let")
- (19, Loop, "loop")
- (20, Match, "match")
- (21, Mod, "mod")
- (22, Move, "move")
- (23, Mut, "mut")
- (24, Pub, "pub")
- (25, Ref, "ref")
- (26, Return, "return")
- (27, SelfValue, "self")
- (28, SelfType, "Self")
- (29, Static, "static")
- (30, Struct, "struct")
- (31, Super, "super")
- (32, Trait, "trait")
- (33, True, "true")
- (34, Type, "type")
- (35, Unsafe, "unsafe")
- (36, Use, "use")
- (37, Where, "where")
- (38, While, "while")
+ (4, As, "as")
+ (5, Box, "box")
+ (6, Break, "break")
+ (7, Const, "const")
+ (8, Continue, "continue")
+ (9, Crate, "crate")
+ (10, Else, "else")
+ (11, Enum, "enum")
+ (12, Extern, "extern")
+ (13, False, "false")
+ (14, Fn, "fn")
+ (15, For, "for")
+ (16, If, "if")
+ (17, Impl, "impl")
+ (18, In, "in")
+ (19, Let, "let")
+ (20, Loop, "loop")
+ (21, Match, "match")
+ (22, Mod, "mod")
+ (23, Move, "move")
+ (24, Mut, "mut")
+ (25, Pub, "pub")
+ (26, Ref, "ref")
+ (27, Return, "return")
+ (28, SelfValue, "self")
+ (29, SelfType, "Self")
+ (30, Static, "static")
+ (31, Struct, "struct")
+ (32, Super, "super")
+ (33, Trait, "trait")
+ (34, True, "true")
+ (35, Type, "type")
+ (36, Unsafe, "unsafe")
+ (37, Use, "use")
+ (38, Where, "where")
+ (39, While, "while")
// Keywords reserved for future use.
- (39, Abstract, "abstract")
- (40, Alignof, "alignof")
- (41, Become, "become")
- (42, Do, "do")
- (43, Final, "final")
- (44, Macro, "macro")
- (45, Offsetof, "offsetof")
- (46, Override, "override")
- (47, Priv, "priv")
- (48, Proc, "proc")
- (49, Pure, "pure")
- (50, Sizeof, "sizeof")
- (51, Typeof, "typeof")
- (52, Unsized, "unsized")
- (53, Virtual, "virtual")
- (54, Yield, "yield")
+ (40, Abstract, "abstract")
+ (41, Alignof, "alignof")
+ (42, Become, "become")
+ (43, Do, "do")
+ (44, Final, "final")
+ (45, Macro, "macro")
+ (46, Offsetof, "offsetof")
+ (47, Override, "override")
+ (48, Priv, "priv")
+ (49, Proc, "proc")
+ (50, Pure, "pure")
+ (51, Sizeof, "sizeof")
+ (52, Typeof, "typeof")
+ (53, Unsized, "unsized")
+ (54, Virtual, "virtual")
+ (55, Yield, "yield")
+
+ // Special lifetime names
+ (56, UnderscoreLifetime, "'_")
+ (57, StaticLifetime, "'static")
// Weak keywords, have special meaning only in specific contexts.
- (55, Auto, "auto")
- (56, Catch, "catch")
- (57, Default, "default")
- (58, Dyn, "dyn")
- (59, StaticLifetime, "'static")
- (60, Union, "union")
+ (58, Auto, "auto")
+ (59, Catch, "catch")
+ (60, Default, "default")
+ (61, Dyn, "dyn")
+ (62, Union, "union")
}
// If an interner exists, return it. Otherwise, prepare a fresh one.
let _ = 0;
let mut b = 0;
let mut _b = 0;
- let mut _ = 0; //~ ERROR expected identifier, found `_`
- //~^ NOTE `_` is a wildcard pattern, not an identifier
- //~| NOTE expected identifier
+ let mut _ = 0; //~ ERROR expected identifier, found reserved identifier `_`
}
}
}
// still recover later
- let bad_syntax = _; //~ ERROR: found `_`
+ let bad_syntax = _; //~ ERROR: expected expression, found reserved identifier `_`
}
// except according to those terms.
fn main() {
- let a = 42._; //~ ERROR unexpected token: `_`
+ let a = 42._; //~ ERROR expected identifier, found reserved identifier `_`
+ //~^ ERROR `{integer}` is a primitive type and therefore doesn't have fields
}
struct TheBackend(Box<TransCrate>);
impl TransCrate for TheBackend {
- fn metadata_loader(&self) -> Box<MetadataLoader> {
+ fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
self.0.metadata_loader()
}
-error: expected expression, found `_`
+error: expected expression, found reserved identifier `_`
--> $DIR/underscore.rs:18:9
|
LL | _
--- /dev/null
+// 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.
+
+macro_rules! identity {
+ ($i: ident) => (
+ $i
+ )
+}
+
+fn main() {
+ let identity!(_) = 10; //~ ERROR no rules expected the token `_`
+}
--- /dev/null
+error: no rules expected the token `_`
+ --> $DIR/underscore-ident-matcher.rs:18:19
+ |
+LL | let identity!(_) = 10; //~ ERROR no rules expected the token `_`
+ | ^
+
+error: aborting due to previous error
+