about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPietro Albini <pietro@pietroalbini.org>2018-11-15 11:04:40 +0100
committerGitHub <noreply@github.com>2018-11-15 11:04:40 +0100
commit3c7acc78783dfb2df5437d3a793fbd194f1ea785 (patch)
tree2289c2ef12600b852d7c8665a821c35fd405b5be
parent202724cddc826f898693177c2b1d990d366d8bcf (diff)
parentc63df7c64fbb1cd010e24ac4eb66b87aab8e650f (diff)
Rollup merge of #55852 - varkor:dotdotequals-lint, r=zackmdavis
Rewrite `...` as `..=` as a `MachineApplicable` 2018 idiom lint

Fixes https://github.com/rust-lang/rust/issues/51043.
-rw-r--r--src/librustc/lint/context.rs7
-rw-r--r--src/librustc/lint/mod.rs2
-rw-r--r--src/librustc_lint/builtin.rs56
-rw-r--r--src/librustc_lint/unused.rs4
-rw-r--r--src/test/ui/lint/inclusive-range-pattern-syntax.fixed6
-rw-r--r--src/test/ui/lint/inclusive-range-pattern-syntax.rs6
-rw-r--r--src/test/ui/lint/inclusive-range-pattern-syntax.stderr6
-rw-r--r--src/test/ui/range/range-inclusive-pattern-precedence.stderr4
8 files changed, 71 insertions, 20 deletions
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 5470aff77f8..8acbaaa844d 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -1020,9 +1020,12 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
     }
 
     fn visit_pat(&mut self, p: &'a ast::Pat) {
-        run_lints!(self, check_pat, p);
+        let mut visit_subpats = true;
+        run_lints!(self, check_pat, p, &mut visit_subpats);
         self.check_id(p.id);
-        ast_visit::walk_pat(self, p);
+        if visit_subpats {
+            ast_visit::walk_pat(self, p);
+        }
     }
 
     fn visit_expr(&mut self, e: &'a ast::Expr) {
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index afd78008109..18922ec5d17 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -341,7 +341,7 @@ pub trait EarlyLintPass: LintPass {
     fn check_block_post(&mut self, _: &EarlyContext<'_>, _: &ast::Block) { }
     fn check_stmt(&mut self, _: &EarlyContext<'_>, _: &ast::Stmt) { }
     fn check_arm(&mut self, _: &EarlyContext<'_>, _: &ast::Arm) { }
-    fn check_pat(&mut self, _: &EarlyContext<'_>, _: &ast::Pat) { }
+    fn check_pat(&mut self, _: &EarlyContext<'_>, _: &ast::Pat, _: &mut bool) { }
     fn check_expr(&mut self, _: &EarlyContext<'_>, _: &ast::Expr) { }
     fn check_expr_post(&mut self, _: &EarlyContext<'_>, _: &ast::Expr) { }
     fn check_ty(&mut self, _: &EarlyContext<'_>, _: &ast::Ty) { }
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 2a9b58200e5..696fee04273 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -40,6 +40,8 @@ use rustc::util::nodemap::FxHashSet;
 
 use syntax::tokenstream::{TokenTree, TokenStream};
 use syntax::ast;
+use syntax::ptr::P;
+use syntax::ast::Expr;
 use syntax::attr;
 use syntax::source_map::Spanned;
 use syntax::edition::Edition;
@@ -47,6 +49,7 @@ use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_a
 use syntax_pos::{BytePos, Span, SyntaxContext};
 use syntax::symbol::keywords;
 use syntax::errors::{Applicability, DiagnosticBuilder};
+use syntax::print::pprust::expr_to_string;
 
 use rustc::hir::{self, GenericParamKind, PatKind};
 use rustc::hir::intravisit::FnKind;
@@ -1407,21 +1410,48 @@ impl LintPass for EllipsisInclusiveRangePatterns {
 }
 
 impl EarlyLintPass for EllipsisInclusiveRangePatterns {
-    fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat) {
-        use self::ast::{PatKind, RangeEnd, RangeSyntax};
+    fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat, visit_subpats: &mut bool) {
+        use self::ast::{PatKind, RangeEnd, RangeSyntax::DotDotDot};
+
+        /// If `pat` is a `...` pattern, return the start and end of the range, as well as the span
+        /// corresponding to the ellipsis.
+        fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(&P<Expr>, &P<Expr>, Span)> {
+            match &pat.node {
+                PatKind::Range(a, b, Spanned { span, node: RangeEnd::Included(DotDotDot), .. }) => {
+                    Some((a, b, *span))
+                }
+                _ => None,
+            }
+        }
 
-        if let PatKind::Range(
-            _, _, Spanned { span, node: RangeEnd::Included(RangeSyntax::DotDotDot) }
-        ) = pat.node {
+        let (parenthesise, endpoints) = match &pat.node {
+            PatKind::Ref(subpat, _) => (true, matches_ellipsis_pat(&subpat)),
+            _ => (false, matches_ellipsis_pat(pat)),
+        };
+
+        if let Some((start, end, join)) = endpoints {
             let msg = "`...` range patterns are deprecated";
-            let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, span, msg);
-            err.span_suggestion_short_with_applicability(
-                span, "use `..=` for an inclusive range", "..=".to_owned(),
-                // FIXME: outstanding problem with precedence in ref patterns:
-                // https://github.com/rust-lang/rust/issues/51043#issuecomment-392252285
-                Applicability::MaybeIncorrect
-            );
-            err.emit()
+            let suggestion = "use `..=` for an inclusive range";
+            if parenthesise {
+                *visit_subpats = false;
+                let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg);
+                err.span_suggestion_with_applicability(
+                    pat.span,
+                    suggestion,
+                    format!("&({}..={})", expr_to_string(&start), expr_to_string(&end)),
+                    Applicability::MachineApplicable,
+                );
+                err.emit();
+            } else {
+                let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, msg);
+                err.span_suggestion_short_with_applicability(
+                    join,
+                    suggestion,
+                    "..=".to_owned(),
+                    Applicability::MachineApplicable,
+                );
+                err.emit();
+            };
         }
     }
 }
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 6d365e6d1ec..7eab7d21002 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -396,12 +396,12 @@ impl EarlyLintPass for UnusedParens {
         self.check_unused_parens_expr(cx, &value, msg, followed_by_block);
     }
 
-    fn check_pat(&mut self, cx: &EarlyContext, p: &ast::Pat) {
+    fn check_pat(&mut self, cx: &EarlyContext, p: &ast::Pat, _: &mut bool) {
         use ast::PatKind::{Paren, Range};
         // The lint visitor will visit each subpattern of `p`. We do not want to lint any range
         // pattern no matter where it occurs in the pattern. For something like `&(a..=b)`, there
         // is a recursive `check_pat` on `a` and `b`, but we will assume that if there are
-        // unnecessry parens they serve a purpose of readability.
+        // unnecessary parens they serve a purpose of readability.
         if let Paren(ref pat) = p.node {
             match pat.node {
                 Range(..) => {}
diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed
index d16859df79e..f0aee8a51f1 100644
--- a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed
+++ b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed
@@ -20,4 +20,10 @@ fn main() {
         //~^ WARN `...` range patterns are deprecated
         _ => {}
     }
+
+    match &despondency {
+        &(1..=2) => {}
+        //~^ WARN `...` range patterns are deprecated
+        _ => {}
+    }
 }
diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.rs b/src/test/ui/lint/inclusive-range-pattern-syntax.rs
index 9d418aec085..97bc04faa77 100644
--- a/src/test/ui/lint/inclusive-range-pattern-syntax.rs
+++ b/src/test/ui/lint/inclusive-range-pattern-syntax.rs
@@ -20,4 +20,10 @@ fn main() {
         //~^ WARN `...` range patterns are deprecated
         _ => {}
     }
+
+    match &despondency {
+        &1...2 => {}
+        //~^ WARN `...` range patterns are deprecated
+        _ => {}
+    }
 }
diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr
index de04fed589b..b13afdbc023 100644
--- a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr
+++ b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr
@@ -10,3 +10,9 @@ note: lint level defined here
 LL | #![warn(ellipsis_inclusive_range_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+warning: `...` range patterns are deprecated
+  --> $DIR/inclusive-range-pattern-syntax.rs:25:9
+   |
+LL |         &1...2 => {}
+   |         ^^^^^^ help: use `..=` for an inclusive range: `&(1..=2)`
+
diff --git a/src/test/ui/range/range-inclusive-pattern-precedence.stderr b/src/test/ui/range/range-inclusive-pattern-precedence.stderr
index cd5ce3035c6..6fa67a5d4fa 100644
--- a/src/test/ui/range/range-inclusive-pattern-precedence.stderr
+++ b/src/test/ui/range/range-inclusive-pattern-precedence.stderr
@@ -11,10 +11,10 @@ LL |         box 10..=15 => {}
    |             ^^^^^^^ help: add parentheses to clarify the precedence: `(10 ..=15)`
 
 warning: `...` range patterns are deprecated
-  --> $DIR/range-inclusive-pattern-precedence.rs:24:11
+  --> $DIR/range-inclusive-pattern-precedence.rs:24:9
    |
 LL |         &0...9 => {}
-   |           ^^^ help: use `..=` for an inclusive range
+   |         ^^^^^^ help: use `..=` for an inclusive range: `&(0..=9)`
    |
 note: lint level defined here
   --> $DIR/range-inclusive-pattern-precedence.rs:19:9