From 50bbf9eb09dc34781cc34e10bfba5f154e833123 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 5 May 2019 14:21:00 +0200 Subject: Handle where clauses in trait solving --- crates/ra_hir/src/ty/lower.rs | 53 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 8 deletions(-) (limited to 'crates/ra_hir/src/ty/lower.rs') diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 8bab7e54b..09d26ce5a 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -5,6 +5,7 @@ //! - Building the type for an item: This happens through the `type_for_def` query. //! //! This usually involves resolving names, collecting generic arguments etc. +use std::sync::Arc; use std::iter; use crate::{ @@ -18,9 +19,9 @@ use crate::{ resolve::{Resolver, Resolution}, path::{PathSegment, GenericArg}, generics::{GenericParams, HasGenericParams}, - adt::VariantDef, Trait + adt::VariantDef, Trait, generics::{ WherePredicate, GenericDef} }; -use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef}; +use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef, GenericPredicate}; impl Ty { pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { @@ -208,16 +209,12 @@ pub(super) fn substs_from_path_segment( } impl TraitRef { - pub(crate) fn from_hir( + pub(crate) fn from_path( db: &impl HirDatabase, resolver: &Resolver, - type_ref: &TypeRef, + path: &Path, explicit_self_ty: Option, ) -> Option { - let path = match type_ref { - TypeRef::Path(path) => path, - _ => return None, - }; let resolved = match resolver.resolve_path(db, &path).take_types()? { Resolution::Def(ModuleDef::Trait(tr)) => tr, _ => return None, @@ -232,6 +229,19 @@ impl TraitRef { Some(TraitRef { trait_: resolved, substs }) } + pub(crate) fn from_hir( + db: &impl HirDatabase, + resolver: &Resolver, + type_ref: &TypeRef, + explicit_self_ty: Option, + ) -> Option { + let path = match type_ref { + TypeRef::Path(path) => path, + _ => return None, + }; + TraitRef::from_path(db, resolver, path, explicit_self_ty) + } + fn substs_from_path( db: &impl HirDatabase, resolver: &Resolver, @@ -246,6 +256,15 @@ impl TraitRef { let substs = Substs::identity(&trait_.generic_params(db)); TraitRef { trait_, substs } } + + pub(crate) fn for_where_predicate( + db: &impl HirDatabase, + resolver: &Resolver, + pred: &WherePredicate, + ) -> Option { + let self_ty = Ty::from_hir(db, resolver, &pred.type_ref); + TraitRef::from_path(db, resolver, &pred.trait_ref, Some(self_ty)) + } } /// Build the declared type of an item. This depends on the namespace; e.g. for @@ -294,6 +313,24 @@ pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { Ty::from_hir(db, &resolver, type_ref) } +/// Resolve the where clause(s) of an item with generics. +pub(crate) fn generic_predicates( + db: &impl HirDatabase, + def: GenericDef, +) -> Arc<[GenericPredicate]> { + let resolver = def.resolver(db); + let generic_params = def.generic_params(db); + let predicates = generic_params + .where_predicates + .iter() + .map(|pred| { + TraitRef::for_where_predicate(db, &resolver, pred) + .map_or(GenericPredicate::Error, GenericPredicate::Implemented) + }) + .collect::>(); + predicates.into() +} + fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { let signature = def.signature(db); let resolver = def.resolver(db); -- cgit v1.2.3