@@ -40,13 +40,16 @@ use rustc::util::nodemap::FxHashSet;
4040
4141use syntax:: tokenstream:: { TokenTree , TokenStream } ;
4242use syntax:: ast;
43+ use syntax:: ptr:: P ;
44+ use syntax:: ast:: Expr ;
4345use syntax:: attr;
4446use syntax:: source_map:: Spanned ;
4547use syntax:: edition:: Edition ;
4648use syntax:: feature_gate:: { AttributeGate , AttributeType , Stability , deprecated_attributes} ;
4749use syntax_pos:: { BytePos , Span , SyntaxContext } ;
4850use syntax:: symbol:: keywords;
4951use syntax:: errors:: { Applicability , DiagnosticBuilder } ;
52+ use syntax:: print:: pprust:: expr_to_string;
5053
5154use rustc:: hir:: { self , GenericParamKind , PatKind } ;
5255use rustc:: hir:: intravisit:: FnKind ;
@@ -1477,21 +1480,48 @@ impl LintPass for EllipsisInclusiveRangePatterns {
14771480}
14781481
14791482impl EarlyLintPass for EllipsisInclusiveRangePatterns {
1480- fn check_pat ( & mut self , cx : & EarlyContext , pat : & ast:: Pat ) {
1481- use self :: ast:: { PatKind , RangeEnd , RangeSyntax } ;
1483+ fn check_pat ( & mut self , cx : & EarlyContext , pat : & ast:: Pat , visit_subpats : & mut bool ) {
1484+ use self :: ast:: { PatKind , RangeEnd , RangeSyntax :: DotDotDot } ;
1485+
1486+ /// If `pat` is a `...` pattern, return the start and end of the range, as well as the span
1487+ /// corresponding to the ellipsis.
1488+ fn matches_ellipsis_pat ( pat : & ast:: Pat ) -> Option < ( & P < Expr > , & P < Expr > , Span ) > {
1489+ match & pat. node {
1490+ PatKind :: Range ( a, b, Spanned { span, node : RangeEnd :: Included ( DotDotDot ) , .. } ) => {
1491+ Some ( ( a, b, * span) )
1492+ }
1493+ _ => None ,
1494+ }
1495+ }
14821496
1483- if let PatKind :: Range (
1484- _, _, Spanned { span, node : RangeEnd :: Included ( RangeSyntax :: DotDotDot ) }
1485- ) = pat. node {
1497+ let ( parenthesise, endpoints) = match & pat. node {
1498+ PatKind :: Ref ( subpat, _) => ( true , matches_ellipsis_pat ( & subpat) ) ,
1499+ _ => ( false , matches_ellipsis_pat ( pat) ) ,
1500+ } ;
1501+
1502+ if let Some ( ( start, end, join) ) = endpoints {
14861503 let msg = "`...` range patterns are deprecated" ;
1487- let mut err = cx. struct_span_lint ( ELLIPSIS_INCLUSIVE_RANGE_PATTERNS , span, msg) ;
1488- err. span_suggestion_short_with_applicability (
1489- span, "use `..=` for an inclusive range" , "..=" . to_owned ( ) ,
1490- // FIXME: outstanding problem with precedence in ref patterns:
1491- // https://github.com/rust-lang/rust/issues/51043#issuecomment-392252285
1492- Applicability :: MaybeIncorrect
1493- ) ;
1494- err. emit ( )
1504+ let suggestion = "use `..=` for an inclusive range" ;
1505+ if parenthesise {
1506+ * visit_subpats = false ;
1507+ let mut err = cx. struct_span_lint ( ELLIPSIS_INCLUSIVE_RANGE_PATTERNS , pat. span , msg) ;
1508+ err. span_suggestion_with_applicability (
1509+ pat. span ,
1510+ suggestion,
1511+ format ! ( "&({}..={})" , expr_to_string( & start) , expr_to_string( & end) ) ,
1512+ Applicability :: MachineApplicable ,
1513+ ) ;
1514+ err. emit ( ) ;
1515+ } else {
1516+ let mut err = cx. struct_span_lint ( ELLIPSIS_INCLUSIVE_RANGE_PATTERNS , join, msg) ;
1517+ err. span_suggestion_short_with_applicability (
1518+ join,
1519+ suggestion,
1520+ "..=" . to_owned ( ) ,
1521+ Applicability :: MachineApplicable ,
1522+ ) ;
1523+ err. emit ( ) ;
1524+ } ;
14951525 }
14961526 }
14971527}
0 commit comments