Remove specific errors for very old obsolete syntax

Replaces existing tests for removed obsolete-syntax errors with tests
for the resulting regular errors, adds a test for each of the removed
parser errors to make sure that obsolete forms don't start working
again, removes some obsolete/superfluous tests that were now failing.

Deletes some amount of dead code in the parser, also includes some small
changes to parser error messages to accomodate new tests.
This commit is contained in:
Benjamin Herr 2013-10-03 11:53:46 +02:00
parent 4bae639d86
commit fa411500f9
29 changed files with 358 additions and 528 deletions

View file

@ -402,7 +402,7 @@ impl Parser {
let mut i = tokens.iter();
// This might be a sign we need a connect method on Iterator.
let b = i.next().map_default(~"", |t| p.token_to_str(*t));
i.fold(b, |b,a| b + " " + p.token_to_str(a))
i.fold(b, |b,a| b + "`, `" + p.token_to_str(a))
}
if edible.contains(self.token) {
self.bump();
@ -548,7 +548,7 @@ impl Parser {
// signal an error if the given string is a strict keyword
pub fn check_strict_keywords(&self) {
if token::is_strict_keyword(self.token) {
self.span_err(*self.last_span,
self.span_err(*self.span,
format!("found `{}` in ident position", self.this_token_to_str()));
}
}
@ -762,8 +762,7 @@ impl Parser {
// is this one of the keywords that signals a closure type?
pub fn token_is_closure_keyword(&self, tok: &token::Token) -> bool {
token::is_keyword(keywords::Pure, tok) ||
token::is_keyword(keywords::Unsafe, tok) ||
token::is_keyword(keywords::Unsafe, tok) ||
token::is_keyword(keywords::Once, tok) ||
token::is_keyword(keywords::Fn, tok)
}
@ -786,12 +785,12 @@ impl Parser {
pub fn parse_ty_bare_fn(&self) -> ty_ {
/*
extern "ABI" [pure|unsafe] fn <'lt> (S) -> T
^~~~^ ^~~~~~~~~~~~^ ^~~~^ ^~^ ^
| | | | |
| | | | Return type
| | | Argument types
| | Lifetimes
extern "ABI" [unsafe] fn <'lt> (S) -> T
^~~~^ ^~~~~~~^ ^~~~^ ^~^ ^
| | | | |
| | | | Return type
| | | Argument types
| | Lifetimes
| |
| Purity
ABI
@ -818,14 +817,14 @@ impl Parser {
-> ty_ {
/*
(&|~|@) ['r] [pure|unsafe] [once] fn [:Bounds] <'lt> (S) -> T
^~~~~~^ ^~~^ ^~~~~~~~~~~~^ ^~~~~^ ^~~~~~~~^ ^~~~^ ^~^ ^
| | | | | | | |
| | | | | | | Return type
| | | | | | Argument types
| | | | | Lifetimes
| | | | Closure bounds
| | | Once-ness (a.k.a., affine)
(&|~|@) ['r] [unsafe] [once] fn [:Bounds] <'lt> (S) -> T
^~~~~~^ ^~~^ ^~~~~~~^ ^~~~~^ ^~~~~~~~^ ^~~~^ ^~^ ^
| | | | | | | |
| | | | | | | Return type
| | | | | | Argument types
| | | | | Lifetimes
| | | | Closure bounds
| | | Once-ness (a.k.a., affine)
| | Purity
| Lifetime bound
Allocation type
@ -840,10 +839,6 @@ impl Parser {
self.expect_keyword(keywords::Fn);
let bounds = self.parse_optional_ty_param_bounds();
if self.parse_fn_ty_sigil().is_some() {
self.obsolete(*self.span, ObsoletePostFnTySigil);
}
let (decl, lifetimes) = self.parse_ty_fn_decl();
return ty_closure(@TyClosure {
@ -865,12 +860,8 @@ impl Parser {
}
}
// looks like this should be called parse_unsafety
pub fn parse_unsafety(&self) -> purity {
if self.eat_keyword(keywords::Pure) {
self.obsolete(*self.last_span, ObsoletePurity);
return impure_fn;
} else if self.eat_keyword(keywords::Unsafe) {
if self.eat_keyword(keywords::Unsafe) {
return unsafe_fn;
} else {
return impure_fn;
@ -1096,26 +1087,10 @@ impl Parser {
// STAR POINTER (bare pointer?)
self.bump();
ty_ptr(self.parse_mt())
} else if *self.token == token::LBRACE {
// STRUCTURAL RECORD (remove?)
let elems = self.parse_unspanned_seq(
&token::LBRACE,
&token::RBRACE,
seq_sep_trailing_allowed(token::COMMA),
|p| p.parse_ty_field()
);
if elems.len() == 0 {
self.unexpected_last(&token::RBRACE);
}
self.obsolete(*self.last_span, ObsoleteRecordType);
ty_nil
} else if *self.token == token::LBRACKET {
// VECTOR
self.expect(&token::LBRACKET);
let mt = self.parse_mt();
if mt.mutbl == MutMutable { // `m_const` too after snapshot
self.obsolete(*self.last_span, ObsoleteMutVector);
}
let mt = mt { ty: ~self.parse_ty(false), mutbl: MutImmutable };
// Parse the `, ..e` in `[ int, ..e ]`
// where `e` is a const expression
@ -1164,7 +1139,7 @@ impl Parser {
pub fn parse_box_or_uniq_pointee(&self,
sigil: ast::Sigil,
ctor: &fn(v: mt) -> ty_) -> ty_ {
// @'foo fn() or @foo/fn() or @fn() are parsed directly as fn types:
// ~'foo fn() or ~fn() are parsed directly as fn types:
match *self.token {
token::LIFETIME(*) => {
let lifetime = self.parse_lifetime();
@ -1172,30 +1147,22 @@ impl Parser {
}
token::IDENT(*) => {
if self.look_ahead(1, |t| *t == token::BINOP(token::SLASH)) &&
self.look_ahead(2, |t|
self.token_is_closure_keyword(t)) {
let lifetime = self.parse_lifetime();
self.obsolete(*self.last_span, ObsoleteLifetimeNotation);
return self.parse_ty_closure(sigil, Some(lifetime));
} else if self.token_is_closure_keyword(self.token) {
if self.token_is_closure_keyword(self.token) {
return self.parse_ty_closure(sigil, None);
}
}
_ => {}
}
// other things are parsed as @ + a type. Note that constructs like
// other things are parsed as @/~ + a type. Note that constructs like
// @[] and @str will be resolved during typeck to slices and so forth,
// rather than boxed ptrs. But the special casing of str/vec is not
// reflected in the AST type.
let mt = self.parse_mt();
if mt.mutbl != MutImmutable && sigil == OwnedSigil {
self.obsolete(*self.last_span, ObsoleteMutOwnedPointer);
if sigil == OwnedSigil {
ctor(mt { ty: ~self.parse_ty(false), mutbl: MutImmutable })
} else {
ctor(self.parse_mt())
}
ctor(mt)
}
pub fn parse_borrowed_pointee(&self) -> ty_ {
@ -1210,25 +1177,6 @@ impl Parser {
return ty_rptr(opt_lifetime, mt);
}
// parse an optional, obsolete argument mode.
pub fn parse_arg_mode(&self) {
if self.eat(&token::BINOP(token::MINUS)) {
self.obsolete(*self.last_span, ObsoleteMode);
} else if self.eat(&token::ANDAND) {
self.obsolete(*self.last_span, ObsoleteMode);
} else if self.eat(&token::BINOP(token::PLUS)) {
let lo = self.last_span.lo;
if self.eat(&token::BINOP(token::PLUS)) {
let hi = self.last_span.hi;
self.obsolete(mk_sp(lo, hi), ObsoleteMode);
} else {
self.obsolete(*self.last_span, ObsoleteMode);
}
} else {
// Ignore.
}
}
pub fn is_named_argument(&self) -> bool {
let offset = match *self.token {
token::BINOP(token::AND) => 1,
@ -1262,7 +1210,6 @@ impl Parser {
let pat = if require_name || self.is_named_argument() {
debug2!("parse_arg_general parse_pat (require_name:{:?})",
require_name);
self.parse_arg_mode();
let pat = self.parse_pat();
if is_mutbl && !ast_util::pat_is_ident(pat) {
@ -1295,7 +1242,6 @@ impl Parser {
// parse an argument in a lambda header e.g. |arg, arg|
pub fn parse_fn_block_arg(&self) -> arg {
self.parse_arg_mode();
let is_mutbl = self.eat_keyword(keywords::Mut);
let pat = self.parse_pat();
let t = if self.eat(&token::COLON) {
@ -1316,10 +1262,7 @@ impl Parser {
}
pub fn maybe_parse_fixed_vstore(&self) -> Option<@ast::Expr> {
if self.eat(&token::BINOP(token::STAR)) {
self.obsolete(*self.last_span, ObsoleteFixedLengthVectorType);
Some(self.parse_expr())
} else if *self.token == token::COMMA &&
if *self.token == token::COMMA &&
self.look_ahead(1, |t| *t == token::DOTDOT) {
self.bump();
self.bump();
@ -1535,17 +1478,6 @@ impl Parser {
token::LIFETIME(*) => {
Some(self.parse_lifetime())
}
// Also accept the (obsolete) syntax `foo/`
token::IDENT(*) => {
if self.look_ahead(1, |t| *t == token::BINOP(token::SLASH)) {
self.obsolete(*self.last_span, ObsoleteLifetimeNotation);
Some(self.parse_lifetime())
} else {
None
}
}
_ => {
None
}
@ -1553,7 +1485,7 @@ impl Parser {
}
/// Parses a single lifetime
// matches lifetime = ( LIFETIME ) | ( IDENT / )
// matches lifetime = LIFETIME
pub fn parse_lifetime(&self) -> ast::Lifetime {
match *self.token {
token::LIFETIME(i) => {
@ -1565,20 +1497,6 @@ impl Parser {
ident: i
};
}
// Also accept the (obsolete) syntax `foo/`
token::IDENT(i, _) => {
let span = self.span;
self.bump();
self.expect(&token::BINOP(token::SLASH));
self.obsolete(*self.last_span, ObsoleteLifetimeNotation);
return ast::Lifetime {
id: ast::DUMMY_NODE_ID,
span: *span,
ident: i
};
}
_ => {
self.fatal(format!("Expected a lifetime name"));
}
@ -1805,10 +1723,7 @@ impl Parser {
return self.parse_block_expr(lo, UnsafeBlock(ast::UserProvided));
} else if *self.token == token::LBRACKET {
self.bump();
let mutbl = self.parse_mutability();
if mutbl == MutMutable {
self.obsolete(*self.last_span, ObsoleteMutVector);
}
let mutbl = MutImmutable;
if *self.token == token::RBRACKET {
// Empty vector.
@ -1897,10 +1812,6 @@ impl Parser {
fields.push(self.parse_field());
while *self.token != token::RBRACE {
if self.try_parse_obsolete_with() {
break;
}
self.commit_expr(fields.last().expr, &[token::COMMA], &[token::RBRACE]);
if self.eat(&token::DOTDOT) {
@ -2277,10 +2188,6 @@ impl Parser {
}
token::TILDE => {
self.bump();
let m = self.parse_mutability();
if m != MutImmutable {
self.obsolete(*self.last_span, ObsoleteMutOwnedPointer);
}
let e = self.parse_prefix_expr();
hi = e.span.hi;
@ -2379,15 +2286,6 @@ impl Parser {
self.mk_expr(lo, rhs.span.hi,
self.mk_assign_op(aop, lhs, rhs))
}
token::LARROW => {
self.obsolete(*self.span, ObsoleteBinaryMove);
// Bogus value (but it's an error)
self.bump(); // <-
self.bump(); // rhs
self.bump(); // ;
self.mk_expr(lo, self.span.hi,
ExprBreak(None))
}
token::DARROW => {
self.obsolete(*self.span, ObsoleteSwap);
self.bump();
@ -2590,8 +2488,7 @@ impl Parser {
let hi = body.span.hi;
return self.mk_expr(lo, hi, ExprLoop(body, opt_ident));
} else {
// This is a 'continue' expression
// FIXME #9467 rm support for 'loop' here after snapshot
// This is an obsolete 'continue' expression
if opt_ident.is_some() {
self.span_err(*self.last_span,
"a label may not be used with a `loop` expression");
@ -2675,20 +2572,11 @@ impl Parser {
// parse the RHS of a local variable declaration (e.g. '= 14;')
fn parse_initializer(&self) -> Option<@Expr> {
match *self.token {
token::EQ => {
if *self.token == token::EQ {
self.bump();
return Some(self.parse_expr());
}
token::LARROW => {
self.obsolete(*self.span, ObsoleteMoveInit);
self.bump();
self.bump();
return None;
}
_ => {
return None;
}
Some(self.parse_expr())
} else {
None
}
}
@ -2893,19 +2781,6 @@ impl Parser {
span: mk_sp(lo, hi)
}
}
token::LBRACE => {
self.bump();
let (_, _) = self.parse_pat_fields();
self.bump();
self.obsolete(*self.span, ObsoleteRecordPattern);
pat = PatWild;
hi = self.last_span.hi;
return @ast::Pat {
id: ast::DUMMY_NODE_ID,
node: pat,
span: mk_sp(lo, hi)
}
}
token::LPAREN => {
// parse (pat,pat,pat,...) as tuple
self.bump();
@ -3420,10 +3295,7 @@ impl Parser {
}
fn parse_optional_purity(&self) -> ast::purity {
if self.eat_keyword(keywords::Pure) {
self.obsolete(*self.last_span, ObsoletePurity);
ast::impure_fn
} else if self.eat_keyword(keywords::Unsafe) {
if self.eat_keyword(keywords::Unsafe) {
ast::unsafe_fn
} else {
ast::impure_fn
@ -3563,7 +3435,7 @@ impl Parser {
cnstr: &fn(v: Mutability) -> ast::explicit_self_,
p: &Parser
) -> ast::explicit_self_ {
// We need to make sure it isn't a mode or a type
// We need to make sure it isn't a type
if p.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) ||
((p.look_ahead(1, |t| token::is_keyword(keywords::Const, t)) ||
p.look_ahead(1, |t| token::is_keyword(keywords::Mut, t))) &&
@ -3637,7 +3509,8 @@ impl Parser {
token::TILDE => {
maybe_parse_explicit_self(|mutability| {
if mutability != MutImmutable {
self.obsolete(*self.last_span, ObsoleteMutOwnedPointer);
self.span_err(*self.last_span,
"mutability declaration not allowed here");
}
sty_uniq
}, self)
@ -3802,7 +3675,6 @@ impl Parser {
// parse trait Foo { ... }
fn parse_item_trait(&self) -> item_info {
let ident = self.parse_ident();
self.parse_region_param();
let tps = self.parse_generics();
// Parse traits, if necessary.
@ -3859,9 +3731,6 @@ impl Parser {
ty = self.parse_ty(false);
opt_trait_ref
} else if self.eat(&token::COLON) {
self.obsolete(*self.span, ObsoleteImplSyntax);
Some(self.parse_trait_ref())
} else {
None
};
@ -3899,12 +3768,7 @@ impl Parser {
// parse struct Foo { ... }
fn parse_item_struct(&self) -> item_info {
let class_name = self.parse_ident();
self.parse_region_param();
let generics = self.parse_generics();
if self.eat(&token::COLON) {
self.obsolete(*self.span, ObsoleteClassTraits);
let _ = self.parse_trait_ref_list(&token::LBRACE);
}
let mut fields: ~[@struct_field];
let is_tuple_like;
@ -3914,10 +3778,7 @@ impl Parser {
is_tuple_like = false;
fields = ~[];
while *self.token != token::RBRACE {
let r = self.parse_struct_decl_field();
for struct_field in r.iter() {
fields.push(*struct_field)
}
fields.push(self.parse_struct_decl_field());
}
if fields.len() == 0 {
self.fatal(format!("Unit-like struct definition should be written as `struct {};`",
@ -3979,23 +3840,15 @@ impl Parser {
vis: visibility,
attrs: ~[Attribute])
-> @struct_field {
if self.eat_obsolete_ident("let") {
self.obsolete(*self.last_span, ObsoleteLet);
}
let a_var = self.parse_name_and_ty(vis, attrs);
match *self.token {
token::SEMI => {
self.obsolete(*self.span, ObsoleteFieldTerminator);
self.bump();
}
token::COMMA => {
self.bump();
}
token::RBRACE => {}
_ => {
self.span_fatal(*self.span,
format!("expected `,`, or '\\}' but found `{}`",
format!("expected `,`, or `\\}` but found `{}`",
self.this_token_to_str()));
}
}
@ -4003,23 +3856,19 @@ impl Parser {
}
// parse an element of a struct definition
fn parse_struct_decl_field(&self) -> ~[@struct_field] {
fn parse_struct_decl_field(&self) -> @struct_field {
let attrs = self.parse_outer_attributes();
if self.try_parse_obsolete_priv_section(attrs) {
return ~[];
}
if self.eat_keyword(keywords::Priv) {
return ~[self.parse_single_struct_field(private, attrs)]
return self.parse_single_struct_field(private, attrs);
}
if self.eat_keyword(keywords::Pub) {
return ~[self.parse_single_struct_field(public, attrs)];
return self.parse_single_struct_field(public, attrs);
}
return ~[self.parse_single_struct_field(inherited, attrs)];
return self.parse_single_struct_field(inherited, attrs);
}
// parse visiility: PUB, PRIV, or nothing
@ -4029,15 +3878,6 @@ impl Parser {
else { inherited }
}
fn parse_staticness(&self) -> bool {
if self.eat_keyword(keywords::Static) {
self.obsolete(*self.last_span, ObsoleteStaticMethod);
true
} else {
false
}
}
// given a termination token and a vector of already-parsed
// attributes (of length 0 or 1), parse all of the items in a module
fn parse_mod_items(&self,
@ -4241,17 +4081,12 @@ impl Parser {
vis: vis }
}
// parse a const definition from a foreign module
fn parse_item_foreign_const(&self, vis: ast::visibility,
attrs: ~[Attribute]) -> @foreign_item {
// parse a static item from a foreign module
fn parse_item_foreign_static(&self, vis: ast::visibility,
attrs: ~[Attribute]) -> @foreign_item {
let lo = self.span.lo;
// XXX: Obsolete; remove after snap.
if self.eat_keyword(keywords::Const) {
self.obsolete(*self.last_span, ObsoleteConstItem);
} else {
self.expect_keyword(keywords::Static);
}
self.expect_keyword(keywords::Static);
let mutbl = self.eat_keyword(keywords::Mut);
let ident = self.parse_ident();
@ -4270,12 +4105,7 @@ impl Parser {
// parse safe/unsafe and fn
fn parse_fn_purity(&self) -> purity {
if self.eat_keyword(keywords::Fn) { impure_fn }
else if self.eat_keyword(keywords::Pure) {
self.obsolete(*self.last_span, ObsoletePurity);
self.expect_keyword(keywords::Fn);
// NB: We parse this as impure for bootstrapping purposes.
impure_fn
} else if self.eat_keyword(keywords::Unsafe) {
else if self.eat_keyword(keywords::Unsafe) {
self.expect_keyword(keywords::Fn);
unsafe_fn
}
@ -4389,7 +4219,6 @@ impl Parser {
// parse type Foo = Bar;
fn parse_item_type(&self) -> item_info {
let ident = self.parse_ident();
self.parse_region_param();
let tps = self.parse_generics();
self.expect(&token::EQ);
let ty = self.parse_ty(false);
@ -4397,23 +4226,12 @@ impl Parser {
(ident, item_ty(ty, tps), None)
}
// parse obsolete region parameter
fn parse_region_param(&self) {
if self.eat(&token::BINOP(token::SLASH)) {
self.obsolete(*self.last_span, ObsoleteLifetimeNotation);
self.expect(&token::BINOP(token::AND));
}
}
// parse a structure-like enum variant definition
// this should probably be renamed or refactored...
fn parse_struct_def(&self) -> @struct_def {
let mut fields: ~[@struct_field] = ~[];
while *self.token != token::RBRACE {
let r = self.parse_struct_decl_field();
for struct_field in r.iter() {
fields.push(*struct_field);
}
fields.push(self.parse_struct_decl_field());
}
self.bump();
@ -4490,36 +4308,7 @@ impl Parser {
// parse an "enum" declaration
fn parse_item_enum(&self) -> item_info {
let id = self.parse_ident();
self.parse_region_param();
let generics = self.parse_generics();
// Newtype syntax
if *self.token == token::EQ {
// enum x = ty;
self.bump();
let ty = self.parse_ty(false);
self.expect(&token::SEMI);
let variant = spanned(ty.span.lo, ty.span.hi, ast::variant_ {
name: id,
attrs: ~[],
kind: tuple_variant_kind(
~[ast::variant_arg {ty: ty, id: ast::DUMMY_NODE_ID}]
),
id: ast::DUMMY_NODE_ID,
disr_expr: None,
vis: public,
});
self.obsolete(*self.last_span, ObsoleteNewtypeEnum);
return (
id,
item_enum(
ast::enum_def { variants: ~[variant] },
generics),
None
);
}
// enum X { ... }
self.expect(&token::LBRACE);
let enum_definition = self.parse_enum_def(&generics);
@ -4648,13 +4437,8 @@ impl Parser {
}
}
// the rest are all guaranteed to be items:
if (self.is_keyword(keywords::Const) ||
(self.is_keyword(keywords::Static) &&
self.look_ahead(1, |t| !token::is_keyword(keywords::Fn, t)))) {
// CONST / STATIC ITEM
if self.is_keyword(keywords::Const) {
self.obsolete(*self.span, ObsoleteConstItem);
}
if self.is_keyword(keywords::Static) {
// STATIC ITEM
self.bump();
let (ident, item_, extra_attrs) = self.parse_item_const();
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
@ -4671,16 +4455,6 @@ impl Parser {
visibility,
maybe_append(attrs, extra_attrs)));
}
if self.eat_keyword(keywords::Pure) {
// PURE FUNCTION ITEM (obsolete)
self.obsolete(*self.last_span, ObsoletePurity);
self.expect_keyword(keywords::Fn);
let (ident, item_, extra_attrs) =
self.parse_item_fn(impure_fn, AbiSet::Rust());
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility,
maybe_append(attrs, extra_attrs)));
}
if self.is_keyword(keywords::Unsafe)
&& self.look_ahead(1u, |t| *t != token::LBRACE) {
// UNSAFE FUNCTION ITEM
@ -4747,13 +4521,12 @@ impl Parser {
let visibility = self.parse_visibility();
if (self.is_keyword(keywords::Const) || self.is_keyword(keywords::Static)) {
// FOREIGN CONST ITEM
let item = self.parse_item_foreign_const(visibility, attrs);
if self.is_keyword(keywords::Static) {
// FOREIGN STATIC ITEM
let item = self.parse_item_foreign_static(visibility, attrs);
return iovi_foreign_item(item);
}
if (self.is_keyword(keywords::Fn) || self.is_keyword(keywords::Pure) ||
self.is_keyword(keywords::Unsafe)) {
if self.is_keyword(keywords::Fn) || self.is_keyword(keywords::Unsafe) {
// FOREIGN FUNCTION ITEM
let item = self.parse_item_foreign_fn(visibility, attrs);
return iovi_foreign_item(item);