From dbc14f9d570e5bc1ddae05e9ccd8f163082b3cac Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 31 Jan 2020 15:17:48 +0100 Subject: First stab at desugaring bounds for APIT --- crates/ra_hir_ty/src/lower.rs | 29 ++++++++++++++++++++++++++--- crates/ra_hir_ty/src/utils.rs | 10 +++++++--- 2 files changed, 33 insertions(+), 6 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 459b96280..f1a11e073 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use hir_def::{ builtin_type::BuiltinType, - generics::WherePredicate, + generics::{WherePredicateTarget, WherePredicate}, path::{GenericArg, Path, PathSegment, PathSegments}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{TypeBound, TypeRef}, @@ -505,7 +505,22 @@ impl GenericPredicate { ctx: &'a TyLoweringContext<'a, impl HirDatabase>, where_predicate: &'a WherePredicate, ) -> impl Iterator + 'a { - let self_ty = Ty::from_hir(ctx, &where_predicate.type_ref); + let self_ty = match &where_predicate.target { + WherePredicateTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref), + WherePredicateTarget::TypeParam(param_id) => { + let generic_def = ctx.resolver.generic_def().expect("generics in scope"); + let generics = generics(ctx.db, generic_def); + let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; + let idx = generics.param_idx(param_id); + match ctx.type_param_mode { + TypeParamLoweringMode::Placeholder => { + let name = generics.param_name(param_id); + Ty::Param { idx, name } + }, + TypeParamLoweringMode::Variable => Ty::Bound(idx), + } + }, + }; GenericPredicate::from_type_bound(ctx, &where_predicate.bound, self_ty) } @@ -595,10 +610,18 @@ pub(crate) fn generic_predicates_for_param_query( ) -> Arc<[GenericPredicate]> { let resolver = def.resolver(db); let ctx = TyLoweringContext::new(db, &resolver); + let generics = generics(db, def); resolver .where_predicates_in_scope() // we have to filter out all other predicates *first*, before attempting to lower them - .filter(|pred| Ty::from_hir_only_param(&ctx, &pred.type_ref) == Some(param_idx)) + .filter(|pred| match &pred.target { + WherePredicateTarget::TypeRef(type_ref) => Ty::from_hir_only_param(&ctx, type_ref) == Some(param_idx), + WherePredicateTarget::TypeParam(local_id) => { + let param_id = hir_def::TypeParamId { parent: def, local_id: *local_id }; + let idx = generics.param_idx(param_id); + idx == param_idx + } + }) .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) .collect() } diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index f116b95e7..77b7de729 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs @@ -12,6 +12,7 @@ use hir_def::{ AssocContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, }; use hir_expand::name::{name, Name}; +use hir_def::generics::WherePredicateTarget; fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec { let resolver = trait_.resolver(db); @@ -19,11 +20,14 @@ fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec { // lifetime problems, but since there usually shouldn't be more than a // few direct traits this should be fine (we could even use some kind of // SmallVec if performance is a concern) - db.generic_params(trait_.into()) + let generic_params = db.generic_params(trait_.into()); + let trait_self = generic_params.find_trait_self_param(); + generic_params .where_predicates .iter() - .filter_map(|pred| match &pred.type_ref { - TypeRef::Path(p) if p == &Path::from(name![Self]) => pred.bound.as_path(), + .filter_map(|pred| match &pred.target { + WherePredicateTarget::TypeRef(TypeRef::Path(p)) if p == &Path::from(name![Self]) => pred.bound.as_path(), + WherePredicateTarget::TypeParam(local_id) if Some(*local_id) == trait_self => pred.bound.as_path(), _ => None, }) .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) { -- cgit v1.2.3