@@ -40,13 +40,16 @@ use rustc::util::nodemap::FxHashSet;
40
40
41
41
use syntax:: tokenstream:: { TokenTree , TokenStream } ;
42
42
use syntax:: ast;
43
+ use syntax:: ptr:: P ;
44
+ use syntax:: ast:: Expr ;
43
45
use syntax:: attr;
44
46
use syntax:: source_map:: Spanned ;
45
47
use syntax:: edition:: Edition ;
46
48
use syntax:: feature_gate:: { AttributeGate , AttributeType , Stability , deprecated_attributes} ;
47
49
use syntax_pos:: { BytePos , Span , SyntaxContext } ;
48
50
use syntax:: symbol:: keywords;
49
51
use syntax:: errors:: { Applicability , DiagnosticBuilder } ;
52
+ use syntax:: print:: pprust:: expr_to_string;
50
53
51
54
use rustc:: hir:: { self , GenericParamKind , PatKind } ;
52
55
use rustc:: hir:: intravisit:: FnKind ;
@@ -1407,21 +1410,48 @@ impl LintPass for EllipsisInclusiveRangePatterns {
1407
1410
}
1408
1411
1409
1412
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
+ }
1412
1426
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 {
1416
1433
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
+ } ;
1425
1455
}
1426
1456
}
1427
1457
}
0 commit comments