Skip to content

Commit c2ecab1

Browse files
committed
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.
2 parents ba27415 + d90d5d1 commit c2ecab1

File tree

26 files changed

+112
-41
lines changed

26 files changed

+112
-41
lines changed

src/librustc/diagnostics.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -359,18 +359,21 @@ lifetime elision rules (see below).
359359
Here are some simple examples of where you'll run into this error:
360360
361361
```compile_fail,E0106
362-
struct Foo { x: &bool } // error
363-
struct Foo<'a> { x: &'a bool } // correct
362+
struct Foo1 { x: &bool }
363+
// ^ expected lifetime parameter
364+
struct Foo2<'a> { x: &'a bool } // correct
364365
365-
struct Bar { x: Foo }
366-
^^^ expected lifetime parameter
367-
struct Bar<'a> { x: Foo<'a> } // correct
366+
struct Bar1 { x: Foo2 }
367+
// ^^^^ expected lifetime parameter
368+
struct Bar2<'a> { x: Foo2<'a> } // correct
368369
369-
enum Bar { A(u8), B(&bool), } // error
370-
enum Bar<'a> { A(u8), B(&'a bool), } // correct
370+
enum Baz1 { A(u8), B(&bool), }
371+
// ^ expected lifetime parameter
372+
enum Baz2<'a> { A(u8), B(&'a bool), } // correct
371373
372-
type MyStr = &str; // error
373-
type MyStr<'a> = &'a str; // correct
374+
type MyStr1 = &str;
375+
// ^ expected lifetime parameter
376+
type MyStr2<'a> = &'a str; // correct
374377
```
375378
376379
Lifetime elision is a special, limited kind of inference for lifetimes in

src/librustc/hir/lowering.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,6 +1876,7 @@ impl<'a> LoweringContext<'a> {
18761876
rules: self.lower_block_check_mode(&b.rules),
18771877
span: b.span,
18781878
targeted_by_break,
1879+
recovered: b.recovered,
18791880
})
18801881
}
18811882

@@ -2740,6 +2741,7 @@ impl<'a> LoweringContext<'a> {
27402741
rules: hir::DefaultBlock,
27412742
span,
27422743
targeted_by_break: false,
2744+
recovered: blk.recovered,
27432745
});
27442746
P(self.expr_block(blk, ThinVec::new()))
27452747
}
@@ -3556,6 +3558,7 @@ impl<'a> LoweringContext<'a> {
35563558
rules: hir::DefaultBlock,
35573559
span,
35583560
targeted_by_break: false,
3561+
recovered: false,
35593562
}
35603563
}
35613564

@@ -3659,6 +3662,7 @@ impl<'a> LoweringContext<'a> {
36593662
stmts,
36603663
expr: Some(expr),
36613664
targeted_by_break: false,
3665+
recovered: false,
36623666
});
36633667
self.expr_block(block, attrs)
36643668
}

src/librustc/hir/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,11 @@ pub struct Block {
690690
/// currently permitted in Rust itself, but it is generated as
691691
/// part of `catch` statements.
692692
pub targeted_by_break: bool,
693+
/// If true, don't emit return value type errors as the parser had
694+
/// to recover from a parse error so this block will not have an
695+
/// appropriate type. A parse error will have been emitted so the
696+
/// compilation will never succeed if this is true.
697+
pub recovered: bool,
693698
}
694699

695700
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]

src/librustc/ich/impls_hir.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,12 +382,14 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Block {
382382
rules,
383383
span,
384384
targeted_by_break,
385+
recovered,
385386
} = *self;
386387

387388
stmts.hash_stable(hcx, hasher);
388389
expr.hash_stable(hcx, hasher);
389390
rules.hash_stable(hcx, hasher);
390391
span.hash_stable(hcx, hasher);
392+
recovered.hash_stable(hcx, hasher);
391393
targeted_by_break.hash_stable(hcx, hasher);
392394
}
393395
}

src/librustc_driver/pretty.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,7 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
729729

730730
fn fold_block(&mut self, b: P<ast::Block>) -> P<ast::Block> {
731731
fn expr_to_block(rules: ast::BlockCheckMode,
732+
recovered: bool,
732733
e: Option<P<ast::Expr>>,
733734
sess: &Session) -> P<ast::Block> {
734735
P(ast::Block {
@@ -744,20 +745,21 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
744745
rules,
745746
id: sess.next_node_id(),
746747
span: syntax_pos::DUMMY_SP,
748+
recovered,
747749
})
748750
}
749751

750752
if !self.within_static_or_const {
751753

752-
let empty_block = expr_to_block(BlockCheckMode::Default, None, self.sess);
754+
let empty_block = expr_to_block(BlockCheckMode::Default, false, None, self.sess);
753755
let loop_expr = P(ast::Expr {
754756
node: ast::ExprKind::Loop(empty_block, None),
755757
id: self.sess.next_node_id(),
756758
span: syntax_pos::DUMMY_SP,
757759
attrs: ast::ThinVec::new(),
758760
});
759761

760-
expr_to_block(b.rules, Some(loop_expr), self.sess)
762+
expr_to_block(b.rules, b.recovered, Some(loop_expr), self.sess)
761763

762764
} else {
763765
fold::noop_fold_block(b, self)

src/librustc_typeck/check/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4279,7 +4279,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
42794279
//
42804280
// #41425 -- label the implicit `()` as being the
42814281
// "found type" here, rather than the "expected type".
4282-
if !self.diverges.get().always() {
4282+
//
4283+
// #44579 -- if the block was recovered during parsing,
4284+
// the type would be nonsensical and it is not worth it
4285+
// to perform the type check, so we avoid generating the
4286+
// diagnostic output.
4287+
if !self.diverges.get().always() && !blk.recovered {
42834288
coerce.coerce_forced_unit(self, &self.misc(blk.span), &mut |err| {
42844289
if let Some(expected_ty) = expected.only_has_type(self) {
42854290
self.consider_hint_about_removing_semicolon(blk,

src/libsyntax/ast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ pub struct Block {
493493
/// Distinguishes between `unsafe { ... }` and `{ ... }`
494494
pub rules: BlockCheckMode,
495495
pub span: Span,
496+
pub recovered: bool,
496497
}
497498

498499
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]

src/libsyntax/ext/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
594594
id: ast::DUMMY_NODE_ID,
595595
rules: BlockCheckMode::Default,
596596
span,
597+
recovered: false,
597598
})
598599
}
599600

src/libsyntax/fold.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -864,11 +864,12 @@ fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T)
864864
}
865865

866866
pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
867-
b.map(|Block {id, stmts, rules, span}| Block {
867+
b.map(|Block {id, stmts, rules, span, recovered}| Block {
868868
id: folder.new_id(id),
869869
stmts: stmts.move_flat_map(|s| folder.fold_stmt(s).into_iter()),
870870
rules,
871871
span: folder.new_span(span),
872+
recovered,
872873
})
873874
}
874875

src/libsyntax/parse/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,7 @@ mod tests {
930930
id: ast::DUMMY_NODE_ID,
931931
rules: ast::BlockCheckMode::Default, // no idea
932932
span: sp(15,21),
933+
recovered: false,
933934
})),
934935
vis: ast::Visibility::Inherited,
935936
span: sp(0,21)})));

0 commit comments

Comments
 (0)