diff options
Diffstat (limited to 'crates/hir_ty/src/traits.rs')
-rw-r--r-- | crates/hir_ty/src/traits.rs | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index e4cdb6d53..a6a63c673 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs | |||
@@ -10,7 +10,9 @@ use stdx::panic_context; | |||
10 | 10 | ||
11 | use crate::{db::HirDatabase, DebruijnIndex, Substs}; | 11 | use crate::{db::HirDatabase, DebruijnIndex, Substs}; |
12 | 12 | ||
13 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; | 13 | use super::{ |
14 | Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TyKind, TypeWalk, | ||
15 | }; | ||
14 | 16 | ||
15 | use self::chalk::{from_chalk, Interner, ToChalk}; | 17 | use self::chalk::{from_chalk, Interner, ToChalk}; |
16 | 18 | ||
@@ -38,26 +40,38 @@ fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> { | |||
38 | /// fn foo<T: Default>(t: T) {} | 40 | /// fn foo<T: Default>(t: T) {} |
39 | /// ``` | 41 | /// ``` |
40 | /// we assume that `T: Default`. | 42 | /// we assume that `T: Default`. |
41 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | 43 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
42 | pub struct TraitEnvironment { | 44 | pub struct TraitEnvironment { |
43 | pub predicates: Vec<GenericPredicate>, | 45 | // When we're using Chalk's Ty we can make this a BTreeMap since it's Ord, |
46 | // but for now it's too annoying... | ||
47 | pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>, | ||
48 | pub(crate) env: chalk_ir::Environment<Interner>, | ||
44 | } | 49 | } |
45 | 50 | ||
46 | impl TraitEnvironment { | 51 | impl TraitEnvironment { |
47 | /// Returns trait refs with the given self type which are supposed to hold | 52 | pub(crate) fn traits_in_scope_from_clauses<'a>( |
48 | /// in this trait env. E.g. if we are in `foo<T: SomeTrait>()`, this will | ||
49 | /// find that `T: SomeTrait` if we call it for `T`. | ||
50 | pub(crate) fn trait_predicates_for_self_ty<'a>( | ||
51 | &'a self, | 53 | &'a self, |
52 | ty: &'a Ty, | 54 | ty: &'a Ty, |
53 | ) -> impl Iterator<Item = &'a TraitRef> + 'a { | 55 | ) -> impl Iterator<Item = TraitId> + 'a { |
54 | self.predicates.iter().filter_map(move |pred| match pred { | 56 | self.traits_from_clauses.iter().filter_map(move |(self_ty, trait_id)| { |
55 | GenericPredicate::Implemented(tr) if tr.self_ty() == ty => Some(tr), | 57 | if self_ty == ty { |
56 | _ => None, | 58 | Some(*trait_id) |
59 | } else { | ||
60 | None | ||
61 | } | ||
57 | }) | 62 | }) |
58 | } | 63 | } |
59 | } | 64 | } |
60 | 65 | ||
66 | impl Default for TraitEnvironment { | ||
67 | fn default() -> Self { | ||
68 | TraitEnvironment { | ||
69 | traits_from_clauses: Vec::new(), | ||
70 | env: chalk_ir::Environment::new(&Interner), | ||
71 | } | ||
72 | } | ||
73 | } | ||
74 | |||
61 | /// Something (usually a goal), along with an environment. | 75 | /// Something (usually a goal), along with an environment. |
62 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | 76 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
63 | pub struct InEnvironment<T> { | 77 | pub struct InEnvironment<T> { |
@@ -129,7 +143,7 @@ pub(crate) fn trait_solve_query( | |||
129 | log::info!("trait_solve_query({})", goal.value.value.display(db)); | 143 | log::info!("trait_solve_query({})", goal.value.value.display(db)); |
130 | 144 | ||
131 | if let Obligation::Projection(pred) = &goal.value.value { | 145 | if let Obligation::Projection(pred) = &goal.value.value { |
132 | if let Ty::BoundVar(_) = &pred.projection_ty.parameters[0] { | 146 | if let TyKind::BoundVar(_) = &pred.projection_ty.substitution[0].interned(&Interner) { |
133 | // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible | 147 | // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible |
134 | return Some(Solution::Ambig(Guidance::Unknown)); | 148 | return Some(Solution::Ambig(Guidance::Unknown)); |
135 | } | 149 | } |