Skip to content

Commit 677d8b5

Browse files
authored
Rollup merge of rust-lang#56999 - petrochenkov:macrecov2, r=estebank
AST/HIR: Introduce `ExprKind::Err` for better error recovery in the front-end This way we can avoid aborting compilation if expansion produces errors and generate `ExprKind::Err`s instead.
2 parents ae6164c + 4a6aa36 commit 677d8b5

File tree

124 files changed

+711
-365
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

124 files changed

+711
-365
lines changed

src/librustc/cfg/construct.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
402402

403403
hir::ExprKind::Closure(..) |
404404
hir::ExprKind::Lit(..) |
405-
hir::ExprKind::Path(_) => {
405+
hir::ExprKind::Path(_) |
406+
hir::ExprKind::Err => {
406407
self.straightline(expr, pred, None::<hir::Expr>.iter())
407408
}
408409
}

src/librustc/hir/intravisit.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
11091109
ExprKind::Yield(ref subexpression) => {
11101110
visitor.visit_expr(subexpression);
11111111
}
1112+
ExprKind::Err => {}
11121113
}
11131114
}
11141115

src/librustc/hir/lowering.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -2719,7 +2719,6 @@ impl<'a> LoweringContext<'a> {
27192719
rules: self.lower_block_check_mode(&b.rules),
27202720
span: b.span,
27212721
targeted_by_break,
2722-
recovered: b.recovered,
27232722
})
27242723
}
27252724

@@ -3791,7 +3790,6 @@ impl<'a> LoweringContext<'a> {
37913790
rules: hir::DefaultBlock,
37923791
span,
37933792
targeted_by_break: false,
3794-
recovered: blk.recovered,
37953793
});
37963794
P(self.expr_block(blk, ThinVec::new()))
37973795
}
@@ -4127,6 +4125,8 @@ impl<'a> LoweringContext<'a> {
41274125
hir::ExprKind::Yield(P(expr))
41284126
}
41294127

4128+
ExprKind::Err => hir::ExprKind::Err,
4129+
41304130
// Desugar `ExprIfLet`
41314131
// from: `if let <pat> = <sub_expr> <body> [<else_opt>]`
41324132
ExprKind::IfLet(ref pats, ref sub_expr, ref body, ref else_opt) => {
@@ -4831,7 +4831,6 @@ impl<'a> LoweringContext<'a> {
48314831
rules: hir::DefaultBlock,
48324832
span,
48334833
targeted_by_break: false,
4834-
recovered: false,
48354834
}
48364835
}
48374836

src/librustc/hir/mod.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -817,11 +817,6 @@ pub struct Block {
817817
/// break out of this block early.
818818
/// Used by `'label: {}` blocks and by `catch` statements.
819819
pub targeted_by_break: bool,
820-
/// If true, don't emit return value type errors as the parser had
821-
/// to recover from a parse error so this block will not have an
822-
/// appropriate type. A parse error will have been emitted so the
823-
/// compilation will never succeed if this is true.
824-
pub recovered: bool,
825820
}
826821

827822
#[derive(Clone, RustcEncodable, RustcDecodable)]
@@ -1372,6 +1367,7 @@ impl Expr {
13721367
ExprKind::Struct(..) => ExprPrecedence::Struct,
13731368
ExprKind::Repeat(..) => ExprPrecedence::Repeat,
13741369
ExprKind::Yield(..) => ExprPrecedence::Yield,
1370+
ExprKind::Err => ExprPrecedence::Err,
13751371
}
13761372
}
13771373

