about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-12-22 07:22:33 +0000
committerbors <bors@rust-lang.org>2017-12-22 07:22:33 +0000
commitc2ecab112131b10894f2930b7b152cfcbdda43e9 (patch)
treeb8e21a041a6f767db4fca384cd011ba1bd9e28f4 /src
parentba2741594ba2d4de2ad8cea69def6408ff5409af (diff)
parentd90d5d19da1126c5e66ede7d23bcfd8e18601a8a (diff)
downloadrust-c2ecab112131b10894f2930b7b152cfcbdda43e9.tar.gz
rust-c2ecab112131b10894f2930b7b152cfcbdda43e9.zip
Auto merge of #46732 - estebank:silence-recovered-blocks, r=petrochenkov
Do not emit type errors on recovered blocks

When a parse error occurs on a block, the parser will recover and create
a block with the statements collected until that point. Now a flag
stating that a recovery has been performed in this block is propagated
so that the type checker knows that the type of the block (which will be
identified as `()`) shouldn't be checked against the expectation to
reduce the amount of irrelevant diagnostic errors shown to the user.

Fix #44579.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/diagnostics.rs21
-rw-r--r--src/librustc/hir/lowering.rs4
-rw-r--r--src/librustc/hir/mod.rs5
-rw-r--r--src/librustc/ich/impls_hir.rs2
-rw-r--r--src/librustc_driver/pretty.rs6
-rw-r--r--src/librustc_typeck/check/mod.rs7
-rw-r--r--src/libsyntax/ast.rs1
-rw-r--r--src/libsyntax/ext/build.rs1
-rw-r--r--src/libsyntax/fold.rs3
-rw-r--r--src/libsyntax/parse/mod.rs1
-rw-r--r--src/libsyntax/parse/parser.rs7
-rw-r--r--src/libsyntax_ext/deriving/mod.rs1
-rw-r--r--src/test/compile-fail/issue-34334.rs1
-rw-r--r--src/test/parse-fail/issue-22647.rs1
-rw-r--r--src/test/parse-fail/keywords-followed-by-double-colon.rs8
-rw-r--r--src/test/parse-fail/mut-patterns.rs1
-rw-r--r--src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs1
-rw-r--r--src/test/ui/impossible_range.rs10
-rw-r--r--src/test/ui/impossible_range.stderr8
-rw-r--r--src/test/ui/issue-44406.stderr2
-rw-r--r--src/test/ui/macro-context.stderr2
-rw-r--r--src/test/ui/mismatched_types/recovered-block.rs31
-rw-r--r--src/test/ui/mismatched_types/recovered-block.stderr18
-rw-r--r--src/test/ui/resolve/token-error-correct.rs1
-rw-r--r--src/test/ui/resolve/token-error-correct.stderr8
-rw-r--r--src/tools/toolstate.toml2
26 files changed, 112 insertions, 41 deletions
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 85ae529ae32..7b48e7801df 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -359,18 +359,21 @@ lifetime elision rules (see below).
 Here are some simple examples of where you'll run into this error:
 
 ```compile_fail,E0106
-struct Foo { x: &bool }        // error
-struct Foo<'a> { x: &'a bool } // correct
+struct Foo1 { x: &bool }
+              // ^ expected lifetime parameter
+struct Foo2<'a> { x: &'a bool } // correct
 
-struct Bar { x: Foo }
-               ^^^ expected lifetime parameter
-struct Bar<'a> { x: Foo<'a> } // correct
+struct Bar1 { x: Foo2 }
+              // ^^^^ expected lifetime parameter
+struct Bar2<'a> { x: Foo2<'a> } // correct
 
-enum Bar { A(u8), B(&bool), }        // error
-enum Bar<'a> { A(u8), B(&'a bool), } // correct
+enum Baz1 { A(u8), B(&bool), }
+                  // ^ expected lifetime parameter
+enum Baz2<'a> { A(u8), B(&'a bool), } // correct
 
-type MyStr = &str;        // error
-type MyStr<'a> = &'a str; // correct
+type MyStr1 = &str;
+           // ^ expected lifetime parameter
+type MyStr2<'a> = &'a str; // correct
 ```
 
 Lifetime elision is a special, limited kind of inference for lifetimes in
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 22e661a876e..6fc35e5302d 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1876,6 +1876,7 @@ impl<'a> LoweringContext<'a> {
             rules: self.lower_block_check_mode(&b.rules),
             span: b.span,
             targeted_by_break,
+            recovered: b.recovered,
         })
     }
 
