diff options
| author | Matthew <mjjasper1@gmail.com> | 2017-05-23 14:00:20 +0100 |
|---|---|---|
| committer | Matthew <mjjasper1@gmail.com> | 2017-05-23 14:00:20 +0100 |
| commit | 6627ef228c1396c045b3e9f24edaf66b76516cbd (patch) | |
| tree | fbead309f0165e668a895b2b33ce607aa0f4d2cb /src/libsyntax/parse | |
| parent | 158b085f06a41004ebf36d87afa3548f8b60861a (diff) | |
| parent | 852b7cb91ed44f6cc77f855bd8281da4accbd2fb (diff) | |
| download | rust-6627ef228c1396c045b3e9f24edaf66b76516cbd.tar.gz rust-6627ef228c1396c045b3e9f24edaf66b76516cbd.zip | |
Stabilize in 1.19
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/attr.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/parse/classify.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/parse/common.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/parse/lexer/comments.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/parse/lexer/mod.rs | 162 | ||||
| -rw-r--r-- | src/libsyntax/parse/mod.rs | 171 | ||||
| -rw-r--r-- | src/libsyntax/parse/obsolete.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 214 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 46 |
9 files changed, 319 insertions, 294 deletions
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 92cec462ffb..082930777e5 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -62,7 +62,7 @@ impl<'a> Parser<'a> { _ => break, } } - return Ok(attrs); + Ok(attrs) } /// Matches `attribute = # ! [ meta_item ]` @@ -182,7 +182,7 @@ impl<'a> Parser<'a> { } let attr = self.parse_attribute(true)?; - assert!(attr.style == ast::AttrStyle::Inner); + assert_eq!(attr.style, ast::AttrStyle::Inner); attrs.push(attr); } token::DocComment(s) => { diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs index 4fe4ec7e4c0..0c6f09ba766 100644 --- a/src/libsyntax/parse/classify.rs +++ b/src/libsyntax/parse/classify.rs @@ -43,14 +43,14 @@ pub fn expr_is_simple_block(e: &ast::Expr) -> bool { } /// this statement requires a semicolon after it. -/// note that in one case (stmt_semi), we've already +/// note that in one case (`stmt_semi`), we've already /// seen the semicolon, and thus don't need another. pub fn stmt_ends_with_semi(stmt: &ast::StmtKind) -> bool { match *stmt { ast::StmtKind::Local(_) => true, - ast::StmtKind::Item(_) => false, ast::StmtKind::Expr(ref e) => expr_requires_semi_to_be_stmt(e), - ast::StmtKind::Semi(..) => false, + ast::StmtKind::Item(_) | + ast::StmtKind::Semi(..) | ast::StmtKind::Mac(..) => false, } } diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs index b57708f9193..fe931f7cf6a 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -12,7 +12,7 @@ use parse::token; -/// SeqSep : a sequence separator (token) +/// `SeqSep` : a sequence separator (token) /// and whether a trailing separator is allowed. pub struct SeqSep { pub sep: Option<token::Token>, diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index c97b8ddf919..8b545d3b909 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -77,7 +77,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> String { while j > i && lines[j - 1].trim().is_empty() { j -= 1; } - lines[i..j].iter().cloned().collect() + lines[i..j].to_vec() } /// remove a "[ \t]*\*" block from each line, if possible @@ -348,8 +348,8 @@ pub fn gather_comments_and_literals(sess: &ParseSess, path: String, srdr: &mut R let mut src = Vec::new(); srdr.read_to_end(&mut src).unwrap(); let src = String::from_utf8(src).unwrap(); - let cm = CodeMap::new(); - let filemap = cm.new_filemap(path, None, src); + let cm = CodeMap::new(sess.codemap().path_mapping().clone()); + let filemap = cm.new_filemap(path, src); let mut rdr = lexer::StringReader::new_raw(sess, filemap); let mut comments: Vec<Comment> = Vec::new(); diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 920b2c401e2..0bcd4578518 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -10,7 +10,7 @@ use ast::{self, Ident}; use syntax_pos::{self, BytePos, CharPos, Pos, Span, NO_EXPANSION}; -use codemap::CodeMap; +use codemap::{CodeMap, FilePathMapping}; use errors::{FatalError, DiagnosticBuilder}; use parse::{token, ParseSess}; use str::char_at; @@ -73,7 +73,7 @@ fn mk_sp(lo: BytePos, hi: BytePos) -> Span { } impl<'a> StringReader<'a> { - fn next_token(&mut self) -> TokenAndSpan where Self: Sized { + fn next_token(&mut self) -> TokenAndSpan { let res = self.try_next_token(); self.unwrap_or_abort(res) } @@ -144,7 +144,7 @@ impl<'a> StringReader<'a> { impl<'a> StringReader<'a> { /// For comments.rs, which hackily pokes into next_pos and ch - pub fn new_raw<'b>(sess: &'a ParseSess, filemap: Rc<syntax_pos::FileMap>) -> Self { + pub fn new_raw(sess: &'a ParseSess, filemap: Rc<syntax_pos::FileMap>) -> Self { let mut sr = StringReader::new_raw_internal(sess, filemap); sr.bump(); sr @@ -180,7 +180,7 @@ impl<'a> StringReader<'a> { pub fn new(sess: &'a ParseSess, filemap: Rc<syntax_pos::FileMap>) -> Self { let mut sr = StringReader::new_raw(sess, filemap); - if let Err(_) = sr.advance_token() { + if sr.advance_token().is_err() { sr.emit_fatal_errors(); panic!(FatalError); } @@ -205,7 +205,7 @@ impl<'a> StringReader<'a> { sr.bump(); - if let Err(_) = sr.advance_token() { + if sr.advance_token().is_err() { sr.emit_fatal_errors(); panic!(FatalError); } @@ -504,7 +504,7 @@ impl<'a> StringReader<'a> { self.bump(); // line comments starting with "///" or "//!" are doc-comments - let doc_comment = self.ch_is('/') || self.ch_is('!'); + let doc_comment = (self.ch_is('/') && !self.nextch_is('/')) || self.ch_is('!'); let start_bpos = self.pos - BytePos(2); while !self.is_eof() { @@ -525,7 +525,7 @@ impl<'a> StringReader<'a> { self.bump(); } - return if doc_comment { + if doc_comment { self.with_str_from(start_bpos, |string| { // comments with only more "/"s are not doc comments let tok = if is_doc_comment(string) { @@ -544,7 +544,7 @@ impl<'a> StringReader<'a> { tok: token::Comment, sp: mk_sp(start_bpos, self.pos), }) - }; + } } Some('*') => { self.bump(); @@ -563,7 +563,7 @@ impl<'a> StringReader<'a> { // I guess this is the only way to figure out if // we're at the beginning of the file... - let cmap = CodeMap::new(); + let cmap = CodeMap::new(FilePathMapping::empty()); cmap.files.borrow_mut().push(self.filemap.clone()); let loc = cmap.lookup_char_pos_adj(self.pos); debug!("Skipping a shebang"); @@ -754,9 +754,7 @@ impl<'a> StringReader<'a> { // integer literal followed by field/method access or a range pattern // (`0..2` and `12.foo()`) if self.ch_is('.') && !self.nextch_is('.') && - !self.nextch() - .unwrap_or('\0') - .is_xid_start() { + !ident_start(self.nextch()) { // might have stuff after the ., and if it does, it needs to start // with a number self.bump(); @@ -766,7 +764,7 @@ impl<'a> StringReader<'a> { } let pos = self.pos; self.check_float_base(start_bpos, pos, base); - return token::Float(self.name_from(start_bpos)); + token::Float(self.name_from(start_bpos)) } else { // it might be a float if it has an exponent if self.ch_is('e') || self.ch_is('E') { @@ -776,7 +774,7 @@ impl<'a> StringReader<'a> { return token::Float(self.name_from(start_bpos)); } // but we certainly have an integer! - return token::Integer(self.name_from(start_bpos)); + token::Integer(self.name_from(start_bpos)) } } @@ -1053,9 +1051,9 @@ impl<'a> StringReader<'a> { self.bump(); if self.ch_is('=') { self.bump(); - return token::BinOpEq(op); + token::BinOpEq(op) } else { - return token::BinOp(op); + token::BinOp(op) } } @@ -1102,15 +1100,15 @@ impl<'a> StringReader<'a> { // One-byte tokens. ';' => { self.bump(); - return Ok(token::Semi); + Ok(token::Semi) } ',' => { self.bump(); - return Ok(token::Comma); + Ok(token::Comma) } '.' => { self.bump(); - return if self.ch_is('.') { + if self.ch_is('.') { self.bump(); if self.ch_is('.') { self.bump(); @@ -1120,61 +1118,61 @@ impl<'a> StringReader<'a> { } } else { Ok(token::Dot) - }; + } } '(' => { self.bump(); - return Ok(token::OpenDelim(token::Paren)); + Ok(token::OpenDelim(token::Paren)) } ')' => { self.bump(); - return Ok(token::CloseDelim(token::Paren)); + Ok(token::CloseDelim(token::Paren)) } '{' => { self.bump(); - return Ok(token::OpenDelim(token::Brace)); + Ok(token::OpenDelim(token::Brace)) } '}' => { self.bump(); - return Ok(token::CloseDelim(token::Brace)); + Ok(token::CloseDelim(token::Brace)) } '[' => { self.bump(); - return Ok(token::OpenDelim(token::Bracket)); + Ok(token::OpenDelim(token::Bracket)) } ']' => { self.bump(); - return Ok(token::CloseDelim(token::Bracket)); + Ok(token::CloseDelim(token::Bracket)) } '@' => { self.bump(); - return Ok(token::At); + Ok(token::At) } '#' => { self.bump(); - return Ok(token::Pound); + Ok(token::Pound) } '~' => { self.bump(); - return Ok(token::Tilde); + Ok(token::Tilde) } '?' => { self.bump(); - return Ok(token::Question); + Ok(token::Question) } ':' => { self.bump(); if self.ch_is(':') { self.bump(); - return Ok(token::ModSep); + Ok(token::ModSep) } else { - return Ok(token::Colon); + Ok(token::Colon) } } '$' => { self.bump(); - return Ok(token::Dollar); + Ok(token::Dollar) } // Multi-byte tokens. @@ -1182,21 +1180,21 @@ impl<'a> StringReader<'a> { self.bump(); if self.ch_is('=') { self.bump(); - return Ok(token::EqEq); + Ok(token::EqEq) } else if self.ch_is('>') { self.bump(); - return Ok(token::FatArrow); + Ok(token::FatArrow) } else { - return Ok(token::Eq); + Ok(token::Eq) } } '!' => { self.bump(); if self.ch_is('=') { self.bump(); - return Ok(token::Ne); + Ok(token::Ne) } else { - return Ok(token::Not); + Ok(token::Not) } } '<' => { @@ -1204,21 +1202,21 @@ impl<'a> StringReader<'a> { match self.ch.unwrap_or('\x00') { '=' => { self.bump(); - return Ok(token::Le); + Ok(token::Le) } '<' => { - return Ok(self.binop(token::Shl)); + Ok(self.binop(token::Shl)) } '-' => { self.bump(); match self.ch.unwrap_or('\x00') { _ => { - return Ok(token::LArrow); + Ok(token::LArrow) } } } _ => { - return Ok(token::Lt); + Ok(token::Lt) } } } @@ -1227,13 +1225,13 @@ impl<'a> StringReader<'a> { match self.ch.unwrap_or('\x00') { '=' => { self.bump(); - return Ok(token::Ge); + Ok(token::Ge) } '>' => { - return Ok(self.binop(token::Shr)); + Ok(self.binop(token::Shr)) } _ => { - return Ok(token::Gt); + Ok(token::Gt) } } } @@ -1303,7 +1301,7 @@ impl<'a> StringReader<'a> { }; self.bump(); // advance ch past token let suffix = self.scan_optional_raw_name(); - return Ok(token::Literal(token::Char(id), suffix)); + Ok(token::Literal(token::Char(id), suffix)) } 'b' => { self.bump(); @@ -1314,7 +1312,7 @@ impl<'a> StringReader<'a> { _ => unreachable!(), // Should have been a token::Ident above. }; let suffix = self.scan_optional_raw_name(); - return Ok(token::Literal(lit, suffix)); + Ok(token::Literal(lit, suffix)) } '"' => { let start_bpos = self.pos; @@ -1345,7 +1343,7 @@ impl<'a> StringReader<'a> { }; self.bump(); let suffix = self.scan_optional_raw_name(); - return Ok(token::Literal(token::Str_(id), suffix)); + Ok(token::Literal(token::Str_(id), suffix)) } 'r' => { let start_bpos = self.pos; @@ -1416,24 +1414,24 @@ impl<'a> StringReader<'a> { Symbol::intern("??") }; let suffix = self.scan_optional_raw_name(); - return Ok(token::Literal(token::StrRaw(id, hash_count), suffix)); + Ok(token::Literal(token::StrRaw(id, hash_count), suffix)) } '-' => { if self.nextch_is('>') { self.bump(); self.bump(); - return Ok(token::RArrow); + Ok(token::RArrow) } else { - return Ok(self.binop(token::Minus)); + Ok(self.binop(token::Minus)) } } '&' => { if self.nextch_is('&') { self.bump(); self.bump(); - return Ok(token::AndAnd); + Ok(token::AndAnd) } else { - return Ok(self.binop(token::And)); + Ok(self.binop(token::And)) } } '|' => { @@ -1441,27 +1439,27 @@ impl<'a> StringReader<'a> { Some('|') => { self.bump(); self.bump(); - return Ok(token::OrOr); + Ok(token::OrOr) } _ => { - return Ok(self.binop(token::Or)); + Ok(self.binop(token::Or)) } } } '+' => { - return Ok(self.binop(token::Plus)); + Ok(self.binop(token::Plus)) } '*' => { - return Ok(self.binop(token::Star)); + Ok(self.binop(token::Star)) } '/' => { - return Ok(self.binop(token::Slash)); + Ok(self.binop(token::Slash)) } '^' => { - return Ok(self.binop(token::Caret)); + Ok(self.binop(token::Caret)) } '%' => { - return Ok(self.binop(token::Percent)); + Ok(self.binop(token::Percent)) } c => { let last_bpos = self.pos; @@ -1470,7 +1468,7 @@ impl<'a> StringReader<'a> { bpos, "unknown start of token", c); - unicode_chars::check_for_substitution(&self, c, &mut err); + unicode_chars::check_for_substitution(self, c, &mut err); self.fatal_errs.push(err); Err(()) } @@ -1492,14 +1490,14 @@ impl<'a> StringReader<'a> { if self.ch_is('\n') { self.bump(); } - return val; + val } fn read_one_line_comment(&mut self) -> String { let val = self.read_to_eol(); assert!((val.as_bytes()[0] == b'/' && val.as_bytes()[1] == b'/') || (val.as_bytes()[0] == b'#' && val.as_bytes()[1] == b'!')); - return val; + val } fn consume_non_eol_whitespace(&mut self) { @@ -1543,7 +1541,7 @@ impl<'a> StringReader<'a> { Symbol::intern("?") }; self.bump(); // advance ch past token - return token::Byte(id); + token::Byte(id) } fn scan_byte_escape(&mut self, delim: char, below_0x7f_only: bool) -> bool { @@ -1576,7 +1574,7 @@ impl<'a> StringReader<'a> { Symbol::intern("??") }; self.bump(); - return token::ByteStr(id); + token::ByteStr(id) } fn scan_raw_byte_string(&mut self) -> token::Lit { @@ -1629,8 +1627,8 @@ impl<'a> StringReader<'a> { self.bump(); } self.bump(); - return token::ByteStrRaw(self.name_from_to(content_start_bpos, content_end_bpos), - hash_count); + token::ByteStrRaw(self.name_from_to(content_start_bpos, content_end_bpos), + hash_count) } } @@ -1648,7 +1646,7 @@ fn in_range(c: Option<char>, lo: char, hi: char) -> bool { } fn is_dec_digit(c: Option<char>) -> bool { - return in_range(c, '0', '9'); + in_range(c, '0', '9') } pub fn is_doc_comment(s: &str) -> bool { @@ -1718,13 +1716,13 @@ mod tests { sess: &'a ParseSess, teststr: String) -> StringReader<'a> { - let fm = cm.new_filemap("zebra.rs".to_string(), None, teststr); + let fm = cm.new_filemap("zebra.rs".to_string(), teststr); StringReader::new(sess, fm) } #[test] fn t1() { - let cm = Rc::new(CodeMap::new()); + let cm = Rc::new(CodeMap::new(FilePathMapping::empty())); let sh = mk_sess(cm.clone()); let mut string_reader = setup(&cm, &sh, @@ -1776,7 +1774,7 @@ mod tests { #[test] fn doublecolonparsing() { - let cm = Rc::new(CodeMap::new()); + let cm = Rc::new(CodeMap::new(FilePathMapping::empty())); let sh = mk_sess(cm.clone()); check_tokenization(setup(&cm, &sh, "a b".to_string()), vec![mk_ident("a"), token::Whitespace, mk_ident("b")]); @@ -1784,7 +1782,7 @@ mod tests { #[test] fn dcparsing_2() { - let cm = Rc::new(CodeMap::new()); + let cm = Rc::new(CodeMap::new(FilePathMapping::empty())); let sh = mk_sess(cm.clone()); check_tokenization(setup(&cm, &sh, "a::b".to_string()), vec![mk_ident("a"), token::ModSep, mk_ident("b")]); @@ -1792,7 +1790,7 @@ mod tests { #[test] fn dcparsing_3() { - let cm = Rc::new(CodeMap::new()); + let cm = Rc::new(CodeMap::new(FilePathMapping::empty())); let sh = mk_sess(cm.clone()); check_tokenization(setup(&cm, &sh, "a ::b".to_string()), vec![mk_ident("a"), token::Whitespace, token::ModSep, mk_ident("b")]); @@ -1800,7 +1798,7 @@ mod tests { #[test] fn dcparsing_4() { - let cm = Rc::new(CodeMap::new()); + let cm = Rc::new(CodeMap::new(FilePathMapping::empty())); let sh = mk_sess(cm.clone()); check_tokenization(setup(&cm, &sh, "a:: b".to_string()), vec![mk_ident("a"), token::ModSep, token::Whitespace, mk_ident("b")]); @@ -1808,7 +1806,7 @@ mod tests { #[test] fn character_a() { - let cm = Rc::new(CodeMap::new()); + let cm = Rc::new(CodeMap::new(FilePathMapping::empty())); let sh = mk_sess(cm.clone()); assert_eq!(setup(&cm, &sh, "'a'".to_string()).next_token().tok, token::Literal(token::Char(Symbol::intern("a")), None)); @@ -1816,7 +1814,7 @@ mod tests { #[test] fn character_space() { - let cm = Rc::new(CodeMap::new()); + let cm = Rc::new(CodeMap::new(FilePathMapping::empty())); let sh = mk_sess(cm.clone()); assert_eq!(setup(&cm, &sh, "' '".to_string()).next_token().tok, token::Literal(token::Char(Symbol::intern(" ")), None)); @@ -1824,7 +1822,7 @@ mod tests { #[test] fn character_escaped() { - let cm = Rc::new(CodeMap::new()); + let cm = Rc::new(CodeMap::new(FilePathMapping::empty())); let sh = mk_sess(cm.clone()); assert_eq!(setup(&cm, &sh, "'\\n'".to_string()).next_token().tok, token::Literal(token::Char(Symbol::intern("\\n")), None)); @@ -1832,7 +1830,7 @@ mod tests { #[test] fn lifetime_name() { - let cm = Rc::new(CodeMap::new()); + let cm = Rc::new(CodeMap::new(FilePathMapping::empty())); let sh = mk_sess(cm.clone()); assert_eq!(setup(&cm, &sh, "'abc".to_string()).next_token().tok, token::Lifetime(Ident::from_str("'abc"))); @@ -1840,7 +1838,7 @@ mod tests { #[test] fn raw_string() { - let cm = Rc::new(CodeMap::new()); + let cm = Rc::new(CodeMap::new(FilePathMapping::empty())); let sh = mk_sess(cm.clone()); assert_eq!(setup(&cm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string()) .next_token() @@ -1850,7 +1848,7 @@ mod tests { #[test] fn literal_suffixes() { - let cm = Rc::new(CodeMap::new()); + let cm = Rc::new(CodeMap::new(FilePathMapping::empty())); let sh = mk_sess(cm.clone()); macro_rules! test { ($input: expr, $tok_type: ident, $tok_contents: expr) => {{ @@ -1894,7 +1892,7 @@ mod tests { #[test] fn nested_block_comments() { - let cm = Rc::new(CodeMap::new()); + let cm = Rc::new(CodeMap::new(FilePathMapping::empty())); let sh = mk_sess(cm.clone()); let mut lexer = setup(&cm, &sh, "/* /* */ */'a'".to_string()); match lexer.next_token().tok { @@ -1907,7 +1905,7 @@ mod tests { #[test] fn crlf_comments() { - let cm = Rc::new(CodeMap::new()); + let cm = Rc::new(CodeMap::new(FilePathMapping::empty())); let sh = mk_sess(cm.clone()); let mut lexer = setup(&cm, &sh, "// test\r\n/// test\r\n".to_string()); let comment = lexer.next_token(); diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index c63a6524f74..1eff819d755 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -11,7 +11,7 @@ //! The main parser interface use ast::{self, CrateConfig}; -use codemap::CodeMap; +use codemap::{CodeMap, FilePathMapping}; use syntax_pos::{self, Span, FileMap, NO_EXPANSION}; use errors::{Handler, ColorConfig, DiagnosticBuilder}; use feature_gate::UnstableFeatures; @@ -53,8 +53,8 @@ pub struct ParseSess { } impl ParseSess { - pub fn new() -> Self { - let cm = Rc::new(CodeMap::new()); + pub fn new(file_path_mapping: FilePathMapping) -> Self { + let cm = Rc::new(CodeMap::new(file_path_mapping)); let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, false, @@ -107,18 +107,18 @@ pub fn parse_crate_attrs_from_file<'a>(input: &Path, sess: &'a ParseSess) parser.parse_inner_attributes() } -pub fn parse_crate_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess) - -> PResult<'a, ast::Crate> { +pub fn parse_crate_from_source_str(name: String, source: String, sess: &ParseSess) + -> PResult<ast::Crate> { new_parser_from_source_str(sess, name, source).parse_crate_mod() } -pub fn parse_crate_attrs_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess) - -> PResult<'a, Vec<ast::Attribute>> { +pub fn parse_crate_attrs_from_source_str(name: String, source: String, sess: &ParseSess) + -> PResult<Vec<ast::Attribute>> { new_parser_from_source_str(sess, name, source).parse_inner_attributes() } -pub fn parse_expr_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess) - -> PResult<'a, P<ast::Expr>> { +pub fn parse_expr_from_source_str(name: String, source: String, sess: &ParseSess) + -> PResult<P<ast::Expr>> { new_parser_from_source_str(sess, name, source).parse_expr() } @@ -126,30 +126,30 @@ pub fn parse_expr_from_source_str<'a>(name: String, source: String, sess: &'a Pa /// /// Returns `Ok(Some(item))` when successful, `Ok(None)` when no item was found, and`Err` /// when a syntax error occurred. -pub fn parse_item_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess) - -> PResult<'a, Option<P<ast::Item>>> { +pub fn parse_item_from_source_str(name: String, source: String, sess: &ParseSess) + -> PResult<Option<P<ast::Item>>> { new_parser_from_source_str(sess, name, source).parse_item() } -pub fn parse_meta_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess) - -> PResult<'a, ast::MetaItem> { +pub fn parse_meta_from_source_str(name: String, source: String, sess: &ParseSess) + -> PResult<ast::MetaItem> { new_parser_from_source_str(sess, name, source).parse_meta_item() } -pub fn parse_stmt_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess) - -> PResult<'a, Option<ast::Stmt>> { +pub fn parse_stmt_from_source_str(name: String, source: String, sess: &ParseSess) + -> PResult<Option<ast::Stmt>> { new_parser_from_source_str(sess, name, source).parse_stmt() } -pub fn parse_stream_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess) +pub fn parse_stream_from_source_str(name: String, source: String, sess: &ParseSess) -> TokenStream { - filemap_to_stream(sess, sess.codemap().new_filemap(name, None, source)) + filemap_to_stream(sess, sess.codemap().new_filemap(name, source)) } // Create a new parser from a source string -pub fn new_parser_from_source_str<'a>(sess: &'a ParseSess, name: String, source: String) - -> Parser<'a> { - filemap_to_parser(sess, sess.codemap().new_filemap(name, None, source)) +pub fn new_parser_from_source_str(sess: &ParseSess, name: String, source: String) + -> Parser { + filemap_to_parser(sess, sess.codemap().new_filemap(name, source)) } /// Create a new parser, handling errors as appropriate @@ -173,7 +173,7 @@ pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess, } /// Given a filemap and config, return a parser -pub fn filemap_to_parser<'a>(sess: &'a ParseSess, filemap: Rc<FileMap>, ) -> Parser<'a> { +pub fn filemap_to_parser(sess: & ParseSess, filemap: Rc<FileMap>, ) -> Parser { let end_pos = filemap.end_pos; let mut parser = stream_to_parser(sess, filemap_to_stream(sess, filemap)); @@ -186,7 +186,7 @@ pub fn filemap_to_parser<'a>(sess: &'a ParseSess, filemap: Rc<FileMap>, ) -> Par // must preserve old name for now, because quote! from the *existing* // compiler expands into it -pub fn new_parser_from_tts<'a>(sess: &'a ParseSess, tts: Vec<TokenTree>) -> Parser<'a> { +pub fn new_parser_from_tts(sess: &ParseSess, tts: Vec<TokenTree>) -> Parser { stream_to_parser(sess, tts.into_iter().collect()) } @@ -216,8 +216,8 @@ pub fn filemap_to_stream(sess: &ParseSess, filemap: Rc<FileMap>) -> TokenStream panictry!(srdr.parse_all_token_trees()) } -/// Given stream and the ParseSess, produce a parser -pub fn stream_to_parser<'a>(sess: &'a ParseSess, stream: TokenStream) -> Parser<'a> { +/// Given stream and the `ParseSess`, produce a parser +pub fn stream_to_parser(sess: &ParseSess, stream: TokenStream) -> Parser { Parser::new(sess, stream, None, false) } @@ -251,7 +251,7 @@ pub fn char_lit(lit: &str) -> (char, isize) { (c, 4) } 'u' => { - assert!(lit.as_bytes()[2] == b'{'); + assert_eq!(lit.as_bytes()[2], b'{'); let idx = lit.find('}').unwrap(); let v = u32::from_str_radix(&lit[3..idx], 16).unwrap(); let c = char::from_u32(v).unwrap(); @@ -261,10 +261,14 @@ pub fn char_lit(lit: &str) -> (char, isize) { } } +pub fn escape_default(s: &str) -> String { + s.chars().map(char::escape_default).flat_map(|x| x).collect() +} + /// Parse a string representing a string literal into its final form. Does /// unescaping. pub fn str_lit(lit: &str) -> String { - debug!("parse_str_lit: given {}", lit.escape_default()); + debug!("parse_str_lit: given {}", escape_default(lit)); let mut res = String::with_capacity(lit.len()); // FIXME #8372: This could be a for-loop if it didn't borrow the iterator @@ -283,51 +287,46 @@ pub fn str_lit(lit: &str) -> String { } let mut chars = lit.char_indices().peekable(); - loop { - match chars.next() { - Some((i, c)) => { - match c { - '\\' => { - let ch = chars.peek().unwrap_or_else(|| { - panic!("{}", error(i)) - }).1; - - if ch == '\n' { - eat(&mut chars); - } else if ch == '\r' { - chars.next(); - let ch = chars.peek().unwrap_or_else(|| { - panic!("{}", error(i)) - }).1; - - if ch != '\n' { - panic!("lexer accepted bare CR"); - } - eat(&mut chars); - } else { - // otherwise, a normal escape - let (c, n) = char_lit(&lit[i..]); - for _ in 0..n - 1 { // we don't need to move past the first \ - chars.next(); - } - res.push(c); - } - }, - '\r' => { - let ch = chars.peek().unwrap_or_else(|| { - panic!("{}", error(i)) - }).1; + while let Some((i, c)) = chars.next() { + match c { + '\\' => { + let ch = chars.peek().unwrap_or_else(|| { + panic!("{}", error(i)) + }).1; + + if ch == '\n' { + eat(&mut chars); + } else if ch == '\r' { + chars.next(); + let ch = chars.peek().unwrap_or_else(|| { + panic!("{}", error(i)) + }).1; - if ch != '\n' { - panic!("lexer accepted bare CR"); - } + if ch != '\n' { + panic!("lexer accepted bare CR"); + } + eat(&mut chars); + } else { + // otherwise, a normal escape + let (c, n) = char_lit(&lit[i..]); + for _ in 0..n - 1 { // we don't need to move past the first \ chars.next(); - res.push('\n'); } - c => res.push(c), + res.push(c); } }, - None => break + '\r' => { + let ch = chars.peek().unwrap_or_else(|| { + panic!("{}", error(i)) + }).1; + + if ch != '\n' { + panic!("lexer accepted bare CR"); + } + chars.next(); + res.push('\n'); + } + c => res.push(c), } } @@ -339,25 +338,19 @@ pub fn str_lit(lit: &str) -> String { /// Parse a string representing a raw string literal into its final form. The /// only operation this does is convert embedded CRLF into a single LF. pub fn raw_str_lit(lit: &str) -> String { - debug!("raw_str_lit: given {}", lit.escape_default()); + debug!("raw_str_lit: given {}", escape_default(lit)); let mut res = String::with_capacity(lit.len()); - // FIXME #8372: This could be a for-loop if it didn't borrow the iterator let mut chars = lit.chars().peekable(); - loop { - match chars.next() { - Some(c) => { - if c == '\r' { - if *chars.peek().unwrap() != '\n' { - panic!("lexer accepted bare CR"); - } - chars.next(); - res.push('\n'); - } else { - res.push(c); - } - }, - None => break + while let Some(c) = chars.next() { + if c == '\r' { + if *chars.peek().unwrap() != '\n' { + panic!("lexer accepted bare CR"); + } + chars.next(); + res.push('\n'); + } else { + res.push(c); } } @@ -455,7 +448,7 @@ pub fn byte_lit(lit: &str) -> (u8, usize) { if lit.len() == 1 { (lit.as_bytes()[0], 1) } else { - assert!(lit.as_bytes()[0] == b'\\', err(0)); + assert_eq!(lit.as_bytes()[0], b'\\', "{}", err(0)); let b = match lit.as_bytes()[1] { b'"' => b'"', b'n' => b'\n', @@ -476,7 +469,7 @@ pub fn byte_lit(lit: &str) -> (u8, usize) { } } }; - return (b, 2); + (b, 2) } } @@ -487,7 +480,7 @@ pub fn byte_str_lit(lit: &str) -> Rc<Vec<u8>> { let error = |i| format!("lexer should have rejected {} at {}", lit, i); /// Eat everything up to a non-whitespace - fn eat<'a, I: Iterator<Item=(usize, u8)>>(it: &mut iter::Peekable<I>) { + fn eat<I: Iterator<Item=(usize, u8)>>(it: &mut iter::Peekable<I>) { loop { match it.peek().map(|x| x.1) { Some(b' ') | Some(b'\n') | Some(b'\r') | Some(b'\t') => { @@ -574,7 +567,7 @@ pub fn integer_lit(s: &str, suffix: Option<Symbol>, diag: Option<(Span, &Handler if let Some(err) = err { err!(diag, |span, diag| diag.span_err(span, err)); } - return filtered_float_lit(Symbol::intern(&s), Some(suf), diag) + return filtered_float_lit(Symbol::intern(s), Some(suf), diag) } } @@ -828,7 +821,7 @@ mod tests { } #[test] fn parse_ident_pat () { - let sess = ParseSess::new(); + let sess = ParseSess::new(FilePathMapping::empty()); let mut parser = string_to_parser(&sess, "b".to_string()); assert!(panictry!(parser.parse_pat()) == P(ast::Pat{ @@ -998,7 +991,7 @@ mod tests { } #[test] fn crlf_doc_comments() { - let sess = ParseSess::new(); + let sess = ParseSess::new(FilePathMapping::empty()); let name = "<source>".to_string(); let source = "/// doc comment\r\nfn foo() {}".to_string(); @@ -1023,7 +1016,7 @@ mod tests { #[test] fn ttdelim_span() { - let sess = ParseSess::new(); + let sess = ParseSess::new(FilePathMapping::empty()); let expr = parse::parse_expr_from_source_str("foo".to_string(), "foo!( fn main() { body } )".to_string(), &sess).unwrap(); diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index d5baec675e4..078e86aa294 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -59,7 +59,7 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { if !self.obsolete_set.contains(&kind) && (error || self.sess.span_diagnostic.can_emit_warnings) { - err.note(&format!("{}", desc)); + err.note(desc); self.obsolete_set.insert(kind); } err.emit(); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1baf0d1b54c..4741f896d3c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -57,12 +57,14 @@ use tokenstream::{self, Delimited, ThinTokenStream, TokenTree, TokenStream}; use symbol::{Symbol, keywords}; use util::ThinVec; +use std::cmp; use std::collections::HashSet; -use std::{cmp, mem, slice}; +use std::mem; use std::path::{self, Path, PathBuf}; +use std::slice; bitflags! { - flags Restrictions: u8 { + pub flags Restrictions: u8 { const RESTRICTION_STMT_EXPR = 1 << 0, const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1, } @@ -246,7 +248,7 @@ impl TokenCursor { fn next_desugared(&mut self) -> TokenAndSpan { let (sp, name) = match self.next() { TokenAndSpan { sp, tok: token::DocComment(name) } => (sp, name), - tok @ _ => return tok, + tok => return tok, }; let stripped = strip_doc_comment_decoration(&name.as_str()); @@ -352,7 +354,7 @@ pub enum Error { } impl Error { - pub fn span_err<'a>(self, sp: Span, handler: &'a errors::Handler) -> DiagnosticBuilder<'a> { + pub fn span_err(self, sp: Span, handler: &errors::Handler) -> DiagnosticBuilder { match self { Error::FileNotFoundForModule { ref mod_name, ref default_path, @@ -476,9 +478,10 @@ impl<'a> Parser<'a> { } fn next_tok(&mut self) -> TokenAndSpan { - let mut next = match self.desugar_doc_comments { - true => self.token_cursor.next_desugared(), - false => self.token_cursor.next(), + let mut next = if self.desugar_doc_comments { + self.token_cursor.next_desugared() + } else { + self.token_cursor.next() }; if next.sp == syntax_pos::DUMMY_SP { next.sp = self.prev_span; @@ -549,7 +552,7 @@ impl<'a> Parser<'a> { // This might be a sign we need a connect method on Iterator. let b = i.next() .map_or("".to_string(), |t| t.to_string()); - i.enumerate().fold(b, |mut b, (i, ref a)| { + i.enumerate().fold(b, |mut b, (i, a)| { if tokens.len() > 2 && i == tokens.len() - 2 { b.push_str(", or "); } else if tokens.len() == 2 && i == tokens.len() - 2 { @@ -600,10 +603,10 @@ impl<'a> Parser<'a> { label_sp }; if self.span.contains(sp) { - err.span_label(self.span, &label_exp); + err.span_label(self.span, label_exp); } else { - err.span_label(sp, &label_exp); - err.span_label(self.span, &"unexpected token"); + err.span_label(sp, label_exp); + err.span_label(self.span, "unexpected token"); } Err(err) } @@ -983,18 +986,15 @@ impl<'a> Parser<'a> { token::CloseDelim(..) | token::Eof => break, _ => {} }; - match sep.sep { - Some(ref t) => { - if first { - first = false; - } else { - if let Err(e) = self.expect(t) { - fe(e); - break; - } + if let Some(ref t) = sep.sep { + if first { + first = false; + } else { + if let Err(e) = self.expect(t) { + fe(e); + break; } } - _ => () } if sep.trailing_sep_allowed && kets.iter().any(|k| self.check(k)) { break; @@ -1451,9 +1451,9 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(keywords::Impl) { // FIXME: figure out priority of `+` in `impl Trait1 + Trait2` (#34511). TyKind::ImplTrait(self.parse_ty_param_bounds()?) - } else if self.check(&token::Question) { + } else if self.check(&token::Question) || + self.check_lifetime() && self.look_ahead(1, |t| t == &token::BinOp(token::Plus)){ // Bound list (trait object type) - // Bound lists starting with `'lt` are not currently supported (#40043) TyKind::TraitObject(self.parse_ty_param_bounds_common(allow_plus)?) } else { let msg = format!("expected type, found {}", self.this_token_descr()); @@ -1490,9 +1490,8 @@ impl<'a> Parser<'a> { let bounds = self.parse_ty_param_bounds()?; let sum_span = ty.span.to(self.prev_span); - let mut err = struct_span_err!(self.sess.span_diagnostic, ty.span, E0178, - "expected a path on the left-hand side of `+`, not `{}`", pprust::ty_to_string(&ty)); - err.span_label(ty.span, &format!("expected a path")); + let mut err = struct_span_err!(self.sess.span_diagnostic, sum_span, E0178, + "expected a path on the left-hand side of `+`, not `{}`", pprust::ty_to_string(ty)); match ty.node { TyKind::Rptr(ref lifetime, ref mut_ty) => { @@ -1511,9 +1510,11 @@ impl<'a> Parser<'a> { err.span_suggestion(sum_span, "try adding parentheses:", sum_with_parens); } TyKind::Ptr(..) | TyKind::BareFn(..) => { - help!(&mut err, "perhaps you forgot parentheses?"); + err.span_label(sum_span, "perhaps you forgot parentheses?"); } - _ => {} + _ => { + err.span_label(sum_span, "expected a path"); + }, } err.emit(); Ok(()) @@ -1544,7 +1545,7 @@ impl<'a> Parser<'a> { pub fn is_named_argument(&mut self) -> bool { let offset = match self.token { - token::BinOp(token::And) => 1, + token::BinOp(token::And) | token::AndAnd => 1, _ if self.token.is_keyword(keywords::Mut) => 1, _ => 0 @@ -2288,7 +2289,7 @@ impl<'a> Parser<'a> { let e = if self.token.can_begin_expr() && !(self.token == token::OpenDelim(token::Brace) && self.restrictions.contains( - Restrictions::RESTRICTION_NO_STRUCT_LITERAL)) { + RESTRICTION_NO_STRUCT_LITERAL)) { Some(self.parse_expr()?) } else { None @@ -2315,7 +2316,7 @@ impl<'a> Parser<'a> { // This is a struct literal, unless we're prohibited // from parsing struct literals here. let prohibited = self.restrictions.contains( - Restrictions::RESTRICTION_NO_STRUCT_LITERAL + RESTRICTION_NO_STRUCT_LITERAL ); if !prohibited { return self.parse_struct_expr(lo, pth, attrs); @@ -2553,7 +2554,7 @@ impl<'a> Parser<'a> { let fstr = n.as_str(); let mut err = self.diagnostic().struct_span_err(self.prev_span, &format!("unexpected token: `{}`", n)); - err.span_label(self.prev_span, &"unexpected token"); + err.span_label(self.prev_span, "unexpected token"); if fstr.chars().all(|x| "0123456789.".contains(x)) { let float = match fstr.parse::<f64>().ok() { Some(f) => f, @@ -2697,6 +2698,19 @@ impl<'a> Parser<'a> { let (span, e) = self.interpolated_or_expr_span(e)?; (span, self.mk_unary(UnOp::Not, e)) } + // Suggest `!` for bitwise negation when encountering a `~` + token::Tilde => { + self.bump(); + let e = self.parse_prefix_expr(None); + let (span, e) = self.interpolated_or_expr_span(e)?; + let span_of_tilde = lo; + let mut err = self.diagnostic().struct_span_err(span_of_tilde, + "`~` can not be used as a unary operator"); + err.span_label(span_of_tilde, "did you mean `!`?"); + err.help("use `!` instead of `~` if you meant to perform bitwise negation"); + err.emit(); + (span, self.mk_unary(UnOp::Not, e)) + } token::BinOp(token::Minus) => { self.bump(); let e = self.parse_prefix_expr(None); @@ -2719,7 +2733,7 @@ impl<'a> Parser<'a> { token::Ident(..) if self.token.is_keyword(keywords::In) => { self.bump(); let place = self.parse_expr_res( - Restrictions::RESTRICTION_NO_STRUCT_LITERAL, + RESTRICTION_NO_STRUCT_LITERAL, None, )?; let blk = self.parse_block()?; @@ -2782,7 +2796,7 @@ impl<'a> Parser<'a> { let cur_op_span = self.span; let restrictions = if op.is_assign_like() { - self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL + self.restrictions & RESTRICTION_NO_STRUCT_LITERAL } else { self.restrictions }; @@ -2832,13 +2846,13 @@ impl<'a> Parser<'a> { let rhs = match op.fixity() { Fixity::Right => self.with_res( - restrictions - Restrictions::RESTRICTION_STMT_EXPR, + restrictions - RESTRICTION_STMT_EXPR, |this| { this.parse_assoc_expr_with(op.precedence(), LhsExpr::NotYetParsed) }), Fixity::Left => self.with_res( - restrictions - Restrictions::RESTRICTION_STMT_EXPR, + restrictions - RESTRICTION_STMT_EXPR, |this| { this.parse_assoc_expr_with(op.precedence() + 1, LhsExpr::NotYetParsed) @@ -2846,7 +2860,7 @@ impl<'a> Parser<'a> { // We currently have no non-associative operators that are not handled above by // the special cases. The code is here only for future convenience. Fixity::None => self.with_res( - restrictions - Restrictions::RESTRICTION_STMT_EXPR, + restrictions - RESTRICTION_STMT_EXPR, |this| { this.parse_assoc_expr_with(op.precedence() + 1, LhsExpr::NotYetParsed) @@ -2956,7 +2970,7 @@ impl<'a> Parser<'a> { if self.token.can_begin_expr() { // parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`. if self.token == token::OpenDelim(token::Brace) { - return !self.restrictions.contains(Restrictions::RESTRICTION_NO_STRUCT_LITERAL); + return !self.restrictions.contains(RESTRICTION_NO_STRUCT_LITERAL); } true } else { @@ -2970,7 +2984,7 @@ impl<'a> Parser<'a> { return self.parse_if_let_expr(attrs); } let lo = self.prev_span; - let cond = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; + let cond = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL, None)?; let thn = self.parse_block()?; let mut els: Option<P<Expr>> = None; let mut hi = thn.span; @@ -2989,7 +3003,7 @@ impl<'a> Parser<'a> { self.expect_keyword(keywords::Let)?; let pat = self.parse_pat()?; self.expect(&token::Eq)?; - let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; + let expr = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL, None)?; let thn = self.parse_block()?; let (hi, els) = if self.eat_keyword(keywords::Else) { let expr = self.parse_else_expr()?; @@ -3043,7 +3057,7 @@ impl<'a> Parser<'a> { let pat = self.parse_pat()?; self.expect_keyword(keywords::In)?; - let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; + let expr = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL, None)?; let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); @@ -3058,7 +3072,7 @@ impl<'a> Parser<'a> { if self.token.is_keyword(keywords::Let) { return self.parse_while_let_expr(opt_ident, span_lo, attrs); } - let cond = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; + let cond = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL, None)?; let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); let span = span_lo.to(body.span); @@ -3072,7 +3086,7 @@ impl<'a> Parser<'a> { self.expect_keyword(keywords::Let)?; let pat = self.parse_pat()?; self.expect(&token::Eq)?; - let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; + let expr = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL, None)?; let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); let span = span_lo.to(body.span); @@ -3102,7 +3116,7 @@ impl<'a> Parser<'a> { fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { let match_span = self.prev_span; let lo = self.prev_span; - let discriminant = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, + let discriminant = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL, None)?; if let Err(mut e) = self.expect(&token::OpenDelim(token::Brace)) { if self.token == token::Token::Semi { @@ -3138,12 +3152,13 @@ impl<'a> Parser<'a> { let attrs = self.parse_outer_attributes()?; let pats = self.parse_pats()?; - let mut guard = None; - if self.eat_keyword(keywords::If) { - guard = Some(self.parse_expr()?); - } + let guard = if self.eat_keyword(keywords::If) { + Some(self.parse_expr()?) + } else { + None + }; self.expect(&token::FatArrow)?; - let expr = self.parse_expr_res(Restrictions::RESTRICTION_STMT_EXPR, None)?; + let expr = self.parse_expr_res(RESTRICTION_STMT_EXPR, None)?; let require_comma = !classify::expr_is_simple_block(&expr) @@ -3584,10 +3599,11 @@ impl<'a> Parser<'a> { let lo = self.span; let pat = self.parse_pat()?; - let mut ty = None; - if self.eat(&token::Colon) { - ty = Some(self.parse_ty()?); - } + let ty = if self.eat(&token::Colon) { + Some(self.parse_ty()?) + } else { + None + }; let init = self.parse_initializer()?; Ok(P(ast::Local { ty: ty, @@ -3724,7 +3740,7 @@ impl<'a> Parser<'a> { self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace)) && // prevent `while catch {} {}`, `if catch {} {} else {}`, etc. - !self.restrictions.contains(Restrictions::RESTRICTION_NO_STRUCT_LITERAL) + !self.restrictions.contains(RESTRICTION_NO_STRUCT_LITERAL) } fn is_union_item(&self) -> bool { @@ -3796,7 +3812,7 @@ impl<'a> Parser<'a> { self.mk_expr(lo.to(hi), ExprKind::Path(None, pth), ThinVec::new()) }; - let expr = self.with_res(Restrictions::RESTRICTION_STMT_EXPR, |this| { + let expr = self.with_res(RESTRICTION_STMT_EXPR, |this| { let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs.into())?; this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr)) })?; @@ -3913,7 +3929,7 @@ impl<'a> Parser<'a> { }, None => { let unused_attrs = |attrs: &[_], s: &mut Self| { - if attrs.len() > 0 { + if !attrs.is_empty() { if s.prev_token_kind == PrevTokenKind::DocComment { s.span_fatal_err(s.prev_span, Error::UselessDocComment).emit(); } else { @@ -3936,7 +3952,7 @@ impl<'a> Parser<'a> { // Remainder are line-expr stmts. let e = self.parse_expr_res( - Restrictions::RESTRICTION_STMT_EXPR, Some(attrs.into()))?; + RESTRICTION_STMT_EXPR, Some(attrs.into()))?; Stmt { id: ast::DUMMY_NODE_ID, span: lo.to(e.span), @@ -3949,7 +3965,7 @@ impl<'a> Parser<'a> { /// Is this expression a successfully-parsed statement? fn expr_is_complete(&mut self, e: &Expr) -> bool { - self.restrictions.contains(Restrictions::RESTRICTION_STMT_EXPR) && + self.restrictions.contains(RESTRICTION_STMT_EXPR) && !classify::expr_requires_semi_to_be_stmt(e) } @@ -4776,7 +4792,7 @@ impl<'a> Parser<'a> { sp, &format!("missing `fn`, `type`, or `const` for {}-item declaration", item_type)); - err.span_label(sp, &"missing `fn`, `type`, or `const`"); + err.span_label(sp, "missing `fn`, `type`, or `const`"); err } @@ -4799,7 +4815,7 @@ impl<'a> Parser<'a> { self.expect(&token::Not)?; } - self.complain_if_pub_macro(&vis, prev_span); + self.complain_if_pub_macro(vis, prev_span); // eat a matched-delimiter token tree: *at_end = true; @@ -4863,7 +4879,9 @@ impl<'a> Parser<'a> { /// impl<T> Foo { ... } /// impl<T> ToString for &'static T { ... } /// impl Send for .. {} - fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> PResult<'a, ItemInfo> { + fn parse_item_impl(&mut self, + unsafety: ast::Unsafety, + defaultness: Defaultness) -> PResult<'a, ItemInfo> { let impl_span = self.span; // First, parse type parameters if necessary. @@ -4899,13 +4917,10 @@ impl<'a> Parser<'a> { } } } else { - match polarity { - ast::ImplPolarity::Negative => { - // This is a negated type implementation - // `impl !MyType {}`, which is not allowed. - self.span_err(neg_span, "inherent implementation can't be negated"); - }, - _ => {} + if polarity == ast::ImplPolarity::Negative { + // This is a negated type implementation + // `impl !MyType {}`, which is not allowed. + self.span_err(neg_span, "inherent implementation can't be negated"); } None }; @@ -4916,6 +4931,11 @@ impl<'a> Parser<'a> { allowed to have generics"); } + if let ast::Defaultness::Default = defaultness { + self.span_err(impl_span, "`default impl` is not allowed for \ + default trait implementations"); + } + self.expect(&token::OpenDelim(token::Brace))?; self.expect(&token::CloseDelim(token::Brace))?; Ok((keywords::Invalid.ident(), @@ -4944,7 +4964,7 @@ impl<'a> Parser<'a> { } Ok((keywords::Invalid.ident(), - ItemKind::Impl(unsafety, polarity, generics, opt_trait, ty, impl_items), + ItemKind::Impl(unsafety, polarity, defaultness, generics, opt_trait, ty, impl_items), Some(attrs))) } } @@ -5122,7 +5142,6 @@ impl<'a> Parser<'a> { } if self.check(&token::OpenDelim(token::Paren)) { - let start_span = self.span; // We don't `self.bump()` the `(` yet because this might be a struct definition where // `()` or a tuple might be allowed. For example, `struct Struct(pub (), pub (usize));`. // Because of this, we only `bump` the `(` if we're assured it is appropriate to do so @@ -5161,12 +5180,9 @@ impl<'a> Parser<'a> { `pub(in path::to::module)`: visible only on the specified path"##; let path = self.parse_path(PathStyle::Mod)?; let path_span = self.prev_span; - let help_msg = format!("to make this visible only to module `{}`, add `in` before \ - the path:", - path); + let help_msg = format!("make this visible only to module `{}` with `in`:", path); self.expect(&token::CloseDelim(token::Paren))?; // `)` - let sp = start_span.to(self.prev_span); - let mut err = self.span_fatal_help(sp, &msg, &suggestion); + let mut err = self.span_fatal_help(path_span, msg, suggestion); err.span_suggestion(path_span, &help_msg, format!("in {}", path)); err.emit(); // emit diagnostic, but continue with public visibility } @@ -5363,24 +5379,25 @@ impl<'a> Parser<'a> { } let mut err = self.diagnostic().struct_span_err(id_sp, "cannot declare a new module at this location"); - let this_module = match self.directory.path.file_name() { - Some(file_name) => file_name.to_str().unwrap().to_owned(), - None => self.root_module_name.as_ref().unwrap().clone(), - }; - err.span_note(id_sp, - &format!("maybe move this module `{0}` to its own directory \ - via `{0}{1}mod.rs`", - this_module, - path::MAIN_SEPARATOR)); + if id_sp != syntax_pos::DUMMY_SP { + let src_path = PathBuf::from(self.sess.codemap().span_to_filename(id_sp)); + if let Some(stem) = src_path.file_stem() { + let mut dest_path = src_path.clone(); + dest_path.set_file_name(stem); + dest_path.push("mod.rs"); + err.span_note(id_sp, + &format!("maybe move this module `{}` to its own \ + directory via `{}`", src_path.to_string_lossy(), + dest_path.to_string_lossy())); + } + } if paths.path_exists { err.span_note(id_sp, &format!("... or maybe `use` the module `{}` instead \ of possibly redeclaring it", paths.name)); - Err(err) - } else { - Err(err) } + Err(err) } else { paths.result.map_err(|err| self.span_fatal_err(id_sp, err)) } @@ -5756,13 +5773,19 @@ impl<'a> Parser<'a> { maybe_append(attrs, extra_attrs)); return Ok(Some(item)); } - if self.check_keyword(keywords::Unsafe) && - self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) + if (self.check_keyword(keywords::Unsafe) && + self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) || + (self.check_keyword(keywords::Default) && + self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) && + self.look_ahead(2, |t| t.is_keyword(keywords::Impl))) { // IMPL ITEM + let defaultness = self.parse_defaultness()?; self.expect_keyword(keywords::Unsafe)?; self.expect_keyword(keywords::Impl)?; - let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe)?; + let (ident, + item_, + extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe, defaultness)?; let prev_span = self.prev_span; let item = self.mk_item(lo.to(prev_span), ident, @@ -5856,9 +5879,16 @@ impl<'a> Parser<'a> { maybe_append(attrs, extra_attrs)); return Ok(Some(item)); } - if self.eat_keyword(keywords::Impl) { + if (self.check_keyword(keywords::Impl)) || + (self.check_keyword(keywords::Default) && + self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) + { // IMPL ITEM - let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal)?; + let defaultness = self.parse_defaultness()?; + self.expect_keyword(keywords::Impl)?; + let (ident, + item_, + extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal, defaultness)?; let prev_span = self.prev_span; let item = self.mk_item(lo.to(prev_span), ident, diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 25cabef70c1..77db604c56e 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -53,6 +53,10 @@ impl DelimToken { pub fn len(self) -> usize { if self == NoDelim { 0 } else { 1 } } + + pub fn is_empty(self) -> bool { + self == NoDelim + } } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] @@ -198,17 +202,17 @@ impl Token { pub fn can_begin_expr(&self) -> bool { match *self { Ident(ident) => ident_can_begin_expr(ident), // value name or keyword - OpenDelim(..) => true, // tuple, array or block - Literal(..) => true, // literal - Not => true, // operator not - BinOp(Minus) => true, // unary minus - BinOp(Star) => true, // dereference - BinOp(Or) | OrOr => true, // closure - BinOp(And) => true, // reference - AndAnd => true, // double reference - DotDot | DotDotDot => true, // range notation - Lt | BinOp(Shl) => true, // associated path - ModSep => true, // global path + OpenDelim(..) | // tuple, array or block + Literal(..) | // literal + Not | // operator not + BinOp(Minus) | // unary minus + BinOp(Star) | // dereference + BinOp(Or) | OrOr | // closure + BinOp(And) | // reference + AndAnd | // double reference + DotDot | DotDotDot | // range notation + Lt | BinOp(Shl) | // associated path + ModSep | // global path Pound => true, // expression attributes Interpolated(ref nt) => match **nt { NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) => true, @@ -222,16 +226,16 @@ impl Token { pub fn can_begin_type(&self) -> bool { match *self { Ident(ident) => ident_can_begin_type(ident), // type name or keyword - OpenDelim(Paren) => true, // tuple - OpenDelim(Bracket) => true, // array - Underscore => true, // placeholder - Not => true, // never - BinOp(Star) => true, // raw pointer - BinOp(And) => true, // reference - AndAnd => true, // double reference - Question => true, // maybe bound in trait object - Lifetime(..) => true, // lifetime bound in trait object - Lt | BinOp(Shl) => true, // associated path + OpenDelim(Paren) | // tuple + OpenDelim(Bracket) | // array + Underscore | // placeholder + Not | // never + BinOp(Star) | // raw pointer + BinOp(And) | // reference + AndAnd | // double reference + Question | // maybe bound in trait object + Lifetime(..) | // lifetime bound in trait object + Lt | BinOp(Shl) | // associated path ModSep => true, // global path Interpolated(ref nt) => match **nt { NtIdent(..) | NtTy(..) | NtPath(..) => true, |
