2012-12-03 16:48:01 -08:00
|
|
|
// Copyright 2012 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.
|
|
|
|
|
2012-09-08 15:50:29 -07:00
|
|
|
/*!
|
|
|
|
Support for parsing unsupported, old syntaxes, for the
|
|
|
|
purpose of reporting errors. Parsing of these syntaxes
|
|
|
|
is tested by compile-test/obsolete-syntax.rs.
|
|
|
|
|
|
|
|
Obsolete syntax that becomes too hard to parse can be
|
|
|
|
removed.
|
|
|
|
*/
|
|
|
|
|
2013-01-08 19:37:25 -08:00
|
|
|
use core::prelude::*;
|
|
|
|
|
2012-09-08 15:50:29 -07:00
|
|
|
use ast::{expr, expr_lit, lit_nil};
|
2012-12-23 17:41:37 -05:00
|
|
|
use ast;
|
2013-01-30 09:56:33 -08:00
|
|
|
use codemap::{span, respan};
|
2013-01-08 19:37:25 -08:00
|
|
|
use parse::parser::Parser;
|
2012-12-13 13:05:22 -08:00
|
|
|
use parse::token::Token;
|
2012-12-23 17:41:37 -05:00
|
|
|
use parse::token;
|
|
|
|
|
|
|
|
use core::str;
|
|
|
|
use core::to_bytes;
|
2012-09-08 15:50:29 -07:00
|
|
|
|
|
|
|
/// The specific types of unsupported syntax
|
2013-03-20 11:52:45 -04:00
|
|
|
#[deriving(Eq)]
|
2012-09-08 15:50:29 -07:00
|
|
|
pub enum ObsoleteSyntax {
|
|
|
|
ObsoleteLowerCaseKindBounds,
|
|
|
|
ObsoleteLet,
|
|
|
|
ObsoleteFieldTerminator,
|
|
|
|
ObsoleteStructCtor,
|
2012-09-10 17:26:20 -07:00
|
|
|
ObsoleteWith,
|
2012-09-10 18:56:07 -07:00
|
|
|
ObsoleteClassTraits,
|
2012-09-23 04:39:27 -07:00
|
|
|
ObsoletePrivSection,
|
2012-10-05 22:07:53 -07:00
|
|
|
ObsoleteModeInFnType,
|
2012-10-23 11:28:20 -07:00
|
|
|
ObsoleteMoveInit,
|
2013-01-23 11:43:58 -08:00
|
|
|
ObsoleteBinaryMove,
|
2013-01-28 10:46:43 -08:00
|
|
|
ObsoleteUnsafeBlock,
|
2013-02-14 21:17:26 -08:00
|
|
|
ObsoleteUnenforcedBound,
|
2013-02-20 18:04:57 -08:00
|
|
|
ObsoleteImplSyntax,
|
|
|
|
ObsoleteTraitBoundSeparator,
|
2013-02-25 15:54:13 -08:00
|
|
|
ObsoleteMutOwnedPointer,
|
2013-02-26 14:50:09 -08:00
|
|
|
ObsoleteMutVector,
|
2013-02-26 17:12:00 -08:00
|
|
|
ObsoleteTraitImplVisibility,
|
2013-03-05 17:36:59 -08:00
|
|
|
ObsoleteRecordType,
|
2013-03-05 18:38:52 -08:00
|
|
|
ObsoleteRecordPattern,
|
2013-02-27 19:41:02 -05:00
|
|
|
ObsoletePostFnTySigil,
|
2013-03-07 15:44:21 -08:00
|
|
|
ObsoleteBareFnType,
|
2013-03-07 18:59:00 -08:00
|
|
|
ObsoleteNewtypeEnum,
|
2013-03-10 11:02:16 -04:00
|
|
|
ObsoleteMode,
|
2013-03-12 19:32:14 -07:00
|
|
|
ObsoleteImplicitSelf,
|
2013-03-14 12:25:48 -07:00
|
|
|
ObsoleteLifetimeNotation,
|
2013-03-21 15:39:17 -07:00
|
|
|
ObsoleteConstManagedPointer,
|
2013-03-22 12:56:10 -07:00
|
|
|
ObsoletePurity,
|
|
|
|
ObsoleteStaticMethod,
|
2012-09-19 18:00:26 -07:00
|
|
|
}
|
2012-09-08 15:50:29 -07:00
|
|
|
|
2013-02-26 17:12:00 -08:00
|
|
|
impl to_bytes::IterBytes for ObsoleteSyntax {
|
2012-11-28 11:36:04 -08:00
|
|
|
#[inline(always)]
|
2013-03-22 11:09:13 -07:00
|
|
|
fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
|
2012-11-28 11:36:04 -08:00
|
|
|
(*self as uint).iter_bytes(lsb0, f);
|
|
|
|
}
|
|
|
|
}
|
2012-09-08 15:50:29 -07:00
|
|
|
|
2013-01-29 13:54:06 -08:00
|
|
|
pub impl Parser {
|
2012-09-08 15:50:29 -07:00
|
|
|
/// Reports an obsolete syntax non-fatal error.
|
2013-03-02 13:02:27 -08:00
|
|
|
fn obsolete(&self, sp: span, kind: ObsoleteSyntax) {
|
2012-09-08 15:50:29 -07:00
|
|
|
let (kind_str, desc) = match kind {
|
|
|
|
ObsoleteLowerCaseKindBounds => (
|
|
|
|
"lower-case kind bounds",
|
|
|
|
"the `send`, `copy`, `const`, and `owned` \
|
|
|
|
kinds are represented as traits now, and \
|
|
|
|
should be camel cased"
|
|
|
|
),
|
|
|
|
ObsoleteLet => (
|
|
|
|
"`let` in field declaration",
|
|
|
|
"declare fields as `field: Type`"
|
|
|
|
),
|
|
|
|
ObsoleteFieldTerminator => (
|
|
|
|
"field declaration terminated with semicolon",
|
|
|
|
"fields are now separated by commas"
|
|
|
|
),
|
|
|
|
ObsoleteStructCtor => (
|
|
|
|
"struct constructor",
|
|
|
|
"structs are now constructed with `MyStruct { foo: val }` \
|
|
|
|
syntax. Structs with private fields cannot be created \
|
|
|
|
outside of their defining module"
|
|
|
|
),
|
|
|
|
ObsoleteWith => (
|
|
|
|
"with",
|
|
|
|
"record update is done with `..`, e.g. \
|
|
|
|
`MyStruct { foo: bar, .. baz }`"
|
|
|
|
),
|
2012-09-10 18:00:03 -07:00
|
|
|
ObsoleteClassTraits => (
|
|
|
|
"class traits",
|
|
|
|
"implemented traits are specified on the impl, as in \
|
|
|
|
`impl foo : bar {`"
|
|
|
|
),
|
2012-09-10 18:56:07 -07:00
|
|
|
ObsoletePrivSection => (
|
|
|
|
"private section",
|
|
|
|
"the `priv` keyword is applied to individual items, methods, \
|
|
|
|
and fields"
|
|
|
|
),
|
2012-09-23 04:39:27 -07:00
|
|
|
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`)"
|
|
|
|
),
|
2012-10-23 11:28:20 -07:00
|
|
|
ObsoleteMoveInit => (
|
|
|
|
"initializer-by-move",
|
|
|
|
"Write `let foo = move bar` instead"
|
|
|
|
),
|
|
|
|
ObsoleteBinaryMove => (
|
|
|
|
"binary move",
|
|
|
|
"Write `foo = move bar` instead"
|
2013-01-23 11:43:58 -08:00
|
|
|
),
|
|
|
|
ObsoleteUnsafeBlock => (
|
|
|
|
"non-standalone unsafe block",
|
|
|
|
"use an inner `unsafe { ... }` block instead"
|
2013-01-28 10:46:43 -08:00
|
|
|
),
|
|
|
|
ObsoleteUnenforcedBound => (
|
|
|
|
"unenforced type parameter bound",
|
|
|
|
"use trait bounds on the functions that take the type as \
|
|
|
|
arguments, not on the types themselves"
|
2013-02-14 21:17:26 -08:00
|
|
|
),
|
|
|
|
ObsoleteImplSyntax => (
|
|
|
|
"colon-separated impl syntax",
|
|
|
|
"write `impl Trait for Type`"
|
2013-02-20 18:04:57 -08:00
|
|
|
),
|
|
|
|
ObsoleteTraitBoundSeparator => (
|
|
|
|
"space-separated trait bounds",
|
|
|
|
"write `+` between trait bounds"
|
|
|
|
),
|
2013-02-25 15:54:13 -08:00
|
|
|
ObsoleteMutOwnedPointer => (
|
2013-02-26 11:32:00 -08:00
|
|
|
"const or mutable owned pointer",
|
2013-02-25 15:54:13 -08:00
|
|
|
"mutability inherits through `~` pointers; place the `~` box
|
|
|
|
in a mutable location, like a mutable local variable or an \
|
|
|
|
`@mut` box"
|
|
|
|
),
|
2013-02-26 14:50:09 -08:00
|
|
|
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"
|
|
|
|
),
|
2013-02-26 17:12:00 -08:00
|
|
|
ObsoleteTraitImplVisibility => (
|
|
|
|
"visibility-qualified trait implementation",
|
|
|
|
"`pub` or `priv` is meaningless for trait implementations, \
|
|
|
|
because the `impl...for...` form defines overloads for \
|
|
|
|
methods that already exist; remove the `pub` or `priv`"
|
|
|
|
),
|
2013-03-05 17:36:59 -08:00
|
|
|
ObsoleteRecordType => (
|
|
|
|
"structural record type",
|
|
|
|
"use a structure instead"
|
|
|
|
),
|
2013-03-05 18:38:52 -08:00
|
|
|
ObsoleteRecordPattern => (
|
|
|
|
"structural record pattern",
|
|
|
|
"use a structure instead"
|
|
|
|
),
|
2013-02-27 19:41:02 -05:00
|
|
|
ObsoletePostFnTySigil => (
|
|
|
|
"fn sigil in postfix position",
|
|
|
|
"Rather than `fn@`, `fn~`, or `fn&`, \
|
|
|
|
write `@fn`, `~fn`, and `&fn` respectively"
|
|
|
|
),
|
2013-03-07 15:44:21 -08:00
|
|
|
ObsoleteBareFnType => (
|
|
|
|
"bare function type",
|
|
|
|
"use `&fn` or `extern fn` instead"
|
|
|
|
),
|
2013-03-07 18:59:00 -08:00
|
|
|
ObsoleteNewtypeEnum => (
|
|
|
|
"newtype enum",
|
|
|
|
"instead of `enum Foo = int`, write `struct Foo(int)`"
|
|
|
|
),
|
2013-03-10 11:02:16 -04:00
|
|
|
ObsoleteMode => (
|
|
|
|
"obsolete argument mode",
|
|
|
|
"replace `-` or `++` mode with `+`"
|
|
|
|
),
|
2013-03-12 19:32:14 -07:00
|
|
|
ObsoleteImplicitSelf => (
|
|
|
|
"implicit self",
|
|
|
|
"use an explicit `self` declaration or declare the method as \
|
|
|
|
static"
|
|
|
|
),
|
2013-03-14 12:25:48 -07:00
|
|
|
ObsoleteLifetimeNotation => (
|
|
|
|
"`/` lifetime notation",
|
|
|
|
"instead of `&foo/bar`, write `&'foo bar`; instead of \
|
|
|
|
`bar/&foo`, write `&bar<'foo>"
|
|
|
|
),
|
2013-03-21 15:39:17 -07:00
|
|
|
ObsoleteConstManagedPointer => (
|
|
|
|
"const `@` pointer",
|
|
|
|
"instead of `@const Foo`, write `@Foo`"
|
|
|
|
),
|
2013-03-22 12:56:10 -07:00
|
|
|
ObsoletePurity => (
|
|
|
|
"pure function",
|
|
|
|
"remove `pure`"
|
|
|
|
),
|
|
|
|
ObsoleteStaticMethod => (
|
|
|
|
"`static` notation",
|
|
|
|
"`static` is superfluous; remove it"
|
|
|
|
),
|
2012-09-08 15:50:29 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
self.report(sp, kind, kind_str, desc);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reports an obsolete syntax non-fatal error, and returns
|
|
|
|
// a placeholder expression
|
2013-03-02 13:02:27 -08:00
|
|
|
fn obsolete_expr(&self, sp: span, kind: ObsoleteSyntax) -> @expr {
|
2012-09-08 15:50:29 -07:00
|
|
|
self.obsolete(sp, kind);
|
|
|
|
self.mk_expr(sp.lo, sp.hi, expr_lit(@respan(sp, lit_nil)))
|
|
|
|
}
|
|
|
|
|
2013-03-02 13:02:27 -08:00
|
|
|
priv fn report(&self, sp: span, kind: ObsoleteSyntax, kind_str: &str,
|
2012-09-08 15:50:29 -07:00
|
|
|
desc: &str) {
|
|
|
|
self.span_err(sp, fmt!("obsolete syntax: %s", kind_str));
|
|
|
|
|
2013-02-08 17:08:02 -05:00
|
|
|
if !self.obsolete_set.contains_key(&kind) {
|
2012-09-08 15:50:29 -07:00
|
|
|
self.sess.span_diagnostic.handler().note(fmt!("%s", desc));
|
|
|
|
self.obsolete_set.insert(kind, ());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-02 13:02:27 -08:00
|
|
|
fn token_is_obsolete_ident(&self, ident: &str, token: Token) -> bool {
|
2012-09-08 15:50:29 -07:00
|
|
|
match token {
|
|
|
|
token::IDENT(copy sid, _) => {
|
|
|
|
str::eq_slice(*self.id_to_str(sid), ident)
|
|
|
|
}
|
|
|
|
_ => false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-02 13:02:27 -08:00
|
|
|
fn is_obsolete_ident(&self, ident: &str) -> bool {
|
2013-02-21 18:12:13 -08:00
|
|
|
self.token_is_obsolete_ident(ident, *self.token)
|
2012-09-08 15:50:29 -07:00
|
|
|
}
|
|
|
|
|
2013-03-02 13:02:27 -08:00
|
|
|
fn eat_obsolete_ident(&self, ident: &str) -> bool {
|
2012-09-08 15:50:29 -07:00
|
|
|
if self.is_obsolete_ident(ident) {
|
|
|
|
self.bump();
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-02 13:02:27 -08:00
|
|
|
fn try_parse_obsolete_struct_ctor(&self) -> bool {
|
2012-09-08 15:50:29 -07:00
|
|
|
if self.eat_obsolete_ident("new") {
|
2013-02-21 18:12:13 -08:00
|
|
|
self.obsolete(*self.last_span, ObsoleteStructCtor);
|
2012-09-08 15:50:29 -07:00
|
|
|
self.parse_fn_decl(|p| p.parse_arg());
|
|
|
|
self.parse_block();
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-02 13:02:27 -08:00
|
|
|
fn try_parse_obsolete_with(&self) -> bool {
|
2013-02-21 18:12:13 -08:00
|
|
|
if *self.token == token::COMMA
|
2012-09-08 15:50:29 -07:00
|
|
|
&& self.token_is_obsolete_ident("with",
|
|
|
|
self.look_ahead(1u)) {
|
|
|
|
self.bump();
|
|
|
|
}
|
|
|
|
if self.eat_obsolete_ident("with") {
|
2013-02-21 18:12:13 -08:00
|
|
|
self.obsolete(*self.last_span, ObsoleteWith);
|
2012-09-08 15:50:29 -07:00
|
|
|
self.parse_expr();
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-02 13:02:27 -08:00
|
|
|
fn try_parse_obsolete_priv_section(&self) -> bool {
|
2013-02-24 09:39:29 -08:00
|
|
|
if self.is_keyword(&~"priv") && self.look_ahead(1) == token::LBRACE {
|
2013-02-24 18:32:02 -08:00
|
|
|
self.obsolete(copy *self.span, ObsoletePrivSection);
|
2013-02-24 09:39:29 -08:00
|
|
|
self.eat_keyword(&~"priv");
|
2012-09-10 18:56:07 -07:00
|
|
|
self.bump();
|
2013-02-21 18:12:13 -08:00
|
|
|
while *self.token != token::RBRACE {
|
2012-09-10 18:56:07 -07:00
|
|
|
self.parse_single_class_item(ast::private);
|
|
|
|
}
|
|
|
|
self.bump();
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
2012-10-20 16:33:59 -07:00
|
|
|
|
2012-09-08 15:50:29 -07:00
|
|
|
}
|
|
|
|
|