diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2017-11-21 08:03:02 -0800 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2017-11-24 07:34:32 -0800 |
| commit | c82e9e8e1e634250b901b69808f65fbe5f3312c3 (patch) | |
| tree | e84815f5482ca3dd0ed07b58198a51f2fc1ef8ef | |
| parent | 7c0387e36a1dab95492de61a2f26262a4526c286 (diff) | |
| download | rust-c82e9e8e1e634250b901b69808f65fbe5f3312c3.tar.gz rust-c82e9e8e1e634250b901b69808f65fbe5f3312c3.zip | |
Do not attemt to continue parsing after `pub ident`
Try to identify the following code in order to provide better diagnostics, but return the error to bail out early during the parse.
19 files changed, 74 insertions, 282 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 0fd2ae9dbc8..eafc6e0decf 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1757,7 +1757,7 @@ impl<'a> LoweringContext<'a> { bounds, items) } - ItemKind::Placeholder | ItemKind::MacroDef(..) | ItemKind::Mac(..) => { + ItemKind::MacroDef(..) | ItemKind::Mac(..) => { panic!("Shouldn't still be around") } } diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index c2dd7edbb10..d8590c1de94 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -113,7 +113,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { return visit::walk_item(self, i); } ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()), - ItemKind::Placeholder | ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => DefPathData::ValueNs(i.ident.name.as_str()), ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()), diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 1492c817ffd..46513a5740a 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -269,7 +269,7 @@ impl<'a> Resolver<'a> { self.define(parent, ident, TypeNS, imported_binding); } - ItemKind::GlobalAsm(..) | ItemKind::Placeholder => {} + ItemKind::GlobalAsm(..) => {} ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 64d242307a7..ae92cb81e27 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1947,8 +1947,7 @@ impl<'a> Resolver<'a> { } } - ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(_) | - ItemKind::Placeholder => { + ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(_) => { // do nothing, these are just around to be encoded } diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index e7cf5782290..b244876226c 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -548,7 +548,6 @@ impl Sig for ast::Item { // FIXME should implement this (e.g., pub use). ast::ItemKind::Use(_) => Err("import"), ast::ItemKind::Mac(..) | ast::ItemKind::MacroDef(_) => Err("Macro"), - ast::ItemKind::Placeholder => Err("placeholder"), } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a09cfbec879..ad9d5865120 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1977,7 +1977,6 @@ pub enum ItemKind { /// A macro definition. MacroDef(MacroDef), - Placeholder, } impl ItemKind { @@ -1999,7 +1998,6 @@ impl ItemKind { ItemKind::Mac(..) | ItemKind::MacroDef(..) | ItemKind::Impl(..) | - ItemKind::Placeholder | ItemKind::AutoImpl(..) => "item" } } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 40370eb8096..cc63bffec48 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -935,7 +935,6 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind { ), ItemKind::Mac(m) => ItemKind::Mac(folder.fold_mac(m)), ItemKind::MacroDef(def) => ItemKind::MacroDef(folder.fold_macro_def(def)), - ItemKind::Placeholder => ItemKind::Placeholder, } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 0eda8e4d66b..f839a839853 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -72,50 +72,6 @@ bitflags! { type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute> >); -enum HasRecovered<'a, T> { - Success(T), - Recovered(T, DiagnosticBuilder<'a>), -} - -impl<'a, T> HasRecovered<'a, T> { - fn new(t: T, err: Option<DiagnosticBuilder<'a>>) -> HasRecovered<'a, T> { - if let Some(err) = err { - HasRecovered::Recovered(t, err) - } else { - HasRecovered::Success(t) - } - } - - fn map<O, F: FnOnce(T) -> O>(self, f: F) -> HasRecovered<'a, O> { - let (t, e) = self.full_unwrap(); - HasRecovered::new(f(t), e) - } - - fn emit(self) -> T { - match self { - HasRecovered::Recovered(t, mut err) => { - err.emit(); - t - } - HasRecovered::Success(t) => t, - } - } - - fn full_unwrap(self) -> (T, Option<DiagnosticBuilder<'a>>) { - match self { - HasRecovered::Recovered(t, err) => (t, Some(err)), - HasRecovered::Success(t) => (t, None), - } - } - - fn into_result(self) -> PResult<'a, T> { - match self { - HasRecovered::Recovered(_, err) => Err(err), - HasRecovered::Success(t) => Ok(t), - } - } -} - /// How to parse a path. #[derive(Copy, Clone, PartialEq)] pub enum PathStyle { @@ -1411,7 +1367,6 @@ impl<'a> Parser<'a> { debug!("parse_trait_methods(): parsing provided method"); *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - let body = body.emit(); attrs.extend(inner_attrs.iter().cloned()); Some(body) } @@ -2447,7 +2402,7 @@ impl<'a> Parser<'a> { let mut attrs = outer_attrs; attrs.extend(self.parse_inner_attributes()?); - let blk = self.parse_block_tail(lo, blk_mode)?.emit(); + let blk = self.parse_block_tail(lo, blk_mode)?; return Ok(self.mk_expr(blk.span, ExprKind::Block(blk), attrs)); } @@ -3204,7 +3159,7 @@ impl<'a> Parser<'a> { let hi = self.prev_span; Ok(self.mk_expr(span_lo.to(hi), - ExprKind::ForLoop(pat, expr, loop_block.emit(), opt_ident), + ExprKind::ForLoop(pat, expr, loop_block, opt_ident), attrs)) } @@ -3217,7 +3172,6 @@ impl<'a> Parser<'a> { } let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; let (iattrs, body) = self.parse_inner_attrs_and_block()?; - let body = body.emit(); attrs.extend(iattrs); let span = span_lo.to(body.span); return Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_ident), attrs)); @@ -3233,7 +3187,6 @@ impl<'a> Parser<'a> { let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); - let body = body.emit(); let span = span_lo.to(body.span); return Ok(self.mk_expr(span, ExprKind::WhileLet(pat, expr, body, opt_ident), attrs)); } @@ -3243,7 +3196,6 @@ impl<'a> Parser<'a> { span_lo: Span, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { let (iattrs, body) = self.parse_inner_attrs_and_block()?; - let body = body.emit(); attrs.extend(iattrs); let span = span_lo.to(body.span); Ok(self.mk_expr(span, ExprKind::Loop(body, opt_ident), attrs)) @@ -3254,7 +3206,6 @@ impl<'a> Parser<'a> { -> PResult<'a, P<Expr>> { let (iattrs, body) = self.parse_inner_attrs_and_block()?; - let body = body.emit(); attrs.extend(iattrs); Ok(self.mk_expr(span_lo.to(body.span), ExprKind::Catch(body), attrs)) } @@ -4301,14 +4252,14 @@ impl<'a> Parser<'a> { return Err(e); } - Ok(self.parse_block_tail(lo, BlockCheckMode::Default)?.emit()) + Ok(self.parse_block_tail(lo, BlockCheckMode::Default)?) } /// Parse a block. Inner attrs are allowed. fn parse_inner_attrs_and_block(&mut self) - -> PResult<'a, (Vec<Attribute>, HasRecovered<'a, P<Block>>)> + -> PResult<'a, (Vec<Attribute>, P<Block>)> { - maybe_whole!(self, NtBlock, |x| (Vec::new(), HasRecovered::Success(x))); + maybe_whole!(self, NtBlock, |x| (Vec::new(), x)); let lo = self.span; self.expect(&token::OpenDelim(token::Brace))?; @@ -4319,15 +4270,14 @@ impl<'a> Parser<'a> { /// Parse the rest of a block expression or function body /// Precondition: already parsed the '{'. fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) - -> PResult<'a, HasRecovered<'a, P<Block>>> + -> PResult<'a, P<Block>> { let mut stmts = vec![]; - let mut error = None; while !self.eat(&token::CloseDelim(token::Brace)) { let stmt = match self.parse_full_stmt(false) { - Err(err) => { - error = Some(err); + Err(mut err) => { + err.emit(); self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Break); break; } @@ -4342,14 +4292,12 @@ impl<'a> Parser<'a> { continue; }; } - let block = HasRecovered::new(P(ast::Block { + Ok(P(ast::Block { stmts, id: ast::DUMMY_NODE_ID, rules: s, span: lo.to(self.prev_span), - }), error); - - Ok(block) + })) } /// Parse a statement, including the trailing semicolon. @@ -4984,22 +4932,11 @@ impl<'a> Parser<'a> { constness: Spanned<Constness>, abi: abi::Abi) -> PResult<'a, ItemInfo> { - - self.parse_item_fn_recoverable(unsafety, constness, abi)?.into_result() - } - - fn parse_item_fn_recoverable(&mut self, - unsafety: Unsafety, - constness: Spanned<Constness>, - abi: abi::Abi) - -> PResult<'a, HasRecovered<'a, ItemInfo>> { let (ident, mut generics) = self.parse_fn_header()?; let decl = self.parse_fn_decl(false)?; generics.where_clause = self.parse_where_clause()?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - Ok(body.map(|body| (ident, - ItemKind::Fn(decl, unsafety, constness, abi, generics, body), - Some(inner_attrs)))) + Ok((ident, ItemKind::Fn(decl, unsafety, constness, abi, generics, body), Some(inner_attrs))) } /// true if we are looking at `const ID`, false for things like `const fn` etc @@ -5183,7 +5120,6 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - let body = body.into_result()?; Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(ast::MethodSig { abi, unsafety, @@ -6369,49 +6305,31 @@ impl<'a> Parser<'a> { let mut err = self.diagnostic() .struct_span_err(sp, "missing `struct` for struct definition"); err.span_suggestion_short(sp, &msg, " struct ".into()); - err.emit(); - self.consume_block(token::Brace); - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - ItemKind::Placeholder, - visibility, - vec![]); - return Ok(Some(item)); + return Err(err); } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { let ident = self.parse_ident().unwrap(); self.consume_block(token::Paren); - let (kw, ambiguous) = if self.check(&token::OpenDelim(token::Brace)) { - self.consume_block(token::Brace); - ("fn", false) + let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) || + self.check(&token::OpenDelim(token::Brace)) + { + ("fn", "method", false) } else if self.check(&token::Colon) { let kw = "struct"; - (kw, false) + (kw, kw, false) } else { - ("fn` or `struct", true) + ("fn` or `struct", "method or struct", true) }; - let msg = format!("missing `{}`{}", kw, - if ambiguous { - "".to_string() - } else { - format!(" for {} definition", kw) - }); + let msg = format!("missing `{}` for {} definition", kw, kw_name); let mut err = self.diagnostic().struct_span_err(sp, &msg); if !ambiguous { - let suggestion = format!("add `{kw}` here to parse `{}` as a public {kw}", + let suggestion = format!("add `{}` here to parse `{}` as a public {}", + kw, ident, - kw=kw); + kw_name); err.span_suggestion_short(sp, &suggestion, format!(" {} ", kw)); } - err.emit(); - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - ItemKind::Placeholder, - visibility, - vec![]); - return Ok(Some(item)); + return Err(err); } } self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, visibility) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 926bdd2a957..38627b40544 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1386,12 +1386,6 @@ impl<'a> State<'a> { self.s.word(";")?; self.end()?; } - ast::ItemKind::Placeholder => { - self.s.word("<placeholder ")?; - self.print_ident(item.ident)?; - self.s.word(">")?; - self.end()?; - } } self.ann.post(self, NodeItem(item)) } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 5a6fbe0a8f8..c2e90f0bb13 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -307,7 +307,6 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { } ItemKind::Mac(ref mac) => visitor.visit_mac(mac), ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id), - ItemKind::Placeholder => (), } walk_list!(visitor, visit_attribute, &item.attrs); } diff --git a/src/test/ui/pub/pub-restricted-error.rs b/src/test/ui/pub/pub-restricted-error.rs index 99af031899a..7f300ed2342 100644 --- a/src/test/ui/pub/pub-restricted-error.rs +++ b/src/test/ui/pub/pub-restricted-error.rs @@ -16,4 +16,4 @@ struct Foo { pub(crate) () foo: usize, } - +fn main() {} diff --git a/src/test/ui/suggestions/pub-ident-missing-kw-unclosed-block.rs b/src/test/ui/suggestions/pub-ident-fn-2.rs index ceaaa0315d2..40c50a4b8dd 100644 --- a/src/test/ui/suggestions/pub-ident-missing-kw-unclosed-block.rs +++ b/src/test/ui/suggestions/pub-ident-fn-2.rs @@ -8,32 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub Struct { - y: usize, -} - -pub Y { - x: usize, - - -pub struct X { - foo(); -} - -pub Z { - x->foo(), -} - -pub foo(foo) { - foo -} +pub foo(s: usize) { bar() } -pub struct X { - foo(); +fn main() { + foo(2); } - -pub Z { - x->foo(), -} - -fn main(){} diff --git a/src/test/ui/suggestions/pub-ident-fn-2.stderr b/src/test/ui/suggestions/pub-ident-fn-2.stderr new file mode 100644 index 00000000000..43b81efbf4c --- /dev/null +++ b/src/test/ui/suggestions/pub-ident-fn-2.stderr @@ -0,0 +1,13 @@ +error: missing `fn` for method definition + --> $DIR/pub-ident-fn-2.rs:11:4 + | +11 | pub foo(s: usize) { bar() } + | ^ + | +help: add `fn` here to parse `foo` as a public method + | +11 | pub fn foo(s: usize) { bar() } + | ^^ + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/pub-ident-missing-kw.rs b/src/test/ui/suggestions/pub-ident-fn-or-struct-2.rs index e2a7c394ec9..6b5ae19e6ff 100644 --- a/src/test/ui/suggestions/pub-ident-missing-kw.rs +++ b/src/test/ui/suggestions/pub-ident-fn-or-struct-2.rs @@ -8,32 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub Struct { - y: usize, -} +pub S(); -pub Y { - x: usize, -} - -pub struct X { - foo(); -} - -pub Z { - x->foo(), -} - -pub foo(foo) { - foo -} - -pub struct X { - foo(); -} - -pub Z { - x->foo(), -} - -fn main(){} +fn main() {} diff --git a/src/test/ui/suggestions/pub-ident-fn-or-struct-2.stderr b/src/test/ui/suggestions/pub-ident-fn-or-struct-2.stderr new file mode 100644 index 00000000000..e8636f67e0b --- /dev/null +++ b/src/test/ui/suggestions/pub-ident-fn-or-struct-2.stderr @@ -0,0 +1,8 @@ +error: missing `fn` or `struct` for method or struct definition + --> $DIR/pub-ident-fn-or-struct-2.rs:11:4 + | +11 | pub S(); + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/pub-ident-fn-or-struct.rs b/src/test/ui/suggestions/pub-ident-fn-or-struct.rs new file mode 100644 index 00000000000..8bb1c6afcbb --- /dev/null +++ b/src/test/ui/suggestions/pub-ident-fn-or-struct.rs @@ -0,0 +1,13 @@ +// Copyright 2017 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. + +pub S (foo) bar + +fn main() {} diff --git a/src/test/ui/suggestions/pub-ident-fn-or-struct.stderr b/src/test/ui/suggestions/pub-ident-fn-or-struct.stderr new file mode 100644 index 00000000000..dc391c1113d --- /dev/null +++ b/src/test/ui/suggestions/pub-ident-fn-or-struct.stderr @@ -0,0 +1,8 @@ +error: missing `fn` or `struct` for method or struct definition + --> $DIR/pub-ident-fn-or-struct.rs:11:4 + | +11 | pub S (foo) bar + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/pub-ident-missing-kw-unclosed-block.stderr b/src/test/ui/suggestions/pub-ident-missing-kw-unclosed-block.stderr deleted file mode 100644 index a580aaac8de..00000000000 --- a/src/test/ui/suggestions/pub-ident-missing-kw-unclosed-block.stderr +++ /dev/null @@ -1,36 +0,0 @@ -error: this file contains an un-closed delimiter - --> $DIR/pub-ident-missing-kw-unclosed-block.rs:29:13 - | -39 | fn main(){} - | ^ - | -help: did you mean to close this delimiter? - --> $DIR/pub-ident-missing-kw-unclosed-block.rs:5:7 - | -15 | pub Y { - | ^ - -error: missing `struct` for struct definition - --> $DIR/pub-ident-missing-kw-unclosed-block.rs:1:4 - | -11 | pub Struct { - | ^ - | -help: add `struct` here to parse `Struct` as a public struct - | -11 | pub struct Struct { - | ^^^^^^ - -error: missing `struct` for struct definition - --> $DIR/pub-ident-missing-kw-unclosed-block.rs:5:4 - | -15 | pub Y { - | ^ - | -help: add `struct` here to parse `Y` as a public struct - | -15 | pub struct Y { - | ^^^^^^ - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/suggestions/pub-ident-missing-kw.stderr b/src/test/ui/suggestions/pub-ident-missing-kw.stderr deleted file mode 100644 index 23ac4eca2b4..00000000000 --- a/src/test/ui/suggestions/pub-ident-missing-kw.stderr +++ /dev/null @@ -1,69 +0,0 @@ -error: missing `struct` for struct definition - --> $DIR/pub-ident-missing-kw.rs:11:4 - | -11 | pub Struct { - | ^ - | -help: add `struct` here to parse `Struct` as a public struct - | -11 | pub struct Struct { - | ^^^^^^ - -error: missing `struct` for struct definition - --> $DIR/pub-ident-missing-kw.rs:15:4 - | -15 | pub Y { - | ^ - | -help: add `struct` here to parse `Y` as a public struct - | -15 | pub struct Y { - | ^^^^^^ - -error: expected `:`, found `(` - --> $DIR/pub-ident-missing-kw.rs:20:8 - | -20 | foo(); - | ^ - -error: missing `struct` for struct definition - --> $DIR/pub-ident-missing-kw.rs:23:4 - | -23 | pub Z { - | ^ - | -help: add `struct` here to parse `Z` as a public struct - | -23 | pub struct Z { - | ^^^^^^ - -error: missing `fn` for fn definition - --> $DIR/pub-ident-missing-kw.rs:27:4 - | -27 | pub foo(foo) { - | ^ - | -help: add `fn` here to parse `foo` as a public fn - | -27 | pub fn foo(foo) { - | ^^ - -error: expected `:`, found `(` - --> $DIR/pub-ident-missing-kw.rs:32:8 - | -32 | foo(); - | ^ - -error: missing `struct` for struct definition - --> $DIR/pub-ident-missing-kw.rs:35:4 - | -35 | pub Z { - | ^ - | -help: add `struct` here to parse `Z` as a public struct - | -35 | pub struct Z { - | ^^^^^^ - -error: aborting due to 7 previous errors - |
