Skip to content

Commit 60e72f4

Browse files
committed
Make suggestions machine-applicable
1 parent fcf8261 commit 60e72f4

File tree

18 files changed

+204
-62
lines changed

18 files changed

+204
-62
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,15 +1096,53 @@ pub struct Arm {
10961096
pub attrs: AttrVec,
10971097
/// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`
10981098
pub pat: P<Pat>,
1099-
/// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }`
1100-
pub guard: Option<P<Expr>>,
1099+
/// Match arm guard, e.g. `if n > 10` in `match foo { n if n > 10 => {}, _ => {} }`
1100+
pub guard: Option<ArmGuard>,
11011101
/// Match arm body. Omitted if the pattern is a never pattern.
1102-
pub body: Option<P<Expr>>,
1102+
pub body: Option<ArmBody>,
11031103
pub span: Span,
11041104
pub id: NodeId,
11051105
pub is_placeholder: bool,
11061106
}
11071107

1108+
/// A guard of a `match` arm.
1109+
///
1110+
/// E.g., `if x > 10` in
1111+
///
1112+
/// ```
1113+
/// match None {
1114+
/// Some(x) if x > 10 => { println!("match!") },
1115+
/// _ => { println!("no match!") },
1116+
/// }
1117+
/// ```
1118+
#[derive(Clone, Encodable, Decodable, Debug)]
1119+
pub struct ArmGuard {
1120+
/// The condition of the guard, e.g. `Some(x) = foo()` in `if Some(x) = foo()`.
1121+
pub cond: P<Expr>,
1122+
/// The span of the guard, including the leading `if`.
1123+
pub span: Span,
1124+
}
1125+
1126+
/// A body of a `match` arm.
1127+
///
1128+
/// E.g., `=> { println!("match!") }` in
1129+
///
1130+
/// ```
1131+
/// match None {
1132+
/// Some(x) if x > 10 => { println!("match!") },
1133+
/// _ => { println!("no match!") },
1134+
/// }
1135+
/// ```
1136+
#[derive(Clone, Encodable, Decodable, Debug)]
1137+
pub struct ArmBody {
1138+
/// The expression of the body.
1139+
pub expr: P<Expr>,
1140+
/// The span of the body, including the leading `=>` but not a trailing `,`.
1141+
pub span: Span,
1142+
/// Whether the body expression is followed by a comma.
1143+
pub trailing_comma: bool,
1144+
}
1145+
11081146
/// A single field in a struct expression, e.g. `x: value` and `y` in `Foo { x: value, y }`.
11091147
#[derive(Clone, Encodable, Decodable, Debug)]
11101148
pub struct ExprField {

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,8 +452,14 @@ pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[
452452
visit_attrs(attrs, vis);
453453
vis.visit_id(id);
454454
vis.visit_pat(pat);
455-
visit_opt(guard, |guard| vis.visit_expr(guard));
456-
visit_opt(body, |body| vis.visit_expr(body));
455+
visit_opt(guard, |guard| {
456+
vis.visit_expr(&mut guard.cond);
457+
vis.visit_span(&mut guard.span);
458+
});
459+
visit_opt(body, |body| {
460+
vis.visit_expr(&mut body.expr);
461+
vis.visit_span(&mut body.span);
462+
});
457463
vis.visit_span(span);
458464
smallvec![arm]
459465
}

compiler/rustc_ast/src/visit.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -950,8 +950,12 @@ pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) {
950950

951951
pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) {
952952
visitor.visit_pat(&arm.pat);
953-
walk_list!(visitor, visit_expr, &arm.guard);
954-
walk_list!(visitor, visit_expr, &arm.body);
953+
if let Some(guard) = &arm.guard {
954+
visitor.visit_expr(&guard.cond);
955+
}
956+
if let Some(body) = &arm.body {
957+
visitor.visit_expr(&body.expr);
958+
}
955959
walk_list!(visitor, visit_attribute, &arm.attrs);
956960
}
957961

compiler/rustc_ast_lowering/messages.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ ast_lowering_misplaced_relax_trait_bound =
111111
ast_lowering_never_pattern_with_body =
112112
a never pattern is always unreachable
113113
.label = this will never be executed
114-
.suggestion = remove this expression
114+
.suggestion = keep only the pattern
115115
116116
ast_lowering_never_pattern_with_guard =
117117
a guard on a never pattern will never be run