@@ -2740,6 +2741,7 @@ impl<'a> LoweringContext<'a> {
                                 rules: hir::DefaultBlock,
                                 span,
                                 targeted_by_break: false,
+                                recovered: blk.recovered,
                             });
                             P(self.expr_block(blk, ThinVec::new()))
                         }
@@ -3556,6 +3558,7 @@ impl<'a> LoweringContext<'a> {
             rules: hir::DefaultBlock,
             span,
             targeted_by_break: false,
+            recovered: false,
         }
     }
 
@@ -3659,6 +3662,7 @@ impl<'a> LoweringContext<'a> {
             stmts,
             expr: Some(expr),
             targeted_by_break: false,
+            recovered: false,
         });
         self.expr_block(block, attrs)
     }
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index ca2f3475fdb..9ab3b5ca15e 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -690,6 +690,11 @@ pub struct Block {
     /// currently permitted in Rust itself, but it is generated as
     /// part of `catch` statements.
     pub targeted_by_break: bool,
+    /// If true, don't emit return value type errors as the parser had
+    /// to recover from a parse error so this block will not have an
+    /// appropriate type. A parse error will have been emitted so the
+    /// compilation will never succeed if this is true.
+    pub recovered: bool,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index bddbdec2c34..125b82ab4d0 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -382,12 +382,14 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Block {
             rules,
             span,
             targeted_by_break,
+            recovered,
         } = *self;
 
         stmts.hash_stable(hcx, hasher);
         expr.hash_stable(hcx, hasher);
         rules.hash_stable(hcx, hasher);
         span.hash_stable(hcx, hasher);
+        recovered.hash_stable(hcx, hasher);
         targeted_by_break.hash_stable(hcx, hasher);
     }
 }
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 769ade5dbcc..4b51a0fbb83 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -729,6 +729,7 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
 
     fn fold_block(&mut self, b: P<ast::Block>) -> P<ast::Block> {
         fn expr_to_block(rules: ast::BlockCheckMode,
+                         recovered: bool,
                          e: Option<P<ast::Expr>>,
                          sess: &Session) -> P<ast::Block> {
             P(ast::Block {
@@ -744,12 +745,13 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
                 rules,
                 id: sess.next_node_id(),
                 span: syntax_pos::DUMMY_SP,
+                recovered,
             })
         }
 
         if !self.within_static_or_const {
 
-            let empty_block = expr_to_block(BlockCheckMode::Default, None, self.sess);
+            let empty_block = expr_to_block(BlockCheckMode::Default, false, None, self.sess);
             let loop_expr = P(ast::Expr {
                 node: ast::ExprKind::Loop(empty_block, None),
                 id: self.sess.next_node_id(),
@@ -757,7 +759,7 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
                 attrs: ast::ThinVec::new(),
             });
 
-            expr_to_block(b.rules, Some(loop_expr), self.sess)
+            expr_to_block(b.rules, b.recovered, Some(loop_expr), self.sess)
 
         } else {
             fold::noop_fold_block(b, self)
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 77272b18f13..ab81d26e771 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4279,7 +4279,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 //
                 // #41425 -- label the implicit `()` as being the
                 // "found type" here, rather than the "expected type".
-                if !self.diverges.get().always() {
+                //
+                // #44579 -- if the block was recovered during parsing,
+                // the type would be nonsensical and it is not worth it
+                // to perform the type check, so we avoid generating the
+                // diagnostic output.
+                if !self.diverges.get().always() && !blk.recovered {
                     coerce.coerce_forced_unit(self, &self.misc(blk.span), &mut |err| {
                         if let Some(expected_ty) = expected.only_has_type(self) {
                             self.consider_hint_about_removing_semicolon(blk,
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 77ce6b7c3ca..e0f14c04c6c 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -493,6 +493,7 @@ pub struct Block {
     /// Distinguishes between `unsafe { ... }` and `{ ... }`
     pub rules: BlockCheckMode,
     pub span: Span,
+    pub recovered: bool,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 0b3272fc1db..34e5610901e 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -594,6 +594,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
            id: ast::DUMMY_NODE_ID,
            rules: BlockCheckMode::Default,
            span,
+           recovered: false,
         })
     }
 
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index d1aef0c5042..9916b74aeb3 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -864,11 +864,12 @@ fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T)
 }
 
 pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
-    b.map(|Block {id, stmts, rules, span}| Block {
+    b.map(|Block {id, stmts, rules, span, recovered}| Block {
         id: folder.new_id(id),
         stmts: stmts.move_flat_map(|s| folder.fold_stmt(s).into_iter()),
         rules,
         span: folder.new_span(span),
+        recovered,
     })
 }
 
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 17bccfc2d0f..a38ceba2f45 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -930,6 +930,7 @@ mod tests {
                                         id: ast::DUMMY_NODE_ID,
                                         rules: ast::BlockCheckMode::Default, // no idea
                                         span: sp(15,21),
+                                        recovered: false,
                                     })),
                             vis: ast::Visibility::Inherited,
                             span: sp(0,21)})));
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index f81421460c7..a4aad81f5f5 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -4372,13 +4372,15 @@ impl<'a> Parser<'a> {
     /// Precondition: already parsed the '{'.
     fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) -> PResult<'a, P<Block>> {
         let mut stmts = vec![];