@@ -1422,7 +1418,8 @@ impl Expr {
14221418
ExprKind::AddrOf(..) |
14231419
ExprKind::Binary(..) |
14241420
ExprKind::Yield(..) |
1425-
ExprKind::Cast(..) => {
1421+
ExprKind::Cast(..) |
1422+
ExprKind::Err => {
14261423
false
14271424
}
14281425
}
@@ -1535,6 +1532,9 @@ pub enum ExprKind {
15351532

15361533
/// A suspension point for generators. This is `yield <expr>` in Rust.
15371534
Yield(P<Expr>),
1535+
1536+
/// Placeholder for an expression that wasn't syntactically well formed in some way.
1537+
Err,
15381538
}
15391539

15401540
/// Optionally `Self`-qualified value/type path or associated extension.

src/librustc/hir/print.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,9 @@ impl<'a> State<'a> {
440440
self.s.word("_")?;
441441
}
442442
hir::TyKind::Err => {
443-
self.s.word("?")?;
443+
self.popen()?;
444+
self.s.word("/*ERROR*/")?;
445+
self.pclose()?;
444446
}
445447
}
446448
self.end()
@@ -1550,6 +1552,11 @@ impl<'a> State<'a> {
15501552
self.word_space("yield")?;
15511553
self.print_expr_maybe_paren(&expr, parser::PREC_JUMP)?;
15521554
}
1555+
hir::ExprKind::Err => {
1556+
self.popen()?;
1557+
self.s.word("/*ERROR*/")?;
1558+
self.pclose()?;
1559+
}
15531560
}
15541561
self.ann.post(self, AnnNode::Expr(expr))?;
15551562
self.end()

src/librustc/ich/impls_hir.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,6 @@ impl_stable_hash_for!(struct hir::Block {
420420
rules,
421421
span,
422422
targeted_by_break,
423-
recovered,
424423
});
425424

