aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/hir/src/code_model.rs1
-rw-r--r--crates/hir_def/src/generics.rs37
-rw-r--r--crates/hir_ty/src/lower.rs18
-rw-r--r--crates/hir_ty/src/utils.rs9
-rw-r--r--crates/ide/src/goto_definition.rs28
-rw-r--r--crates/mbe/src/tests.rs12
-rw-r--r--crates/parser/src/grammar.rs2
-rw-r--r--crates/parser/src/grammar/type_params.rs2
-rw-r--r--crates/parser/src/grammar/types.rs26
-rw-r--r--crates/parser/src/lib.rs2
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast43
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs1
12 files changed, 151 insertions, 30 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index d6c7e71ea..73ca6ba9f 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -1268,7 +1268,6 @@ impl LifetimeParam {
1268 } 1268 }
1269} 1269}
1270 1270
1271// FIXME: rename from `ImplDef` to `Impl`
1272#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 1271#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1273pub struct Impl { 1272pub struct Impl {
1274 pub(crate) id: ImplId, 1273 pub(crate) id: ImplId,
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index 41134d23b..bb8fca009 100644
--- a/crates/hir_def/src/generics.rs
+++ b/crates/hir_def/src/generics.rs
@@ -62,6 +62,7 @@ pub struct GenericParams {
62pub enum WherePredicate { 62pub enum WherePredicate {
63 TypeBound { target: WherePredicateTypeTarget, bound: TypeBound }, 63 TypeBound { target: WherePredicateTypeTarget, bound: TypeBound },
64 Lifetime { target: LifetimeRef, bound: LifetimeRef }, 64 Lifetime { target: LifetimeRef, bound: LifetimeRef },
65 ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound },
65} 66}
66 67
67#[derive(Clone, PartialEq, Eq, Debug)] 68#[derive(Clone, PartialEq, Eq, Debug)]
@@ -69,7 +70,6 @@ pub enum WherePredicateTypeTarget {
69 TypeRef(TypeRef), 70 TypeRef(TypeRef),
70 /// For desugared where predicates that can directly refer to a type param. 71 /// For desugared where predicates that can directly refer to a type param.
71 TypeParam(LocalTypeParamId), 72 TypeParam(LocalTypeParamId),
72 // FIXME: ForLifetime(Vec<LifetimeParamId>, TypeRef)
73} 73}
74 74
75#[derive(Default)] 75#[derive(Default)]
@@ -234,7 +234,7 @@ impl GenericParams {
234 for bound in 234 for bound in
235 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) 235 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
236 { 236 {
237 self.add_where_predicate_from_bound(lower_ctx, bound, target.clone()); 237 self.add_where_predicate_from_bound(lower_ctx, bound, None, target.clone());
238 } 238 }
239 } 239 }
240 240
@@ -279,8 +279,25 @@ impl GenericParams {
279 } else { 279 } else {
280 continue; 280 continue;
281 }; 281 };
282
283 let lifetimes: Option<Box<_>> = pred.generic_param_list().map(|param_list| {
284 // Higher-Ranked Trait Bounds
285 param_list
286 .lifetime_params()
287 .map(|lifetime_param| {
288 lifetime_param
289 .lifetime()
290 .map_or_else(Name::missing, |lt| Name::new_lifetime(&lt))
291 })
292 .collect()
293 });
282 for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { 294 for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
283 self.add_where_predicate_from_bound(lower_ctx, bound, target.clone()); 295 self.add_where_predicate_from_bound(
296 lower_ctx,
297 bound,
298 lifetimes.as_ref(),
299 target.clone(),
300 );
284 } 301 }
285 } 302 }
286 } 303 }
@@ -289,6 +306,7 @@ impl GenericParams {
289 &mut self, 306 &mut self,
290 lower_ctx: &LowerCtx, 307 lower_ctx: &LowerCtx,
291 bound: ast::TypeBound, 308 bound: ast::TypeBound,
309 hrtb_lifetimes: Option<&Box<[Name]>>,
292 target: Either<TypeRef, LifetimeRef>, 310 target: Either<TypeRef, LifetimeRef>,
293 ) { 311 ) {
294 if bound.question_mark_token().is_some() { 312 if bound.question_mark_token().is_some() {
@@ -297,9 +315,16 @@ impl GenericParams {
297 } 315 }
298 let bound = TypeBound::from_ast(lower_ctx, bound); 316 let bound = TypeBound::from_ast(lower_ctx, bound);
299 let predicate = match (target, bound) { 317 let predicate = match (target, bound) {
300 (Either::Left(type_ref), bound) => WherePredicate::TypeBound { 318 (Either::Left(type_ref), bound) => match hrtb_lifetimes {
301 target: WherePredicateTypeTarget::TypeRef(type_ref), 319 Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
302 bound, 320 lifetimes: hrtb_lifetimes.clone(),
321 target: WherePredicateTypeTarget::TypeRef(type_ref),
322 bound,
323 },
324 None => WherePredicate::TypeBound {
325 target: WherePredicateTypeTarget::TypeRef(type_ref),
326 bound,
327 },
303 }, 328 },
304 (Either::Right(lifetime), TypeBound::Lifetime(bound)) => { 329 (Either::Right(lifetime), TypeBound::Lifetime(bound)) => {
305 WherePredicate::Lifetime { target: lifetime, bound } 330 WherePredicate::Lifetime { target: lifetime, bound }
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 8392cb770..8da56cd11 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -675,7 +675,8 @@ impl GenericPredicate {
675 where_predicate: &'a WherePredicate, 675 where_predicate: &'a WherePredicate,
676 ) -> impl Iterator<Item = GenericPredicate> + 'a { 676 ) -> impl Iterator<Item = GenericPredicate> + 'a {
677 match where_predicate { 677 match where_predicate {
678 WherePredicate::TypeBound { target, bound } => { 678 WherePredicate::ForLifetime { target, bound, .. }
679 | WherePredicate::TypeBound { target, bound } => {
679 let self_ty = match target { 680 let self_ty = match target {
680 WherePredicateTypeTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref), 681 WherePredicateTypeTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref),
681 WherePredicateTypeTarget::TypeParam(param_id) => { 682 WherePredicateTypeTarget::TypeParam(param_id) => {
@@ -888,14 +889,13 @@ pub(crate) fn generic_predicates_for_param_query(
888 .where_predicates_in_scope() 889 .where_predicates_in_scope()
889 // we have to filter out all other predicates *first*, before attempting to lower them 890 // we have to filter out all other predicates *first*, before attempting to lower them
890 .filter(|pred| match pred { 891 .filter(|pred| match pred {
891 WherePredicate::TypeBound { 892 WherePredicate::ForLifetime { target, .. }
892 target: WherePredicateTypeTarget::TypeRef(type_ref), 893 | WherePredicate::TypeBound { target, .. } => match target {
893 .. 894 WherePredicateTypeTarget::TypeRef(type_ref) => {
894 } => Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id), 895 Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id)
895 WherePredicate::TypeBound { 896 }
896 target: WherePredicateTypeTarget::TypeParam(local_id), 897 WherePredicateTypeTarget::TypeParam(local_id) => *local_id == param_id.local_id,
897 .. 898 },
898 } => *local_id == param_id.local_id,
899 WherePredicate::Lifetime { .. } => false, 899 WherePredicate::Lifetime { .. } => false,
900 }) 900 })
901 .flat_map(|pred| { 901 .flat_map(|pred| {
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index af880c065..65b79df0d 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -5,7 +5,9 @@ use std::sync::Arc;
5use hir_def::{ 5use hir_def::{
6 adt::VariantData, 6 adt::VariantData,
7 db::DefDatabase, 7 db::DefDatabase,
8 generics::{GenericParams, TypeParamData, TypeParamProvenance, WherePredicateTypeTarget}, 8 generics::{
9 GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
10 },
9 path::Path, 11 path::Path,
10 resolver::{HasResolver, TypeNs}, 12 resolver::{HasResolver, TypeNs},
11 type_ref::TypeRef, 13 type_ref::TypeRef,
@@ -27,7 +29,8 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
27 .where_predicates 29 .where_predicates
28 .iter() 30 .iter()
29 .filter_map(|pred| match pred { 31 .filter_map(|pred| match pred {
30 hir_def::generics::WherePredicate::TypeBound { target, bound } => match target { 32 WherePredicate::ForLifetime { target, bound, .. }
33 | WherePredicate::TypeBound { target, bound } => match target {
31 WherePredicateTypeTarget::TypeRef(TypeRef::Path(p)) 34 WherePredicateTypeTarget::TypeRef(TypeRef::Path(p))
32 if p == &Path::from(name![Self]) => 35 if p == &Path::from(name![Self]) =>
33 { 36 {
@@ -38,7 +41,7 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
38 } 41 }
39 _ => None, 42 _ => None,
40 }, 43 },
41 hir_def::generics::WherePredicate::Lifetime { .. } => None, 44 WherePredicate::Lifetime { .. } => None,
42 }) 45 })
43 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) { 46 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) {
44 Some(TypeNs::TraitId(t)) => Some(t), 47 Some(TypeNs::TraitId(t)) => Some(t),
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 7a12e9965..431da5d9c 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -1077,4 +1077,32 @@ fn foo<'foobar>(_: &'foobar ()) {
1077}"#, 1077}"#,
1078 ) 1078 )
1079 } 1079 }
1080
1081 #[test]
1082 #[ignore] // requires the HIR to somehow track these hrtb lifetimes
1083 fn goto_lifetime_hrtb() {
1084 check(
1085 r#"trait Foo<T> {}
1086fn foo<T>() where for<'a> T: Foo<&'a<|> (u8, u16)>, {}
1087 //^^
1088"#,
1089 );
1090 check(
1091 r#"trait Foo<T> {}
1092fn foo<T>() where for<'a<|>> T: Foo<&'a (u8, u16)>, {}
1093 //^^
1094"#,
1095 );
1096 }
1097
1098 #[test]
1099 #[ignore] // requires ForTypes to be implemented
1100 fn goto_lifetime_hrtb_for_type() {
1101 check(
1102 r#"trait Foo<T> {}
1103fn foo<T>() where T: for<'a> Foo<&'a<|> (u8, u16)>, {}
1104 //^^
1105"#,
1106 );
1107 }
1080} 1108}
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs
index f10e7a9b6..451fa1456 100644
--- a/crates/mbe/src/tests.rs
+++ b/crates/mbe/src/tests.rs
@@ -1004,6 +1004,18 @@ fn test_underscore() {
1004} 1004}
1005 1005
1006#[test] 1006#[test]
1007fn test_vertical_bar_with_pat() {
1008 parse_macro(
1009 r#"
1010 macro_rules! foo {
1011 (| $pat:pat | ) => { 0 }
1012 }
1013 "#,
1014 )
1015 .assert_expand_items(r#"foo! { | x | }"#, r#"0"#);
1016}
1017
1018#[test]
1007fn test_lifetime() { 1019fn test_lifetime() {
1008 parse_macro( 1020 parse_macro(
1009 r#" 1021 r#"
diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs
index 1a078f6b4..f08c8bab7 100644
--- a/crates/parser/src/grammar.rs
+++ b/crates/parser/src/grammar.rs
@@ -55,7 +55,7 @@ pub(crate) mod fragments {
55 use super::*; 55 use super::*;
56 56
57 pub(crate) use super::{ 57 pub(crate) use super::{
58 expressions::block_expr, paths::type_path as path, patterns::pattern, types::type_, 58 expressions::block_expr, paths::type_path as path, patterns::pattern_single, types::type_,
59 }; 59 };
60 60
61 pub(crate) fn expr(p: &mut Parser) { 61 pub(crate) fn expr(p: &mut Parser) {
diff --git a/crates/parser/src/grammar/type_params.rs b/crates/parser/src/grammar/type_params.rs
index 9c3f7c28a..4aeccd193 100644
--- a/crates/parser/src/grammar/type_params.rs
+++ b/crates/parser/src/grammar/type_params.rs
@@ -113,7 +113,7 @@ fn type_bound(p: &mut Parser) -> bool {
113 p.eat(T![?]); 113 p.eat(T![?]);
114 match p.current() { 114 match p.current() {
115 LIFETIME_IDENT => lifetime(p), 115 LIFETIME_IDENT => lifetime(p),
116 T![for] => types::for_type(p), 116 T![for] => types::for_type(p, false),
117 _ if paths::is_use_path_start(p) => types::path_type_(p, false), 117 _ if paths::is_use_path_start(p) => types::path_type_(p, false),
118 _ => { 118 _ => {
119 m.abandon(p); 119 m.abandon(p);
diff --git a/crates/parser/src/grammar/types.rs b/crates/parser/src/grammar/types.rs
index 36a15eace..94cbf7d85 100644
--- a/crates/parser/src/grammar/types.rs
+++ b/crates/parser/src/grammar/types.rs
@@ -44,7 +44,7 @@ fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) {
44 T![&] => ref_type(p), 44 T![&] => ref_type(p),
45 T![_] => infer_type(p), 45 T![_] => infer_type(p),
46 T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p), 46 T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p),
47 T![for] => for_type(p), 47 T![for] => for_type(p, allow_bounds),
48 T![impl] => impl_trait_type(p), 48 T![impl] => impl_trait_type(p),
49 T![dyn] => dyn_trait_type(p), 49 T![dyn] => dyn_trait_type(p),
50 // Some path types are not allowed to have bounds (no plus) 50 // Some path types are not allowed to have bounds (no plus)
@@ -227,7 +227,7 @@ pub(super) fn for_binder(p: &mut Parser) {
227// type A = for<'a> fn() -> (); 227// type A = for<'a> fn() -> ();
228// type B = for<'a> unsafe extern "C" fn(&'a ()) -> (); 228// type B = for<'a> unsafe extern "C" fn(&'a ()) -> ();
229// type Obj = for<'a> PartialEq<&'a i32>; 229// type Obj = for<'a> PartialEq<&'a i32>;
230pub(super) fn for_type(p: &mut Parser) { 230pub(super) fn for_type(p: &mut Parser, allow_bounds: bool) {
231 assert!(p.at(T![for])); 231 assert!(p.at(T![for]));
232 let m = p.start(); 232 let m = p.start();
233 for_binder(p); 233 for_binder(p);
@@ -240,7 +240,13 @@ pub(super) fn for_type(p: &mut Parser) {
240 } 240 }
241 } 241 }
242 type_no_bounds(p); 242 type_no_bounds(p);
243 m.complete(p, FOR_TYPE); 243 let completed = m.complete(p, FOR_TYPE);
244
245 // test no_dyn_trait_leading_for
246 // type A = for<'a> Test<'a> + Send;
247 if allow_bounds {
248 opt_type_bounds_as_dyn_trait_type(p, completed);
249 }
244} 250}
245 251
246// test impl_trait_type 252// test impl_trait_type
@@ -290,7 +296,7 @@ fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) {
290 let path = m.complete(p, kind); 296 let path = m.complete(p, kind);
291 297
292 if allow_bounds { 298 if allow_bounds {
293 opt_path_type_bounds_as_dyn_trait_type(p, path); 299 opt_type_bounds_as_dyn_trait_type(p, path);
294 } 300 }
295} 301}
296 302
@@ -304,19 +310,23 @@ pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) {
304 // fn foo() -> Box<dyn T + 'f> {} 310 // fn foo() -> Box<dyn T + 'f> {}
305 let path = m.complete(p, PATH_TYPE); 311 let path = m.complete(p, PATH_TYPE);
306 if allow_bounds { 312 if allow_bounds {
307 opt_path_type_bounds_as_dyn_trait_type(p, path); 313 opt_type_bounds_as_dyn_trait_type(p, path);
308 } 314 }
309} 315}
310 316
311/// This turns a parsed PATH_TYPE optionally into a DYN_TRAIT_TYPE 317/// This turns a parsed PATH_TYPE or FOR_TYPE optionally into a DYN_TRAIT_TYPE
312/// with a TYPE_BOUND_LIST 318/// with a TYPE_BOUND_LIST
313fn opt_path_type_bounds_as_dyn_trait_type(p: &mut Parser, path_type_marker: CompletedMarker) { 319fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser, type_marker: CompletedMarker) {
320 assert!(matches!(
321 type_marker.kind(),
322 SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_CALL
323 ));
314 if !p.at(T![+]) { 324 if !p.at(T![+]) {
315 return; 325 return;
316 } 326 }
317 327
318 // First create a TYPE_BOUND from the completed PATH_TYPE 328 // First create a TYPE_BOUND from the completed PATH_TYPE
319 let m = path_type_marker.precede(p).complete(p, TYPE_BOUND); 329 let m = type_marker.precede(p).complete(p, TYPE_BOUND);
320 330
321 // Next setup a marker for the TYPE_BOUND_LIST 331 // Next setup a marker for the TYPE_BOUND_LIST
322 let m = m.precede(p); 332 let m = m.precede(p);
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index ab8e4c70e..811e740f9 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -112,7 +112,7 @@ pub fn parse_fragment(
112 FragmentKind::Path => grammar::fragments::path, 112 FragmentKind::Path => grammar::fragments::path,
113 FragmentKind::Expr => grammar::fragments::expr, 113 FragmentKind::Expr => grammar::fragments::expr,
114 FragmentKind::Type => grammar::fragments::type_, 114 FragmentKind::Type => grammar::fragments::type_,
115 FragmentKind::Pattern => grammar::fragments::pattern, 115 FragmentKind::Pattern => grammar::fragments::pattern_single,
116 FragmentKind::Item => grammar::fragments::item, 116 FragmentKind::Item => grammar::fragments::item,
117 FragmentKind::Block => grammar::fragments::block_expr, 117 FragmentKind::Block => grammar::fragments::block_expr,
118 FragmentKind::Visibility => grammar::fragments::opt_visibility, 118 FragmentKind::Visibility => grammar::fragments::opt_visibility,
diff --git a/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast b/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast
new file mode 100644
index 000000000..edfcb288c
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast
@@ -0,0 +1,43 @@
1[email protected]
2 [email protected]
3 [email protected] "type"
4 [email protected] " "
5 [email protected]
6 [email protected] "A"
7 [email protected] " "
8 [email protected] "="
9 [email protected] " "
10 [email protected]
11 [email protected]
12 [email protected]
13 [email protected]
14 [email protected] "for"
15 [email protected]
16 [email protected] "<"
17 [email protected]
18 [email protected]
19 [email protected] "\'a"
20 [email protected] ">"
21 [email protected] " "
22 [email protected]
23 [email protected]
24 [email protected]
25 [email protected]
26 [email protected] "Test"
27 [email protected]
28 [email protected] "<"
29 [email protected]
30 [email protected]
31 [email protected] "\'a"
32 [email protected] ">"
33 [email protected] " "
34 [email protected] "+"
35 [email protected] " "
36 [email protected]
37 [email protected]
38 [email protected]
39 [email protected]
40 [email protected]
41 [email protected] "Send"
42 [email protected] ";"
43 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs b/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs
new file mode 100644
index 000000000..47a71fd19
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs
@@ -0,0 +1 @@
type A = for<'a> Test<'a> + Send;