+        let mut recovered = false;
 
         while !self.eat(&token::CloseDelim(token::Brace)) {
             let stmt = match self.parse_full_stmt(false) {
                 Err(mut err) => {
                     err.emit();
-                    self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Break);
+                    self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
                     self.eat(&token::CloseDelim(token::Brace));
+                    recovered = true;
                     break;
                 }
                 Ok(stmt) => stmt,
@@ -4397,12 +4399,13 @@ impl<'a> Parser<'a> {
             id: ast::DUMMY_NODE_ID,
             rules: s,
             span: lo.to(self.prev_span),
+            recovered,
         }))
     }
 
     /// Parse a statement, including the trailing semicolon.
     pub fn parse_full_stmt(&mut self, macro_legacy_warnings: bool) -> PResult<'a, Option<Stmt>> {
-        let mut stmt = match self.parse_stmt_(macro_legacy_warnings) {
+        let mut stmt = match self.parse_stmt_without_recovery(macro_legacy_warnings)? {
             Some(stmt) => stmt,
             None => return Ok(None),
         };
diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs
index d769732381c..8159893e784 100644
--- a/src/libsyntax_ext/deriving/mod.rs
+++ b/src/libsyntax_ext/deriving/mod.rs
@@ -160,5 +160,6 @@ fn call_intrinsic(cx: &ExtCtxt,
         id: ast::DUMMY_NODE_ID,
         rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
         span,
+        recovered: false,
     }))
 }
diff --git a/src/test/compile-fail/issue-34334.rs b/src/test/compile-fail/issue-34334.rs
index 95b5fabc81e..a752a36ade2 100644
--- a/src/test/compile-fail/issue-34334.rs
+++ b/src/test/compile-fail/issue-34334.rs
@@ -11,5 +11,4 @@
 fn main () {
     let sr: Vec<(u32, _, _) = vec![]; //~ ERROR expected one of `,` or `>`, found `=`
     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
-    //~^ ERROR cannot find value `sr` in this scope
 }