426425
impl_stable_hash_for!(struct hir::Pat {
@@ -602,7 +601,8 @@ impl_stable_hash_for!(enum hir::ExprKind {
602601
InlineAsm(asm, inputs, outputs),
603602
Struct(path, fields, base),
604603
Repeat(val, times),
605-
Yield(val)
604+
Yield(val),
605+
Err
606606
});
607607

608608
impl_stable_hash_for!(enum hir::LocalSource {

src/librustc/lint/levels.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -232,24 +232,22 @@ impl<'a> LintLevelsBuilder<'a> {
232232
match item.node {
233233
ast::MetaItemKind::Word => {} // actual lint names handled later
234234
ast::MetaItemKind::NameValue(ref name_value) => {
235-
let gate_reasons = !self.sess.features_untracked().lint_reasons;
236235
if item.ident == "reason" {
237236
// found reason, reslice meta list to exclude it
238237
metas = &metas[0..metas.len()-1];
239238
// FIXME (#55112): issue unused-attributes lint if we thereby
240239
// don't have any lint names (`#[level(reason = "foo")]`)
241240
if let ast::LitKind::Str(rationale, _) = name_value.node {
242-
if gate_reasons {
241+
if !self.sess.features_untracked().lint_reasons {
243242
feature_gate::emit_feature_err(
244243
&self.sess.parse_sess,
245244
"lint_reasons",
246245
item.span,
247246
feature_gate::GateIssue::Language,
248247
"lint reasons are experimental"
249248
);
250-
} else {
251-
reason = Some(rationale);
252249
}
250+
reason = Some(rationale);
253251
} else {
254252
let mut err = bad_attr(name_value.span);
255253
err.help("reason must be a string literal");

src/librustc/middle/expr_use_visitor.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
489489
}
490490

491491
hir::ExprKind::Continue(..) |
492-
hir::ExprKind::Lit(..) => {}
492+
hir::ExprKind::Lit(..) |
493+
hir::ExprKind::Err => {}
493494

494495
hir::ExprKind::Loop(ref blk, _, _) => {
495496
self.walk_block(&blk);

src/librustc/middle/liveness.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
525525
hir::ExprKind::Box(..) |
526526
hir::ExprKind::Yield(..) |
527527
hir::ExprKind::Type(..) |
528+
hir::ExprKind::Err |
528529
hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => {
529530
intravisit::walk_expr(ir, expr);
530531
}
@@ -1264,7 +1265,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
12641265
self.propagate_through_exprs(inputs, succ)
12651266
}
12661267

1267-
hir::ExprKind::Lit(..) | hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => {
1268+
hir::ExprKind::Lit(..) | hir::ExprKind::Err |
1269+
hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => {
12681270
succ
12691271
}
12701272

@@ -1531,7 +1533,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) {
15311533
hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) |
15321534
hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) |
15331535
hir::ExprKind::Closure(..) | hir::ExprKind::Path(_) | hir::ExprKind::Yield(..) |
1534-
hir::ExprKind::Box(..) | hir::ExprKind::Type(..) => {
1536+
hir::ExprKind::Box(..) | hir::ExprKind::Type(..) | hir::ExprKind::Err => {
15351537
intravisit::walk_expr(this, expr);
15361538
}
15371539
}

src/librustc/middle/mem_categorization.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
697697
hir::ExprKind::Block(..) | hir::ExprKind::Loop(..) | hir::ExprKind::Match(..) |
698698
hir::ExprKind::Lit(..) | hir::ExprKind::Break(..) |
699699
hir::ExprKind::Continue(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) |
700-
hir::ExprKind::InlineAsm(..) | hir::ExprKind::Box(..) => {
700+
hir::ExprKind::InlineAsm(..) | hir::ExprKind::Box(..) | hir::ExprKind::Err => {
701701
Ok(self.cat_rvalue_node(expr.hir_id, expr.span, expr_ty))
702702
}
703703
}

src/librustc_driver/driver.rs

-10
Original file line numberDiff line numberDiff line change
@@ -997,7 +997,6 @@ where
997997
};
998998

999999
let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver);
1000-
let err_count = ecx.parse_sess.span_diagnostic.err_count();
10011000

10021001
// Expand macros now!
10031002
let krate = time(sess, "expand crate", || {
@@ -1023,9 +1022,6 @@ where
10231022
let msg = "missing fragment specifier";
10241023
sess.buffer_lint(lint, ast::CRATE_NODE_ID, span, msg);
10251024
}
1026-
if ecx.parse_sess.span_diagnostic.err_count() - ecx.resolve_err_count > err_count {
1027-
ecx.parse_sess.span_diagnostic.abort_if_errors();
1028-
}
10291025
if cfg!(windows) {
10301026
env::set_var("PATH", &old_path);
10311027
}
@@ -1129,12 +1125,6 @@ where
11291125
})
11301126
})?;
11311127

1132-
// Unresolved macros might be due to mistyped `#[macro_use]`,
1133-
// so abort after checking for unknown attributes. (#49074)
1134-
if resolver.found_unresolved_macro {
1135-
sess.diagnostic().abort_if_errors();
1136-
}
1137-
11381128
// Lower ast -> hir.
11391129
// First, we need to collect the dep_graph.
11401130
let dep_graph = match future_dep_graph {

src/librustc_driver/pretty.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -751,15 +751,13 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
751751

752752
fn fold_block(&mut self, b: P<ast::Block>) -> P<ast::Block> {
753753
fn stmt_to_block(rules: ast::BlockCheckMode,
754-
recovered: bool,
755754
s: Option<ast::Stmt>,
756755
sess: &Session) -> ast::Block {
757756
ast::Block {
758757
stmts: s.into_iter().collect(),
759758
rules,
760759
id: sess.next_node_id(),
761760
span: syntax_pos::DUMMY_SP,
762-
recovered,
763761
}
764762
}
765763

@@ -778,7 +776,7 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
778776
}
779777
}
780778

781-
let empty_block = stmt_to_block(BlockCheckMode::Default, false, None, self.sess);
779+
let empty_block = stmt_to_block(BlockCheckMode::Default, None, self.sess);
782780
let loop_expr = P(ast::Expr {
783781
node: ast::ExprKind::Loop(P(empty_block), None),
784782
id: self.sess.next_node_id(),
@@ -819,7 +817,7 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
819817
old_blocks.push(new_block);
820818
}
821819

822-
stmt_to_block(b.rules, b.recovered, Some(loop_stmt), self.sess)
820+
stmt_to_block(b.rules, Some(loop_stmt), self.sess)
823821
} else {
824822
//push `loop {}` onto the end of our fresh block and yield that
825823
new_block.stmts.push(loop_stmt);

src/librustc_mir/hair/cx/expr.rs

+1
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
790790
hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: fields.to_ref() },
791791

792792
hir::ExprKind::Yield(ref v) => ExprKind::Yield { value: v.to_ref() },
793+
hir::ExprKind::Err => unreachable!(),
793794
};
794795

795796
Expr {

src/librustc_passes/ast_validation.rs

-30
Original file line numberDiff line numberDiff line change
@@ -288,25 +288,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
288288
visit::walk_ty(self, ty)
289289
}
290290

291-
fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
292-
// Check if the path in this `use` is not generic, such as `use foo::bar<T>;` While this
293-
// can't happen normally thanks to the parser, a generic might sneak in if the `use` is
294-
// built using a macro.
295-
//
296-
// macro_use foo {
297-
// ($p:path) => { use $p; }
298-
// }
299-
// foo!(bar::baz<T>);
300-
use_tree.prefix.segments.iter().find(|segment| {
301-
segment.args.is_some()
302-
}).map(|segment| {
303-
self.err_handler().span_err(segment.args.as_ref().unwrap().span(),
304-
"generic arguments in import path");
305-
});
306-
307-
visit::walk_use_tree(self, use_tree, id);
308-
}
309-
310291
fn visit_label(&mut self, label: &'a Label) {
311292
self.check_label(label.ident);
312293
visit::walk_label(self, label);
@@ -443,17 +424,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
443424
visit::walk_foreign_item(self, fi)
444425
}
445426

446-
fn visit_vis(&mut self, vis: &'a Visibility) {
447-
if let VisibilityKind::Restricted { ref path, .. } = vis.node {
448-
path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
449-
self.err_handler().span_err(segment.args.as_ref().unwrap().span(),
450-
"generic arguments in visibility path");
451-
});
452-
}
453-
454-
visit::walk_vis(self, vis)
455-
}
456-
457427
fn visit_generics(&mut self, generics: &'a Generics) {
458428
let mut seen_non_lifetime_param = false;
459429
let mut seen_default = None;

src/librustc_passes/rvalue_promotion.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,8 @@ fn check_expr_kind<'a, 'tcx>(
459459
struct_result
460460
}
461461

462-
hir::ExprKind::Lit(_) => Promotable,
462+
hir::ExprKind::Lit(_) |
463+
hir::ExprKind::Err => Promotable,
463464

464465
hir::ExprKind::AddrOf(_, ref expr) |
465466
hir::ExprKind::Repeat(ref expr, _) => {

src/librustc_resolve/lib.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1584,7 +1584,6 @@ pub struct Resolver<'a> {
15841584
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
15851585
macro_defs: FxHashMap<Mark, DefId>,
15861586
local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
1587-
pub found_unresolved_macro: bool,
15881587

15891588
/// List of crate local macros that we need to warn about as being unused.
15901589
/// Right now this only includes macro_rules! macros, and macros 2.0.
@@ -1919,7 +1918,6 @@ impl<'a> Resolver<'a> {
19191918
name_already_seen: FxHashMap::default(),
19201919
potentially_unused_imports: Vec::new(),
19211920
struct_constructors: Default::default(),
1922-
found_unresolved_macro: false,
19231921
unused_macros: FxHashSet::default(),
19241922
current_type_ascription: Vec::new(),
19251923
injected_crate: None,
@@ -2032,8 +2030,10 @@ impl<'a> Resolver<'a> {
20322030
record_used_id: Option<NodeId>,
20332031
path_span: Span)
20342032
-> Option<LexicalScopeBinding<'a>> {
2035-
let record_used = record_used_id.is_some();
20362033
assert!(ns == TypeNS || ns == ValueNS);
2034+
if ident.name == keywords::Invalid.name() {
2035+
return Some(LexicalScopeBinding::Def(Def::Err));
2036+
}
20372037
if ns == TypeNS {
20382038
ident.span = if ident.name == keywords::SelfUpper.name() {
20392039
// FIXME(jseyfried) improve `Self` hygiene
@@ -2046,6 +2046,7 @@ impl<'a> Resolver<'a> {
20462046
}
20472047

20482048
// Walk backwards up the ribs in scope.
2049+
let record_used = record_used_id.is_some();
20492050
let mut module = self.graph_root;
20502051
for i in (0 .. self.ribs[ns].len()).rev() {
20512052
if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() {

0 commit comments

Comments
 (0)