Skip to content

Commit eefbae7

Browse files
bors[bot]Veykril
andauthored
Merge #6921
6921: Higher-ranked trait bounds for where clauses r=flodiebold a=Veykril There is a slight problem with this which is also noted in a FIXME now but `LifetimeParameters` of these ForLifetime where clauses allocate the lifetimes in the corresponding arena as if they were lifetimes of the item itself and not just the clause they belong to. I wasn't entirely sure what I could do about this but given nothing really uses lifetimes like that currently I figured it might be fine? Open to suggestions for that problem. Co-authored-by: Lukas Wirth <[email protected]>
2 parents f312555 + fa65d6b commit eefbae7

File tree

5 files changed

+74
-19
lines changed

5 files changed

+74
-19
lines changed

crates/hir/src/code_model.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1268,7 +1268,6 @@ impl LifetimeParam {
12681268
}
12691269
}
12701270

1271-
// FIXME: rename from `ImplDef` to `Impl`
12721271
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12731272
pub struct Impl {
12741273
pub(crate) id: ImplId,

crates/hir_def/src/generics.rs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,14 @@ pub struct GenericParams {
6262
pub enum WherePredicate {
6363
TypeBound { target: WherePredicateTypeTarget, bound: TypeBound },
6464
Lifetime { target: LifetimeRef, bound: LifetimeRef },
65+
ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound },
6566
}
6667

6768
#[derive(Clone, PartialEq, Eq, Debug)]
6869
pub enum WherePredicateTypeTarget {
6970
TypeRef(TypeRef),
7071
/// For desugared where predicates that can directly refer to a type param.
7172
TypeParam(LocalTypeParamId),
72-
// FIXME: ForLifetime(Vec<LifetimeParamId>, TypeRef)
7373
}
7474

7575
#[derive(Default)]
@@ -234,7 +234,7 @@ impl GenericParams {
234234
for bound in
235235
node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
236236
{
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());
238238
}
239239
}
240240

@@ -279,8 +279,25 @@ impl GenericParams {
279279
} else {
280280
continue;
281281
};
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+
});
282294
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+
);
284301
}
285302
}
286303
}
@@ -289,6 +306,7 @@ impl GenericParams {
289306
&mut self,
290307
lower_ctx: &LowerCtx,
291308
bound: ast::TypeBound,
309+
hrtb_lifetimes: Option<&Box<[Name]>>,
292310
target: Either<TypeRef, LifetimeRef>,
293311
) {
294312
if bound.question_mark_token().is_some() {
@@ -297,9 +315,16 @@ impl GenericParams {
297315
}
298316
let bound = TypeBound::from_ast(lower_ctx, bound);
299317
let predicate = match (target, bound) {
300-
(Either::Left(type_ref), bound) => WherePredicate::TypeBound {
301-
target: WherePredicateTypeTarget::TypeRef(type_ref),
302-
bound,
318+
(Either::Left(type_ref), bound) => match hrtb_lifetimes {
319+
Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
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+
},
303328
},
304329
(Either::Right(lifetime), TypeBound::Lifetime(bound)) => {
305330
WherePredicate::Lifetime { target: lifetime, bound }

crates/hir_ty/src/lower.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,8 @@ impl GenericPredicate {
675675
where_predicate: &'a WherePredicate,
676676
) -> impl Iterator<Item = GenericPredicate> + 'a {
677677
match where_predicate {
678-
WherePredicate::TypeBound { target, bound } => {
678+
WherePredicate::ForLifetime { target, bound, .. }
679+
| WherePredicate::TypeBound { target, bound } => {
679680
let self_ty = match target {
680681
WherePredicateTypeTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref),
681682
WherePredicateTypeTarget::TypeParam(param_id) => {
@@ -888,14 +889,13 @@ pub(crate) fn generic_predicates_for_param_query(
888889
.where_predicates_in_scope()
889890
// we have to filter out all other predicates *first*, before attempting to lower them
890891
.filter(|pred| match pred {
891-
WherePredicate::TypeBound {
892-
target: WherePredicateTypeTarget::TypeRef(type_ref),
893-
..
894-
} => Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id),
895-
WherePredicate::TypeBound {
896-
target: WherePredicateTypeTarget::TypeParam(local_id),
897-
..
898-
} => *local_id == param_id.local_id,
892+
WherePredicate::ForLifetime { target, .. }
893+
| WherePredicate::TypeBound { target, .. } => match target {
894+
WherePredicateTypeTarget::TypeRef(type_ref) => {
895+
Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id)
896+
}
897+
WherePredicateTypeTarget::TypeParam(local_id) => *local_id == param_id.local_id,
898+
},
899899
WherePredicate::Lifetime { .. } => false,
900900
})
901901
.flat_map(|pred| {

crates/hir_ty/src/utils.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ use std::sync::Arc;
55
use hir_def::{
66
adt::VariantData,
77
db::DefDatabase,
8-
generics::{GenericParams, TypeParamData, TypeParamProvenance, WherePredicateTypeTarget},
8+
generics::{
9+
GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
10+
},
911
path::Path,
1012
resolver::{HasResolver, TypeNs},
1113
type_ref::TypeRef,
@@ -27,7 +29,8 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
2729
.where_predicates
2830
.iter()
2931
.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 {
3134
WherePredicateTypeTarget::TypeRef(TypeRef::Path(p))
3235
if p == &Path::from(name![Self]) =>
3336
{
@@ -38,7 +41,7 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
3841
}
3942
_ => None,
4043
},
41-
hir_def::generics::WherePredicate::Lifetime { .. } => None,
44+
WherePredicate::Lifetime { .. } => None,
4245
})
4346
.filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) {
4447
Some(TypeNs::TraitId(t)) => Some(t),

crates/ide/src/goto_definition.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,4 +1077,32 @@ fn foo<'foobar>(_: &'foobar ()) {
10771077
}"#,
10781078
)
10791079
}
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> {}
1086+
fn foo<T>() where for<'a> T: Foo<&'a<|> (u8, u16)>, {}
1087+
//^^
1088+
"#,
1089+
);
1090+
check(
1091+
r#"trait Foo<T> {}
1092+
fn 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> {}
1103+
fn foo<T>() where T: for<'a> Foo<&'a<|> (u8, u16)>, {}
1104+
//^^
1105+
"#,
1106+
);
1107+
}
10801108
}

0 commit comments

Comments
 (0)