diff --git a/src/test/parse-fail/issue-22647.rs b/src/test/parse-fail/issue-22647.rs
index 3da9d1a8712..1ace57edba3 100644
--- a/src/test/parse-fail/issue-22647.rs
+++ b/src/test/parse-fail/issue-22647.rs
@@ -16,7 +16,6 @@ fn main() {
         println!("Y {}",x);
         return x;
     };
-    //~^ ERROR expected item, found `;`
 
     caller(bar_handler);
 }
diff --git a/src/test/parse-fail/keywords-followed-by-double-colon.rs b/src/test/parse-fail/keywords-followed-by-double-colon.rs
index bb8a1dfdb19..7a5b48c5f00 100644
--- a/src/test/parse-fail/keywords-followed-by-double-colon.rs
+++ b/src/test/parse-fail/keywords-followed-by-double-colon.rs
@@ -11,6 +11,10 @@
 // compile-flags: -Z parse-only
 
 fn main() {
-    struct::foo();  //~ ERROR expected identifier
-    mut::baz(); //~ ERROR expected expression, found keyword `mut`
+    struct::foo();
+    //~^ ERROR expected identifier
+}
+fn bar() {
+    mut::baz();
+    //~^ ERROR expected expression, found keyword `mut`
 }
diff --git a/src/test/parse-fail/mut-patterns.rs b/src/test/parse-fail/mut-patterns.rs
index ffb45597552..71d826c67f8 100644
--- a/src/test/parse-fail/mut-patterns.rs
+++ b/src/test/parse-fail/mut-patterns.rs
@@ -15,5 +15,4 @@
 pub fn main() {
     struct Foo { x: isize }
     let mut Foo { x: x } = Foo { x: 3 }; //~ ERROR: expected one of `:`, `;`, `=`, or `@`, found `{`
-    //~^ ERROR expected item, found `=`
 }
diff --git a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs
index e84a982f7b3..5afa9a217e0 100644
--- a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs
+++ b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs
@@ -131,6 +131,7 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P<Expr>)) {
                     id: DUMMY_NODE_ID,
                     rules: BlockCheckMode::Default,
                     span: DUMMY_SP,
+                    recovered: false,
                 });
                 iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None)));
             },
diff --git a/src/test/ui/impossible_range.rs b/src/test/ui/impossible_range.rs
index 330a9213bc7..5c72c506e6b 100644
--- a/src/test/ui/impossible_range.rs
+++ b/src/test/ui/impossible_range.rs
@@ -17,11 +17,13 @@ pub fn main() {
     0..;
     ..1;
     0..1;
-
     ..=; //~ERROR inclusive range with no end
-    0..=; //~ERROR inclusive range with no end
+         //~^HELP bounded at the end
+}
+
+fn _foo1() {
     ..=1;
     0..=1;
+    0..=; //~ERROR inclusive range with no end
+          //~^HELP bounded at the end
 }
-
-
diff --git a/src/test/ui/impossible_range.stderr b/src/test/ui/impossible_range.stderr
index 75c6d859621..e0e26bc4db0 100644
--- a/src/test/ui/impossible_range.stderr
+++ b/src/test/ui/impossible_range.stderr
@@ -1,15 +1,15 @@
 error[E0586]: inclusive range with no end
-  --> $DIR/impossible_range.rs:21:8
+  --> $DIR/impossible_range.rs:20:8
    |
-21 |     ..=; //~ERROR inclusive range with no end
+20 |     ..=; //~ERROR inclusive range with no end
    |        ^
    |
    = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error[E0586]: inclusive range with no end
-  --> $DIR/impossible_range.rs:22:9
+  --> $DIR/impossible_range.rs:27:9
    |
-22 |     0..=; //~ERROR inclusive range with no end
+27 |     0..=; //~ERROR inclusive range with no end
    |         ^
    |
    = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
