Skip to content

Commit 14607ba

Browse files
authored
Merge pull request rust-lang#18419 from ChayimFriedman2/leading-or
fix: Put leading `|` in patterns under `OrPat`
2 parents 0d441c3 + f50b201 commit 14607ba

File tree

11 files changed

+87
-31
lines changed

11 files changed

+87
-31
lines changed

src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1598,6 +1598,10 @@ impl ExprCollector<'_> {
15981598
for (id, _) in current_is_used.into_iter() {
15991599
binding_list.check_is_used(self, id);
16001600
}
1601+
if let &[pat] = &*pats {
1602+
// Leading pipe without real OR pattern. Leaving an one-item OR pattern may confuse later stages.
1603+
return pat;
1604+
}
16011605
Pat::Or(pats.into())
16021606
}
16031607
ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat(), binding_list),

src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
3434
pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
3535
let pipe_token = ctx.find_token_syntax_at_offset(T![|])?;
3636
let or_pat = ast::OrPat::cast(pipe_token.parent()?)?.clone_for_update();
37+
if or_pat.leading_pipe().is_some_and(|it| it == pipe_token) {
38+
return None;
39+
}
3740
let match_arm = ast::MatchArm::cast(or_pat.syntax().parent()?)?;
3841
let match_arm_body = match_arm.expr()?;
3942

src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ const RANGE_PAT_END_FIRST: TokenSet =
2121
expressions::LITERAL_FIRST.union(paths::PATH_FIRST).union(TokenSet::new(&[T![-], T![const]]));
2222

2323
pub(crate) fn pattern(p: &mut Parser<'_>) {
24-
pattern_r(p, PAT_RECOVERY_SET);
24+
let m = p.start();
25+
pattern_r(p, m, false, PAT_RECOVERY_SET);
2526
}
2627

2728
/// Parses a pattern list separated by pipes `|`.
@@ -36,8 +37,9 @@ pub(crate) fn pattern_single(p: &mut Parser<'_>) {
3637
/// Parses a pattern list separated by pipes `|`
3738
/// using the given `recovery_set`.
3839
pub(super) fn pattern_top_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
39-
p.eat(T![|]);
40-
pattern_r(p, recovery_set);
40+
let m = p.start();
41+
let has_leading_pipe = p.eat(T![|]);
42+
pattern_r(p, m, has_leading_pipe, recovery_set);
4143
}
4244

