diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_cli/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/ra_cli/src/analysis_bench.rs | 54 | ||||
-rw-r--r-- | crates/ra_cli/src/analysis_stats.rs | 83 | ||||
-rw-r--r-- | crates/ra_cli/src/main.rs | 56 | ||||
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 16 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 54 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 63 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 77 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/unify.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/coercion.rs | 22 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits.rs | 3 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/highlighting.html | 1 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/rainbow_highlighting.html | 1 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 1 | ||||
-rw-r--r-- | crates/ra_ide_db/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main.rs | 7 | ||||
-rw-r--r-- | crates/ra_prof/src/lib.rs | 7 |
17 files changed, 317 insertions, 133 deletions
diff --git a/crates/ra_cli/Cargo.toml b/crates/ra_cli/Cargo.toml index bcd408421..53d4876f6 100644 --- a/crates/ra_cli/Cargo.toml +++ b/crates/ra_cli/Cargo.toml | |||
@@ -6,8 +6,10 @@ authors = ["rust-analyzer developers"] | |||
6 | publish = false | 6 | publish = false |
7 | 7 | ||
8 | [dependencies] | 8 | [dependencies] |
9 | itertools = "0.8.0" | ||
9 | pico-args = "0.3.0" | 10 | pico-args = "0.3.0" |
10 | env_logger = { version = "0.7.1", default-features = false } | 11 | env_logger = { version = "0.7.1", default-features = false } |
12 | rand = { version = "0.7.0", features = ["small_rng"] } | ||
11 | 13 | ||
12 | ra_syntax = { path = "../ra_syntax" } | 14 | ra_syntax = { path = "../ra_syntax" } |
13 | ra_ide = { path = "../ra_ide" } | 15 | ra_ide = { path = "../ra_ide" } |
diff --git a/crates/ra_cli/src/analysis_bench.rs b/crates/ra_cli/src/analysis_bench.rs index 5485a38ff..4835a68ce 100644 --- a/crates/ra_cli/src/analysis_bench.rs +++ b/crates/ra_cli/src/analysis_bench.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | use std::{ | 3 | use std::{ |
4 | path::{Path, PathBuf}, | 4 | path::{Path, PathBuf}, |
5 | str::FromStr, | ||
5 | sync::Arc, | 6 | sync::Arc, |
6 | time::Instant, | 7 | time::Instant, |
7 | }; | 8 | }; |
@@ -14,12 +15,35 @@ use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FilePosition, LineCol}; | |||
14 | 15 | ||
15 | use crate::Result; | 16 | use crate::Result; |
16 | 17 | ||
18 | pub(crate) struct Position { | ||
19 | path: PathBuf, | ||
20 | line: u32, | ||
21 | column: u32, | ||
22 | } | ||
23 | |||
24 | impl FromStr for Position { | ||
25 | type Err = Box<dyn std::error::Error + Send + Sync>; | ||
26 | fn from_str(s: &str) -> Result<Self> { | ||
27 | let (path_line, column) = rsplit_at_char(s, ':')?; | ||
28 | let (path, line) = rsplit_at_char(path_line, ':')?; | ||
29 | Ok(Position { path: path.into(), line: line.parse()?, column: column.parse()? }) | ||
30 | } | ||
31 | } | ||
32 | |||
33 | fn rsplit_at_char(s: &str, c: char) -> Result<(&str, &str)> { | ||
34 | let idx = s.rfind(':').ok_or_else(|| format!("no `{}` in {}", c, s))?; | ||
35 | Ok((&s[..idx], &s[idx + 1..])) | ||
36 | } | ||
37 | |||
17 | pub(crate) enum Op { | 38 | pub(crate) enum Op { |
18 | Highlight { path: PathBuf }, | 39 | Highlight { path: PathBuf }, |
19 | Complete { path: PathBuf, line: u32, column: u32 }, | 40 | Complete(Position), |
41 | GotoDef(Position), | ||
20 | } | 42 | } |
21 | 43 | ||
22 | pub(crate) fn run(verbose: bool, path: &Path, op: Op) -> Result<()> { | 44 | pub(crate) fn run(verbose: bool, path: &Path, op: Op) -> Result<()> { |
45 | ra_prof::init(); | ||
46 | |||
23 | let start = Instant::now(); | 47 | let start = Instant::now(); |
24 | eprint!("loading: "); | 48 | eprint!("loading: "); |
25 | let (mut host, roots) = ra_batch::load_cargo(path)?; | 49 | let (mut host, roots) = ra_batch::load_cargo(path)?; |
@@ -29,7 +53,7 @@ pub(crate) fn run(verbose: bool, path: &Path, op: Op) -> Result<()> { | |||
29 | let file_id = { | 53 | let file_id = { |
30 | let path = match &op { | 54 | let path = match &op { |
31 | Op::Highlight { path } => path, | 55 | Op::Highlight { path } => path, |
32 | Op::Complete { path, .. } => path, | 56 | Op::Complete(pos) | Op::GotoDef(pos) => &pos.path, |
33 | }; | 57 | }; |
34 | let path = std::env::current_dir()?.join(path).canonicalize()?; | 58 | let path = std::env::current_dir()?.join(path).canonicalize()?; |
35 | roots | 59 | roots |
@@ -49,7 +73,7 @@ pub(crate) fn run(verbose: bool, path: &Path, op: Op) -> Result<()> { | |||
49 | .ok_or_else(|| format!("Can't find {:?}", path))? | 73 | .ok_or_else(|| format!("Can't find {:?}", path))? |
50 | }; | 74 | }; |
51 | 75 | ||
52 | match op { | 76 | match &op { |
53 | Op::Highlight { .. } => { | 77 | Op::Highlight { .. } => { |
54 | let res = do_work(&mut host, file_id, |analysis| { | 78 | let res = do_work(&mut host, file_id, |analysis| { |
55 | analysis.diagnostics(file_id).unwrap(); | 79 | analysis.diagnostics(file_id).unwrap(); |
@@ -59,16 +83,30 @@ pub(crate) fn run(verbose: bool, path: &Path, op: Op) -> Result<()> { | |||
59 | println!("\n{}", res); | 83 | println!("\n{}", res); |
60 | } | 84 | } |
61 | } | 85 | } |
62 | Op::Complete { line, column, .. } => { | 86 | Op::Complete(pos) | Op::GotoDef(pos) => { |
87 | let is_completion = match op { | ||
88 | Op::Complete(..) => true, | ||
89 | _ => false, | ||
90 | }; | ||
91 | |||
63 | let offset = host | 92 | let offset = host |
64 | .analysis() | 93 | .analysis() |
65 | .file_line_index(file_id)? | 94 | .file_line_index(file_id)? |
66 | .offset(LineCol { line, col_utf16: column }); | 95 | .offset(LineCol { line: pos.line - 1, col_utf16: pos.column }); |
67 | let file_postion = FilePosition { file_id, offset }; | 96 | let file_postion = FilePosition { file_id, offset }; |
68 | 97 | ||
69 | let res = do_work(&mut host, file_id, |analysis| analysis.completions(file_postion)); | 98 | if is_completion { |
70 | if verbose { | 99 | let res = |
71 | println!("\n{:#?}", res); | 100 | do_work(&mut host, file_id, |analysis| analysis.completions(file_postion)); |
101 | if verbose { | ||
102 | println!("\n{:#?}", res); | ||
103 | } | ||
104 | } else { | ||
105 | let res = | ||
106 | do_work(&mut host, file_id, |analysis| analysis.goto_definition(file_postion)); | ||
107 | if verbose { | ||
108 | println!("\n{:#?}", res); | ||
109 | } | ||
72 | } | 110 | } |
73 | } | 111 | } |
74 | } | 112 | } |
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs index 833235bff..6d2dd34c6 100644 --- a/crates/ra_cli/src/analysis_stats.rs +++ b/crates/ra_cli/src/analysis_stats.rs | |||
@@ -2,6 +2,9 @@ | |||
2 | 2 | ||
3 | use std::{collections::HashSet, fmt::Write, path::Path, time::Instant}; | 3 | use std::{collections::HashSet, fmt::Write, path::Path, time::Instant}; |
4 | 4 | ||
5 | use itertools::Itertools; | ||
6 | use rand::{seq::SliceRandom, thread_rng}; | ||
7 | |||
5 | use hir::{ | 8 | use hir::{ |
6 | db::{DefDatabase, HirDatabase}, | 9 | db::{DefDatabase, HirDatabase}, |
7 | AssocItem, Crate, HasSource, HirDisplay, ModuleDef, | 10 | AssocItem, Crate, HasSource, HirDisplay, ModuleDef, |
@@ -19,6 +22,7 @@ pub fn run( | |||
19 | path: &Path, | 22 | path: &Path, |
20 | only: Option<&str>, | 23 | only: Option<&str>, |
21 | with_deps: bool, | 24 | with_deps: bool, |
25 | randomize: bool, | ||
22 | ) -> Result<()> { | 26 | ) -> Result<()> { |
23 | let db_load_time = Instant::now(); | 27 | let db_load_time = Instant::now(); |
24 | let (mut host, roots) = ra_batch::load_cargo(path)?; | 28 | let (mut host, roots) = ra_batch::load_cargo(path)?; |
@@ -41,7 +45,11 @@ pub fn run( | |||
41 | }) | 45 | }) |
42 | .collect::<HashSet<_>>(); | 46 | .collect::<HashSet<_>>(); |
43 | 47 | ||
44 | for krate in Crate::all(db) { | 48 | let mut krates = Crate::all(db); |
49 | if randomize { | ||
50 | krates.shuffle(&mut thread_rng()); | ||
51 | } | ||
52 | for krate in krates { | ||
45 | let module = krate.root_module(db).expect("crate without root module"); | 53 | let module = krate.root_module(db).expect("crate without root module"); |
46 | let file_id = module.definition_source(db).file_id; | 54 | let file_id = module.definition_source(db).file_id; |
47 | if members.contains(&db.file_source_root(file_id.original_file(db))) { | 55 | if members.contains(&db.file_source_root(file_id.original_file(db))) { |
@@ -50,6 +58,10 @@ pub fn run( | |||
50 | } | 58 | } |
51 | } | 59 | } |
52 | 60 | ||
61 | if randomize { | ||
62 | visit_queue.shuffle(&mut thread_rng()); | ||
63 | } | ||
64 | |||
53 | println!("Crates in this dir: {}", num_crates); | 65 | println!("Crates in this dir: {}", num_crates); |
54 | let mut num_decls = 0; | 66 | let mut num_decls = 0; |
55 | let mut funcs = Vec::new(); | 67 | let mut funcs = Vec::new(); |
@@ -79,10 +91,14 @@ pub fn run( | |||
79 | println!("Total functions: {}", funcs.len()); | 91 | println!("Total functions: {}", funcs.len()); |
80 | println!("Item Collection: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage()); | 92 | println!("Item Collection: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage()); |
81 | 93 | ||
94 | if randomize { | ||
95 | funcs.shuffle(&mut thread_rng()); | ||
96 | } | ||
97 | |||
82 | let inference_time = Instant::now(); | 98 | let inference_time = Instant::now(); |
83 | let mut bar = match verbosity { | 99 | let mut bar = match verbosity { |
84 | Verbosity::Verbose | Verbosity::Normal => ProgressReport::new(funcs.len() as u64), | 100 | Verbosity::Quiet | Verbosity::Spammy => ProgressReport::hidden(), |
85 | Verbosity::Quiet => ProgressReport::hidden(), | 101 | _ => ProgressReport::new(funcs.len() as u64), |
86 | }; | 102 | }; |
87 | 103 | ||
88 | bar.tick(); | 104 | bar.tick(); |
@@ -92,7 +108,20 @@ pub fn run( | |||
92 | let mut num_type_mismatches = 0; | 108 | let mut num_type_mismatches = 0; |
93 | for f in funcs { | 109 | for f in funcs { |
94 | let name = f.name(db); | 110 | let name = f.name(db); |
95 | let mut msg = format!("processing: {}", name); | 111 | let full_name = f |
112 | .module(db) | ||
113 | .path_to_root(db) | ||
114 | .into_iter() | ||
115 | .rev() | ||
116 | .filter_map(|it| it.name(db)) | ||
117 | .chain(Some(f.name(db))) | ||
118 | .join("::"); | ||
119 | if let Some(only_name) = only { | ||
120 | if name.to_string() != only_name && full_name != only_name { | ||
121 | continue; | ||
122 | } | ||
123 | } | ||
124 | let mut msg = format!("processing: {}", full_name); | ||
96 | if verbosity.is_verbose() { | 125 | if verbosity.is_verbose() { |
97 | let src = f.source(db); | 126 | let src = f.source(db); |
98 | let original_file = src.file_id.original_file(db); | 127 | let original_file = src.file_id.original_file(db); |
@@ -100,15 +129,15 @@ pub fn run( | |||
100 | let syntax_range = src.value.syntax().text_range(); | 129 | let syntax_range = src.value.syntax().text_range(); |
101 | write!(msg, " ({:?} {})", path, syntax_range).unwrap(); | 130 | write!(msg, " ({:?} {})", path, syntax_range).unwrap(); |
102 | } | 131 | } |
103 | bar.set_message(&msg); | 132 | if verbosity.is_spammy() { |
104 | if let Some(only_name) = only { | 133 | bar.println(format!("{}", msg)); |
105 | if name.to_string() != only_name { | ||
106 | continue; | ||
107 | } | ||
108 | } | 134 | } |
135 | bar.set_message(&msg); | ||
109 | let f_id = FunctionId::from(f); | 136 | let f_id = FunctionId::from(f); |
110 | let body = db.body(f_id.into()); | 137 | let body = db.body(f_id.into()); |
111 | let inference_result = db.infer(f_id.into()); | 138 | let inference_result = db.infer(f_id.into()); |
139 | let (previous_exprs, previous_unknown, previous_partially_unknown) = | ||
140 | (num_exprs, num_exprs_unknown, num_exprs_partially_unknown); | ||
112 | for (expr_id, _) in body.exprs.iter() { | 141 | for (expr_id, _) in body.exprs.iter() { |
113 | let ty = &inference_result[expr_id]; | 142 | let ty = &inference_result[expr_id]; |
114 | num_exprs += 1; | 143 | num_exprs += 1; |
@@ -125,6 +154,33 @@ pub fn run( | |||
125 | num_exprs_partially_unknown += 1; | 154 | num_exprs_partially_unknown += 1; |
126 | } | 155 | } |
127 | } | 156 | } |
157 | if only.is_some() && verbosity.is_spammy() { | ||
158 | // in super-verbose mode for just one function, we print every single expression | ||
159 | let (_, sm) = db.body_with_source_map(f_id.into()); | ||
160 | let src = sm.expr_syntax(expr_id); | ||
161 | if let Some(src) = src { | ||
162 | let original_file = src.file_id.original_file(db); | ||
163 | let line_index = host.analysis().file_line_index(original_file).unwrap(); | ||
164 | let text_range = src.value.either( | ||
165 | |it| it.syntax_node_ptr().range(), | ||
166 | |it| it.syntax_node_ptr().range(), | ||
167 | ); | ||
168 | let (start, end) = ( | ||
169 | line_index.line_col(text_range.start()), | ||
170 | line_index.line_col(text_range.end()), | ||
171 | ); | ||
172 | bar.println(format!( | ||
173 | "{}:{}-{}:{}: {}", | ||
174 | start.line + 1, | ||
175 | start.col_utf16, | ||
176 | end.line + 1, | ||
177 | end.col_utf16, | ||
178 | ty.display(db) | ||
179 | )); | ||
180 | } else { | ||
181 | bar.println(format!("unknown location: {}", ty.display(db))); | ||
182 | } | ||
183 | } | ||
128 | if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) { | 184 | if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) { |
129 | num_type_mismatches += 1; | 185 | num_type_mismatches += 1; |
130 | if verbosity.is_verbose() { | 186 | if verbosity.is_verbose() { |
@@ -164,6 +220,15 @@ pub fn run( | |||
164 | } | 220 | } |
165 | } | 221 | } |
166 | } | 222 | } |
223 | if verbosity.is_spammy() { | ||
224 | bar.println(format!( | ||
225 | "In {}: {} exprs, {} unknown, {} partial", | ||
226 | full_name, | ||
227 | num_exprs - previous_exprs, | ||
228 | num_exprs_unknown - previous_unknown, | ||
229 | num_exprs_partially_unknown - previous_partially_unknown | ||
230 | )); | ||
231 | } | ||
167 | bar.inc(1); | 232 | bar.inc(1); |
168 | } | 233 | } |
169 | bar.finish_and_clear(); | 234 | bar.finish_and_clear(); |
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs index 806612c2c..750cbab86 100644 --- a/crates/ra_cli/src/main.rs +++ b/crates/ra_cli/src/main.rs | |||
@@ -16,6 +16,7 @@ type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>; | |||
16 | 16 | ||
17 | #[derive(Clone, Copy)] | 17 | #[derive(Clone, Copy)] |
18 | pub enum Verbosity { | 18 | pub enum Verbosity { |
19 | Spammy, | ||
19 | Verbose, | 20 | Verbose, |
20 | Normal, | 21 | Normal, |
21 | Quiet, | 22 | Quiet, |
@@ -24,7 +25,13 @@ pub enum Verbosity { | |||
24 | impl Verbosity { | 25 | impl Verbosity { |
25 | fn is_verbose(self) -> bool { | 26 | fn is_verbose(self) -> bool { |
26 | match self { | 27 | match self { |
27 | Verbosity::Verbose => true, | 28 | Verbosity::Verbose | Verbosity::Spammy => true, |
29 | _ => false, | ||
30 | } | ||
31 | } | ||
32 | fn is_spammy(self) -> bool { | ||
33 | match self { | ||
34 | Verbosity::Spammy => true, | ||
28 | _ => false, | 35 | _ => false, |
29 | } | 36 | } |
30 | } | 37 | } |
@@ -86,14 +93,18 @@ fn main() -> Result<()> { | |||
86 | return Ok(()); | 93 | return Ok(()); |
87 | } | 94 | } |
88 | let verbosity = match ( | 95 | let verbosity = match ( |
96 | matches.contains(["-vv", "--spammy"]), | ||
89 | matches.contains(["-v", "--verbose"]), | 97 | matches.contains(["-v", "--verbose"]), |
90 | matches.contains(["-q", "--quiet"]), | 98 | matches.contains(["-q", "--quiet"]), |
91 | ) { | 99 | ) { |
92 | (false, false) => Verbosity::Normal, | 100 | (true, _, true) => Err("Invalid flags: -q conflicts with -vv")?, |
93 | (false, true) => Verbosity::Quiet, | 101 | (true, _, false) => Verbosity::Spammy, |
94 | (true, false) => Verbosity::Verbose, | 102 | (false, false, false) => Verbosity::Normal, |
95 | (true, true) => Err("Invalid flags: -q conflicts with -v")?, | 103 | (false, false, true) => Verbosity::Quiet, |
104 | (false, true, false) => Verbosity::Verbose, | ||
105 | (false, true, true) => Err("Invalid flags: -q conflicts with -v")?, | ||
96 | }; | 106 | }; |
107 | let randomize = matches.contains("--randomize"); | ||
97 | let memory_usage = matches.contains("--memory-usage"); | 108 | let memory_usage = matches.contains("--memory-usage"); |
98 | let only: Option<String> = matches.opt_value_from_str(["-o", "--only"])?; | 109 | let only: Option<String> = matches.opt_value_from_str(["-o", "--only"])?; |
99 | let with_deps: bool = matches.contains("--with-deps"); | 110 | let with_deps: bool = matches.contains("--with-deps"); |
@@ -111,6 +122,7 @@ fn main() -> Result<()> { | |||
111 | path.as_ref(), | 122 | path.as_ref(), |
112 | only.as_ref().map(String::as_ref), | 123 | only.as_ref().map(String::as_ref), |
113 | with_deps, | 124 | with_deps, |
125 | randomize, | ||
114 | )?; | 126 | )?; |
115 | } | 127 | } |
116 | "analysis-bench" => { | 128 | "analysis-bench" => { |
@@ -120,25 +132,16 @@ fn main() -> Result<()> { | |||
120 | } | 132 | } |
121 | let verbose = matches.contains(["-v", "--verbose"]); | 133 | let verbose = matches.contains(["-v", "--verbose"]); |
122 | let path: String = matches.opt_value_from_str("--path")?.unwrap_or_default(); | 134 | let path: String = matches.opt_value_from_str("--path")?.unwrap_or_default(); |
123 | let highlight_path = matches.opt_value_from_str("--highlight")?; | 135 | let highlight_path: Option<String> = matches.opt_value_from_str("--highlight")?; |
124 | let complete_path = matches.opt_value_from_str("--complete")?; | 136 | let complete_path: Option<String> = matches.opt_value_from_str("--complete")?; |
125 | if highlight_path.is_some() && complete_path.is_some() { | 137 | let goto_def_path: Option<String> = matches.opt_value_from_str("--goto-def")?; |
126 | panic!("either --highlight or --complete must be set, not both") | 138 | let op = match (highlight_path, complete_path, goto_def_path) { |
127 | } | 139 | (Some(path), None, None) => analysis_bench::Op::Highlight { path: path.into() }, |
128 | let op = if let Some(path) = highlight_path { | 140 | (None, Some(position), None) => analysis_bench::Op::Complete(position.parse()?), |
129 | let path: String = path; | 141 | (None, None, Some(position)) => analysis_bench::Op::GotoDef(position.parse()?), |
130 | analysis_bench::Op::Highlight { path: path.into() } | 142 | _ => panic!( |
131 | } else if let Some(path_line_col) = complete_path { | 143 | "exactly one of `--highlight`, `--complete` or `--goto-def` must be set" |
132 | let path_line_col: String = path_line_col; | 144 | ), |
133 | let (path_line, column) = rsplit_at_char(path_line_col.as_str(), ':')?; | ||
134 | let (path, line) = rsplit_at_char(path_line, ':')?; | ||
135 | analysis_bench::Op::Complete { | ||
136 | path: path.into(), | ||
137 | line: line.parse()?, | ||
138 | column: column.parse()?, | ||
139 | } | ||
140 | } else { | ||
141 | panic!("either --highlight or --complete must be set") | ||
142 | }; | 145 | }; |
143 | matches.finish().or_else(handle_extra_flags)?; | 146 | matches.finish().or_else(handle_extra_flags)?; |
144 | analysis_bench::run(verbose, path.as_ref(), op)?; | 147 | analysis_bench::run(verbose, path.as_ref(), op)?; |
@@ -171,8 +174,3 @@ fn read_stdin() -> Result<String> { | |||
171 | std::io::stdin().read_to_string(&mut buff)?; | 174 | std::io::stdin().read_to_string(&mut buff)?; |
172 | Ok(buff) | 175 | Ok(buff) |
173 | } | 176 | } |
174 | |||
175 | fn rsplit_at_char(s: &str, c: char) -> Result<(&str, &str)> { | ||
176 | let idx = s.rfind(':').ok_or_else(|| format!("no `{}` in {}", c, s))?; | ||
177 | Ok((&s[..idx], &s[idx + 1..])) | ||
178 | } | ||
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index bb9a35c5d..94d5b4cfd 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -15,11 +15,9 @@ use hir_def::{ | |||
15 | }, | 15 | }, |
16 | expr::{ExprId, PatId}, | 16 | expr::{ExprId, PatId}, |
17 | resolver::{self, resolver_for_scope, Resolver, TypeNs, ValueNs}, | 17 | resolver::{self, resolver_for_scope, Resolver, TypeNs, ValueNs}, |
18 | DefWithBodyId, TraitId, | 18 | AsMacroCall, DefWithBodyId, TraitId, |
19 | }; | ||
20 | use hir_expand::{ | ||
21 | hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, | ||
22 | }; | 19 | }; |
20 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile, MacroCallId}; | ||
23 | use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment}; | 21 | use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment}; |
24 | use ra_syntax::{ | 22 | use ra_syntax::{ |
25 | ast::{self, AstNode}, | 23 | ast::{self, AstNode}, |
@@ -363,12 +361,10 @@ impl SourceAnalyzer { | |||
363 | db: &impl HirDatabase, | 361 | db: &impl HirDatabase, |
364 | macro_call: InFile<&ast::MacroCall>, | 362 | macro_call: InFile<&ast::MacroCall>, |
365 | ) -> Option<Expansion> { | 363 | ) -> Option<Expansion> { |
366 | let def = self.resolve_macro_call(db, macro_call)?.id; | 364 | let macro_call_id = macro_call.as_call_id(db, |path| { |
367 | let ast_id = AstId::new( | 365 | self.resolver.resolve_path_as_macro(db, &path).map(|it| it.into()) |
368 | macro_call.file_id, | 366 | })?; |
369 | db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), | 367 | Some(Expansion { macro_call_id }) |
370 | ); | ||
371 | Some(Expansion { macro_call_id: def.as_call_id(db, MacroCallKind::FnLike(ast_id)) }) | ||
372 | } | 368 | } |
373 | } | 369 | } |
374 | 370 | ||
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 142c52d35..010d35e55 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -7,9 +7,7 @@ use std::{mem, ops::Index, sync::Arc}; | |||
7 | 7 | ||
8 | use drop_bomb::DropBomb; | 8 | use drop_bomb::DropBomb; |
9 | use either::Either; | 9 | use either::Either; |
10 | use hir_expand::{ | 10 | use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId}; |
11 | ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId, | ||
12 | }; | ||
13 | use ra_arena::{map::ArenaMap, Arena}; | 11 | use ra_arena::{map::ArenaMap, Arena}; |
14 | use ra_prof::profile; | 12 | use ra_prof::profile; |
15 | use ra_syntax::{ast, AstNode, AstPtr}; | 13 | use ra_syntax::{ast, AstNode, AstPtr}; |
@@ -23,7 +21,7 @@ use crate::{ | |||
23 | nameres::CrateDefMap, | 21 | nameres::CrateDefMap, |
24 | path::{ModPath, Path}, | 22 | path::{ModPath, Path}, |
25 | src::HasSource, | 23 | src::HasSource, |
26 | DefWithBodyId, HasModule, Lookup, ModuleId, | 24 | AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, |
27 | }; | 25 | }; |
28 | 26 | ||
29 | pub(crate) struct Expander { | 27 | pub(crate) struct Expander { |
@@ -51,30 +49,26 @@ impl Expander { | |||
51 | db: &DB, | 49 | db: &DB, |
52 | macro_call: ast::MacroCall, | 50 | macro_call: ast::MacroCall, |
53 | ) -> Option<(Mark, T)> { | 51 | ) -> Option<(Mark, T)> { |
54 | let ast_id = AstId::new( | 52 | let macro_call = InFile::new(self.current_file_id, ¯o_call); |
55 | self.current_file_id, | 53 | |
56 | db.ast_id_map(self.current_file_id).ast_id(¯o_call), | 54 | if let Some(call_id) = |
57 | ); | 55 | macro_call.as_call_id(db, |path| self.resolve_path_as_macro(db, &path)) |
58 | 56 | { | |
59 | if let Some(path) = macro_call.path().and_then(|path| self.parse_mod_path(path)) { | 57 | let file_id = call_id.as_file(); |
60 | if let Some(def) = self.resolve_path_as_macro(db, &path) { | 58 | if let Some(node) = db.parse_or_expand(file_id) { |
61 | let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); | 59 | if let Some(expr) = T::cast(node) { |
62 | let file_id = call_id.as_file(); | 60 | log::debug!("macro expansion {:#?}", expr.syntax()); |
63 | if let Some(node) = db.parse_or_expand(file_id) { | 61 | |
64 | if let Some(expr) = T::cast(node) { | 62 | let mark = Mark { |
65 | log::debug!("macro expansion {:#?}", expr.syntax()); | 63 | file_id: self.current_file_id, |
66 | 64 | ast_id_map: mem::take(&mut self.ast_id_map), | |
67 | let mark = Mark { | 65 | bomb: DropBomb::new("expansion mark dropped"), |
68 | file_id: self.current_file_id, | 66 | }; |
69 | ast_id_map: mem::take(&mut self.ast_id_map), | 67 | self.hygiene = Hygiene::new(db, file_id); |
70 | bomb: DropBomb::new("expansion mark dropped"), | 68 | self.current_file_id = file_id; |
71 | }; | 69 | self.ast_id_map = db.ast_id_map(file_id); |
72 | self.hygiene = Hygiene::new(db, file_id); | 70 | |
73 | self.current_file_id = file_id; | 71 | return Some((mark, expr)); |
74 | self.ast_id_map = db.ast_id_map(file_id); | ||
75 | |||
76 | return Some((mark, expr)); | ||
77 | } | ||
78 | } | 72 | } |
79 | } | 73 | } |
80 | } | 74 | } |
@@ -99,10 +93,6 @@ impl Expander { | |||
99 | Path::from_src(path, &self.hygiene) | 93 | Path::from_src(path, &self.hygiene) |
100 | } | 94 | } |
101 | 95 | ||
102 | fn parse_mod_path(&mut self, path: ast::Path) -> Option<ModPath> { | ||
103 | ModPath::from_src(path, &self.hygiene) | ||
104 | } | ||
105 | |||
106 | fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &ModPath) -> Option<MacroDefId> { | 96 | fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &ModPath) -> Option<MacroDefId> { |
107 | self.crate_def_map | 97 | self.crate_def_map |
108 | .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other) | 98 | .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other) |
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index feb3a300d..aa0b558b8 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -46,7 +46,10 @@ mod marks; | |||
46 | 46 | ||
47 | use std::hash::Hash; | 47 | use std::hash::Hash; |
48 | 48 | ||
49 | use hir_expand::{ast_id_map::FileAstId, AstId, HirFileId, InFile, MacroDefId}; | 49 | use hir_expand::{ |
50 | ast_id_map::FileAstId, db::AstDatabase, hygiene::Hygiene, AstId, HirFileId, InFile, | ||
51 | MacroCallId, MacroCallKind, MacroDefId, | ||
52 | }; | ||
50 | use ra_arena::{impl_arena_id, RawId}; | 53 | use ra_arena::{impl_arena_id, RawId}; |
51 | use ra_db::{impl_intern_key, salsa, CrateId}; | 54 | use ra_db::{impl_intern_key, salsa, CrateId}; |
52 | use ra_syntax::{ast, AstNode}; | 55 | use ra_syntax::{ast, AstNode}; |
@@ -413,3 +416,61 @@ impl HasModule for StaticLoc { | |||
413 | self.container.module(db) | 416 | self.container.module(db) |
414 | } | 417 | } |
415 | } | 418 | } |
419 | |||
420 | /// A helper trait for converting to MacroCallId | ||
421 | pub trait AsMacroCall { | ||
422 | fn as_call_id( | ||
423 | &self, | ||
424 | db: &(impl db::DefDatabase + AstDatabase), | ||
425 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | ||
426 | ) -> Option<MacroCallId>; | ||
427 | } | ||
428 | |||
429 | impl AsMacroCall for InFile<&ast::MacroCall> { | ||
430 | fn as_call_id( | ||
431 | &self, | ||
432 | db: &(impl db::DefDatabase + AstDatabase), | ||
433 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | ||
434 | ) -> Option<MacroCallId> { | ||
435 | let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); | ||
436 | let h = Hygiene::new(db, self.file_id); | ||
437 | let path = path::ModPath::from_src(self.value.path()?, &h)?; | ||
438 | |||
439 | AstIdWithPath::new(ast_id.file_id, ast_id.value, path).as_call_id(db, resolver) | ||
440 | } | ||
441 | } | ||
442 | |||
443 | /// Helper wrapper for `AstId` with `ModPath` | ||
444 | #[derive(Clone, Debug, Eq, PartialEq)] | ||
445 | struct AstIdWithPath<T: ast::AstNode> { | ||
446 | pub ast_id: AstId<T>, | ||
447 | pub path: path::ModPath, | ||
448 | } | ||
449 | |||
450 | impl<T: ast::AstNode> AstIdWithPath<T> { | ||
451 | pub fn new(file_id: HirFileId, ast_id: FileAstId<T>, path: path::ModPath) -> AstIdWithPath<T> { | ||
452 | AstIdWithPath { ast_id: AstId::new(file_id, ast_id), path } | ||
453 | } | ||
454 | } | ||
455 | |||
456 | impl AsMacroCall for AstIdWithPath<ast::MacroCall> { | ||
457 | fn as_call_id( | ||
458 | &self, | ||
459 | db: &impl AstDatabase, | ||
460 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | ||
461 | ) -> Option<MacroCallId> { | ||
462 | let def = resolver(self.path.clone())?; | ||
463 | Some(def.as_call_id(db, MacroCallKind::FnLike(self.ast_id.clone()))) | ||
464 | } | ||
465 | } | ||
466 | |||
467 | impl AsMacroCall for AstIdWithPath<ast::ModuleItem> { | ||
468 | fn as_call_id( | ||
469 | &self, | ||
470 | db: &impl AstDatabase, | ||
471 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | ||
472 | ) -> Option<MacroCallId> { | ||
473 | let def = resolver(self.path.clone())?; | ||
474 | Some(def.as_call_id(db, MacroCallKind::Attr(self.ast_id.clone()))) | ||
475 | } | ||
476 | } | ||
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index b1f3f525d..51c65a5d7 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -7,7 +7,7 @@ use hir_expand::{ | |||
7 | builtin_derive::find_builtin_derive, | 7 | builtin_derive::find_builtin_derive, |
8 | builtin_macro::find_builtin_macro, | 8 | builtin_macro::find_builtin_macro, |
9 | name::{name, AsName, Name}, | 9 | name::{name, AsName, Name}, |
10 | HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | 10 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, |
11 | }; | 11 | }; |
12 | use ra_cfg::CfgOptions; | 12 | use ra_cfg::CfgOptions; |
13 | use ra_db::{CrateId, FileId}; | 13 | use ra_db::{CrateId, FileId}; |
@@ -25,8 +25,9 @@ use crate::{ | |||
25 | path::{ImportAlias, ModPath, PathKind}, | 25 | path::{ImportAlias, ModPath, PathKind}, |
26 | per_ns::PerNs, | 26 | per_ns::PerNs, |
27 | visibility::Visibility, | 27 | visibility::Visibility, |
28 | AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, | 28 | AdtId, AsMacroCall, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, |
29 | LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, | 29 | FunctionLoc, ImplLoc, Intern, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, |
30 | TraitLoc, TypeAliasLoc, UnionLoc, | ||
30 | }; | 31 | }; |
31 | 32 | ||
32 | pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { | 33 | pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { |
@@ -99,11 +100,16 @@ struct ImportDirective { | |||
99 | #[derive(Clone, Debug, Eq, PartialEq)] | 100 | #[derive(Clone, Debug, Eq, PartialEq)] |
100 | struct MacroDirective { | 101 | struct MacroDirective { |
101 | module_id: LocalModuleId, | 102 | module_id: LocalModuleId, |
102 | ast_id: AstId<ast::MacroCall>, | 103 | ast_id: AstIdWithPath<ast::MacroCall>, |
103 | path: ModPath, | ||
104 | legacy: Option<MacroCallId>, | 104 | legacy: Option<MacroCallId>, |
105 | } | 105 | } |
106 | 106 | ||
107 | #[derive(Clone, Debug, Eq, PartialEq)] | ||
108 | struct DeriveDirective { | ||
109 | module_id: LocalModuleId, | ||
110 | ast_id: AstIdWithPath<ast::ModuleItem>, | ||
111 | } | ||
112 | |||
107 | /// Walks the tree of module recursively | 113 | /// Walks the tree of module recursively |
108 | struct DefCollector<'a, DB> { | 114 | struct DefCollector<'a, DB> { |
109 | db: &'a DB, | 115 | db: &'a DB, |
@@ -112,7 +118,7 @@ struct DefCollector<'a, DB> { | |||
112 | unresolved_imports: Vec<ImportDirective>, | 118 | unresolved_imports: Vec<ImportDirective>, |
113 | resolved_imports: Vec<ImportDirective>, | 119 | resolved_imports: Vec<ImportDirective>, |
114 | unexpanded_macros: Vec<MacroDirective>, | 120 | unexpanded_macros: Vec<MacroDirective>, |
115 | unexpanded_attribute_macros: Vec<(LocalModuleId, AstId<ast::ModuleItem>, ModPath)>, | 121 | unexpanded_attribute_macros: Vec<DeriveDirective>, |
116 | mod_dirs: FxHashMap<LocalModuleId, ModDir>, | 122 | mod_dirs: FxHashMap<LocalModuleId, ModDir>, |
117 | cfg_options: &'a CfgOptions, | 123 | cfg_options: &'a CfgOptions, |
118 | } | 124 | } |
@@ -515,16 +521,16 @@ where | |||
515 | return false; | 521 | return false; |
516 | } | 522 | } |
517 | 523 | ||
518 | let resolved_res = self.def_map.resolve_path_fp_with_macro( | 524 | if let Some(call_id) = directive.ast_id.as_call_id(self.db, |path| { |
519 | self.db, | 525 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
520 | ResolveMode::Other, | 526 | self.db, |
521 | directive.module_id, | 527 | ResolveMode::Other, |
522 | &directive.path, | 528 | directive.module_id, |
523 | BuiltinShadowMode::Module, | 529 | &path, |
524 | ); | 530 | BuiltinShadowMode::Module, |
525 | 531 | ); | |
526 | if let Some(def) = resolved_res.resolved_def.take_macros() { | 532 | resolved_res.resolved_def.take_macros() |
527 | let call_id = def.as_call_id(self.db, MacroCallKind::FnLike(directive.ast_id)); | 533 | }) { |
528 | resolved.push((directive.module_id, call_id)); | 534 | resolved.push((directive.module_id, call_id)); |
529 | res = ReachedFixedPoint::No; | 535 | res = ReachedFixedPoint::No; |
530 | return false; | 536 | return false; |
@@ -532,12 +538,11 @@ where | |||
532 | 538 | ||
533 | true | 539 | true |
534 | }); | 540 | }); |
535 | attribute_macros.retain(|(module_id, ast_id, path)| { | 541 | attribute_macros.retain(|directive| { |
536 | let resolved_res = self.resolve_attribute_macro(path); | 542 | if let Some(call_id) = |
537 | 543 | directive.ast_id.as_call_id(self.db, |path| self.resolve_attribute_macro(&path)) | |
538 | if let Some(def) = resolved_res { | 544 | { |
539 | let call_id = def.as_call_id(self.db, MacroCallKind::Attr(*ast_id)); | 545 | resolved.push((directive.module_id, call_id)); |
540 | resolved.push((*module_id, call_id)); | ||
541 | res = ReachedFixedPoint::No; | 546 | res = ReachedFixedPoint::No; |
542 | return false; | 547 | return false; |
543 | } | 548 | } |
@@ -833,20 +838,22 @@ where | |||
833 | }; | 838 | }; |
834 | let path = ModPath::from_tt_ident(ident); | 839 | let path = ModPath::from_tt_ident(ident); |
835 | 840 | ||
836 | let ast_id = AstId::new(self.file_id, def.kind.ast_id()); | 841 | let ast_id = AstIdWithPath::new(self.file_id, def.kind.ast_id(), path); |
837 | self.def_collector.unexpanded_attribute_macros.push((self.module_id, ast_id, path)); | 842 | self.def_collector |
843 | .unexpanded_attribute_macros | ||
844 | .push(DeriveDirective { module_id: self.module_id, ast_id }); | ||
838 | } | 845 | } |
839 | } | 846 | } |
840 | } | 847 | } |
841 | 848 | ||
842 | fn collect_macro(&mut self, mac: &raw::MacroData) { | 849 | fn collect_macro(&mut self, mac: &raw::MacroData) { |
843 | let ast_id = AstId::new(self.file_id, mac.ast_id); | 850 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); |
844 | 851 | ||
845 | // Case 0: builtin macros | 852 | // Case 0: builtin macros |
846 | if mac.builtin { | 853 | if mac.builtin { |
847 | if let Some(name) = &mac.name { | 854 | if let Some(name) = &mac.name { |
848 | let krate = self.def_collector.def_map.krate; | 855 | let krate = self.def_collector.def_map.krate; |
849 | if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) { | 856 | if let Some(macro_id) = find_builtin_macro(name, krate, ast_id.ast_id) { |
850 | self.def_collector.define_macro( | 857 | self.def_collector.define_macro( |
851 | self.module_id, | 858 | self.module_id, |
852 | name.clone(), | 859 | name.clone(), |
@@ -862,7 +869,7 @@ where | |||
862 | if is_macro_rules(&mac.path) { | 869 | if is_macro_rules(&mac.path) { |
863 | if let Some(name) = &mac.name { | 870 | if let Some(name) = &mac.name { |
864 | let macro_id = MacroDefId { | 871 | let macro_id = MacroDefId { |
865 | ast_id: Some(ast_id), | 872 | ast_id: Some(ast_id.ast_id), |
866 | krate: Some(self.def_collector.def_map.krate), | 873 | krate: Some(self.def_collector.def_map.krate), |
867 | kind: MacroDefKind::Declarative, | 874 | kind: MacroDefKind::Declarative, |
868 | }; | 875 | }; |
@@ -872,15 +879,13 @@ where | |||
872 | } | 879 | } |
873 | 880 | ||
874 | // Case 2: try to resolve in legacy scope and expand macro_rules | 881 | // Case 2: try to resolve in legacy scope and expand macro_rules |
875 | if let Some(macro_def) = mac.path.as_ident().and_then(|name| { | 882 | if let Some(macro_call_id) = ast_id.as_call_id(self.def_collector.db, |path| { |
876 | self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) | 883 | path.as_ident().and_then(|name| { |
884 | self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) | ||
885 | }) | ||
877 | }) { | 886 | }) { |
878 | let macro_call_id = | ||
879 | macro_def.as_call_id(self.def_collector.db, MacroCallKind::FnLike(ast_id)); | ||
880 | |||
881 | self.def_collector.unexpanded_macros.push(MacroDirective { | 887 | self.def_collector.unexpanded_macros.push(MacroDirective { |
882 | module_id: self.module_id, | 888 | module_id: self.module_id, |
883 | path: mac.path.clone(), | ||
884 | ast_id, | 889 | ast_id, |
885 | legacy: Some(macro_call_id), | 890 | legacy: Some(macro_call_id), |
886 | }); | 891 | }); |
@@ -890,14 +895,12 @@ where | |||
890 | 895 | ||
891 | // Case 3: resolve in module scope, expand during name resolution. | 896 | // Case 3: resolve in module scope, expand during name resolution. |
892 | // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only. | 897 | // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only. |
893 | let mut path = mac.path.clone(); | 898 | if ast_id.path.is_ident() { |
894 | if path.is_ident() { | 899 | ast_id.path.kind = PathKind::Super(0); |
895 | path.kind = PathKind::Super(0); | ||
896 | } | 900 | } |
897 | 901 | ||
898 | self.def_collector.unexpanded_macros.push(MacroDirective { | 902 | self.def_collector.unexpanded_macros.push(MacroDirective { |
899 | module_id: self.module_id, | 903 | module_id: self.module_id, |
900 | path, | ||
901 | ast_id, | 904 | ast_id, |
902 | legacy: None, | 905 | legacy: None, |
903 | }); | 906 | }); |
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs index fe05642ae..1dc842f40 100644 --- a/crates/ra_hir_ty/src/infer/unify.rs +++ b/crates/ra_hir_ty/src/infer/unify.rs | |||
@@ -249,6 +249,8 @@ impl InferenceTable { | |||
249 | match (ty1, ty2) { | 249 | match (ty1, ty2) { |
250 | (Ty::Unknown, _) | (_, Ty::Unknown) => true, | 250 | (Ty::Unknown, _) | (_, Ty::Unknown) => true, |
251 | 251 | ||
252 | (Ty::Placeholder(p1), Ty::Placeholder(p2)) if *p1 == *p2 => true, | ||
253 | |||
252 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) | 254 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) |
253 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) | 255 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) |
254 | | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) | 256 | | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) |
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index fc5ef36a5..42330b269 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs | |||
@@ -526,3 +526,25 @@ fn test() { | |||
526 | "### | 526 | "### |
527 | ); | 527 | ); |
528 | } | 528 | } |
529 | |||
530 | #[test] | ||
531 | fn coerce_placeholder_ref() { | ||
532 | // placeholders should unify, even behind references | ||
533 | assert_snapshot!( | ||
534 | infer_with_mismatches(r#" | ||
535 | struct S<T> { t: T } | ||
536 | impl<TT> S<TT> { | ||
537 | fn get(&self) -> &TT { | ||
538 | &self.t | ||
539 | } | ||
540 | } | ||
541 | "#, true), | ||
542 | @r###" | ||
543 | [51; 55) 'self': &S<TT> | ||
544 | [64; 87) '{ ... }': &TT | ||
545 | [74; 81) '&self.t': &TT | ||
546 | [75; 79) 'self': &S<TT> | ||
547 | [75; 81) 'self.t': TT | ||
548 | "### | ||
549 | ); | ||
550 | } | ||
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs index 88af61e87..ff8e75b48 100644 --- a/crates/ra_hir_ty/src/traits.rs +++ b/crates/ra_hir_ty/src/traits.rs | |||
@@ -60,6 +60,9 @@ impl TraitSolver { | |||
60 | context.0.db.check_canceled(); | 60 | context.0.db.check_canceled(); |
61 | let remaining = fuel.get(); | 61 | let remaining = fuel.get(); |
62 | fuel.set(remaining - 1); | 62 | fuel.set(remaining - 1); |
63 | if remaining == 0 { | ||
64 | log::debug!("fuel exhausted"); | ||
65 | } | ||
63 | remaining > 0 | 66 | remaining > 0 |
64 | }) | 67 | }) |
65 | } | 68 | } |
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html index 1cc55e78b..a02dbaf2f 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html | |||
@@ -16,6 +16,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
16 | .literal { color: #BFEBBF; } | 16 | .literal { color: #BFEBBF; } |
17 | .literal\.numeric { color: #6A8759; } | 17 | .literal\.numeric { color: #6A8759; } |
18 | .macro { color: #94BFF3; } | 18 | .macro { color: #94BFF3; } |
19 | .module { color: #AFD8AF; } | ||
19 | .variable { color: #DCDCCC; } | 20 | .variable { color: #DCDCCC; } |
20 | .variable\.mut { color: #DCDCCC; text-decoration: underline; } | 21 | .variable\.mut { color: #DCDCCC; text-decoration: underline; } |
21 | 22 | ||
diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html index 918fd4b97..95f038f00 100644 --- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html | |||
@@ -16,6 +16,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
16 | .literal { color: #BFEBBF; } | 16 | .literal { color: #BFEBBF; } |
17 | .literal\.numeric { color: #6A8759; } | 17 | .literal\.numeric { color: #6A8759; } |
18 | .macro { color: #94BFF3; } | 18 | .macro { color: #94BFF3; } |
19 | .module { color: #AFD8AF; } | ||
19 | .variable { color: #DCDCCC; } | 20 | .variable { color: #DCDCCC; } |
20 | .variable\.mut { color: #DCDCCC; text-decoration: underline; } | 21 | .variable\.mut { color: #DCDCCC; text-decoration: underline; } |
21 | 22 | ||
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 174e13595..20c414ca1 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -365,6 +365,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
365 | .literal { color: #BFEBBF; } | 365 | .literal { color: #BFEBBF; } |
366 | .literal\\.numeric { color: #6A8759; } | 366 | .literal\\.numeric { color: #6A8759; } |
367 | .macro { color: #94BFF3; } | 367 | .macro { color: #94BFF3; } |
368 | .module { color: #AFD8AF; } | ||
368 | .variable { color: #DCDCCC; } | 369 | .variable { color: #DCDCCC; } |
369 | .variable\\.mut { color: #DCDCCC; text-decoration: underline; } | 370 | .variable\\.mut { color: #DCDCCC; text-decoration: underline; } |
370 | 371 | ||
diff --git a/crates/ra_ide_db/Cargo.toml b/crates/ra_ide_db/Cargo.toml index 716e88bc1..495fffb5a 100644 --- a/crates/ra_ide_db/Cargo.toml +++ b/crates/ra_ide_db/Cargo.toml | |||
@@ -22,7 +22,6 @@ fst = { version = "0.3.1", default-features = false } | |||
22 | rustc-hash = "1.0" | 22 | rustc-hash = "1.0" |
23 | unicase = "2.2.0" | 23 | unicase = "2.2.0" |
24 | superslice = "1.0.0" | 24 | superslice = "1.0.0" |
25 | rand = { version = "0.7.0", features = ["small_rng"] } | ||
26 | once_cell = "1.2.0" | 25 | once_cell = "1.2.0" |
27 | 26 | ||
28 | ra_syntax = { path = "../ra_syntax" } | 27 | ra_syntax = { path = "../ra_syntax" } |
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs index c8a017c5c..ed2eaabd4 100644 --- a/crates/ra_lsp_server/src/main.rs +++ b/crates/ra_lsp_server/src/main.rs | |||
@@ -15,13 +15,8 @@ fn main() -> Result<()> { | |||
15 | 15 | ||
16 | fn setup_logging() -> Result<()> { | 16 | fn setup_logging() -> Result<()> { |
17 | std::env::set_var("RUST_BACKTRACE", "short"); | 17 | std::env::set_var("RUST_BACKTRACE", "short"); |
18 | |||
19 | env_logger::try_init()?; | 18 | env_logger::try_init()?; |
20 | 19 | ra_prof::init(); | |
21 | ra_prof::set_filter(match std::env::var("RA_PROFILE") { | ||
22 | Ok(spec) => ra_prof::Filter::from_spec(&spec), | ||
23 | Err(_) => ra_prof::Filter::disabled(), | ||
24 | }); | ||
25 | Ok(()) | 20 | Ok(()) |
26 | } | 21 | } |
27 | 22 | ||
diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index d38ff397e..c0bfbc2ee 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs | |||
@@ -26,6 +26,13 @@ pub use crate::memory_usage::{Bytes, MemoryUsage}; | |||
26 | #[global_allocator] | 26 | #[global_allocator] |
27 | static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; | 27 | static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; |
28 | 28 | ||
29 | pub fn init() { | ||
30 | set_filter(match std::env::var("RA_PROFILE") { | ||
31 | Ok(spec) => Filter::from_spec(&spec), | ||
32 | Err(_) => Filter::disabled(), | ||
33 | }); | ||
34 | } | ||
35 | |||
29 | /// Set profiling filter. It specifies descriptions allowed to profile. | 36 | /// Set profiling filter. It specifies descriptions allowed to profile. |
30 | /// This is helpful when call stack has too many nested profiling scopes. | 37 | /// This is helpful when call stack has too many nested profiling scopes. |
31 | /// Additionally filter can specify maximum depth of profiling scopes nesting. | 38 | /// Additionally filter can specify maximum depth of profiling scopes nesting. |