diff --git a/src/test/ui/issue-44406.stderr b/src/test/ui/issue-44406.stderr
index 2e71b001d7a..dd6435a954e 100644
--- a/src/test/ui/issue-44406.stderr
+++ b/src/test/ui/issue-44406.stderr
@@ -13,5 +13,3 @@ error: expected type, found keyword `true`
 18 |     foo!(true); //~ ERROR expected type, found keyword
    |          ^^^^ expecting a type here because of type ascription
 
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/macro-context.stderr b/src/test/ui/macro-context.stderr
index 37d99913d97..2be89b67d11 100644
--- a/src/test/ui/macro-context.stderr
+++ b/src/test/ui/macro-context.stderr
@@ -43,5 +43,3 @@ error: expected expression, found reserved keyword `typeof`
 26 |     m!();
    |     ----- in this macro invocation
 
-error: aborting due to 4 previous errors
-
diff --git a/src/test/ui/mismatched_types/recovered-block.rs b/src/test/ui/mismatched_types/recovered-block.rs
new file mode 100644
index 00000000000..f3e3579f2bc
--- /dev/null
+++ b/src/test/ui/mismatched_types/recovered-block.rs
@@ -0,0 +1,31 @@
+// 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.
+
+use std::env;
+
+pub struct Foo {
+    text: String
+}
+
+pub fn foo() -> Foo {
+    let args: Vec<String> = env::args().collect();
+    let text = args[1].clone();
+
+    pub Foo { text }
+}
+//~^^ ERROR missing `struct` for struct definition
+
+pub fn bar() -> Foo {
+    fn
+    Foo { text: "".to_string() }
+}
+//~^^ ERROR expected one of `(` or `<`, found `{`
+
+fn main() {}
diff --git a/src/test/ui/mismatched_types/recovered-block.stderr b/src/test/ui/mismatched_types/recovered-block.stderr
new file mode 100644
index 00000000000..dcaf2812f59
--- /dev/null
+++ b/src/test/ui/mismatched_types/recovered-block.stderr
@@ -0,0 +1,18 @@
+error: missing `struct` for struct definition
+  --> $DIR/recovered-block.rs:21:8
+   |
+21 |     pub Foo { text }
+   |        ^
+help: add `struct` here to parse `Foo` as a public struct
+   |
+21 |     pub struct Foo { text }
+   |         ^^^^^^
+
+error: expected one of `(` or `<`, found `{`
+  --> $DIR/recovered-block.rs:27:9
+   |
+27 |     Foo { text: "".to_string() }
+   |         ^ expected one of `(` or `<` here
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/resolve/token-error-correct.rs b/src/test/ui/resolve/token-error-correct.rs
index f8b5e670b84..c88f823839d 100644
--- a/src/test/ui/resolve/token-error-correct.rs
+++ b/src/test/ui/resolve/token-error-correct.rs
@@ -16,4 +16,3 @@ fn main() {
 }
 //~^ ERROR: incorrect close delimiter: `}`
 //~| ERROR: incorrect close delimiter: `}`
-//~| ERROR: expected expression, found `)`
diff --git a/src/test/ui/resolve/token-error-correct.stderr b/src/test/ui/resolve/token-error-correct.stderr
index 0e396f6254a..e26f0e85aa6 100644
--- a/src/test/ui/resolve/token-error-correct.stderr
+++ b/src/test/ui/resolve/token-error-correct.stderr
@@ -28,11 +28,5 @@ error: expected expression, found `;`
 14 |     foo(bar(;
    |             ^
 
-error: expected expression, found `)`
-  --> $DIR/token-error-correct.rs:16:1
-   |
-16 | }
-   | ^
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/tools/toolstate.toml b/src/tools/toolstate.toml
index b29e505c3b0..6901343e367 100644
--- a/src/tools/toolstate.toml
+++ b/src/tools/toolstate.toml
@@ -26,7 +26,7 @@
 miri = "Broken"
 
 # ping @Manishearth @llogiq @mcarton @oli-obk
-clippy = "Testing"
+clippy = "Broken"
 
 # ping @nrc
 rls = "Broken"