4345
// test or_pattern
@@ -51,11 +53,10 @@ pub(super) fn pattern_top_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
5153
// }
5254
/// Parses a pattern list separated by pipes `|`, with no leading `|`,using the
5355
/// given `recovery_set`.
54-
fn pattern_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
55-
let m = p.start();
56+
fn pattern_r(p: &mut Parser<'_>, m: Marker, has_leading_pipe: bool, recovery_set: TokenSet) {
5657
pattern_single_r(p, recovery_set);
5758

58-
if !p.at(T![|]) {
59+
if !p.at(T![|]) && !has_leading_pipe {
5960
m.abandon(p);
6061
return;
6162
}

src/tools/rust-analyzer/crates/parser/src/tests/top_entries.rs

+32
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,38 @@ fn macro_pattern() {
195195
error 0: expected pattern
196196
"#]],
197197
);
198+
199+
check(
200+
TopEntryPoint::Pattern,
201+
"| 42 | 43",
202+
expect![[r#"
203+
OR_PAT
204+
PIPE "|"
205+
WHITESPACE " "
206+
LITERAL_PAT
207+
LITERAL
208+
INT_NUMBER "42"
209+
WHITESPACE " "
210+
PIPE "|"
211+
WHITESPACE " "
212+
LITERAL_PAT
213+
LITERAL
214+
INT_NUMBER "43"
215+
"#]],
216+
);
217+
218+
check(
219+
TopEntryPoint::Pattern,
220+
"| 42",
221+
expect![[r#"
222+
OR_PAT
223+
PIPE "|"
224+
WHITESPACE " "
225+
LITERAL_PAT
226+
LITERAL
227+
INT_NUMBER "42"
228+
"#]],
229+
);
198230
}
199231

200232
#[test]

src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arm.rast

+8-7
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,9 @@ SOURCE_FILE
102102
COMMA ","
103103
WHITESPACE "\n "
104104
MATCH_ARM
105-
PIPE "|"
106-
WHITESPACE " "
107105
OR_PAT
106+
PIPE "|"
107+
WHITESPACE " "
108108
IDENT_PAT
109109
NAME
110110
IDENT "X"
@@ -132,11 +132,12 @@ SOURCE_FILE
132132
COMMA ","
133133
WHITESPACE "\n "
134134
MATCH_ARM
135-
PIPE "|"
136-
WHITESPACE " "
137-
IDENT_PAT
138-
NAME
139-
IDENT "X"
135+
OR_PAT
136+
PIPE "|"
137+
WHITESPACE " "
138+
IDENT_PAT
139+
NAME
140+
IDENT "X"
140141
WHITESPACE " "
141142
FAT_ARROW "=>"
142143
WHITESPACE " "

src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/slice_pat.rast

+6-5
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@ SOURCE_FILE
4343
WHITESPACE " "
4444
SLICE_PAT
4545
L_BRACK "["
46-
PIPE "|"
47-
WHITESPACE " "
48-
IDENT_PAT
49-
NAME
50-
IDENT "a"
46+
OR_PAT
47+
PIPE "|"
48+
WHITESPACE " "
49+
IDENT_PAT
50+
NAME
51+
IDENT "a"
5152
COMMA ","
5253
WHITESPACE " "
5354
REST_PAT

src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_pat.rast

+8-7
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ SOURCE_FILE
9191
WHITESPACE " "
9292
TUPLE_PAT
9393
L_PAREN "("
94-
PIPE "|"
95-
WHITESPACE " "
9694
OR_PAT
95+
PIPE "|"
96+
WHITESPACE " "
9797
IDENT_PAT
9898
NAME
9999
IDENT "a"
@@ -105,11 +105,12 @@ SOURCE_FILE
105105
IDENT "a"
106106
COMMA ","
107107
WHITESPACE " "
108-
PIPE "|"
109-
WHITESPACE " "
110-
IDENT_PAT
111-
NAME
112-
IDENT "b"
108+
OR_PAT
109+
PIPE "|"
110+
WHITESPACE " "
111+
IDENT_PAT
112+
NAME
113+
IDENT "b"
113114
R_PAREN ")"
114115
WHITESPACE " "
115116
EQ "="

src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_pat_fields.rast

+6-5
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,12 @@ SOURCE_FILE
110110
NAME_REF
111111
IDENT "S"
112112
L_PAREN "("
113-
PIPE "|"
114-
WHITESPACE " "
115-
IDENT_PAT
116-
NAME
117-
IDENT "a"
113+
OR_PAT
114+
PIPE "|"
115+
WHITESPACE " "
116+
IDENT_PAT
117+
NAME
118+
IDENT "a"
118119
R_PAREN ")"
119120
WHITESPACE " "
120121
EQ "="

src/tools/rust-analyzer/crates/syntax/rust.ungram

+1-1
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ PathPat =
736736
Path
737737

738738
OrPat =
739-
(Pat ('|' Pat)* '|'?)
739+
'|'? (Pat ('|' Pat)*)
740740

741741
BoxPat =
742742
'box' Pat

src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,8 @@ pub struct OrPat {
12831283
impl OrPat {
12841284
#[inline]
12851285
pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
1286+
#[inline]
1287+
pub fn pipe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![|]) }
12861288
}
12871289

12881290
#[derive(Debug, Clone, PartialEq, Eq, Hash)]

src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1140,3 +1140,13 @@ impl From<ast::AssocItem> for ast::AnyHasAttrs {
11401140
Self::new(node)
11411141
}
11421142
}
1143+
1144+
impl ast::OrPat {
1145+
pub fn leading_pipe(&self) -> Option<SyntaxToken> {
1146+
self.syntax
1147+
.children_with_tokens()
1148+
.find(|it| !it.kind().is_trivia())
1149+
.and_then(NodeOrToken::into_token)
1150+
.filter(|it| it.kind() == T![|])
1151+
}
1152+
}

0 commit comments

Comments
 (0)