Make the parser’s ‘expected <foo>, found <bar>’ errors more accurate
As an example of what this changes, the following code: let x: [int ..4]; Currently spits out ‘expected `]`, found `..`’. However, a comma would also be valid there, as would a number of other tokens. This change adjusts the parser to produce more accurate errors, so that that example now produces ‘expected one of `(`, `+`, `,`, `::`, or `]`, found `..`’.
This commit is contained in:
parent
3a325c666d
commit
108bca53f0
29 changed files with 155 additions and 95 deletions
|
@ -87,6 +87,7 @@ use std::mem;
|
||||||
use std::num::Float;
|
use std::num::Float;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
flags Restrictions: u8 {
|
flags Restrictions: u8 {
|
||||||
|
@ -303,6 +304,22 @@ pub struct Parser<'a> {
|
||||||
/// name is not known. This does not change while the parser is descending
|
/// name is not known. This does not change while the parser is descending
|
||||||
/// into modules, and sub-parsers have new values for this name.
|
/// into modules, and sub-parsers have new values for this name.
|
||||||
pub root_module_name: Option<String>,
|
pub root_module_name: Option<String>,
|
||||||
|
pub expected_tokens: Vec<TokenType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deriving(PartialEq, Eq, Clone)]
|
||||||
|
pub enum TokenType {
|
||||||
|
Token(token::Token),
|
||||||
|
Operator,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TokenType {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
match *self {
|
||||||
|
TokenType::Token(ref t) => format!("`{}`", Parser::token_to_string(t)),
|
||||||
|
TokenType::Operator => "an operator".into_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_plain_ident_or_underscore(t: &token::Token) -> bool {
|
fn is_plain_ident_or_underscore(t: &token::Token) -> bool {
|
||||||
|
@ -347,6 +364,7 @@ impl<'a> Parser<'a> {
|
||||||
open_braces: Vec::new(),
|
open_braces: Vec::new(),
|
||||||
owns_directory: true,
|
owns_directory: true,
|
||||||
root_module_name: None,
|
root_module_name: None,
|
||||||
|
expected_tokens: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,6 +393,7 @@ impl<'a> Parser<'a> {
|
||||||
/// Expect and consume the token t. Signal an error if
|
/// Expect and consume the token t. Signal an error if
|
||||||
/// the next token is not t.
|
/// the next token is not t.
|
||||||
pub fn expect(&mut self, t: &token::Token) {
|
pub fn expect(&mut self, t: &token::Token) {
|
||||||
|
if self.expected_tokens.is_empty() {
|
||||||
if self.token == *t {
|
if self.token == *t {
|
||||||
self.bump();
|
self.bump();
|
||||||
} else {
|
} else {
|
||||||
|
@ -384,6 +403,9 @@ impl<'a> Parser<'a> {
|
||||||
token_str,
|
token_str,
|
||||||
this_token_str).as_slice())
|
this_token_str).as_slice())
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
self.expect_one_of(slice::ref_slice(t), &[]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expect next token to be edible or inedible token. If edible,
|
/// Expect next token to be edible or inedible token. If edible,
|
||||||
|
@ -392,15 +414,20 @@ impl<'a> Parser<'a> {
|
||||||
pub fn expect_one_of(&mut self,
|
pub fn expect_one_of(&mut self,
|
||||||
edible: &[token::Token],
|
edible: &[token::Token],
|
||||||
inedible: &[token::Token]) {
|
inedible: &[token::Token]) {
|
||||||
fn tokens_to_string(tokens: &[token::Token]) -> String {
|
fn tokens_to_string(tokens: &[TokenType]) -> String {
|
||||||
let mut i = tokens.iter();
|
let mut i = tokens.iter();
|
||||||
// This might be a sign we need a connect method on Iterator.
|
// This might be a sign we need a connect method on Iterator.
|
||||||
let b = i.next()
|
let b = i.next()
|
||||||
.map_or("".to_string(), |t| Parser::token_to_string(t));
|
.map_or("".into_string(), |t| t.to_string());
|
||||||
i.fold(b, |b,a| {
|
i.enumerate().fold(b, |mut b, (i, ref a)| {
|
||||||
let mut b = b;
|
if tokens.len() > 2 && i == tokens.len() - 2 {
|
||||||
b.push_str("`, `");
|
b.push_str(", or ");
|
||||||
b.push_str(Parser::token_to_string(a).as_slice());
|
} else if tokens.len() == 2 && i == tokens.len() - 2 {
|
||||||
|
b.push_str(" or ");
|
||||||
|
} else {
|
||||||
|
b.push_str(", ");
|
||||||
|
}
|
||||||
|
b.push_str(&*a.to_string());
|
||||||
b
|
b
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -409,17 +436,21 @@ impl<'a> Parser<'a> {
|
||||||
} else if inedible.contains(&self.token) {
|
} else if inedible.contains(&self.token) {
|
||||||
// leave it in the input
|
// leave it in the input
|
||||||
} else {
|
} else {
|
||||||
let mut expected = edible.iter().map(|x| x.clone()).collect::<Vec<_>>();
|
let mut expected = edible.iter().map(|x| TokenType::Token(x.clone()))
|
||||||
expected.push_all(inedible);
|
.collect::<Vec<_>>();
|
||||||
|
expected.extend(inedible.iter().map(|x| TokenType::Token(x.clone())));
|
||||||
|
expected.push_all(&*self.expected_tokens);
|
||||||
|
expected.sort_by(|a, b| a.to_string().cmp(&b.to_string()));
|
||||||
|
expected.dedup();
|
||||||
let expect = tokens_to_string(expected.as_slice());
|
let expect = tokens_to_string(expected.as_slice());
|
||||||
let actual = self.this_token_to_string();
|
let actual = self.this_token_to_string();
|
||||||
self.fatal(
|
self.fatal(
|
||||||
(if expected.len() != 1 {
|
(if expected.len() != 1 {
|
||||||
(format!("expected one of `{}`, found `{}`",
|
(format!("expected one of {}, found `{}`",
|
||||||
expect,
|
expect,
|
||||||
actual))
|
actual))
|
||||||
} else {
|
} else {
|
||||||
(format!("expected `{}`, found `{}`",
|
(format!("expected {}, found `{}`",
|
||||||
expect,
|
expect,
|
||||||
actual))
|
actual))
|
||||||
}).as_slice()
|
}).as_slice()
|
||||||
|
@ -514,10 +545,20 @@ impl<'a> Parser<'a> {
|
||||||
spanned(lo, hi, node)
|
spanned(lo, hi, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if the next token is `tok`, and return `true` if so.
|
||||||
|
///
|
||||||
|
/// This method is will automatically add `tok` to `expected_tokens` if `tok` is not
|
||||||
|
/// encountered.
|
||||||
|
pub fn check(&mut self, tok: &token::Token) -> bool {
|
||||||
|
let is_present = self.token == *tok;
|
||||||
|
if !is_present { self.expected_tokens.push(TokenType::Token(tok.clone())); }
|
||||||
|
is_present
|
||||||
|
}
|
||||||
|
|
||||||
/// Consume token 'tok' if it exists. Returns true if the given
|
/// Consume token 'tok' if it exists. Returns true if the given
|
||||||
/// token was present, false otherwise.
|
/// token was present, false otherwise.
|
||||||
pub fn eat(&mut self, tok: &token::Token) -> bool {
|
pub fn eat(&mut self, tok: &token::Token) -> bool {
|
||||||
let is_present = self.token == *tok;
|
let is_present = self.check(tok);
|
||||||
if is_present { self.bump() }
|
if is_present { self.bump() }
|
||||||
is_present
|
is_present
|
||||||
}
|
}
|
||||||
|
@ -739,7 +780,7 @@ impl<'a> Parser<'a> {
|
||||||
// commas in generic parameters, because it can stop either after
|
// commas in generic parameters, because it can stop either after
|
||||||
// parsing a type or after parsing a comma.
|
// parsing a type or after parsing a comma.
|
||||||
for i in iter::count(0u, 1) {
|
for i in iter::count(0u, 1) {
|
||||||
if self.token == token::Gt
|
if self.check(&token::Gt)
|
||||||
|| self.token == token::BinOp(token::Shr)
|
|| self.token == token::BinOp(token::Shr)
|
||||||
|| self.token == token::Ge
|
|| self.token == token::Ge
|
||||||
|| self.token == token::BinOpEq(token::Shr) {
|
|| self.token == token::BinOpEq(token::Shr) {
|
||||||
|
@ -798,7 +839,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
if sep.trailing_sep_allowed && self.token == *ket { break; }
|
if sep.trailing_sep_allowed && self.check(ket) { break; }
|
||||||
v.push(f(self));
|
v.push(f(self));
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
|
@ -881,6 +922,7 @@ impl<'a> Parser<'a> {
|
||||||
self.span = next.sp;
|
self.span = next.sp;
|
||||||
self.token = next.tok;
|
self.token = next.tok;
|
||||||
self.tokens_consumed += 1u;
|
self.tokens_consumed += 1u;
|
||||||
|
self.expected_tokens.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Advance the parser by one token and return the bumped token.
|
/// Advance the parser by one token and return the bumped token.
|
||||||
|
@ -999,7 +1041,7 @@ impl<'a> Parser<'a> {
|
||||||
self.parse_proc_type(lifetime_defs)
|
self.parse_proc_type(lifetime_defs)
|
||||||
} else if self.token_is_bare_fn_keyword() || self.token_is_closure_keyword() {
|
} else if self.token_is_bare_fn_keyword() || self.token_is_closure_keyword() {
|
||||||
self.parse_ty_bare_fn_or_ty_closure(lifetime_defs)
|
self.parse_ty_bare_fn_or_ty_closure(lifetime_defs)
|
||||||
} else if self.token == token::ModSep ||
|
} else if self.check(&token::ModSep) ||
|
||||||
self.token.is_ident() ||
|
self.token.is_ident() ||
|
||||||
self.token.is_path()
|
self.token.is_path()
|
||||||
{
|
{
|
||||||
|
@ -1101,7 +1143,7 @@ impl<'a> Parser<'a> {
|
||||||
/// Parses an optional unboxed closure kind (`&:`, `&mut:`, or `:`).
|
/// Parses an optional unboxed closure kind (`&:`, `&mut:`, or `:`).
|
||||||
pub fn parse_optional_unboxed_closure_kind(&mut self)
|
pub fn parse_optional_unboxed_closure_kind(&mut self)
|
||||||
-> Option<UnboxedClosureKind> {
|
-> Option<UnboxedClosureKind> {
|
||||||
if self.token == token::BinOp(token::And) &&
|
if self.check(&token::BinOp(token::And)) &&
|
||||||
self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) &&
|
self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) &&
|
||||||
self.look_ahead(2, |t| *t == token::Colon) {
|
self.look_ahead(2, |t| *t == token::Colon) {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
@ -1211,7 +1253,8 @@ impl<'a> Parser<'a> {
|
||||||
lifetime_defs: Vec<ast::LifetimeDef>)
|
lifetime_defs: Vec<ast::LifetimeDef>)
|
||||||
-> Vec<ast::LifetimeDef>
|
-> Vec<ast::LifetimeDef>
|
||||||
{
|
{
|
||||||
if self.eat(&token::Lt) {
|
if self.token == token::Lt {
|
||||||
|
self.bump();
|
||||||
if lifetime_defs.is_empty() {
|
if lifetime_defs.is_empty() {
|
||||||
self.warn("deprecated syntax; use the `for` keyword now \
|
self.warn("deprecated syntax; use the `for` keyword now \
|
||||||
(e.g. change `fn<'a>` to `for<'a> fn`)");
|
(e.g. change `fn<'a>` to `for<'a> fn`)");
|
||||||
|
@ -1430,7 +1473,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let lo = self.span.lo;
|
let lo = self.span.lo;
|
||||||
|
|
||||||
let t = if self.token == token::OpenDelim(token::Paren) {
|
let t = if self.check(&token::OpenDelim(token::Paren)) {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
|
||||||
// (t) is a parenthesized ty
|
// (t) is a parenthesized ty
|
||||||
|
@ -1440,7 +1483,7 @@ impl<'a> Parser<'a> {
|
||||||
let mut last_comma = false;
|
let mut last_comma = false;
|
||||||
while self.token != token::CloseDelim(token::Paren) {
|
while self.token != token::CloseDelim(token::Paren) {
|
||||||
ts.push(self.parse_ty_sum());
|
ts.push(self.parse_ty_sum());
|
||||||
if self.token == token::Comma {
|
if self.check(&token::Comma) {
|
||||||
last_comma = true;
|
last_comma = true;
|
||||||
self.bump();
|
self.bump();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1464,11 +1507,11 @@ impl<'a> Parser<'a> {
|
||||||
_ => self.obsolete(last_span, ObsoleteOwnedType)
|
_ => self.obsolete(last_span, ObsoleteOwnedType)
|
||||||
}
|
}
|
||||||
TyTup(vec![self.parse_ty()])
|
TyTup(vec![self.parse_ty()])
|
||||||
} else if self.token == token::BinOp(token::Star) {
|
} else if self.check(&token::BinOp(token::Star)) {
|
||||||
// STAR POINTER (bare pointer?)
|
// STAR POINTER (bare pointer?)
|
||||||
self.bump();
|
self.bump();
|
||||||
TyPtr(self.parse_ptr())
|
TyPtr(self.parse_ptr())
|
||||||
} else if self.token == token::OpenDelim(token::Bracket) {
|
} else if self.check(&token::OpenDelim(token::Bracket)) {
|
||||||
// VECTOR
|
// VECTOR
|
||||||
self.expect(&token::OpenDelim(token::Bracket));
|
self.expect(&token::OpenDelim(token::Bracket));
|
||||||
let t = self.parse_ty_sum();
|
let t = self.parse_ty_sum();
|
||||||
|
@ -1481,7 +1524,7 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
self.expect(&token::CloseDelim(token::Bracket));
|
self.expect(&token::CloseDelim(token::Bracket));
|
||||||
t
|
t
|
||||||
} else if self.token == token::BinOp(token::And) ||
|
} else if self.check(&token::BinOp(token::And)) ||
|
||||||
self.token == token::AndAnd {
|
self.token == token::AndAnd {
|
||||||
// BORROWED POINTER
|
// BORROWED POINTER
|
||||||
self.expect_and();
|
self.expect_and();
|
||||||
|
@ -1492,7 +1535,7 @@ impl<'a> Parser<'a> {
|
||||||
self.token_is_closure_keyword() {
|
self.token_is_closure_keyword() {
|
||||||
// BARE FUNCTION OR CLOSURE
|
// BARE FUNCTION OR CLOSURE
|
||||||
self.parse_ty_bare_fn_or_ty_closure(Vec::new())
|
self.parse_ty_bare_fn_or_ty_closure(Vec::new())
|
||||||
} else if self.token == token::BinOp(token::Or) ||
|
} else if self.check(&token::BinOp(token::Or)) ||
|
||||||
self.token == token::OrOr ||
|
self.token == token::OrOr ||
|
||||||
(self.token == token::Lt &&
|
(self.token == token::Lt &&
|
||||||
self.look_ahead(1, |t| {
|
self.look_ahead(1, |t| {
|
||||||
|
@ -1509,7 +1552,7 @@ impl<'a> Parser<'a> {
|
||||||
TyTypeof(e)
|
TyTypeof(e)
|
||||||
} else if self.eat_keyword(keywords::Proc) {
|
} else if self.eat_keyword(keywords::Proc) {
|
||||||
self.parse_proc_type(Vec::new())
|
self.parse_proc_type(Vec::new())
|
||||||
} else if self.token == token::Lt {
|
} else if self.check(&token::Lt) {
|
||||||
// QUALIFIED PATH `<TYPE as TRAIT_REF>::item`
|
// QUALIFIED PATH `<TYPE as TRAIT_REF>::item`
|
||||||
self.bump();
|
self.bump();
|
||||||
let self_type = self.parse_ty_sum();
|
let self_type = self.parse_ty_sum();
|
||||||
|
@ -1523,7 +1566,7 @@ impl<'a> Parser<'a> {
|
||||||
trait_ref: P(trait_ref),
|
trait_ref: P(trait_ref),
|
||||||
item_name: item_name,
|
item_name: item_name,
|
||||||
}))
|
}))
|
||||||
} else if self.token == token::ModSep ||
|
} else if self.check(&token::ModSep) ||
|
||||||
self.token.is_ident() ||
|
self.token.is_ident() ||
|
||||||
self.token.is_path() {
|
self.token.is_path() {
|
||||||
// NAMED TYPE
|
// NAMED TYPE
|
||||||
|
@ -1532,7 +1575,8 @@ impl<'a> Parser<'a> {
|
||||||
// TYPE TO BE INFERRED
|
// TYPE TO BE INFERRED
|
||||||
TyInfer
|
TyInfer
|
||||||
} else {
|
} else {
|
||||||
let msg = format!("expected type, found token {}", self.token);
|
let this_token_str = self.this_token_to_string();
|
||||||
|
let msg = format!("expected type, found `{}`", this_token_str);
|
||||||
self.fatal(msg.as_slice());
|
self.fatal(msg.as_slice());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1635,7 +1679,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn maybe_parse_fixed_vstore(&mut self) -> Option<P<ast::Expr>> {
|
pub fn maybe_parse_fixed_vstore(&mut self) -> Option<P<ast::Expr>> {
|
||||||
if self.token == token::Comma &&
|
if self.check(&token::Comma) &&
|
||||||
self.look_ahead(1, |t| *t == token::DotDot) {
|
self.look_ahead(1, |t| *t == token::DotDot) {
|
||||||
self.bump();
|
self.bump();
|
||||||
self.bump();
|
self.bump();
|
||||||
|
@ -1959,9 +2003,10 @@ impl<'a> Parser<'a> {
|
||||||
token::Gt => { return res; }
|
token::Gt => { return res; }
|
||||||
token::BinOp(token::Shr) => { return res; }
|
token::BinOp(token::Shr) => { return res; }
|
||||||
_ => {
|
_ => {
|
||||||
|
let this_token_str = self.this_token_to_string();
|
||||||
let msg = format!("expected `,` or `>` after lifetime \
|
let msg = format!("expected `,` or `>` after lifetime \
|
||||||
name, got: {}",
|
name, found `{}`",
|
||||||
self.token);
|
this_token_str);
|
||||||
self.fatal(msg.as_slice());
|
self.fatal(msg.as_slice());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2126,7 +2171,7 @@ impl<'a> Parser<'a> {
|
||||||
es.push(self.parse_expr());
|
es.push(self.parse_expr());
|
||||||
self.commit_expr(&**es.last().unwrap(), &[],
|
self.commit_expr(&**es.last().unwrap(), &[],
|
||||||
&[token::Comma, token::CloseDelim(token::Paren)]);
|
&[token::Comma, token::CloseDelim(token::Paren)]);
|
||||||
if self.token == token::Comma {
|
if self.check(&token::Comma) {
|
||||||
trailing_comma = true;
|
trailing_comma = true;
|
||||||
|
|
||||||
self.bump();
|
self.bump();
|
||||||
|
@ -2167,14 +2212,14 @@ impl<'a> Parser<'a> {
|
||||||
token::OpenDelim(token::Bracket) => {
|
token::OpenDelim(token::Bracket) => {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
|
||||||
if self.token == token::CloseDelim(token::Bracket) {
|
if self.check(&token::CloseDelim(token::Bracket)) {
|
||||||
// Empty vector.
|
// Empty vector.
|
||||||
self.bump();
|
self.bump();
|
||||||
ex = ExprVec(Vec::new());
|
ex = ExprVec(Vec::new());
|
||||||
} else {
|
} else {
|
||||||
// Nonempty vector.
|
// Nonempty vector.
|
||||||
let first_expr = self.parse_expr();
|
let first_expr = self.parse_expr();
|
||||||
if self.token == token::Comma &&
|
if self.check(&token::Comma) &&
|
||||||
self.look_ahead(1, |t| *t == token::DotDot) {
|
self.look_ahead(1, |t| *t == token::DotDot) {
|
||||||
// Repeating vector syntax: [ 0, ..512 ]
|
// Repeating vector syntax: [ 0, ..512 ]
|
||||||
self.bump();
|
self.bump();
|
||||||
|
@ -2182,7 +2227,7 @@ impl<'a> Parser<'a> {
|
||||||
let count = self.parse_expr();
|
let count = self.parse_expr();
|
||||||
self.expect(&token::CloseDelim(token::Bracket));
|
self.expect(&token::CloseDelim(token::Bracket));
|
||||||
ex = ExprRepeat(first_expr, count);
|
ex = ExprRepeat(first_expr, count);
|
||||||
} else if self.token == token::Comma {
|
} else if self.check(&token::Comma) {
|
||||||
// Vector with two or more elements.
|
// Vector with two or more elements.
|
||||||
self.bump();
|
self.bump();
|
||||||
let remaining_exprs = self.parse_seq_to_end(
|
let remaining_exprs = self.parse_seq_to_end(
|
||||||
|
@ -2284,7 +2329,7 @@ impl<'a> Parser<'a> {
|
||||||
ex = ExprBreak(None);
|
ex = ExprBreak(None);
|
||||||
}
|
}
|
||||||
hi = self.span.hi;
|
hi = self.span.hi;
|
||||||
} else if self.token == token::ModSep ||
|
} else if self.check(&token::ModSep) ||
|
||||||
self.token.is_ident() &&
|
self.token.is_ident() &&
|
||||||
!self.token.is_keyword(keywords::True) &&
|
!self.token.is_keyword(keywords::True) &&
|
||||||
!self.token.is_keyword(keywords::False) {
|
!self.token.is_keyword(keywords::False) {
|
||||||
|
@ -2292,7 +2337,7 @@ impl<'a> Parser<'a> {
|
||||||
self.parse_path(LifetimeAndTypesWithColons);
|
self.parse_path(LifetimeAndTypesWithColons);
|
||||||
|
|
||||||
// `!`, as an operator, is prefix, so we know this isn't that
|
// `!`, as an operator, is prefix, so we know this isn't that
|
||||||
if self.token == token::Not {
|
if self.check(&token::Not) {
|
||||||
// MACRO INVOCATION expression
|
// MACRO INVOCATION expression
|
||||||
self.bump();
|
self.bump();
|
||||||
|
|
||||||
|
@ -2309,7 +2354,7 @@ impl<'a> Parser<'a> {
|
||||||
tts,
|
tts,
|
||||||
EMPTY_CTXT));
|
EMPTY_CTXT));
|
||||||
}
|
}
|
||||||
if self.token == token::OpenDelim(token::Brace) {
|
if self.check(&token::OpenDelim(token::Brace)) {
|
||||||
// This is a struct literal, unless we're prohibited
|
// This is a struct literal, unless we're prohibited
|
||||||
// from parsing struct literals here.
|
// from parsing struct literals here.
|
||||||
if !self.restrictions.contains(RESTRICTION_NO_STRUCT_LITERAL) {
|
if !self.restrictions.contains(RESTRICTION_NO_STRUCT_LITERAL) {
|
||||||
|
@ -2840,6 +2885,7 @@ impl<'a> Parser<'a> {
|
||||||
self.restrictions.contains(RESTRICTION_NO_BAR_OP) {
|
self.restrictions.contains(RESTRICTION_NO_BAR_OP) {
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
self.expected_tokens.push(TokenType::Operator);
|
||||||
|
|
||||||
let cur_opt = self.token.to_binop();
|
let cur_opt = self.token.to_binop();
|
||||||
match cur_opt {
|
match cur_opt {
|
||||||
|
@ -3079,7 +3125,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Parse the RHS of a local variable declaration (e.g. '= 14;')
|
/// Parse the RHS of a local variable declaration (e.g. '= 14;')
|
||||||
fn parse_initializer(&mut self) -> Option<P<Expr>> {
|
fn parse_initializer(&mut self) -> Option<P<Expr>> {
|
||||||
if self.token == token::Eq {
|
if self.check(&token::Eq) {
|
||||||
self.bump();
|
self.bump();
|
||||||
Some(self.parse_expr())
|
Some(self.parse_expr())
|
||||||
} else {
|
} else {
|
||||||
|
@ -3092,7 +3138,7 @@ impl<'a> Parser<'a> {
|
||||||
let mut pats = Vec::new();
|
let mut pats = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
pats.push(self.parse_pat());
|
pats.push(self.parse_pat());
|
||||||
if self.token == token::BinOp(token::Or) { self.bump(); }
|
if self.check(&token::BinOp(token::Or)) { self.bump(); }
|
||||||
else { return pats; }
|
else { return pats; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -3114,11 +3160,11 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if before_slice {
|
if before_slice {
|
||||||
if self.token == token::DotDot {
|
if self.check(&token::DotDot) {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
|
||||||
if self.token == token::Comma ||
|
if self.check(&token::Comma) ||
|
||||||
self.token == token::CloseDelim(token::Bracket) {
|
self.check(&token::CloseDelim(token::Bracket)) {
|
||||||
slice = Some(P(ast::Pat {
|
slice = Some(P(ast::Pat {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
node: PatWild(PatWildMulti),
|
node: PatWild(PatWildMulti),
|
||||||
|
@ -3135,7 +3181,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let subpat = self.parse_pat();
|
let subpat = self.parse_pat();
|
||||||
if before_slice && self.token == token::DotDot {
|
if before_slice && self.check(&token::DotDot) {
|
||||||
self.bump();
|
self.bump();
|
||||||
slice = Some(subpat);
|
slice = Some(subpat);
|
||||||
before_slice = false;
|
before_slice = false;
|
||||||
|
@ -3160,13 +3206,13 @@ impl<'a> Parser<'a> {
|
||||||
} else {
|
} else {
|
||||||
self.expect(&token::Comma);
|
self.expect(&token::Comma);
|
||||||
// accept trailing commas
|
// accept trailing commas
|
||||||
if self.token == token::CloseDelim(token::Brace) { break }
|
if self.check(&token::CloseDelim(token::Brace)) { break }
|
||||||
}
|
}
|
||||||
|
|
||||||
let lo = self.span.lo;
|
let lo = self.span.lo;
|
||||||
let hi;
|
let hi;
|
||||||
|
|
||||||
if self.token == token::DotDot {
|
if self.check(&token::DotDot) {
|
||||||
self.bump();
|
self.bump();
|
||||||
if self.token != token::CloseDelim(token::Brace) {
|
if self.token != token::CloseDelim(token::Brace) {
|
||||||
let token_str = self.this_token_to_string();
|
let token_str = self.this_token_to_string();
|
||||||
|
@ -3187,7 +3233,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let fieldname = self.parse_ident();
|
let fieldname = self.parse_ident();
|
||||||
|
|
||||||
let (subpat, is_shorthand) = if self.token == token::Colon {
|
let (subpat, is_shorthand) = if self.check(&token::Colon) {
|
||||||
match bind_type {
|
match bind_type {
|
||||||
BindByRef(..) | BindByValue(MutMutable) => {
|
BindByRef(..) | BindByValue(MutMutable) => {
|
||||||
let token_str = self.this_token_to_string();
|
let token_str = self.this_token_to_string();
|
||||||
|
@ -3267,15 +3313,15 @@ impl<'a> Parser<'a> {
|
||||||
token::OpenDelim(token::Paren) => {
|
token::OpenDelim(token::Paren) => {
|
||||||
// parse (pat,pat,pat,...) as tuple
|
// parse (pat,pat,pat,...) as tuple
|
||||||
self.bump();
|
self.bump();
|
||||||
if self.token == token::CloseDelim(token::Paren) {
|
if self.check(&token::CloseDelim(token::Paren)) {
|
||||||
self.bump();
|
self.bump();
|
||||||
pat = PatTup(vec![]);
|
pat = PatTup(vec![]);
|
||||||
} else {
|
} else {
|
||||||
let mut fields = vec!(self.parse_pat());
|
let mut fields = vec!(self.parse_pat());
|
||||||
if self.look_ahead(1, |t| *t != token::CloseDelim(token::Paren)) {
|
if self.look_ahead(1, |t| *t != token::CloseDelim(token::Paren)) {
|
||||||
while self.token == token::Comma {
|
while self.check(&token::Comma) {
|
||||||
self.bump();
|
self.bump();
|
||||||
if self.token == token::CloseDelim(token::Paren) { break; }
|
if self.check(&token::CloseDelim(token::Paren)) { break; }
|
||||||
fields.push(self.parse_pat());
|
fields.push(self.parse_pat());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3318,7 +3364,7 @@ impl<'a> Parser<'a> {
|
||||||
// These expressions are limited to literals (possibly
|
// These expressions are limited to literals (possibly
|
||||||
// preceded by unary-minus) or identifiers.
|
// preceded by unary-minus) or identifiers.
|
||||||
let val = self.parse_literal_maybe_minus();
|
let val = self.parse_literal_maybe_minus();
|
||||||
if (self.token == token::DotDotDot) &&
|
if (self.check(&token::DotDotDot)) &&
|
||||||
self.look_ahead(1, |t| {
|
self.look_ahead(1, |t| {
|
||||||
*t != token::Comma && *t != token::CloseDelim(token::Bracket)
|
*t != token::Comma && *t != token::CloseDelim(token::Bracket)
|
||||||
}) {
|
}) {
|
||||||
|
@ -3621,7 +3667,7 @@ impl<'a> Parser<'a> {
|
||||||
let hi = self.span.hi;
|
let hi = self.span.hi;
|
||||||
|
|
||||||
if id.name == token::special_idents::invalid.name {
|
if id.name == token::special_idents::invalid.name {
|
||||||
if self.token == token::Dot {
|
if self.check(&token::Dot) {
|
||||||
let span = self.span;
|
let span = self.span;
|
||||||
let token_string = self.this_token_to_string();
|
let token_string = self.this_token_to_string();
|
||||||
self.span_err(span,
|
self.span_err(span,
|
||||||
|
@ -3934,7 +3980,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let bounds = self.parse_colon_then_ty_param_bounds();
|
let bounds = self.parse_colon_then_ty_param_bounds();
|
||||||
|
|
||||||
let default = if self.token == token::Eq {
|
let default = if self.check(&token::Eq) {
|
||||||
self.bump();
|
self.bump();
|
||||||
Some(self.parse_ty_sum())
|
Some(self.parse_ty_sum())
|
||||||
}
|
}
|
||||||
|
@ -4334,7 +4380,7 @@ impl<'a> Parser<'a> {
|
||||||
(optional_unboxed_closure_kind, args)
|
(optional_unboxed_closure_kind, args)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let output = if self.token == token::RArrow {
|
let output = if self.check(&token::RArrow) {
|
||||||
self.parse_ret_ty()
|
self.parse_ret_ty()
|
||||||
} else {
|
} else {
|
||||||
Return(P(Ty {
|
Return(P(Ty {
|
||||||
|
@ -4359,7 +4405,7 @@ impl<'a> Parser<'a> {
|
||||||
seq_sep_trailing_allowed(token::Comma),
|
seq_sep_trailing_allowed(token::Comma),
|
||||||
|p| p.parse_fn_block_arg());
|
|p| p.parse_fn_block_arg());
|
||||||
|
|
||||||
let output = if self.token == token::RArrow {
|
let output = if self.check(&token::RArrow) {
|
||||||
self.parse_ret_ty()
|
self.parse_ret_ty()
|
||||||
} else {
|
} else {
|
||||||
Return(P(Ty {
|
Return(P(Ty {
|
||||||
|
@ -4616,7 +4662,7 @@ impl<'a> Parser<'a> {
|
||||||
token::get_ident(class_name)).as_slice());
|
token::get_ident(class_name)).as_slice());
|
||||||
}
|
}
|
||||||
self.bump();
|
self.bump();
|
||||||
} else if self.token == token::OpenDelim(token::Paren) {
|
} else if self.check(&token::OpenDelim(token::Paren)) {
|
||||||
// It's a tuple-like struct.
|
// It's a tuple-like struct.
|
||||||
is_tuple_like = true;
|
is_tuple_like = true;
|
||||||
fields = self.parse_unspanned_seq(
|
fields = self.parse_unspanned_seq(
|
||||||
|
@ -4801,7 +4847,7 @@ impl<'a> Parser<'a> {
|
||||||
fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> ItemInfo {
|
fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> ItemInfo {
|
||||||
let id_span = self.span;
|
let id_span = self.span;
|
||||||
let id = self.parse_ident();
|
let id = self.parse_ident();
|
||||||
if self.token == token::Semi {
|
if self.check(&token::Semi) {
|
||||||
self.bump();
|
self.bump();
|
||||||
// This mod is in an external file. Let's go get it!
|
// This mod is in an external file. Let's go get it!
|
||||||
let (m, attrs) = self.eval_src_mod(id, outer_attrs, id_span);
|
let (m, attrs) = self.eval_src_mod(id, outer_attrs, id_span);
|
||||||
|
@ -5044,7 +5090,8 @@ impl<'a> Parser<'a> {
|
||||||
let (maybe_path, ident) = match self.token {
|
let (maybe_path, ident) = match self.token {
|
||||||
token::Ident(..) => {
|
token::Ident(..) => {
|
||||||
let the_ident = self.parse_ident();
|
let the_ident = self.parse_ident();
|
||||||
let path = if self.eat(&token::Eq) {
|
let path = if self.token == token::Eq {
|
||||||
|
self.bump();
|
||||||
let path = self.parse_str();
|
let path = self.parse_str();
|
||||||
let span = self.span;
|
let span = self.span;
|
||||||
self.obsolete(span, ObsoleteExternCrateRenaming);
|
self.obsolete(span, ObsoleteExternCrateRenaming);
|
||||||
|
@ -5184,7 +5231,7 @@ impl<'a> Parser<'a> {
|
||||||
token::get_ident(ident)).as_slice());
|
token::get_ident(ident)).as_slice());
|
||||||
}
|
}
|
||||||
kind = StructVariantKind(struct_def);
|
kind = StructVariantKind(struct_def);
|
||||||
} else if self.token == token::OpenDelim(token::Paren) {
|
} else if self.check(&token::OpenDelim(token::Paren)) {
|
||||||
all_nullary = false;
|
all_nullary = false;
|
||||||
let arg_tys = self.parse_enum_variant_seq(
|
let arg_tys = self.parse_enum_variant_seq(
|
||||||
&token::OpenDelim(token::Paren),
|
&token::OpenDelim(token::Paren),
|
||||||
|
@ -5348,7 +5395,7 @@ impl<'a> Parser<'a> {
|
||||||
visibility,
|
visibility,
|
||||||
maybe_append(attrs, extra_attrs));
|
maybe_append(attrs, extra_attrs));
|
||||||
return IoviItem(item);
|
return IoviItem(item);
|
||||||
} else if self.token == token::OpenDelim(token::Brace) {
|
} else if self.check(&token::OpenDelim(token::Brace)) {
|
||||||
return self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs);
|
return self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5629,7 +5676,7 @@ impl<'a> Parser<'a> {
|
||||||
fn parse_view_path(&mut self) -> P<ViewPath> {
|
fn parse_view_path(&mut self) -> P<ViewPath> {
|
||||||
let lo = self.span.lo;
|
let lo = self.span.lo;
|
||||||
|
|
||||||
if self.token == token::OpenDelim(token::Brace) {
|
if self.check(&token::OpenDelim(token::Brace)) {
|
||||||
// use {foo,bar}
|
// use {foo,bar}
|
||||||
let idents = self.parse_unspanned_seq(
|
let idents = self.parse_unspanned_seq(
|
||||||
&token::OpenDelim(token::Brace),
|
&token::OpenDelim(token::Brace),
|
||||||
|
@ -5653,7 +5700,7 @@ impl<'a> Parser<'a> {
|
||||||
self.bump();
|
self.bump();
|
||||||
let path_lo = self.span.lo;
|
let path_lo = self.span.lo;
|
||||||
path = vec!(self.parse_ident());
|
path = vec!(self.parse_ident());
|
||||||
while self.token == token::ModSep {
|
while self.check(&token::ModSep) {
|
||||||
self.bump();
|
self.bump();
|
||||||
let id = self.parse_ident();
|
let id = self.parse_ident();
|
||||||
path.push(id);
|
path.push(id);
|
||||||
|
@ -5677,7 +5724,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
token::ModSep => {
|
token::ModSep => {
|
||||||
// foo::bar or foo::{a,b,c} or foo::*
|
// foo::bar or foo::{a,b,c} or foo::*
|
||||||
while self.token == token::ModSep {
|
while self.check(&token::ModSep) {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
|
||||||
match self.token {
|
match self.token {
|
||||||
|
@ -5846,7 +5893,7 @@ impl<'a> Parser<'a> {
|
||||||
loop {
|
loop {
|
||||||
match self.parse_foreign_item(attrs, macros_allowed) {
|
match self.parse_foreign_item(attrs, macros_allowed) {
|
||||||
IoviNone(returned_attrs) => {
|
IoviNone(returned_attrs) => {
|
||||||
if self.token == token::CloseDelim(token::Brace) {
|
if self.check(&token::CloseDelim(token::Brace)) {
|
||||||
attrs = returned_attrs;
|
attrs = returned_attrs;
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
13
src/test/compile-fail/better-expected.rs
Normal file
13
src/test/compile-fail/better-expected.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 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.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x: [int ..3]; //~ ERROR expected one of `(`, `+`, `,`, `::`, or `]`, found `..`
|
||||||
|
}
|
|
@ -8,4 +8,4 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
# //~ ERROR 11:1: 11:2 error: expected `[`, found `<eof>`
|
# //~ ERROR 11:1: 11:2 error: expected one of `!` or `[`, found `<eof>`
|
||||||
|
|
|
@ -8,4 +8,4 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
impl Foo; //~ ERROR expected `{`, found `;`
|
impl Foo; //~ ERROR expected one of `(`, `+`, `::`, or `{`, found `;`
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// error-pattern:expected `[`, found `vec`
|
// error-pattern:expected one of `!` or `[`, found `vec`
|
||||||
mod blade_runner {
|
mod blade_runner {
|
||||||
#vec[doc(
|
#vec[doc(
|
||||||
brief = "Blade Runner is probably the best movie ever",
|
brief = "Blade Runner is probably the best movie ever",
|
||||||
|
|
|
@ -12,5 +12,5 @@
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let t = (42i, 42i);
|
let t = (42i, 42i);
|
||||||
t.0::<int>; //~ ERROR expected one of `;`, `}`, found `::`
|
t.0::<int>; //~ ERROR expected one of `.`, `;`, `}`, or an operator, found `::`
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,4 +13,4 @@
|
||||||
fn main()
|
fn main()
|
||||||
{
|
{
|
||||||
let x = 3
|
let x = 3
|
||||||
} //~ ERROR: expected `;`, found `}`
|
} //~ ERROR: expected one of `.`, `;`, or an operator, found `}`
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
let a = Vec::new();
|
let a = Vec::new();
|
||||||
match a {
|
match a {
|
||||||
[1, tail.., tail..] => {}, //~ ERROR: expected `,`, found `..`
|
[1, tail.., tail..] => {}, //~ ERROR: expected one of `!`, `,`, or `@`, found `..`
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ struct S {
|
||||||
y: int
|
y: int
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cmp, ToString for S { //~ ERROR: expected `{`, found `,`
|
impl Cmp, ToString for S { //~ ERROR: expected one of `(`, `+`, `::`, or `{`, found `,`
|
||||||
fn eq(&&other: S) { false }
|
fn eq(&&other: S) { false }
|
||||||
fn to_string(&self) -> String { "hi".to_string() }
|
fn to_string(&self) -> String { "hi".to_string() }
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,5 +12,5 @@
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
struct Foo { x: int }
|
struct Foo { x: int }
|
||||||
let mut Foo { x: x } = Foo { x: 3 }; //~ ERROR: expected `;`, found `{`
|
let mut Foo { x: x } = Foo { x: 3 }; //~ ERROR: expected one of `:`, `;`, `=`, or `@`, found `{`
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,5 +8,5 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
fn foo(x) { //~ ERROR expected `:`, found `)`
|
fn foo(x) { //~ ERROR expected one of `!`, `:`, or `@`, found `)`
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
match 22i {
|
match 22i {
|
||||||
0 .. 3 => {} //~ ERROR expected `=>`, found `..`
|
0 .. 3 => {} //~ ERROR expected one of `...`, `=>`, or `|`, found `..`
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,5 +10,5 @@
|
||||||
|
|
||||||
static s: &'static str =
|
static s: &'static str =
|
||||||
r#"
|
r#"
|
||||||
"## //~ ERROR expected `;`, found `#`
|
"## //~ ERROR expected one of `.`, `;`, or an operator, found `#`
|
||||||
;
|
;
|
||||||
|
|
|
@ -8,4 +8,4 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
type closure = Box<lt/fn()>; //~ ERROR expected `,`, found `/`
|
type closure = Box<lt/fn()>; //~ ERROR expected one of `(`, `+`, `,`, `::`, or `>`, found `/`
|
||||||
|
|
|
@ -8,4 +8,4 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
enum e = int; //~ ERROR expected `{`, found `=`
|
enum e = int; //~ ERROR expected one of `<` or `{`, found `=`
|
||||||
|
|
|
@ -8,4 +8,4 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
type v = [int * 3]; //~ ERROR expected `]`, found `*`
|
type v = [int * 3]; //~ ERROR expected one of `(`, `+`, `,`, `::`, or `]`, found `*`
|
||||||
|
|
|
@ -11,5 +11,5 @@
|
||||||
fn removed_moves() {
|
fn removed_moves() {
|
||||||
let mut x = 0;
|
let mut x = 0;
|
||||||
let y <- x;
|
let y <- x;
|
||||||
//~^ ERROR expected `;`, found `<-`
|
//~^ ERROR expected one of `!`, `:`, `;`, `=`, or `@`, found `<-`
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,5 +12,5 @@ fn removed_moves() {
|
||||||
let mut x = 0;
|
let mut x = 0;
|
||||||
let y = 0;
|
let y = 0;
|
||||||
y <- x;
|
y <- x;
|
||||||
//~^ ERROR expected one of `;`, `}`, found `<-`
|
//~^ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `<-`
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,5 +11,5 @@
|
||||||
fn f() {
|
fn f() {
|
||||||
let v = [mut 1, 2, 3, 4];
|
let v = [mut 1, 2, 3, 4];
|
||||||
//~^ ERROR expected identifier, found keyword `mut`
|
//~^ ERROR expected identifier, found keyword `mut`
|
||||||
//~^^ ERROR expected `]`, found `1`
|
//~^^ ERROR expected one of `!`, `,`, `.`, `::`, `]`, `{`, or an operator, found `1`
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,4 +10,4 @@
|
||||||
|
|
||||||
type v = [mut int];
|
type v = [mut int];
|
||||||
//~^ ERROR expected identifier, found keyword `mut`
|
//~^ ERROR expected identifier, found keyword `mut`
|
||||||
//~^^ ERROR expected `]`, found `int`
|
//~^^ ERROR expected one of `(`, `+`, `,`, `::`, or `]`, found `int`
|
||||||
|
|
|
@ -8,4 +8,4 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
type bptr = &lifetime/int; //~ ERROR expected `;`, found `/`
|
type bptr = &lifetime/int; //~ ERROR expected one of `(`, `+`, `::`, or `;`, found `/`
|
||||||
|
|
|
@ -8,4 +8,4 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
type t = { f: () }; //~ ERROR expected type, found token OpenDelim(Brace)
|
type t = { f: () }; //~ ERROR expected type, found `{`
|
||||||
|
|
|
@ -11,5 +11,5 @@
|
||||||
fn f() {
|
fn f() {
|
||||||
let a_box = box mut 42;
|
let a_box = box mut 42;
|
||||||
//~^ ERROR expected identifier, found keyword `mut`
|
//~^ ERROR expected identifier, found keyword `mut`
|
||||||
//~^^ ERROR expected `;`, found `42`
|
//~^^ ERROR expected one of `!`, `.`, `::`, `;`, `{`, or an operator, found `42`
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,4 +10,4 @@
|
||||||
|
|
||||||
type mut_box = Box<mut int>;
|
type mut_box = Box<mut int>;
|
||||||
//~^ ERROR expected identifier, found keyword `mut`
|
//~^ ERROR expected identifier, found keyword `mut`
|
||||||
//~^^ ERROR expected `,`, found `int`
|
//~^^ ERROR expected one of `(`, `+`, `,`, `::`, or `>`, found `int`
|
||||||
|
|
|
@ -16,5 +16,5 @@ fn removed_with() {
|
||||||
|
|
||||||
let a = S { foo: (), bar: () };
|
let a = S { foo: (), bar: () };
|
||||||
let b = S { foo: () with a };
|
let b = S { foo: () with a };
|
||||||
//~^ ERROR expected one of `,`, `}`, found `with`
|
//~^ ERROR expected one of `,`, `.`, `}`, or an operator, found `with`
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ impl Foo {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
for x in Foo {
|
for x in Foo {
|
||||||
x: 3 //~ ERROR expected one of `;`, `}`
|
x: 3 //~ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `:`
|
||||||
}.hi() {
|
}.hi() {
|
||||||
println!("yo");
|
println!("yo");
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ impl Foo {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
if Foo {
|
if Foo {
|
||||||
x: 3 //~ ERROR expected one of `;`, `}`
|
x: 3 //~ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `:`
|
||||||
}.hi() {
|
}.hi() {
|
||||||
println!("yo");
|
println!("yo");
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct Foo {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match Foo {
|
match Foo {
|
||||||
x: 3 //~ ERROR expected `=>`
|
x: 3 //~ ERROR expected one of `!`, `=>`, `@`, or `|`, found `:`
|
||||||
} {
|
} {
|
||||||
Foo {
|
Foo {
|
||||||
x: x
|
x: x
|
||||||
|
|
|
@ -20,7 +20,7 @@ impl Foo {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
while Foo {
|
while Foo {
|
||||||
x: 3 //~ ERROR expected one of `;`, `}`
|
x: 3 //~ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `:`
|
||||||
}.hi() {
|
}.hi() {
|
||||||
println!("yo");
|
println!("yo");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue