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

@ -531,9 +531,7 @@ pub enum Expr_ {
ExprWhile(@Expr, Block),
// FIXME #6993: change to Option<Name>
ExprForLoop(@Pat, @Expr, Block, Option<Ident>),
/* Conditionless loop (can be exited with break, cont, or ret)
Same semantics as while(true) { body }, but typestate knows that the
(implicit) condition is always true. */
// Conditionless loop (can be exited with break, cont, or ret)
// FIXME #6993: change to Option<Name>
ExprLoop(Block, Option<Ident>),
ExprMatch(@Expr, ~[Arm]),

View File

@ -17,11 +17,10 @@ Obsolete syntax that becomes too hard to parse can be
removed.
*/
use ast::{Expr, ExprLit, lit_nil, Attribute};
use ast;
use ast::{Expr, ExprLit, lit_nil};
use codemap::{Span, respan};
use parse::parser::Parser;
use parse::token::{keywords, Token};
use parse::token::Token;
use parse::token;
use std::str;
@ -30,32 +29,9 @@ use std::to_bytes;
/// The specific types of unsupported syntax
#[deriving(Eq)]
pub enum ObsoleteSyntax {
ObsoleteLet,
ObsoleteFieldTerminator,
ObsoleteWith,
ObsoleteClassTraits,
ObsoletePrivSection,
ObsoleteModeInFnType,
ObsoleteMoveInit,
ObsoleteBinaryMove,
ObsoleteSwap,
ObsoleteUnsafeBlock,
ObsoleteUnenforcedBound,
ObsoleteImplSyntax,
ObsoleteMutOwnedPointer,
ObsoleteMutVector,
ObsoleteRecordType,
ObsoleteRecordPattern,
ObsoletePostFnTySigil,
ObsoleteBareFnType,
ObsoleteNewtypeEnum,
ObsoleteMode,
ObsoleteImplicitSelf,
ObsoleteLifetimeNotation,
ObsoletePurity,
ObsoleteStaticMethod,
ObsoleteConstItem,
ObsoleteFixedLengthVectorType,
ObsoleteNamedExternModule,
ObsoleteMultipleLocalDecl,
ObsoleteMutWithMultipleBindings,
@ -87,50 +63,12 @@ pub trait ParserObsoleteMethods {
fn token_is_obsolete_ident(&self, ident: &str, token: &Token) -> bool;
fn is_obsolete_ident(&self, ident: &str) -> bool;
fn eat_obsolete_ident(&self, ident: &str) -> bool;
fn try_parse_obsolete_with(&self) -> bool;
fn try_parse_obsolete_priv_section(&self, attrs: &[Attribute]) -> bool;
}
impl ParserObsoleteMethods for Parser {
/// Reports an obsolete syntax non-fatal error.
fn obsolete(&self, sp: Span, kind: ObsoleteSyntax) {
let (kind_str, desc) = match kind {
ObsoleteLet => (
"`let` in field declaration",
"declare fields as `field: Type`"
),
ObsoleteFieldTerminator => (
"field declaration terminated with semicolon",
"fields are now separated by commas"
),
ObsoleteWith => (
"with",
"record update is done with `..`, e.g. \
`MyStruct { foo: bar, .. baz }`"
),
ObsoleteClassTraits => (
"class traits",
"implemented traits are specified on the impl, as in \
`impl foo : bar {`"
),
ObsoletePrivSection => (
"private section",
"the `priv` keyword is applied to individual items, methods, \
and fields"
),
ObsoleteModeInFnType => (
"mode without identifier in fn type",
"to use a (deprecated) mode in a fn type, you should \
give the argument an explicit name (like `&&v: int`)"
),
ObsoleteMoveInit => (
"initializer-by-move",
"Write `let foo = move bar` instead"
),
ObsoleteBinaryMove => (
"binary move",
"Write `foo = move bar` instead"
),
ObsoleteSwap => (
"swap",
"Use std::util::{swap, replace} instead"
@ -139,79 +77,10 @@ impl ParserObsoleteMethods for Parser {
"non-standalone unsafe block",
"use an inner `unsafe { ... }` block instead"
),
ObsoleteUnenforcedBound => (
"unenforced type parameter bound",
"use trait bounds on the functions that take the type as \
arguments, not on the types themselves"
),
ObsoleteImplSyntax => (
"colon-separated impl syntax",
"write `impl Trait for Type`"
),
ObsoleteMutOwnedPointer => (
"const or mutable owned pointer",
"mutability inherits through `~` pointers; place the `~` box
in a mutable location, like a mutable local variable or an \
`@mut` box"
),
ObsoleteMutVector => (
"const or mutable vector",
"mutability inherits through `~` pointers; place the vector \
in a mutable location, like a mutable local variable or an \
`@mut` box"
),
ObsoleteRecordType => (
"structural record type",
"use a structure instead"
),
ObsoleteRecordPattern => (
"structural record pattern",
"use a structure instead"
),
ObsoletePostFnTySigil => (
"fn sigil in postfix position",
"Rather than `fn@`, `fn~`, or `fn&`, \
write `@fn`, `~fn`, and `&fn` respectively"
),
ObsoleteBareFnType => (
"bare function type",
"use `&fn` or `extern fn` instead"
),
ObsoleteNewtypeEnum => (
"newtype enum",
"instead of `enum Foo = int`, write `struct Foo(int)`"
),
ObsoleteMode => (
"obsolete argument mode",
"replace `-` or `++` mode with `+`"
),
ObsoleteImplicitSelf => (
"implicit self",
"use an explicit `self` declaration or declare the method as \
static"
),
ObsoleteLifetimeNotation => (
"`/` lifetime notation",
"instead of `&foo/bar`, write `&'foo bar`; instead of \
`bar/&foo`, write `&bar<'foo>"
),
ObsoletePurity => (
"pure function",
"remove `pure`"
),
ObsoleteStaticMethod => (
"`static` notation",
"`static` is superfluous; remove it"
),
ObsoleteConstItem => (
"`const` item",
"`const` items are now `static` items; replace `const` with \
`static`"
),
ObsoleteFixedLengthVectorType => (
"fixed-length vector notation",
"instead of `[T * N]`, write `[T, ..N]`"
),
ObsoleteNamedExternModule => (
"named external module",
"instead of `extern mod foo { ... }`, write `mod foo { \
@ -297,37 +166,4 @@ impl ParserObsoleteMethods for Parser {
false
}
}
fn try_parse_obsolete_with(&self) -> bool {
if *self.token == token::COMMA
&& self.look_ahead(1,
|t| self.token_is_obsolete_ident("with", t)) {
self.bump();
}
if self.eat_obsolete_ident("with") {
self.obsolete(*self.last_span, ObsoleteWith);
self.parse_expr();
true
} else {
false
}
}
fn try_parse_obsolete_priv_section(&self, attrs: &[Attribute])
-> bool {
if self.is_keyword(keywords::Priv) &&
self.look_ahead(1, |t| *t == token::LBRACE) {
self.obsolete(*self.span, ObsoletePrivSection);
self.eat_keyword(keywords::Priv);
self.bump();
while *self.token != token::RBRACE {
self.parse_single_struct_field(ast::private, attrs.to_owned());
}
self.bump();
true
} else {
false
}
}
}

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);

View File

@ -134,9 +134,6 @@ impl StrInterner {
new_idx
}
// this isn't "pure" in the traditional sense, because it can go from
// failing to returning a value as items are interned. But for typestate,
// where we first check a pred and then rely on it, ceasing to fail is ok.
pub fn get(&self, idx: uint) -> @str { self.vect[idx] }
pub fn len(&self) -> uint { let vect = &*self.vect; vect.len() }

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -8,47 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct s {
let foo: (),
//~^ ERROR obsolete syntax: `let` in field declaration
bar: ();
//~^ ERROR obsolete syntax: field declaration terminated with semicolon
}
struct q : r {
//~^ ERROR obsolete syntax: class traits
foo: int
}
struct sss {
bar: int,
priv {
//~^ ERROR obsolete syntax: private section
foo: ()
}
}
fn obsolete_with() {
struct S {
foo: (),
bar: (),
}
let a = S { foo: (), bar: () };
let b = S { foo: () with a };
//~^ ERROR obsolete syntax: with
let c = S { foo: (), with a };
//~^ ERROR obsolete syntax: with
}
fn obsolete_moves() {
let mut x = 0;
let y <- x;
//~^ ERROR obsolete syntax: initializer-by-move
y <- x;
//~^ ERROR obsolete syntax: binary move
}
extern mod obsolete_name {
//~^ ERROR obsolete syntax: named external module
fn bar();

View File

@ -0,0 +1,14 @@
// Copyright 2013 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.
struct q : r {
//~^ ERROR expected `{`, `(`, or `;` after struct name
foo: int
}

View File

@ -0,0 +1,11 @@
// Copyright 2013 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.
type closure = ~lt/fn(); //~ ERROR expected `;` but found `/`

View File

@ -0,0 +1,11 @@
// Copyright 2013 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.
const i: int = 42; //~ ERROR expected item but found `const`

View File

@ -0,0 +1,11 @@
// Copyright 2013 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.
enum e = int; //~ ERROR expected `{` but found `=`

View File

@ -0,0 +1,13 @@
// Copyright 2013 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.
extern {
const i: int; //~ ERROR unexpected token: `const`
}

View File

@ -0,0 +1,15 @@
// Copyright 2013 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.
struct s {
let foo: (),
//~^ ERROR found `let` in ident position
//~^^ ERROR expected `:` but found `foo`
}

View File

@ -0,0 +1,14 @@
// Copyright 2013 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.
struct s {
bar: ();
//~^ ERROR expected `,`, or `}` but found `;`
}

View File

@ -0,0 +1,11 @@
// Copyright 2013 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.
type v = [int * 3]; //~ ERROR expected `]` but found `*`

View File

@ -0,0 +1,11 @@
// Copyright 2013 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.
pure fn f() {} //~ ERROR expected item but found `pure`

View File

@ -0,0 +1,13 @@
// Copyright 2013 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 f() {
let x: fn~() = || (); //~ ERROR expected `(` but found `~`
}

View File

@ -0,0 +1,15 @@
// Copyright 2013 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 removed_moves() {
let mut x = 0;
let y <- x;
//~^ ERROR expected `;` but found `<-`
}

View File

@ -0,0 +1,16 @@
// Copyright 2013 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 removed_moves() {
let mut x = 0;
let y = 0;
y <- x;
//~^ ERROR expected one of `;`, `}` but found `<-`
}

View File

@ -0,0 +1,11 @@
// Copyright 2013 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 f(+x: int) {} //~ ERROR unexpected token: `+`

View File

@ -0,0 +1,15 @@
// Copyright 2013 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 f() {
let v = [mut 1, 2, 3, 4];
//~^ ERROR found `mut` in ident position
//~^^ ERROR expected `]` but found `1`
}

