-// Copyright 2012-2014 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.
-
use rustc_target::spec::abi::{self, Abi};
use ast::{AngleBracketedArgs, ParenthesisedArgs, AttrStyle, BareFnTy};
use ast::{GenericBound, TraitBoundModifier};
use ast::{BinOpKind, UnOp};
use ast::{RangeEnd, RangeSyntax};
use {ast, attr};
+use ext::base::DummyResult;
use source_map::{self, SourceMap, Spanned, respan};
use syntax_pos::{self, Span, MultiSpan, BytePos, FileName};
use errors::{self, Applicability, DiagnosticBuilder, DiagnosticId};
let mut err = self.struct_span_err(self.span,
&format!("expected identifier, found {}",
self.this_token_descr()));
+ if let token::Ident(ident, false) = &self.token {
+ if ident.is_reserved() && !ident.is_path_segment_keyword() &&
+ ident.name != keywords::Underscore.name()
+ {
+ err.span_suggestion_with_applicability(
+ self.span,
+ "you can escape reserved keywords to use them as identifiers",
+ format!("r#{}", ident),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
if let Some(token_descr) = self.token_descr() {
err.span_label(self.span, format!("expected identifier, found {}", token_descr));
} else {
if text.is_empty() {
self.span_bug(sp, "found empty literal suffix in Some")
}
- self.span_err(sp, &format!("{} with a suffix is invalid", kind));
+ let msg = format!("{} with a suffix is invalid", kind);
+ self.struct_span_err(sp, &msg)
+ .span_label(sp, msg)
+ .emit();
}
}
}
Mutability::Immutable
} else {
let span = self.prev_span;
- self.span_err(span,
- "expected mut or const in raw pointer type (use \
- `*mut T` or `*const T` as appropriate)");
+ let msg = "expected mut or const in raw pointer type";
+ self.struct_span_err(span, msg)
+ .span_label(span, msg)
+ .help("use `*mut T` or `*const T` as appropriate")
+ .emit();
Mutability::Immutable
};
let t = self.parse_ty_no_plus()?;
let parser_snapshot_before_ty = self.clone();
self.eat_incorrect_doc_comment("a method argument's type");
let mut ty = self.parse_ty();
- if ty.is_ok() && self.token == token::Colon {
+ if ty.is_ok() && self.token != token::Comma &&
+ self.token != token::CloseDelim(token::Paren) {
// This wasn't actually a type, but a pattern looking like a type,
// so we are going to rollback and re-parse for recovery.
ty = self.unexpected();
let mut err = self.fatal(&format!("unknown macro variable `{}`", name));
err.span_label(self.span, "unknown macro variable");
err.emit();
+ self.bump();
return
}
token::Interpolated(ref nt) => {
ddpos = Some(fields.len());
} else {
// Emit a friendly error, ignore `..` and continue parsing
- self.span_err(self.prev_span,
- "`..` can only be used once per tuple or tuple struct pattern");
+ self.struct_span_err(
+ self.prev_span,
+ "`..` can only be used once per tuple or tuple struct pattern",
+ )
+ .span_label(self.prev_span, "can only be used once per pattern")
+ .emit();
}
} else if !self.check(&token::CloseDelim(token::Paren)) {
fields.push(self.parse_pat(None)?);
if ddpos == Some(fields.len()) && trailing_comma {
// `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed.
- self.span_err(self.prev_span, "trailing comma is not permitted after `..`");
+ let msg = "trailing comma is not permitted after `..`";
+ self.struct_span_err(self.prev_span, msg)
+ .span_label(self.prev_span, msg)
+ .emit();
}
Ok((fields, ddpos, trailing_comma))
/// Precondition: already parsed the '{'.
fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) -> PResult<'a, P<Block>> {
let mut stmts = vec![];
- let mut recovered = false;
-
while !self.eat(&token::CloseDelim(token::Brace)) {
let stmt = match self.parse_full_stmt(false) {
Err(mut err) => {
err.emit();
self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
- self.eat(&token::CloseDelim(token::Brace));
- recovered = true;
- break;
+ Some(Stmt {
+ id: ast::DUMMY_NODE_ID,
+ node: StmtKind::Expr(DummyResult::raw_expr(self.span, true)),
+ span: self.span,
+ })
}
Ok(stmt) => stmt,
};
id: ast::DUMMY_NODE_ID,
rules: s,
span: lo.to(self.prev_span),
- recovered,
}))
}
// Check for trailing attributes and stop parsing.
if !attrs.is_empty() {
let param_kind = if seen_ty_param.is_some() { "type" } else { "lifetime" };
- self.span_err(attrs[0].span,
- &format!("trailing attribute after {} parameters", param_kind));
+ self.struct_span_err(
+ attrs[0].span,
+ &format!("trailing attribute after {} parameters", param_kind),
+ )
+ .span_label(attrs[0].span, "attributes must go before parameters")
+ .emit();
}
break
}
// Parse lifetime argument.
args.push(GenericArg::Lifetime(self.expect_lifetime()));
if seen_type || seen_binding {
- self.span_err(self.prev_span,
- "lifetime parameters must be declared prior to type parameters");
+ self.struct_span_err(
+ self.prev_span,
+ "lifetime parameters must be declared prior to type parameters"
+ )
+ .span_label(self.prev_span, "must be declared prior to type parameters")
+ .emit();
}
} else if self.check_ident() && self.look_ahead(1, |t| t == &token::Eq) {
// Parse associated type binding.
// Parse type argument.
let ty_param = self.parse_ty()?;
if seen_binding {
- self.span_err(ty_param.span,
- "type parameters must be declared prior to associated type bindings");
+ self.struct_span_err(
+ ty_param.span,
+ "type parameters must be declared prior to associated type bindings"
+ )
+ .span_label(
+ ty_param.span,
+ "must be declared prior to associated type bindings",
+ )
+ .emit();
}
args.push(GenericArg::Type(ty_param));
seen_type = true;
// change we parse those generics now, but report an error.
if self.choose_generics_over_qpath() {
let generics = self.parse_generics()?;
- self.span_err(generics.span,
- "generic parameters on `where` clauses are reserved for future use");
+ self.struct_span_err(
+ generics.span,
+ "generic parameters on `where` clauses are reserved for future use",
+ )
+ .span_label(generics.span, "currently unsupported")
+ .emit();
}
loop {
// *mut self
// *not_self
// Emit special error for `self` cases.
+ let msg = "cannot pass `self` by raw pointer";
(if isolated_self(self, 1) {
self.bump();
- self.span_err(self.span, "cannot pass `self` by raw pointer");
+ self.struct_span_err(self.span, msg)
+ .span_label(self.span, msg)
+ .emit();
SelfKind::Value(Mutability::Immutable)
} else if self.look_ahead(1, |t| t.is_mutability()) &&
isolated_self(self, 2) {
self.bump();
self.bump();
- self.span_err(self.span, "cannot pass `self` by raw pointer");
+ self.struct_span_err(self.span, msg)
+ .span_label(self.span, msg)
+ .emit();
SelfKind::Value(Mutability::Immutable)
} else {
return Ok(None);
tps.where_clause = self.parse_where_clause()?;
self.expect(&token::Semi)?;
if unsafety != Unsafety::Normal {
- self.span_err(self.prev_span, "trait aliases cannot be unsafe");
+ let msg = "trait aliases cannot be unsafe";
+ self.struct_span_err(self.prev_span, msg)
+ .span_label(self.prev_span, msg)
+ .emit();
}
Ok((ident, ItemKind::TraitAlias(tps, bounds), None))
} else {
Some(ty_second) => {
// impl Trait for Type
if !has_for {
- self.span_err(missing_for_span, "missing `for` in a trait impl");
+ self.struct_span_err(missing_for_span, "missing `for` in a trait impl")
+ .span_suggestion_short_with_applicability(
+ missing_for_span,
+ "add `for` here",
+ " for ".to_string(),
+ Applicability::MachineApplicable,
+ ).emit();
}
let ty_first = ty_first.into_inner();
fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef> {
let mut variants = Vec::new();
let mut all_nullary = true;
- let mut any_disr = None;
+ let mut any_disr = vec![];
while self.token != token::CloseDelim(token::Brace) {
let variant_attrs = self.parse_outer_attributes()?;
let vlo = self.span;
id: ast::DUMMY_NODE_ID,
value: self.parse_expr()?,
});
- any_disr = disr_expr.as_ref().map(|c| c.value.span);
+ if let Some(sp) = disr_expr.as_ref().map(|c| c.value.span) {
+ any_disr.push(sp);
+ }
struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
} else {
struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
if !self.eat(&token::Comma) { break; }
}
self.expect(&token::CloseDelim(token::Brace))?;
- match any_disr {
- Some(disr_span) if !all_nullary =>
- self.span_err(disr_span,
- "discriminator values can only be used with a field-less enum"),
- _ => ()
+ if !any_disr.is_empty() && !all_nullary {
+ let mut err =self.struct_span_err(
+ any_disr.clone(),
+ "discriminator values can only be used with a field-less enum",
+ );
+ for sp in any_disr {
+ err.span_label(sp, "only valid in field-less enums");
+ }
+ err.emit();
}
Ok(ast::EnumDef { variants })