pub enum WherePredicate {
TypeBound { target: WherePredicateTypeTarget, bound: TypeBound },
Lifetime { target: LifetimeRef, bound: LifetimeRef },
+ ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound },
}
#[derive(Clone, PartialEq, Eq, Debug)]
TypeRef(TypeRef),
/// For desugared where predicates that can directly refer to a type param.
TypeParam(LocalTypeParamId),
- // FIXME: ForLifetime(Vec<LifetimeParamId>, TypeRef)
}
#[derive(Default)]
for bound in
node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
{
- self.add_where_predicate_from_bound(lower_ctx, bound, target.clone());
+ self.add_where_predicate_from_bound(lower_ctx, bound, None, target.clone());
}
}
} else {
continue;
};
+
+ let lifetimes: Option<Box<_>> = pred.generic_param_list().map(|param_list| {
+ // Higher-Ranked Trait Bounds
+ param_list
+ .lifetime_params()
+ .map(|lifetime_param| {
+ lifetime_param
+ .lifetime()
+ .map_or_else(Name::missing, |lt| Name::new_lifetime(<))
+ })
+ .collect()
+ });
for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
- self.add_where_predicate_from_bound(lower_ctx, bound, target.clone());
+ self.add_where_predicate_from_bound(
+ lower_ctx,
+ bound,
+ lifetimes.as_ref(),
+ target.clone(),
+ );
}
}
}
&mut self,
lower_ctx: &LowerCtx,
bound: ast::TypeBound,
+ hrtb_lifetimes: Option<&Box<[Name]>>,
target: Either<TypeRef, LifetimeRef>,
) {
if bound.question_mark_token().is_some() {
}
let bound = TypeBound::from_ast(lower_ctx, bound);
let predicate = match (target, bound) {
- (Either::Left(type_ref), bound) => WherePredicate::TypeBound {
- target: WherePredicateTypeTarget::TypeRef(type_ref),
- bound,
+ (Either::Left(type_ref), bound) => match hrtb_lifetimes {
+ Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
+ lifetimes: hrtb_lifetimes.clone(),
+ target: WherePredicateTypeTarget::TypeRef(type_ref),
+ bound,
+ },
+ None => WherePredicate::TypeBound {
+ target: WherePredicateTypeTarget::TypeRef(type_ref),
+ bound,
+ },
},
(Either::Right(lifetime), TypeBound::Lifetime(bound)) => {
WherePredicate::Lifetime { target: lifetime, bound }
where_predicate: &'a WherePredicate,
) -> impl Iterator<Item = GenericPredicate> + 'a {
match where_predicate {
- WherePredicate::TypeBound { target, bound } => {
+ WherePredicate::ForLifetime { target, bound, .. }
+ | WherePredicate::TypeBound { target, bound } => {
let self_ty = match target {
WherePredicateTypeTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref),
WherePredicateTypeTarget::TypeParam(param_id) => {
.where_predicates_in_scope()
// we have to filter out all other predicates *first*, before attempting to lower them
.filter(|pred| match pred {
- WherePredicate::TypeBound {
- target: WherePredicateTypeTarget::TypeRef(type_ref),
- ..
- } => Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id),
- WherePredicate::TypeBound {
- target: WherePredicateTypeTarget::TypeParam(local_id),
- ..
- } => *local_id == param_id.local_id,
+ WherePredicate::ForLifetime { target, .. }
+ | WherePredicate::TypeBound { target, .. } => match target {
+ WherePredicateTypeTarget::TypeRef(type_ref) => {
+ Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id)
+ }
+ WherePredicateTypeTarget::TypeParam(local_id) => *local_id == param_id.local_id,
+ },
WherePredicate::Lifetime { .. } => false,
})
.flat_map(|pred| {
use hir_def::{
adt::VariantData,
db::DefDatabase,
- generics::{GenericParams, TypeParamData, TypeParamProvenance, WherePredicateTypeTarget},
+ generics::{
+ GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
+ },
path::Path,
resolver::{HasResolver, TypeNs},
type_ref::TypeRef,
.where_predicates
.iter()
.filter_map(|pred| match pred {
- hir_def::generics::WherePredicate::TypeBound { target, bound } => match target {
+ WherePredicate::ForLifetime { target, bound, .. }
+ | WherePredicate::TypeBound { target, bound } => match target {
WherePredicateTypeTarget::TypeRef(TypeRef::Path(p))
if p == &Path::from(name![Self]) =>
{
}
_ => None,
},
- hir_def::generics::WherePredicate::Lifetime { .. } => None,
+ WherePredicate::Lifetime { .. } => None,
})
.filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) {
Some(TypeNs::TraitId(t)) => Some(t),
}"#,
)
}
+
+ #[test]
+ #[ignore] // requires the HIR to somehow track these hrtb lifetimes
+ fn goto_lifetime_hrtb() {
+ check(
+ r#"trait Foo<T> {}
+fn foo<T>() where for<'a> T: Foo<&'a<|> (u8, u16)>, {}
+ //^^
+"#,
+ );
+ check(
+ r#"trait Foo<T> {}
+fn foo<T>() where for<'a<|>> T: Foo<&'a (u8, u16)>, {}
+ //^^
+"#,
+ );
+ }
+
+ #[test]
+ #[ignore] // requires ForTypes to be implemented
+ fn goto_lifetime_hrtb_for_type() {
+ check(
+ r#"trait Foo<T> {}
+fn foo<T>() where T: for<'a> Foo<&'a<|> (u8, u16)>, {}
+ //^^
+"#,
+ );
+ }
}