diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/db.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 19 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 11 |
5 files changed, 33 insertions, 10 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 8aaf0375a..689dd6225 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -161,6 +161,13 @@ pub trait HirDatabase: DefDatabase { | |||
161 | #[salsa::invoke(crate::ty::traits::solver)] | 161 | #[salsa::invoke(crate::ty::traits::solver)] |
162 | #[salsa::volatile] | 162 | #[salsa::volatile] |
163 | fn solver(&self, krate: Crate) -> Arc<Mutex<crate::ty::traits::Solver>>; | 163 | fn solver(&self, krate: Crate) -> Arc<Mutex<crate::ty::traits::Solver>>; |
164 | |||
165 | #[salsa::invoke(crate::ty::traits::implements)] | ||
166 | fn implements( | ||
167 | &self, | ||
168 | krate: Crate, | ||
169 | goal: crate::ty::Canonical<crate::ty::TraitRef>, | ||
170 | ) -> Option<crate::ty::traits::Solution>; | ||
164 | } | 171 | } |
165 | 172 | ||
166 | #[test] | 173 | #[test] |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index f4eee835f..12429a668 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -240,7 +240,7 @@ impl TraitRef { | |||
240 | /// many there are. This is used to erase irrelevant differences between types | 240 | /// many there are. This is used to erase irrelevant differences between types |
241 | /// before using them in queries. | 241 | /// before using them in queries. |
242 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 242 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
243 | pub(crate) struct Canonical<T> { | 243 | pub struct Canonical<T> { |
244 | pub value: T, | 244 | pub value: T, |
245 | pub num_vars: usize, | 245 | pub num_vars: usize, |
246 | } | 246 | } |
@@ -534,3 +534,20 @@ impl HirDisplay for Ty { | |||
534 | Ok(()) | 534 | Ok(()) |
535 | } | 535 | } |
536 | } | 536 | } |
537 | |||
538 | impl HirDisplay for TraitRef { | ||
539 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | ||
540 | write!( | ||
541 | f, | ||
542 | "{}: {}", | ||
543 | self.substs[0].display(f.db), | ||
544 | self.trait_.name(f.db).unwrap_or_else(Name::missing) | ||
545 | )?; | ||
546 | if self.substs.len() > 1 { | ||
547 | write!(f, "<")?; | ||
548 | f.write_joined(&self.substs[1..], ", ")?; | ||
549 | write!(f, ">")?; | ||
550 | } | ||
551 | Ok(()) | ||
552 | } | ||
553 | } | ||
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index edce1afe7..1e7d97f51 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -328,8 +328,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
328 | Obligation::Trait(tr) => { | 328 | Obligation::Trait(tr) => { |
329 | let canonicalized = self.canonicalizer().canonicalize_trait_ref(tr.clone()); | 329 | let canonicalized = self.canonicalizer().canonicalize_trait_ref(tr.clone()); |
330 | ( | 330 | ( |
331 | super::traits::implements( | 331 | self.db.implements( |
332 | self.db, | ||
333 | self.resolver.krate().unwrap(), | 332 | self.resolver.krate().unwrap(), |
334 | canonicalized.value.clone(), | 333 | canonicalized.value.clone(), |
335 | ), | 334 | ), |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 607e9ba79..d8b8c836c 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -196,8 +196,7 @@ fn iterate_trait_method_candidates<T>( | |||
196 | if name.map_or(true, |name| sig.name() == name) && sig.has_self_param() { | 196 | if name.map_or(true, |name| sig.name() == name) && sig.has_self_param() { |
197 | if !known_implemented { | 197 | if !known_implemented { |
198 | let trait_ref = canonical_trait_ref(db, t, ty.clone()); | 198 | let trait_ref = canonical_trait_ref(db, t, ty.clone()); |
199 | // FIXME cache this implements check (without solution) in a query? | 199 | if db.implements(krate, trait_ref).is_none() { |
200 | if super::traits::implements(db, krate, trait_ref).is_none() { | ||
201 | continue 'traits; | 200 | continue 'traits; |
202 | } | 201 | } |
203 | } | 202 | } |
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs index a1ed0c028..4bbc99f0e 100644 --- a/crates/ra_hir/src/ty/traits.rs +++ b/crates/ra_hir/src/ty/traits.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | //! Trait solving using Chalk. | 1 | //! Trait solving using Chalk. |
2 | use std::sync::{Arc, Mutex}; | 2 | use std::sync::{Arc, Mutex}; |
3 | 3 | ||
4 | use rustc_hash::FxHashSet; | ||
4 | use log::debug; | 5 | use log::debug; |
5 | use chalk_ir::cast::Cast; | 6 | use chalk_ir::cast::Cast; |
6 | 7 | ||
@@ -31,7 +32,7 @@ pub(crate) fn impls_for_trait( | |||
31 | krate: Crate, | 32 | krate: Crate, |
32 | trait_: Trait, | 33 | trait_: Trait, |
33 | ) -> Arc<[ImplBlock]> { | 34 | ) -> Arc<[ImplBlock]> { |
34 | let mut impls = Vec::new(); | 35 | let mut impls = FxHashSet::default(); |
35 | // We call the query recursively here. On the one hand, this means we can | 36 | // We call the query recursively here. On the one hand, this means we can |
36 | // reuse results from queries for different crates; on the other hand, this | 37 | // reuse results from queries for different crates; on the other hand, this |
37 | // will only ever get called for a few crates near the root of the tree (the | 38 | // will only ever get called for a few crates near the root of the tree (the |
@@ -42,7 +43,7 @@ pub(crate) fn impls_for_trait( | |||
42 | } | 43 | } |
43 | let crate_impl_blocks = db.impls_in_crate(krate); | 44 | let crate_impl_blocks = db.impls_in_crate(krate); |
44 | impls.extend(crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_)); | 45 | impls.extend(crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_)); |
45 | impls.into() | 46 | impls.into_iter().collect::<Vec<_>>().into() |
46 | } | 47 | } |
47 | 48 | ||
48 | fn solve( | 49 | fn solve( |
@@ -125,11 +126,11 @@ fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) - | |||
125 | } | 126 | } |
126 | 127 | ||
127 | #[derive(Clone, Debug, PartialEq, Eq)] | 128 | #[derive(Clone, Debug, PartialEq, Eq)] |
128 | pub(crate) struct SolutionVariables(pub Canonical<Vec<Ty>>); | 129 | pub struct SolutionVariables(pub Canonical<Vec<Ty>>); |
129 | 130 | ||
130 | #[derive(Clone, Debug, PartialEq, Eq)] | 131 | #[derive(Clone, Debug, PartialEq, Eq)] |
131 | /// A (possible) solution for a proposed goal. | 132 | /// A (possible) solution for a proposed goal. |
132 | pub(crate) enum Solution { | 133 | pub enum Solution { |
133 | /// The goal indeed holds, and there is a unique value for all existential | 134 | /// The goal indeed holds, and there is a unique value for all existential |
134 | /// variables. | 135 | /// variables. |
135 | Unique(SolutionVariables), | 136 | Unique(SolutionVariables), |
@@ -144,7 +145,7 @@ pub(crate) enum Solution { | |||
144 | #[derive(Clone, Debug, PartialEq, Eq)] | 145 | #[derive(Clone, Debug, PartialEq, Eq)] |
145 | /// When a goal holds ambiguously (e.g., because there are multiple possible | 146 | /// When a goal holds ambiguously (e.g., because there are multiple possible |
146 | /// solutions), we issue a set of *guidance* back to type inference. | 147 | /// solutions), we issue a set of *guidance* back to type inference. |
147 | pub(crate) enum Guidance { | 148 | pub enum Guidance { |
148 | /// The existential variables *must* have the given values if the goal is | 149 | /// The existential variables *must* have the given values if the goal is |
149 | /// ever to hold, but that alone isn't enough to guarantee the goal will | 150 | /// ever to hold, but that alone isn't enough to guarantee the goal will |
150 | /// actually hold. | 151 | /// actually hold. |