@@ -64,34 +64,45 @@ impl_lint_pass!(UnnestedOrPatterns => [UNNESTED_OR_PATTERNS]);
64
64
impl EarlyLintPass for UnnestedOrPatterns {
65
65
fn check_arm ( & mut self , cx : & EarlyContext < ' _ > , a : & ast:: Arm ) {
66
66
if self . msrv . meets ( msrvs:: OR_PATTERNS ) {
67
- lint_unnested_or_patterns ( cx, & a. pat ) ;
67
+ lint_unnested_or_patterns ( cx, & a. pat , PatternSource :: Arm ) ;
68
68
}
69
69
}
70
70
71
71
fn check_expr ( & mut self , cx : & EarlyContext < ' _ > , e : & ast:: Expr ) {
72
72
if self . msrv . meets ( msrvs:: OR_PATTERNS ) {
73
73
if let ast:: ExprKind :: Let ( pat, _, _, _) = & e. kind {
74
- lint_unnested_or_patterns ( cx, pat) ;
74
+ lint_unnested_or_patterns ( cx, pat, PatternSource :: Expr ) ;
75
75
}
76
76
}
77
77
}
78
78
79
79
fn check_param ( & mut self , cx : & EarlyContext < ' _ > , p : & ast:: Param ) {
80
80
if self . msrv . meets ( msrvs:: OR_PATTERNS ) {
81
- lint_unnested_or_patterns ( cx, & p. pat ) ;
81
+ lint_unnested_or_patterns ( cx, & p. pat , PatternSource :: Param ) ;
82
82
}
83
83
}
84
84
85
85
fn check_local ( & mut self , cx : & EarlyContext < ' _ > , l : & ast:: Local ) {
86
86
if self . msrv . meets ( msrvs:: OR_PATTERNS ) {
87
- lint_unnested_or_patterns ( cx, & l. pat ) ;
87
+ lint_unnested_or_patterns ( cx, & l. pat , PatternSource :: Local ) ;
88
88
}
89
89
}
90
90
91
91
extract_msrv_attr ! ( ) ;
92
92
}
93
93
94
- fn lint_unnested_or_patterns ( cx : & EarlyContext < ' _ > , pat : & Pat ) {
94
+ enum PatternSource {
95
+ /// The pattern is part of a match arm
96
+ Arm ,
97
+ /// The pattern is part of a if/while let
98
+ Expr ,
99
+ /// The pattern is part of a function parameter
100
+ Param ,
101
+ /// The pattern is part of a let binding
102
+ Local ,
103
+ }
104
+
105
+ fn lint_unnested_or_patterns ( cx : & EarlyContext < ' _ > , pat : & Pat , source : PatternSource ) {
95
106
if let Ident ( .., None ) | Expr ( _) | Wild | Path ( ..) | Range ( ..) | Rest | MacCall ( _) = pat. kind {
96
107
// This is a leaf pattern, so cloning is unprofitable.
97
108
return ;
@@ -109,12 +120,15 @@ fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) {
109
120
110
121
span_lint_and_then ( cx, UNNESTED_OR_PATTERNS , pat. span , "unnested or-patterns" , |db| {
111
122
insert_necessary_parens ( & mut pat) ;
112
- db. span_suggestion_verbose (
113
- pat. span ,
114
- "nest the patterns" ,
115
- pprust:: pat_to_string ( & pat) ,
116
- Applicability :: MachineApplicable ,
117
- ) ;
123
+
124
+ // Insert additional parens if it is an or-pattern and the source is a local or parameter. This is
125
+ // inserted after `pat_to_string` because doing it before will break the spans
126
+ let new_pat = if matches ! ( pat. kind, Or ( _) ) && matches ! ( source, PatternSource :: Local | PatternSource :: Param ) {
127
+ format ! ( "({})" , pprust:: pat_to_string( & pat) )
128
+ } else {
129
+ pprust:: pat_to_string ( & pat)
130
+ } ;
131
+ db. span_suggestion_verbose ( pat. span , "nest the patterns" , new_pat, Applicability :: MachineApplicable ) ;
118
132
} ) ;
119
133
}
120
134
0 commit comments