mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-03 10:33:34 +00:00
Insert missing expr/pat for leading comma tuples
This commit is contained in:
parent
7d1bf7023d
commit
0e28202832
@ -542,9 +542,18 @@ impl ExprCollector<'_> {
|
||||
self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
|
||||
}
|
||||
ast::Expr::TupleExpr(e) => {
|
||||
let exprs = e.fields().map(|expr| self.collect_expr(expr)).collect();
|
||||
let mut exprs: Vec<_> = e.fields().map(|expr| self.collect_expr(expr)).collect();
|
||||
// if there is a leading comma, the user is most likely to type out a leading expression
|
||||
// so we insert a missing expression at the beginning for IDE features
|
||||
if comma_follows_token(e.l_paren_token()) {
|
||||
exprs.insert(0, self.missing_expr());
|
||||
}
|
||||
|
||||
self.alloc_expr(
|
||||
Expr::Tuple { exprs, is_assignee_expr: self.is_lowering_assignee_expr },
|
||||
Expr::Tuple {
|
||||
exprs: exprs.into_boxed_slice(),
|
||||
is_assignee_expr: self.is_lowering_assignee_expr,
|
||||
},
|
||||
syntax_ptr,
|
||||
)
|
||||
}
|
||||
@ -1180,7 +1189,11 @@ impl ExprCollector<'_> {
|
||||
ast::Pat::TupleStructPat(p) => {
|
||||
let path =
|
||||
p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
|
||||
let (args, ellipsis) = self.collect_tuple_pat(p.fields(), binding_list);
|
||||
let (args, ellipsis) = self.collect_tuple_pat(
|
||||
p.fields(),
|
||||
comma_follows_token(p.l_paren_token()),
|
||||
binding_list,
|
||||
);
|
||||
Pat::TupleStruct { path, args, ellipsis }
|
||||
}
|
||||
ast::Pat::RefPat(p) => {
|
||||
@ -1199,7 +1212,11 @@ impl ExprCollector<'_> {
|
||||
}
|
||||
ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat(), binding_list),
|
||||
ast::Pat::TuplePat(p) => {
|
||||
let (args, ellipsis) = self.collect_tuple_pat(p.fields(), binding_list);
|
||||
let (args, ellipsis) = self.collect_tuple_pat(
|
||||
p.fields(),
|
||||
comma_follows_token(p.l_paren_token()),
|
||||
binding_list,
|
||||
);
|
||||
Pat::Tuple { args, ellipsis }
|
||||
}
|
||||
ast::Pat::WildcardPat(_) => Pat::Wild,
|
||||
@ -1323,18 +1340,24 @@ impl ExprCollector<'_> {
|
||||
fn collect_tuple_pat(
|
||||
&mut self,
|
||||
args: AstChildren<ast::Pat>,
|
||||
has_leading_comma: bool,
|
||||
binding_list: &mut BindingList,
|
||||
) -> (Box<[PatId]>, Option<usize>) {
|
||||
// Find the location of the `..`, if there is one. Note that we do not
|
||||
// consider the possibility of there being multiple `..` here.
|
||||
let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::RestPat(_)));
|
||||
// We want to skip the `..` pattern here, since we account for it above.
|
||||
let args = args
|
||||
let mut args: Vec<_> = args
|
||||
.filter(|p| !matches!(p, ast::Pat::RestPat(_)))
|
||||
.map(|p| self.collect_pat(p, binding_list))
|
||||
.collect();
|
||||
// if there is a leading comma, the user is most likely to type out a leading pattern
|
||||
// so we insert a missing pattern at the beginning for IDE features
|
||||
if has_leading_comma {
|
||||
args.insert(0, self.missing_pat());
|
||||
}
|
||||
|
||||
(args, ellipsis)
|
||||
(args.into_boxed_slice(), ellipsis)
|
||||
}
|
||||
|
||||
// endregion: patterns
|
||||
@ -1493,3 +1516,8 @@ impl ExprCollector<'_> {
|
||||
self.body.labels.alloc(label)
|
||||
}
|
||||
}
|
||||
|
||||
fn comma_follows_token(t: Option<syntax::SyntaxToken>) -> bool {
|
||||
(|| syntax::algo::skip_trivia_token(t?.next_token()?, syntax::Direction::Next))()
|
||||
.map_or(false, |it| it.kind() == syntax::T![,])
|
||||
}
|
||||
|
@ -1996,7 +1996,6 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn test_tuple_expr_expected() {
|
||||
// FIXME: Seems like we discard valuable results in typeck here
|
||||
check(
|
||||
r#"
|
||||
fn main() {
|
||||
@ -2004,19 +2003,20 @@ fn main() {
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
(&str, u32)
|
||||
^^^^ ---
|
||||
(&str, u32, u32)
|
||||
^^^^ --- ---
|
||||
"#]],
|
||||
);
|
||||
// FIXME: Should typeck report a 4-ary tuple for the expression here?
|
||||
check(
|
||||
r#"
|
||||
fn main() {
|
||||
let _: (&str, u32, u32, u32)= ($0, 1, 3);
|
||||
let _: (&str, u32, u32, u32) = ($0, 1, 3);
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
(&str, u32)
|
||||
^^^^ ---
|
||||
(&str, u32, u32)
|
||||
^^^^ --- ---
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
@ -2026,15 +2026,25 @@ fn main() {
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
(&str, u32, u32)
|
||||
^^^^ --- ---
|
||||
(&str, u32, u32, i32)
|
||||
^^^^ --- --- ---
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tuple_pat_free() {
|
||||
// FIXME: Seems like we discard valuable results in typeck here
|
||||
check(
|
||||
r#"
|
||||
fn main() {
|
||||
let ($0, 1, 3);
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
({unknown}, i32, i32)
|
||||
^^^^^^^^^ --- ---
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
fn main() {
|
||||
@ -2123,10 +2133,9 @@ fn main() {
|
||||
let ($0, 1, 3): (i32, i32, i32);
|
||||
}
|
||||
"#,
|
||||
// FIXME: tuple pat should be of size 3 ideally
|
||||
expect![[r#"
|
||||
(i32, i32)
|
||||
^^^ ---
|
||||
(i32, i32, i32)
|
||||
^^^ --- ---
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
@ -2182,7 +2191,7 @@ fn main() {
|
||||
let ($0 1, 3) = (1, 2, 3);
|
||||
}
|
||||
"#,
|
||||
// FIXME: tuple pat should be of size 3 ideally
|
||||
// FIXME: Should typeck report a 3-ary tuple for the pattern here?
|
||||
expect![[r#"
|
||||
(i32, i32)
|
||||
^^^ ---
|
||||
|
Loading…
Reference in New Issue
Block a user