diff options
-rw-r--r-- | crates/ra_cli/src/analysis_stats.rs | 9 | ||||
-rw-r--r-- | crates/ra_cli/src/main.rs | 7 | ||||
-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 |
7 files changed, 45 insertions, 14 deletions
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs index 4516ed660..86ee0cb63 100644 --- a/crates/ra_cli/src/analysis_stats.rs +++ b/crates/ra_cli/src/analysis_stats.rs | |||
@@ -7,7 +7,7 @@ use ra_syntax::AstNode; | |||
7 | 7 | ||
8 | use crate::Result; | 8 | use crate::Result; |
9 | 9 | ||
10 | pub fn run(verbose: bool) -> Result<()> { | 10 | pub fn run(verbose: bool, only: Option<&str>) -> Result<()> { |
11 | let db_load_time = Instant::now(); | 11 | let db_load_time = Instant::now(); |
12 | let (db, roots) = BatchDatabase::load_cargo(".")?; | 12 | let (db, roots) = BatchDatabase::load_cargo(".")?; |
13 | println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed()); | 13 | println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed()); |
@@ -57,14 +57,19 @@ pub fn run(verbose: bool) -> Result<()> { | |||
57 | let mut num_exprs_unknown = 0; | 57 | let mut num_exprs_unknown = 0; |
58 | let mut num_exprs_partially_unknown = 0; | 58 | let mut num_exprs_partially_unknown = 0; |
59 | for f in funcs { | 59 | for f in funcs { |
60 | let name = f.name(&db); | ||
60 | if verbose { | 61 | if verbose { |
61 | let (file_id, source) = f.source(&db); | 62 | let (file_id, source) = f.source(&db); |
62 | let original_file = file_id.original_file(&db); | 63 | let original_file = file_id.original_file(&db); |
63 | let path = db.file_relative_path(original_file); | 64 | let path = db.file_relative_path(original_file); |
64 | let syntax_range = source.syntax().range(); | 65 | let syntax_range = source.syntax().range(); |
65 | let name = f.name(&db); | ||
66 | println!("{} ({:?} {})", name, path, syntax_range); | 66 | println!("{} ({:?} {})", name, path, syntax_range); |
67 | } | 67 | } |
68 | if let Some(only_name) = only { | ||
69 | if name.to_string() != only_name { | ||
70 | continue; | ||
71 | } | ||
72 | } | ||
68 | let body = f.body(&db); | 73 | let body = f.body(&db); |
69 | let inference_result = f.infer(&db); | 74 | let inference_result = f.infer(&db); |
70 | for (expr_id, _) in body.exprs() { | 75 | for (expr_id, _) in body.exprs() { |
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs index 45555be6e..11790d2e7 100644 --- a/crates/ra_cli/src/main.rs +++ b/crates/ra_cli/src/main.rs | |||
@@ -23,7 +23,9 @@ fn main() -> Result<()> { | |||
23 | .subcommand(SubCommand::with_name("parse").arg(Arg::with_name("no-dump").long("--no-dump"))) | 23 | .subcommand(SubCommand::with_name("parse").arg(Arg::with_name("no-dump").long("--no-dump"))) |
24 | .subcommand(SubCommand::with_name("symbols")) | 24 | .subcommand(SubCommand::with_name("symbols")) |
25 | .subcommand( | 25 | .subcommand( |
26 | SubCommand::with_name("analysis-stats").arg(Arg::with_name("verbose").short("v")), | 26 | SubCommand::with_name("analysis-stats") |
27 | .arg(Arg::with_name("verbose").short("v")) | ||
28 | .arg(Arg::with_name("only").short("o").takes_value(true)), | ||
27 | ) | 29 | ) |
28 | .get_matches(); | 30 | .get_matches(); |
29 | match matches.subcommand() { | 31 | match matches.subcommand() { |
@@ -51,7 +53,8 @@ fn main() -> Result<()> { | |||
51 | } | 53 | } |
52 | ("analysis-stats", Some(matches)) => { | 54 | ("analysis-stats", Some(matches)) => { |
53 | let verbose = matches.is_present("verbose"); | 55 | let verbose = matches.is_present("verbose"); |
54 | analysis_stats::run(verbose)?; | 56 | let only = matches.value_of("only"); |
57 | analysis_stats::run(verbose, only)?; | ||
55 | } | 58 | } |
56 | _ => unreachable!(), | 59 | _ => unreachable!(), |
57 | } | 60 | } |
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. |