compiler/rustc_ast_lowering/src/errors.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,16 +354,19 @@ pub struct MatchArmWithNoBody {
354354
pub struct NeverPatternWithBody {
355355
#[primary_span]
356356
#[label]
357-
#[suggestion(code = "", applicability = "maybe-incorrect")]
358357
pub span: Span,
358+
#[suggestion(code = "{suggestion}", applicability = "machine-applicable")]
359+
pub suggestion_span: Span,
360+
pub suggestion: &'static str,
359361
}
360362

361363
#[derive(Diagnostic)]
362364
#[diag(ast_lowering_never_pattern_with_guard)]
363365
pub struct NeverPatternWithGuard {
364366
#[primary_span]
365-
#[suggestion(code = "", applicability = "maybe-incorrect")]
366367
pub span: Span,
368+
#[suggestion(code = "", applicability = "machine-applicable")]
369+
pub suggestion: Span,
367370
}
368371

369372
#[derive(Diagnostic, Clone, Copy)]

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -551,8 +551,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
551551

552552
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
553553
let pat = self.lower_pat(&arm.pat);
554-
let mut guard = arm.guard.as_ref().map(|cond| {
555-
if let ExprKind::Let(pat, scrutinee, span, is_recovered) = &cond.kind {
554+
let mut guard = arm.guard.as_ref().map(|guard| {
555+
if let ExprKind::Let(pat, scrutinee, span, is_recovered) = &guard.cond.kind {
556556
hir::Guard::IfLet(self.arena.alloc(hir::Let {
557557
hir_id: self.next_id(),
558558
span: self.lower_span(*span),
@@ -562,7 +562,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
562562
is_recovered: *is_recovered,
563563
}))
564564
} else {
565-
hir::Guard::If(self.lower_expr(cond))
565+
hir::Guard::If(self.lower_expr(&guard.cond))
566566
}
567567
});
568568
let hir_id = self.next_id();
@@ -572,17 +572,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
572572
let body = if let Some(body) = &arm.body
573573
&& !is_never_pattern
574574
{
575-
self.lower_expr(body)
575+
self.lower_expr(&body.expr)
576576
} else {
577577
// Either `body.is_none()` or `is_never_pattern` here.
578578
if !is_never_pattern {
579579
let suggestion = span.shrink_to_hi();
580580
self.tcx.sess.emit_err(MatchArmWithNoBody { span, suggestion });
581581
} else if let Some(body) = &arm.body {
582-
self.tcx.sess.emit_err(NeverPatternWithBody { span: body.span });
582+
let suggestion = if body.trailing_comma { "" } else { "," };
583+
let mut suggestion_span = body.span;
584+
if let Some(g) = &arm.guard {
585+
suggestion_span = g.span.to(suggestion_span);
586+
}
587+
self.tcx.sess.emit_err(NeverPatternWithBody {
588+
span: body.expr.span,
589+
suggestion_span,
590+
suggestion,
591+
});
583592
guard = None;
584593
} else if let Some(g) = &arm.guard {
585-
self.tcx.sess.emit_err(NeverPatternWithGuard { span: g.span });
594+
self.tcx
595+
.sess
596+
.emit_err(NeverPatternWithGuard { span: g.cond.span, suggestion: g.span });
586597
guard = None;
587598
}
588599

compiler/rustc_ast_pretty/src/pprust/state/expr.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -628,14 +628,14 @@ impl<'a> State<'a> {
628628
self.space();
629629
if let Some(e) = &arm.guard {
630630
self.word_space("if");
631-
self.print_expr(e);
631+
self.print_expr(&e.cond);
632632
self.space();
633633
}
634634

635635
if let Some(body) = &arm.body {
636636
self.word_space("=>");
637637

638-
match &body.kind {
638+
match &body.expr.kind {
639639
ast::ExprKind::Block(blk, opt_label) => {
640640
if let Some(label) = opt_label {
641641
self.print_ident(label.ident);
@@ -652,7 +652,7 @@ impl<'a> State<'a> {
652652
}
653653
_ => {
654654
self.end(); // Close the ibox for the pattern.
655-
self.print_expr(body);
655+
self.print_expr(&body.expr);
656656
self.word(",");
657657
}
658658
}

compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::deriving::generic::ty::*;
22
use crate::deriving::generic::*;
33
use crate::deriving::{path_std, pathvec_std};
4-
use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind};
4+
use rustc_ast::{ArmBody, ExprKind, ItemKind, MetaItem, PatKind};
55
use rustc_expand::base::{Annotatable, ExtCtxt};
66
use rustc_span::symbol::{sym, Ident};
77
use rustc_span::Span;
@@ -136,7 +136,8 @@ fn cs_partial_cmp(
136136
&& let Some(last) = arms.last_mut()
137137
&& let PatKind::Wild = last.pat.kind
138138
{
139-
last.body = Some(expr2);
139+
last.body =
140+
Some(ArmBody { span: expr2.span, expr: expr2, trailing_comma: false });
140141
expr1
141142
} else {
142143
let eq_arm = cx.arm(

compiler/rustc_expand/src/build.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::base::ExtCtxt;
2+
use ast::ArmBody;
23
use rustc_ast::ptr::P;
34
use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp};
45
use rustc_ast::{attr, token, util::literal};
@@ -505,7 +506,7 @@ impl<'a> ExtCtxt<'a> {
505506
attrs: AttrVec::new(),
506507
pat,
507508
guard: None,
508-
body: Some(expr),
509+
body: Some(ArmBody { expr, span, trailing_comma: false }),
509510
span,
510511
id: ast::DUMMY_NODE_ID,
511512
is_placeholder: false,

compiler/rustc_expand/src/placeholders.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ pub fn placeholder(
119119
}]),
120120
AstFragmentKind::Arms => AstFragment::Arms(smallvec![ast::Arm {
121121
attrs: Default::default(),
122-
body: Some(expr_placeholder()),
122+
body: Some(ast::ArmBody { expr: expr_placeholder(), span, trailing_comma: false }),
123123
guard: None,
124124
id,
125125
pat: pat(),

0 commit comments

Comments
 (0)