Skip to content

Commit 70d6c53

Browse files
authored
Rollup merge of rust-lang#55852 - varkor:dotdotequals-lint, r=zackmdavis
Rewrite `...` as `..=` as a `MachineApplicable` 2018 idiom lint Fixes rust-lang#51043.
2 parents 345fbb0 + c63df7c commit 70d6c53

8 files changed

+71
-20
lines changed

src/librustc/lint/context.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1020,9 +1020,12 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
10201020
}
10211021

10221022
fn visit_pat(&mut self, p: &'a ast::Pat) {
1023-
run_lints!(self, check_pat, p);
1023+
let mut visit_subpats = true;
1024+
run_lints!(self, check_pat, p, &mut visit_subpats);
10241025
self.check_id(p.id);
1025-
ast_visit::walk_pat(self, p);
1026+
if visit_subpats {
1027+
ast_visit::walk_pat(self, p);
1028+
}
10261029
}
10271030

10281031
fn visit_expr(&mut self, e: &'a ast::Expr) {

src/librustc/lint/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ pub trait EarlyLintPass: LintPass {
341341
fn check_block_post(&mut self, _: &EarlyContext<'_>, _: &ast::Block) { }
342342
fn check_stmt(&mut self, _: &EarlyContext<'_>, _: &ast::Stmt) { }
343343
fn check_arm(&mut self, _: &EarlyContext<'_>, _: &ast::Arm) { }
344-
fn check_pat(&mut self, _: &EarlyContext<'_>, _: &ast::Pat) { }
344+
fn check_pat(&mut self, _: &EarlyContext<'_>, _: &ast::Pat, _: &mut bool) { }
345345
fn check_expr(&mut self, _: &EarlyContext<'_>, _: &ast::Expr) { }
346346
fn check_expr_post(&mut self, _: &EarlyContext<'_>, _: &ast::Expr) { }
347347
fn check_ty(&mut self, _: &EarlyContext<'_>, _: &ast::Ty) { }

src/librustc_lint/builtin.rs

+43-13
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,16 @@ use rustc::util::nodemap::FxHashSet;
4040

4141
use syntax::tokenstream::{TokenTree, TokenStream};
4242
use syntax::ast;
43+
use syntax::ptr::P;
44+
use syntax::ast::Expr;
4345
use syntax::attr;
4446
use syntax::source_map::Spanned;
4547
use syntax::edition::Edition;
4648
use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes};
4749
use syntax_pos::{BytePos, Span, SyntaxContext};
4850
use syntax::symbol::keywords;
4951
use syntax::errors::{Applicability, DiagnosticBuilder};
52+
use syntax::print::pprust::expr_to_string;
5053

5154
use rustc::hir::{self, GenericParamKind, PatKind};
5255
use rustc::hir::intravisit::FnKind;
@@ -1407,21 +1410,48 @@ impl LintPass for EllipsisInclusiveRangePatterns {
14071410
}
14081411

14091412
impl EarlyLintPass for EllipsisInclusiveRangePatterns {
1410-
fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat) {
1411-
use self::ast::{PatKind, RangeEnd, RangeSyntax};
1413+
fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat, visit_subpats: &mut bool) {
1414+
use self::ast::{PatKind, RangeEnd, RangeSyntax::DotDotDot};
1415+
1416+
/// If `pat` is a `...` pattern, return the start and end of the range, as well as the span
1417+
/// corresponding to the ellipsis.
1418+
fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(&P<Expr>, &P<Expr>, Span)> {
1419+
match &pat.node {
1420+
PatKind::Range(a, b, Spanned { span, node: RangeEnd::Included(DotDotDot), .. }) => {
1421+
Some((a, b, *span))
1422+
}
1423+
_ => None,
1424+
}
1425+
}
14121426

1413-
if let PatKind::Range(
1414-
_, _, Spanned { span, node: RangeEnd::Included(RangeSyntax::DotDotDot) }
1415-
) = pat.node {
1427+
let (parenthesise, endpoints) = match &pat.node {
1428+
PatKind::Ref(subpat, _) => (true, matches_ellipsis_pat(&subpat)),
1429+
_ => (false, matches_ellipsis_pat(pat)),
1430+
};
1431+
1432+
if let Some((start, end, join)) = endpoints {
14161433
let msg = "`...` range patterns are deprecated";
1417-
let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, span, msg);
1418-
err.span_suggestion_short_with_applicability(
1419-
span, "use `..=` for an inclusive range", "..=".to_owned(),
1420-
// FIXME: outstanding problem with precedence in ref patterns:
1421-
// https://github.com/rust-lang/rust/issues/51043#issuecomment-392252285
1422-
Applicability::MaybeIncorrect
1423-
);
1424-
err.emit()
1434+
let suggestion = "use `..=` for an inclusive range";
1435+
if parenthesise {
1436+
*visit_subpats = false;
1437+
let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg);
1438+
err.span_suggestion_with_applicability(
1439+
pat.span,
1440+
suggestion,
1441+
format!("&({}..={})", expr_to_string(&start), expr_to_string(&end)),
1442+
Applicability::MachineApplicable,
1443+
);
1444+
err.emit();
1445+
} else {
1446+
let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, msg);
1447+
err.span_suggestion_short_with_applicability(
1448+
join,
1449+
suggestion,
1450+
"..=".to_owned(),
1451+
Applicability::MachineApplicable,
1452+
);
1453+
err.emit();
1454+
};
14251455
}
14261456
}
14271457
}

src/librustc_lint/unused.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -396,12 +396,12 @@ impl EarlyLintPass for UnusedParens {
396396
self.check_unused_parens_expr(cx, &value, msg, followed_by_block);
397397
}
398398

399-
fn check_pat(&mut self, cx: &EarlyContext, p: &ast::Pat) {
399+
fn check_pat(&mut self, cx: &EarlyContext, p: &ast::Pat, _: &mut bool) {
400400
use ast::PatKind::{Paren, Range};
401401
// The lint visitor will visit each subpattern of `p`. We do not want to lint any range
402402
// pattern no matter where it occurs in the pattern. For something like `&(a..=b)`, there
403403
// is a recursive `check_pat` on `a` and `b`, but we will assume that if there are
404-
// unnecessry parens they serve a purpose of readability.
404+
// unnecessary parens they serve a purpose of readability.
405405
if let Paren(ref pat) = p.node {
406406
match pat.node {
407407
Range(..) => {}

src/test/ui/lint/inclusive-range-pattern-syntax.fixed

+6
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,10 @@ fn main() {
2020
//~^ WARN `...` range patterns are deprecated
2121
_ => {}
2222
}
23+
24+
match &despondency {
25+
&(1..=2) => {}
26+
//~^ WARN `...` range patterns are deprecated
27+
_ => {}
28+
}
2329
}

src/test/ui/lint/inclusive-range-pattern-syntax.rs

+6
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,10 @@ fn main() {
2020
//~^ WARN `...` range patterns are deprecated
2121
_ => {}
2222
}
23+
24+
match &despondency {
25+
&1...2 => {}
26+
//~^ WARN `...` range patterns are deprecated
27+
_ => {}
28+
}
2329
}

src/test/ui/lint/inclusive-range-pattern-syntax.stderr

+6
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,9 @@ note: lint level defined here
1010
LL | #![warn(ellipsis_inclusive_range_patterns)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

13+
warning: `...` range patterns are deprecated
14+
--> $DIR/inclusive-range-pattern-syntax.rs:25:9
15+
|
16+
LL | &1...2 => {}
17+
| ^^^^^^ help: use `..=` for an inclusive range: `&(1..=2)`
18+

src/test/ui/range/range-inclusive-pattern-precedence.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ LL | box 10..=15 => {}
1111
| ^^^^^^^ help: add parentheses to clarify the precedence: `(10 ..=15)`
1212

1313
warning: `...` range patterns are deprecated
14-
--> $DIR/range-inclusive-pattern-precedence.rs:24:11
14+
--> $DIR/range-inclusive-pattern-precedence.rs:24:9
1515
|
1616
LL | &0...9 => {}
17-
| ^^^ help: use `..=` for an inclusive range
17+
| ^^^^^^ help: use `..=` for an inclusive range: `&(0..=9)`
1818
|
1919
note: lint level defined here
2020
--> $DIR/range-inclusive-pattern-precedence.rs:19:9

0 commit comments

Comments
 (0)