Skip to content

Commit 0ba6f4e

Browse files
committed
Auto merge of #17676 - winstxnhdw:precise-capturing, r=Veykril
feat: add preliminary support for `+ use<..>` `precise_capturing` syntax ## Summary This PR adds basic support for the following syntax. ```rs fn captures<'a: 'a, 'b: 'b, T>() -> impl Sized + use<'b, T> {} // ~~~~~~~~~~~~~~~~~~~~~~~ // This opaque type does not capture `'a`. fn outlives<'o, T: 'o>(_: T) {} fn caller<'o, 'a, 'b: 'o, T: 'o>() { // ~~ // ^ Note that we don't need `'a: 'o`. outlives::<'o>(captures::<'a, 'b, T>()); } ``` Related to #17598
2 parents fa5ff86 + 9f74787 commit 0ba6f4e

File tree

9 files changed

+237
-89
lines changed

9 files changed

+237
-89
lines changed

crates/hir-def/src/hir/type_ref.rs

+1
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ impl TypeBound {
379379
None => TypeBound::Error,
380380
}
381381
}
382+
ast::TypeBoundKind::Use(_) => TypeBound::Error,
382383
ast::TypeBoundKind::Lifetime(lifetime) => {
383384
TypeBound::Lifetime(LifetimeRef::new(&lifetime))
384385
}

crates/ide-db/src/generated/lints.rs

+147-89
Large diffs are not rendered by default.

crates/parser/src/grammar/generic_params.rs

+6
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,12 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
144144
match p.current() {
145145
LIFETIME_IDENT => lifetime(p),
146146
T![for] => types::for_type(p, false),
147+
// test precise_capturing
148+
// fn captures<'a: 'a, 'b: 'b, T>() -> impl Sized + use<'b, T> {}
149+
T![use] => {
150+
p.bump_any();
151+
generic_param_list(p)
152+
}
147153
T![?] if p.nth_at(1, T![for]) => {
148154
// test question_for_type_trait_bound
149155
// fn f<T>() where T: ?for<> Sized {}

crates/parser/test_data/generated/runner.rs

+4
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,10 @@ mod ok {
467467
#[test]
468468
fn postfix_range() { run_and_expect_no_errors("test_data/parser/inline/ok/postfix_range.rs"); }
469469
#[test]
470+
fn precise_capturing() {
471+
run_and_expect_no_errors("test_data/parser/inline/ok/precise_capturing.rs");
472+
}
473+
#[test]
470474
fn pub_parens_typepath() {
471475
run_and_expect_no_errors("test_data/parser/inline/ok/pub_parens_typepath.rs");
472476
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
SOURCE_FILE
2+
FN
3+
FN_KW "fn"
4+
WHITESPACE " "
5+
NAME
6+
IDENT "captures"
7+
GENERIC_PARAM_LIST
8+
L_ANGLE "<"
9+
LIFETIME_PARAM
10+
LIFETIME
11+
LIFETIME_IDENT "'a"
12+
COLON ":"
13+
WHITESPACE " "
14+
LIFETIME
15+
LIFETIME_IDENT "'a"
16+
COMMA ","
17+
WHITESPACE " "
18+
LIFETIME_PARAM
19+
LIFETIME
20+
LIFETIME_IDENT "'b"
21+
COLON ":"
22+
WHITESPACE " "
23+
LIFETIME
24+
LIFETIME_IDENT "'b"
25+
COMMA ","
26+
WHITESPACE " "
27+
TYPE_PARAM
28+
NAME
29+
IDENT "T"
30+
R_ANGLE ">"
31+
PARAM_LIST
32+
L_PAREN "("
33+
R_PAREN ")"
34+
WHITESPACE " "
35+
RET_TYPE
36+
THIN_ARROW "->"
37+
WHITESPACE " "
38+
IMPL_TRAIT_TYPE
39+
IMPL_KW "impl"
40+
WHITESPACE " "
41+
TYPE_BOUND_LIST
42+
TYPE_BOUND
43+
PATH_TYPE
44+
PATH
45+
PATH_SEGMENT
46+
NAME_REF
47+
IDENT "Sized"
48+
WHITESPACE " "
49+
PLUS "+"
50+
WHITESPACE " "
51+
TYPE_BOUND
52+
USE_KW "use"
53+
GENERIC_PARAM_LIST
54+
L_ANGLE "<"
55+
LIFETIME_PARAM
56+
LIFETIME
57+
LIFETIME_IDENT "'b"
58+
COMMA ","
59+
WHITESPACE " "
60+
TYPE_PARAM
61+
NAME
62+
IDENT "T"
63+
R_ANGLE ">"
64+
WHITESPACE " "
65+
BLOCK_EXPR
66+
STMT_LIST
67+
L_CURLY "{"
68+
R_CURLY "}"
69+
WHITESPACE "\n"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn captures<'a: 'a, 'b: 'b, T>() -> impl Sized + use<'b, T> {}

crates/syntax/rust.ungram

+1
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,7 @@ TypeBoundList =
629629
TypeBound =
630630
Lifetime
631631
| ('~' 'const' | 'const')? 'async'? '?'? Type
632+
| 'use' GenericParamList
632633

633634
//************************//
634635
// Patterns //

crates/syntax/src/ast/generated/nodes.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1788,6 +1788,8 @@ pub struct TypeBound {
17881788
pub(crate) syntax: SyntaxNode,
17891789
}
17901790
impl TypeBound {
1791+
#[inline]
1792+
pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
17911793
#[inline]
17921794
pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
17931795
#[inline]
@@ -1799,6 +1801,8 @@ impl TypeBound {
17991801
#[inline]
18001802
pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
18011803
#[inline]
1804+
pub fn use_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![use]) }
1805+
#[inline]
18021806
pub fn tilde_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![~]) }
18031807
}
18041808

crates/syntax/src/ast/node_ext.rs

+4
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,8 @@ pub enum TypeBoundKind {
794794
PathType(ast::PathType),
795795
/// for<'a> ...
796796
ForType(ast::ForType),
797+
/// use
798+
Use(ast::GenericParamList),
797799
/// 'a
798800
Lifetime(ast::Lifetime),
799801
}
@@ -804,6 +806,8 @@ impl ast::TypeBound {
804806
TypeBoundKind::PathType(path_type)
805807
} else if let Some(for_type) = support::children(self.syntax()).next() {
806808
TypeBoundKind::ForType(for_type)
809+
} else if let Some(generic_param_list) = self.generic_param_list() {
810+
TypeBoundKind::Use(generic_param_list)
807811
} else if let Some(lifetime) = self.lifetime() {
808812
TypeBoundKind::Lifetime(lifetime)
809813
} else {

0 commit comments

Comments
 (0)