View File

@ -0,0 +1,13 @@
// Copyright 2013 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.
type v = [mut int];
//~^ ERROR found `mut` in ident position
//~^^ ERROR expected `]` but found `int`

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -8,16 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct cat : int { //~ ERROR trait
meows: uint,
}
fn cat(in_x : uint) -> cat {
cat {
meows: in_x
struct sss {
bar: int,
priv {
//~^ ERROR expected ident
foo: ()
}
}
fn main() {
let nyan = cat(0u);
}

View File

@ -0,0 +1,11 @@
// Copyright 2013 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.
type bptr = &lifetime/int; //~ ERROR expected `;` but found `/`

View File

@ -0,0 +1,11 @@
// Copyright 2013 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.
type t = { f: () }; //~ ERROR expected type, found token LBRACE

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -8,10 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern:unexpected token: `}`
// Issue #1200
struct S;
type t = {};
fn main() {
impl S {
static fn f() {} //~ ERROR unexpected token: `static`
}

View File

@ -0,0 +1,15 @@
// Copyright 2013 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 f() {
let box = ~mut 42;
//~^ ERROR found `mut` in ident position
//~^^ ERROR expected `;` but found `42`
}

View File

@ -0,0 +1,13 @@
// Copyright 2013 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.
type mut_box = ~mut int;
//~^ ERROR found `mut` in ident position
//~^^ ERROR expected `;` but found `int`

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -8,17 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use extra;
struct S;
struct Deserializer : extra::serialization::deserializer{ //~ ERROR obsolete syntax: class traits
x: ()
impl S {
fn f(~mut self) {} //~ ERROR mutability declaration not allowed here
}
struct Foo {
a: ()
}
fn deserialize_foo<__D: extra::serialization::deserializer>(__d: __D) {
}
fn main() { let des = Deserializer(); let foo = deserialize_foo(des); }

View File

@ -0,0 +1,20 @@
// Copyright 2013 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 removed_with() {
struct S {
foo: (),
bar: (),
}
let a = S { foo: (), bar: () };
let b = S { foo: () with a };
//~^ ERROR expected one of `,`, `}` but found `with`
}

View File

@ -0,0 +1,20 @@
// Copyright 2013 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 removed_with() {
struct S {
foo: (),
bar: (),
}
let a = S { foo: (), bar: () };
let b = S { foo: (), with a };
//~^ ERROR expected `:` but found `a`
}