aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/assists/src/handlers/add_lifetime_to_type.rs228
-rw-r--r--crates/assists/src/handlers/fill_match_arms.rs21
-rw-r--r--crates/assists/src/handlers/replace_if_let_with_match.rs73
-rw-r--r--crates/assists/src/lib.rs2
-rw-r--r--crates/assists/src/tests/generated.rs19
-rw-r--r--crates/assists/src/utils.rs19
-rw-r--r--crates/completion/src/completions/dot.rs22
-rw-r--r--crates/completion/src/completions/flyimport.rs16
-rw-r--r--crates/completion/src/completions/fn_param.rs4
-rw-r--r--crates/completion/src/completions/mod_.rs10
-rw-r--r--crates/completion/src/completions/qualified_path.rs54
-rw-r--r--crates/completion/src/completions/record.rs8
-rw-r--r--crates/completion/src/completions/trait_impl.rs13
-rw-r--r--crates/completion/src/completions/unqualified_path.rs88
-rw-r--r--crates/completion/src/item.rs75
-rw-r--r--crates/completion/src/lib.rs91
-rw-r--r--crates/completion/src/render.rs118
-rw-r--r--crates/completion/src/render/const_.rs5
-rw-r--r--crates/completion/src/render/enum_variant.rs5
-rw-r--r--crates/completion/src/render/function.rs10
-rw-r--r--crates/completion/src/render/macro_.rs5
-rw-r--r--crates/completion/src/render/type_alias.rs5
-rw-r--r--crates/hir/src/code_model.rs92
-rw-r--r--crates/hir/src/diagnostics.rs2
-rw-r--r--crates/hir/src/has_source.rs6
-rw-r--r--crates/hir/src/semantics/source_to_def.rs14
-rw-r--r--crates/hir_def/src/attr.rs2
-rw-r--r--crates/hir_def/src/body.rs2
-rw-r--r--crates/hir_def/src/child_by_source.rs2
-rw-r--r--crates/hir_def/src/db.rs15
-rw-r--r--crates/hir_def/src/find_path.rs37
-rw-r--r--crates/hir_def/src/import_map.rs4
-rw-r--r--crates/hir_def/src/item_tree.rs13
-rw-r--r--crates/hir_def/src/item_tree/lower.rs2
-rw-r--r--crates/hir_def/src/lib.rs31
-rw-r--r--crates/hir_def/src/nameres.rs75
-rw-r--r--crates/hir_def/src/nameres/collector.rs29
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs67
-rw-r--r--crates/hir_def/src/nameres/tests.rs62
-rw-r--r--crates/hir_def/src/nameres/tests/block.rs26
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs16
-rw-r--r--crates/hir_def/src/path.rs1
-rw-r--r--crates/hir_def/src/resolver.rs8
-rw-r--r--crates/hir_def/src/test_db.rs6
-rw-r--r--crates/hir_def/src/visibility.rs2
-rw-r--r--crates/hir_expand/src/builtin_macro.rs26
-rw-r--r--crates/hir_expand/src/name.rs3
-rw-r--r--crates/hir_ty/src/diagnostics.rs116
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs85
-rw-r--r--crates/hir_ty/src/display.rs2
-rw-r--r--crates/hir_ty/src/lib.rs14
-rw-r--r--crates/hir_ty/src/lower.rs2
-rw-r--r--crates/hir_ty/src/method_resolution.rs6
-rw-r--r--crates/hir_ty/src/test_db.rs2
-rw-r--r--crates/hir_ty/src/tests.rs8
-rw-r--r--crates/hir_ty/src/traits/chalk.rs4
-rw-r--r--crates/ide/src/diagnostics.rs3
-rw-r--r--crates/ide/src/diagnostics/fixes.rs33
-rw-r--r--crates/ide/src/display/navigation_target.rs37
-rw-r--r--crates/ide/src/file_structure.rs3
-rw-r--r--crates/ide/src/lib.rs2
-rw-r--r--crates/ide/src/references.rs16
-rw-r--r--crates/ide/src/runnables.rs4
-rw-r--r--crates/ide/src/syntax_highlighting.rs4
-rw-r--r--crates/ide/src/syntax_highlighting/format.rs3
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs4
-rw-r--r--crates/ide/src/syntax_highlighting/tags.rs2
-rw-r--r--crates/ide_db/src/lib.rs24
-rw-r--r--crates/ide_db/src/symbol_index.rs14
-rw-r--r--crates/ide_db/src/ty_filter.rs15
-rw-r--r--crates/parser/src/grammar/items/consts.rs2
-rw-r--r--crates/profile/Cargo.toml2
-rw-r--r--crates/rust-analyzer/src/bin/main.rs7
-rw-r--r--crates/rust-analyzer/src/config.rs7
-rw-r--r--crates/rust-analyzer/src/handlers.rs73
-rw-r--r--crates/rust-analyzer/src/to_proto.rs45
-rw-r--r--crates/stdx/src/lib.rs1
-rw-r--r--crates/syntax/Cargo.toml2
-rw-r--r--crates/syntax/src/validation.rs16
-rw-r--r--crates/syntax/test_data/parser/err/0047_mutable_const_item.rast22
-rw-r--r--crates/syntax/test_data/parser/err/0047_mutable_const_item.rs1
-rw-r--r--crates/syntax/test_data/parser/ok/0024_const_item.rast23
-rw-r--r--crates/syntax/test_data/parser/ok/0024_const_item.rs1
83 files changed, 1383 insertions, 656 deletions
diff --git a/crates/assists/src/handlers/add_lifetime_to_type.rs b/crates/assists/src/handlers/add_lifetime_to_type.rs
new file mode 100644
index 000000000..c1603e972
--- /dev/null
+++ b/crates/assists/src/handlers/add_lifetime_to_type.rs
@@ -0,0 +1,228 @@
1use ast::FieldList;
2use syntax::ast::{self, AstNode, GenericParamsOwner, NameOwner, RefType, Type};
3
4use crate::{AssistContext, AssistId, AssistKind, Assists};
5
6// Assist: add_lifetime_to_type
7//
8// Adds a new lifetime to a struct, enum or union.
9//
10// ```
11// struct Point {
12// x: &$0u32,
13// y: u32,
14// }
15// ```
16// ->
17// ```
18// struct Point<'a> {
19// x: &'a u32,
20// y: u32,
21// }
22// ```
23pub(crate) fn add_lifetime_to_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
24 let ref_type_focused = ctx.find_node_at_offset::<ast::RefType>()?;
25 if ref_type_focused.lifetime().is_some() {
26 return None;
27 }
28
29 let node = ctx.find_node_at_offset::<ast::AdtDef>()?;
30 let has_lifetime = node
31 .generic_param_list()
32 .map(|gen_list| gen_list.lifetime_params().count() > 0)
33 .unwrap_or_default();
34
35 if has_lifetime {
36 return None;
37 }
38
39 let ref_types = fetch_borrowed_types(&node)?;
40 let target = node.syntax().text_range();
41
42 acc.add(
43 AssistId("add_lifetime_to_type", AssistKind::Generate),
44 "Add lifetime`",
45 target,
46 |builder| {
47 match node.generic_param_list() {
48 Some(gen_param) => {
49 if let Some(left_angle) = gen_param.l_angle_token() {
50 builder.insert(left_angle.text_range().end(), "'a, ");
51 }
52 }
53 None => {
54 if let Some(name) = node.name() {
55 builder.insert(name.syntax().text_range().end(), "<'a>");
56 }
57 }
58 }
59
60 for ref_type in ref_types {
61 if let Some(amp_token) = ref_type.amp_token() {
62 builder.insert(amp_token.text_range().end(), "'a ");
63 }
64 }
65 },
66 )
67}
68
69fn fetch_borrowed_types(node: &ast::AdtDef) -> Option<Vec<RefType>> {
70 let ref_types: Vec<RefType> = match node {
71 ast::AdtDef::Enum(enum_) => {
72 let variant_list = enum_.variant_list()?;
73 variant_list
74 .variants()
75 .filter_map(|variant| {
76 let field_list = variant.field_list()?;
77
78 find_ref_types_from_field_list(&field_list)
79 })
80 .flatten()
81 .collect()
82 }
83 ast::AdtDef::Struct(strukt) => {
84 let field_list = strukt.field_list()?;
85 find_ref_types_from_field_list(&field_list)?
86 }
87 ast::AdtDef::Union(un) => {
88 let record_field_list = un.record_field_list()?;
89 record_field_list
90 .fields()
91 .filter_map(|r_field| {
92 if let Type::RefType(ref_type) = r_field.ty()? {
93 if ref_type.lifetime().is_none() {
94 return Some(ref_type);
95 }
96 }
97
98 None
99 })
100 .collect()
101 }
102 };
103
104 if ref_types.is_empty() {
105 None
106 } else {
107 Some(ref_types)
108 }
109}
110
111fn find_ref_types_from_field_list(field_list: &FieldList) -> Option<Vec<RefType>> {
112 let ref_types: Vec<RefType> = match field_list {
113 ast::FieldList::RecordFieldList(record_list) => record_list
114 .fields()
115 .filter_map(|f| {
116 if let Type::RefType(ref_type) = f.ty()? {
117 if ref_type.lifetime().is_none() {
118 return Some(ref_type);
119 }
120 }
121
122 None
123 })
124 .collect(),
125 ast::FieldList::TupleFieldList(tuple_field_list) => tuple_field_list
126 .fields()
127 .filter_map(|f| {
128 if let Type::RefType(ref_type) = f.ty()? {
129 if ref_type.lifetime().is_none() {
130 return Some(ref_type);
131 }
132 }
133
134 None
135 })
136 .collect(),
137 };
138
139 if ref_types.is_empty() {
140 None
141 } else {
142 Some(ref_types)
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use crate::tests::{check_assist, check_assist_not_applicable};
149
150 use super::*;
151
152 #[test]
153 fn add_lifetime_to_struct() {
154 check_assist(
155 add_lifetime_to_type,
156 "struct Foo { a: &$0i32 }",
157 "struct Foo<'a> { a: &'a i32 }",
158 );
159
160 check_assist(
161 add_lifetime_to_type,
162 "struct Foo { a: &$0i32, b: &usize }",
163 "struct Foo<'a> { a: &'a i32, b: &'a usize }",
164 );
165
166 check_assist(
167 add_lifetime_to_type,
168 "struct Foo { a: &$0i32, b: usize }",
169 "struct Foo<'a> { a: &'a i32, b: usize }",
170 );
171
172 check_assist(
173 add_lifetime_to_type,
174 "struct Foo<T> { a: &$0T, b: usize }",
175 "struct Foo<'a, T> { a: &'a T, b: usize }",
176 );
177
178 check_assist_not_applicable(add_lifetime_to_type, "struct Foo<'a> { a: &$0'a i32 }");
179 check_assist_not_applicable(add_lifetime_to_type, "struct Foo { a: &'a$0 i32 }");
180 }
181
182 #[test]
183 fn add_lifetime_to_enum() {
184 check_assist(
185 add_lifetime_to_type,
186 "enum Foo { Bar { a: i32 }, Other, Tuple(u32, &$0u32)}",
187 "enum Foo<'a> { Bar { a: i32 }, Other, Tuple(u32, &'a u32)}",
188 );
189
190 check_assist(
191 add_lifetime_to_type,
192 "enum Foo { Bar { a: &$0i32 }}",
193 "enum Foo<'a> { Bar { a: &'a i32 }}",
194 );
195
196 check_assist(
197 add_lifetime_to_type,
198 "enum Foo<T> { Bar { a: &$0i32, b: &T }}",
199 "enum Foo<'a, T> { Bar { a: &'a i32, b: &'a T }}",
200 );
201
202 check_assist_not_applicable(add_lifetime_to_type, "enum Foo<'a> { Bar { a: &$0'a i32 }}");
203 check_assist_not_applicable(add_lifetime_to_type, "enum Foo { Bar, $0Misc }");
204 }
205
206 #[test]
207 fn add_lifetime_to_union() {
208 check_assist(
209 add_lifetime_to_type,
210 "union Foo { a: &$0i32 }",
211 "union Foo<'a> { a: &'a i32 }",
212 );
213
214 check_assist(
215 add_lifetime_to_type,
216 "union Foo { a: &$0i32, b: &usize }",
217 "union Foo<'a> { a: &'a i32, b: &'a usize }",
218 );
219
220 check_assist(
221 add_lifetime_to_type,
222 "union Foo<T> { a: &$0T, b: usize }",
223 "union Foo<'a, T> { a: &'a T, b: usize }",
224 );
225
226 check_assist_not_applicable(add_lifetime_to_type, "struct Foo<'a> { a: &'a $0i32 }");
227 }
228}
diff --git a/crates/assists/src/handlers/fill_match_arms.rs b/crates/assists/src/handlers/fill_match_arms.rs
index da47187e4..7663d211d 100644
--- a/crates/assists/src/handlers/fill_match_arms.rs
+++ b/crates/assists/src/handlers/fill_match_arms.rs
@@ -8,7 +8,7 @@ use syntax::ast::{self, make, AstNode, MatchArm, NameOwner, Pat};
8use test_utils::mark; 8use test_utils::mark;
9 9
10use crate::{ 10use crate::{
11 utils::{render_snippet, Cursor}, 11 utils::{does_pat_match_variant, render_snippet, Cursor},
12 AssistContext, AssistId, AssistKind, Assists, 12 AssistContext, AssistId, AssistKind, Assists,
13}; 13};
14 14
@@ -147,25 +147,6 @@ fn is_variant_missing(existing_arms: &mut Vec<MatchArm>, var: &Pat) -> bool {
147 }) 147 })
148} 148}
149 149
150fn does_pat_match_variant(pat: &Pat, var: &Pat) -> bool {
151 let first_node_text = |pat: &Pat| pat.syntax().first_child().map(|node| node.text());
152
153 let pat_head = match pat {
154 Pat::IdentPat(bind_pat) => {
155 if let Some(p) = bind_pat.pat() {
156 first_node_text(&p)
157 } else {
158 return false;
159 }
160 }
161 pat => first_node_text(pat),
162 };
163
164 let var_head = first_node_text(var);
165
166 pat_head == var_head
167}
168
169fn resolve_enum_def(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<hir::Enum> { 150fn resolve_enum_def(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<hir::Enum> {
170 sema.type_of_expr(&expr)?.autoderef(sema.db).find_map(|ty| match ty.as_adt() { 151 sema.type_of_expr(&expr)?.autoderef(sema.db).find_map(|ty| match ty.as_adt() {
171 Some(Adt::Enum(e)) => Some(e), 152 Some(Adt::Enum(e)) => Some(e),
diff --git a/crates/assists/src/handlers/replace_if_let_with_match.rs b/crates/assists/src/handlers/replace_if_let_with_match.rs
index aee3397ab..aee880625 100644
--- a/crates/assists/src/handlers/replace_if_let_with_match.rs
+++ b/crates/assists/src/handlers/replace_if_let_with_match.rs
@@ -10,7 +10,10 @@ use syntax::{
10 AstNode, 10 AstNode,
11}; 11};
12 12
13use crate::{utils::unwrap_trivial_block, AssistContext, AssistId, AssistKind, Assists}; 13use crate::{
14 utils::{does_pat_match_variant, unwrap_trivial_block},
15 AssistContext, AssistId, AssistKind, Assists,
16};
14 17
15// Assist: replace_if_let_with_match 18// Assist: replace_if_let_with_match
16// 19//
@@ -66,7 +69,13 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext)
66 .sema 69 .sema
67 .type_of_pat(&pat) 70 .type_of_pat(&pat)
68 .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty)) 71 .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty))
69 .map(|it| it.sad_pattern()) 72 .map(|it| {
73 if does_pat_match_variant(&pat, &it.sad_pattern()) {
74 it.happy_pattern()
75 } else {
76 it.sad_pattern()
77 }
78 })
70 .unwrap_or_else(|| make::wildcard_pat().into()); 79 .unwrap_or_else(|| make::wildcard_pat().into());
71 let else_expr = unwrap_trivial_block(else_block); 80 let else_expr = unwrap_trivial_block(else_block);
72 make::match_arm(vec![pattern], else_expr) 81 make::match_arm(vec![pattern], else_expr)
@@ -279,6 +288,36 @@ fn foo(x: Option<i32>) {
279 } 288 }
280 289
281 #[test] 290 #[test]
291 fn special_case_inverted_option() {
292 check_assist(
293 replace_if_let_with_match,
294 r#"
295enum Option<T> { Some(T), None }
296use Option::*;
297
298fn foo(x: Option<i32>) {
299 $0if let None = x {
300 println!("none")
301 } else {
302 println!("some")
303 }
304}
305 "#,
306 r#"
307enum Option<T> { Some(T), None }
308use Option::*;
309
310fn foo(x: Option<i32>) {
311 match x {
312 None => println!("none"),
313 Some(_) => println!("some"),
314 }
315}
316 "#,
317 );
318 }
319
320 #[test]
282 fn special_case_result() { 321 fn special_case_result() {
283 check_assist( 322 check_assist(
284 replace_if_let_with_match, 323 replace_if_let_with_match,
@@ -309,6 +348,36 @@ fn foo(x: Result<i32, ()>) {
309 } 348 }
310 349
311 #[test] 350 #[test]
351 fn special_case_inverted_result() {
352 check_assist(
353 replace_if_let_with_match,
354 r#"
355enum Result<T, E> { Ok(T), Err(E) }
356use Result::*;
357
358fn foo(x: Result<i32, ()>) {
359 $0if let Err(x) = x {
360 println!("{}", x)
361 } else {
362 println!("ok")
363 }
364}
365 "#,
366 r#"
367enum Result<T, E> { Ok(T), Err(E) }
368use Result::*;
369
370fn foo(x: Result<i32, ()>) {
371 match x {
372 Err(x) => println!("{}", x),
373 Ok(_) => println!("ok"),
374 }
375}
376 "#,
377 );
378 }
379
380 #[test]
312 fn nested_indent() { 381 fn nested_indent() {
313 check_assist( 382 check_assist(
314 replace_if_let_with_match, 383 replace_if_let_with_match,
diff --git a/crates/assists/src/lib.rs b/crates/assists/src/lib.rs
index 14178a651..559b9651e 100644
--- a/crates/assists/src/lib.rs
+++ b/crates/assists/src/lib.rs
@@ -108,6 +108,7 @@ mod handlers {
108 pub(crate) type Handler = fn(&mut Assists, &AssistContext) -> Option<()>; 108 pub(crate) type Handler = fn(&mut Assists, &AssistContext) -> Option<()>;
109 109
110 mod add_explicit_type; 110 mod add_explicit_type;
111 mod add_lifetime_to_type;
111 mod add_missing_impl_members; 112 mod add_missing_impl_members;
112 mod add_turbo_fish; 113 mod add_turbo_fish;
113 mod apply_demorgan; 114 mod apply_demorgan;
@@ -164,6 +165,7 @@ mod handlers {
164 &[ 165 &[
165 // These are alphabetic for the foolish consistency 166 // These are alphabetic for the foolish consistency
166 add_explicit_type::add_explicit_type, 167 add_explicit_type::add_explicit_type,
168 add_lifetime_to_type::add_lifetime_to_type,
167 add_turbo_fish::add_turbo_fish, 169 add_turbo_fish::add_turbo_fish,
168 apply_demorgan::apply_demorgan, 170 apply_demorgan::apply_demorgan,
169 auto_import::auto_import, 171 auto_import::auto_import,
diff --git a/crates/assists/src/tests/generated.rs b/crates/assists/src/tests/generated.rs
index d48d063b4..9aa807f10 100644
--- a/crates/assists/src/tests/generated.rs
+++ b/crates/assists/src/tests/generated.rs
@@ -104,6 +104,25 @@ impl Trait<u32> for () {
104} 104}
105 105
106#[test] 106#[test]
107fn doctest_add_lifetime_to_type() {
108 check_doc_test(
109 "add_lifetime_to_type",
110 r#####"
111struct Point {
112 x: &$0u32,
113 y: u32,
114}
115"#####,
116 r#####"
117struct Point<'a> {
118 x: &'a u32,
119 y: u32,
120}
121"#####,
122 )
123}
124
125#[test]
107fn doctest_add_turbo_fish() { 126fn doctest_add_turbo_fish() {
108 check_doc_test( 127 check_doc_test(
109 "add_turbo_fish", 128 "add_turbo_fish",
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs
index 44c35bafa..4e762e18b 100644
--- a/crates/assists/src/utils.rs
+++ b/crates/assists/src/utils.rs
@@ -248,3 +248,22 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
248pub(crate) fn next_prev() -> impl Iterator<Item = Direction> { 248pub(crate) fn next_prev() -> impl Iterator<Item = Direction> {
249 [Direction::Next, Direction::Prev].iter().copied() 249 [Direction::Next, Direction::Prev].iter().copied()
250} 250}
251
252pub(crate) fn does_pat_match_variant(pat: &ast::Pat, var: &ast::Pat) -> bool {
253 let first_node_text = |pat: &ast::Pat| pat.syntax().first_child().map(|node| node.text());
254
255 let pat_head = match pat {
256 ast::Pat::IdentPat(bind_pat) => {
257 if let Some(p) = bind_pat.pat() {
258 first_node_text(&p)
259 } else {
260 return pat.syntax().text() == var.syntax().text();
261 }
262 }
263 pat => first_node_text(pat),
264 };
265
266 let var_head = first_node_text(var);
267
268 pat_head == var_head
269}
diff --git a/crates/completion/src/completions/dot.rs b/crates/completion/src/completions/dot.rs
index d04eef65a..0880a3830 100644
--- a/crates/completion/src/completions/dot.rs
+++ b/crates/completion/src/completions/dot.rs
@@ -83,7 +83,7 @@ fn foo(s: S) { s.$0 }
83"#, 83"#,
84 expect![[r#" 84 expect![[r#"
85 fd foo u32 85 fd foo u32
86 me bar() fn bar(&self) 86 me bar() -> ()
87 "#]], 87 "#]],
88 ); 88 );
89 } 89 }
@@ -99,7 +99,7 @@ impl S {
99"#, 99"#,
100 expect![[r#" 100 expect![[r#"
101 fd the_field (u32,) 101 fd the_field (u32,)
102 me foo() fn foo(self) 102 me foo() -> ()
103 "#]], 103 "#]],
104 ) 104 )
105 } 105 }
@@ -115,7 +115,7 @@ impl A {
115"#, 115"#,
116 expect![[r#" 116 expect![[r#"
117 fd the_field (u32, i32) 117 fd the_field (u32, i32)
118 me foo() fn foo(&self) 118 me foo() -> ()
119 "#]], 119 "#]],
120 ) 120 )
121 } 121 }
@@ -165,7 +165,7 @@ mod m {
165fn foo(a: A) { a.$0 } 165fn foo(a: A) { a.$0 }
166"#, 166"#,
167 expect![[r#" 167 expect![[r#"
168 me the_method() pub(crate) fn the_method(&self) 168 me the_method() -> ()
169 "#]], 169 "#]],
170 ); 170 );
171 } 171 }
@@ -198,7 +198,7 @@ impl A<i32> {
198fn foo(a: A<u32>) { a.$0 } 198fn foo(a: A<u32>) { a.$0 }
199"#, 199"#,
200 expect![[r#" 200 expect![[r#"
201 me the_method() fn the_method(&self) 201 me the_method() -> ()
202 "#]], 202 "#]],
203 ) 203 )
204 } 204 }
@@ -213,7 +213,7 @@ impl Trait for A {}
213fn foo(a: A) { a.$0 } 213fn foo(a: A) { a.$0 }
214"#, 214"#,
215 expect![[r#" 215 expect![[r#"
216 me the_method() fn the_method(&self) 216 me the_method() -> ()
217 "#]], 217 "#]],
218 ); 218 );
219 } 219 }
@@ -228,7 +228,7 @@ impl<T> Trait for T {}
228fn foo(a: &A) { a.$0 } 228fn foo(a: &A) { a.$0 }
229", 229",
230 expect![[r#" 230 expect![[r#"
231 me the_method() fn the_method(&self) 231 me the_method() -> ()
232 "#]], 232 "#]],
233 ); 233 );
234 } 234 }
@@ -246,7 +246,7 @@ impl Trait for A {}
246fn foo(a: A) { a.$0 } 246fn foo(a: A) { a.$0 }
247", 247",
248 expect![[r#" 248 expect![[r#"
249 me the_method() fn the_method(&self) 249 me the_method() -> ()
250 "#]], 250 "#]],
251 ); 251 );
252 } 252 }
@@ -300,7 +300,7 @@ impl T {
300} 300}
301"#, 301"#,
302 expect![[r#" 302 expect![[r#"
303 me blah() pub fn blah(&self) 303 me blah() -> ()
304 "#]], 304 "#]],
305 ); 305 );
306 } 306 }
@@ -409,7 +409,7 @@ fn foo() {
409} 409}
410"#, 410"#,
411 expect![[r#" 411 expect![[r#"
412 me the_method() pub fn the_method(&self) 412 me the_method() -> ()
413 "#]], 413 "#]],
414 ); 414 );
415 } 415 }
@@ -424,7 +424,7 @@ macro_rules! make_s { () => { S }; }
424fn main() { make_s!().f$0; } 424fn main() { make_s!().f$0; }
425"#, 425"#,
426 expect![[r#" 426 expect![[r#"
427 me foo() fn foo(&self) 427 me foo() -> ()
428 "#]], 428 "#]],
429 ) 429 )
430 } 430 }
diff --git a/crates/completion/src/completions/flyimport.rs b/crates/completion/src/completions/flyimport.rs
index dc0b38a16..6591127b1 100644
--- a/crates/completion/src/completions/flyimport.rs
+++ b/crates/completion/src/completions/flyimport.rs
@@ -366,8 +366,8 @@ fn main() {
366 check( 366 check(
367 fixture, 367 fixture,
368 expect![[r#" 368 expect![[r#"
369 fn weird_function() (dep::test_mod::TestTrait) fn weird_function() 369 fn weird_function() (dep::test_mod::TestTrait) -> ()
370 "#]], 370 "#]],
371 ); 371 );
372 372
373 check_edit( 373 check_edit(
@@ -459,8 +459,8 @@ fn main() {
459 check( 459 check(
460 fixture, 460 fixture,
461 expect![[r#" 461 expect![[r#"
462 me random_method() (dep::test_mod::TestTrait) fn random_method(&self) 462 me random_method() (dep::test_mod::TestTrait) -> ()
463 "#]], 463 "#]],
464 ); 464 );
465 465
466 check_edit( 466 check_edit(
@@ -629,8 +629,8 @@ fn main() {
629} 629}
630 "#, 630 "#,
631 expect![[r#" 631 expect![[r#"
632 me random_method() (dep::test_mod::TestTrait) fn random_method(&self) DEPRECATED 632 me random_method() (dep::test_mod::TestTrait) -> () DEPRECATED
633 "#]], 633 "#]],
634 ); 634 );
635 635
636 check( 636 check(
@@ -660,8 +660,8 @@ fn main() {
660"#, 660"#,
661 expect![[r#" 661 expect![[r#"
662 ct SPECIAL_CONST (dep::test_mod::TestTrait) DEPRECATED 662 ct SPECIAL_CONST (dep::test_mod::TestTrait) DEPRECATED
663 fn weird_function() (dep::test_mod::TestTrait) fn weird_function() DEPRECATED 663 fn weird_function() (dep::test_mod::TestTrait) -> () DEPRECATED
664 "#]], 664 "#]],
665 ); 665 );
666 } 666 }
667} 667}
diff --git a/crates/completion/src/completions/fn_param.rs b/crates/completion/src/completions/fn_param.rs
index 5505c3559..38e33a93e 100644
--- a/crates/completion/src/completions/fn_param.rs
+++ b/crates/completion/src/completions/fn_param.rs
@@ -6,7 +6,7 @@ use syntax::{
6 match_ast, AstNode, 6 match_ast, AstNode,
7}; 7};
8 8
9use crate::{CompletionContext, CompletionItem, CompletionKind, Completions}; 9use crate::{CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions};
10 10
11/// Complete repeated parameters, both name and type. For example, if all 11/// Complete repeated parameters, both name and type. For example, if all
12/// functions in a file have a `spam: &mut Spam` parameter, a completion with 12/// functions in a file have a `spam: &mut Spam` parameter, a completion with
@@ -58,7 +58,7 @@ pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
58 }) 58 })
59 .for_each(|(label, lookup)| { 59 .for_each(|(label, lookup)| {
60 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label) 60 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label)
61 .kind(crate::CompletionItemKind::Binding) 61 .kind(CompletionItemKind::Binding)
62 .lookup_by(lookup) 62 .lookup_by(lookup)
63 .add_to(acc) 63 .add_to(acc)
64 }); 64 });
diff --git a/crates/completion/src/completions/mod_.rs b/crates/completion/src/completions/mod_.rs
index 00e951ca9..352fc7c77 100644
--- a/crates/completion/src/completions/mod_.rs
+++ b/crates/completion/src/completions/mod_.rs
@@ -3,11 +3,13 @@
3use std::iter; 3use std::iter;
4 4
5use hir::{Module, ModuleSource}; 5use hir::{Module, ModuleSource};
6use ide_db::base_db::{SourceDatabaseExt, VfsPath}; 6use ide_db::{
7use ide_db::RootDatabase; 7 base_db::{SourceDatabaseExt, VfsPath},
8 RootDatabase, SymbolKind,
9};
8use rustc_hash::FxHashSet; 10use rustc_hash::FxHashSet;
9 11
10use crate::{CompletionItem, CompletionItemKind}; 12use crate::CompletionItem;
11 13
12use crate::{context::CompletionContext, item::CompletionKind, Completions}; 14use crate::{context::CompletionContext, item::CompletionKind, Completions};
13 15
@@ -79,7 +81,7 @@ pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Op
79 label.push(';'); 81 label.push(';');
80 } 82 }
81 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), &label) 83 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), &label)
82 .kind(CompletionItemKind::Module) 84 .kind(SymbolKind::Module)
83 .add_to(acc) 85 .add_to(acc)
84 }); 86 });
85 87
diff --git a/crates/completion/src/completions/qualified_path.rs b/crates/completion/src/completions/qualified_path.rs
index 33df26761..bbeaab496 100644
--- a/crates/completion/src/completions/qualified_path.rs
+++ b/crates/completion/src/completions/qualified_path.rs
@@ -359,8 +359,8 @@ impl S {
359fn foo() { let _ = S::$0 } 359fn foo() { let _ = S::$0 }
360"#, 360"#,
361 expect![[r#" 361 expect![[r#"
362 fn a() fn a() 362 fn a() -> ()
363 me b(…) fn b(&self) 363 me b(…) -> ()
364 ct C const C: i32 = 42; 364 ct C const C: i32 = 42;
365 ta T type T = i32; 365 ta T type T = i32;
366 "#]], 366 "#]],
@@ -387,7 +387,7 @@ mod m {
387fn foo() { let _ = S::$0 } 387fn foo() { let _ = S::$0 }
388"#, 388"#,
389 expect![[r#" 389 expect![[r#"
390 fn public_method() pub(crate) fn public_method() 390 fn public_method() -> ()
391 ct PUBLIC_CONST pub(crate) const PUBLIC_CONST: u32 = 1; 391 ct PUBLIC_CONST pub(crate) const PUBLIC_CONST: u32 = 1;
392 ta PublicType pub(crate) type PublicType = u32; 392 ta PublicType pub(crate) type PublicType = u32;
393 "#]], 393 "#]],
@@ -404,7 +404,7 @@ impl E { fn m() { } }
404fn foo() { let _ = E::$0 } 404fn foo() { let _ = E::$0 }
405 "#, 405 "#,
406 expect![[r#" 406 expect![[r#"
407 fn m() fn m() 407 fn m() -> ()
408 "#]], 408 "#]],
409 ); 409 );
410 } 410 }
@@ -419,7 +419,7 @@ impl U { fn m() { } }
419fn foo() { let _ = U::$0 } 419fn foo() { let _ = U::$0 }
420"#, 420"#,
421 expect![[r#" 421 expect![[r#"
422 fn m() fn m() 422 fn m() -> ()
423 "#]], 423 "#]],
424 ); 424 );
425 } 425 }
@@ -449,7 +449,7 @@ trait Trait { fn m(); }
449fn foo() { let _ = Trait::$0 } 449fn foo() { let _ = Trait::$0 }
450"#, 450"#,
451 expect![[r#" 451 expect![[r#"
452 fn m() fn m() 452 fn m() -> ()
453 "#]], 453 "#]],
454 ); 454 );
455 } 455 }
@@ -466,7 +466,7 @@ impl Trait for S {}
466fn foo() { let _ = S::$0 } 466fn foo() { let _ = S::$0 }
467"#, 467"#,
468 expect![[r#" 468 expect![[r#"
469 fn m() fn m() 469 fn m() -> ()
470 "#]], 470 "#]],
471 ); 471 );
472 } 472 }
@@ -483,7 +483,7 @@ impl Trait for S {}
483fn foo() { let _ = <S as Trait>::$0 } 483fn foo() { let _ = <S as Trait>::$0 }
484"#, 484"#,
485 expect![[r#" 485 expect![[r#"
486 fn m() fn m() 486 fn m() -> ()
487 "#]], 487 "#]],
488 ); 488 );
489 } 489 }
@@ -512,11 +512,11 @@ fn foo<T: Sub>() { T::$0 }
512 ta SubTy type SubTy; 512 ta SubTy type SubTy;
513 ta Ty type Ty; 513 ta Ty type Ty;
514 ct C2 const C2: (); 514 ct C2 const C2: ();
515 fn subfunc() fn subfunc() 515 fn subfunc() -> ()
516 me submethod(…) fn submethod(&self) 516 me submethod(…) -> ()
517 ct CONST const CONST: u8; 517 ct CONST const CONST: u8;
518 fn func() fn func() 518 fn func() -> ()
519 me method(…) fn method(&self) 519 me method(…) -> ()
520 "#]], 520 "#]],
521 ); 521 );
522 } 522 }
@@ -552,11 +552,11 @@ impl<T> Sub for Wrap<T> {
552 ta SubTy type SubTy; 552 ta SubTy type SubTy;
553 ta Ty type Ty; 553 ta Ty type Ty;
554 ct CONST const CONST: u8 = 0; 554 ct CONST const CONST: u8 = 0;
555 fn func() fn func() 555 fn func() -> ()
556 me method(…) fn method(&self) 556 me method(…) -> ()
557 ct C2 const C2: () = (); 557 ct C2 const C2: () = ();
558 fn subfunc() fn subfunc() 558 fn subfunc() -> ()
559 me submethod(…) fn submethod(&self) 559 me submethod(…) -> ()
560 "#]], 560 "#]],
561 ); 561 );
562 } 562 }
@@ -573,8 +573,8 @@ impl T { fn bar() {} }
573fn main() { T::$0; } 573fn main() { T::$0; }
574"#, 574"#,
575 expect![[r#" 575 expect![[r#"
576 fn foo() fn foo() 576 fn foo() -> ()
577 fn bar() fn bar() 577 fn bar() -> ()
578 "#]], 578 "#]],
579 ); 579 );
580 } 580 }
@@ -589,7 +589,7 @@ macro_rules! foo { () => {} }
589fn main() { let _ = crate::$0 } 589fn main() { let _ = crate::$0 }
590 "#, 590 "#,
591 expect![[r##" 591 expect![[r##"
592 fn main() fn main() 592 fn main() -> ()
593 ma foo!(…) #[macro_export] macro_rules! foo 593 ma foo!(…) #[macro_export] macro_rules! foo
594 "##]], 594 "##]],
595 ); 595 );
@@ -633,7 +633,7 @@ mod p {
633"#, 633"#,
634 expect![[r#" 634 expect![[r#"
635 ct RIGHT_CONST 635 ct RIGHT_CONST
636 fn right_fn() fn wrong_fn() 636 fn right_fn() -> ()
637 st RightType 637 st RightType
638 "#]], 638 "#]],
639 ); 639 );
@@ -680,8 +680,8 @@ fn main() { m!(self::f$0); }
680fn foo() {} 680fn foo() {}
681"#, 681"#,
682 expect![[r#" 682 expect![[r#"
683 fn main() fn main() 683 fn main() -> ()
684 fn foo() fn foo() 684 fn foo() -> ()
685 "#]], 685 "#]],
686 ); 686 );
687 } 687 }
@@ -699,7 +699,7 @@ mod m {
699"#, 699"#,
700 expect![[r#" 700 expect![[r#"
701 md z 701 md z
702 fn z() pub fn z() 702 fn z() -> ()
703 "#]], 703 "#]],
704 ); 704 );
705 } 705 }
@@ -719,7 +719,7 @@ fn foo() {
719} 719}
720"#, 720"#,
721 expect![[r#" 721 expect![[r#"
722 fn new() pub fn new() -> HashMap<K, V, RandomState> 722 fn new() -> HashMap<K, V, RandomState>
723 "#]], 723 "#]],
724 ); 724 );
725 } 725 }
@@ -752,8 +752,8 @@ fn main() {
752} 752}
753"#, 753"#,
754 expect![[r#" 754 expect![[r#"
755 fn main() fn main() 755 fn main() -> ()
756 fn foo(…) fn foo(a: i32, b: i32) 756 fn foo(…) -> ()
757 "#]], 757 "#]],
758 ); 758 );
759 } 759 }
@@ -776,7 +776,7 @@ impl Foo {
776 expect![[r#" 776 expect![[r#"
777 ev Bar () 777 ev Bar ()
778 ev Baz () 778 ev Baz ()
779 me foo(…) fn foo(self) 779 me foo(…) -> ()
780 "#]], 780 "#]],
781 ); 781 );
782 } 782 }
diff --git a/crates/completion/src/completions/record.rs b/crates/completion/src/completions/record.rs
index bb6354ded..0a7927eb8 100644
--- a/crates/completion/src/completions/record.rs
+++ b/crates/completion/src/completions/record.rs
@@ -1,10 +1,8 @@
1//! Complete fields in record literals and patterns. 1//! Complete fields in record literals and patterns.
2use ide_db::helpers::FamousDefs; 2use ide_db::{helpers::FamousDefs, SymbolKind};
3use syntax::ast::Expr; 3use syntax::ast::Expr;
4 4
5use crate::{ 5use crate::{item::CompletionKind, CompletionContext, CompletionItem, Completions};
6 item::CompletionKind, CompletionContext, CompletionItem, CompletionItemKind, Completions,
7};
8 6
9pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { 7pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
10 let missing_fields = match (ctx.record_pat_syntax.as_ref(), ctx.record_lit_syntax.as_ref()) { 8 let missing_fields = match (ctx.record_pat_syntax.as_ref(), ctx.record_lit_syntax.as_ref()) {
@@ -31,7 +29,7 @@ pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) ->
31 "..Default::default()", 29 "..Default::default()",
32 ) 30 )
33 .insert_text(completion_text) 31 .insert_text(completion_text)
34 .kind(CompletionItemKind::Field) 32 .kind(SymbolKind::Field)
35 .build(), 33 .build(),
36 ); 34 );
37 } 35 }
diff --git a/crates/completion/src/completions/trait_impl.rs b/crates/completion/src/completions/trait_impl.rs
index 135ae49dc..b999540b8 100644
--- a/crates/completion/src/completions/trait_impl.rs
+++ b/crates/completion/src/completions/trait_impl.rs
@@ -32,7 +32,7 @@
32//! ``` 32//! ```
33 33
34use hir::{self, HasAttrs, HasSource}; 34use hir::{self, HasAttrs, HasSource};
35use ide_db::traits::get_missing_assoc_items; 35use ide_db::{traits::get_missing_assoc_items, SymbolKind};
36use syntax::{ 36use syntax::{
37 ast::{self, edit, Impl}, 37 ast::{self, edit, Impl},
38 display::function_declaration, 38 display::function_declaration,
@@ -152,7 +152,7 @@ fn add_function_impl(
152 let completion_kind = if func.self_param(ctx.db).is_some() { 152 let completion_kind = if func.self_param(ctx.db).is_some() {
153 CompletionItemKind::Method 153 CompletionItemKind::Method
154 } else { 154 } else {
155 CompletionItemKind::Function 155 CompletionItemKind::SymbolKind(SymbolKind::Function)
156 }; 156 };
157 let range = TextRange::new(fn_def_node.text_range().start(), ctx.source_range().end()); 157 let range = TextRange::new(fn_def_node.text_range().start(), ctx.source_range().end());
158 158
@@ -188,7 +188,7 @@ fn add_type_alias_impl(
188 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone()) 188 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
189 .text_edit(TextEdit::replace(range, snippet)) 189 .text_edit(TextEdit::replace(range, snippet))
190 .lookup_by(alias_name) 190 .lookup_by(alias_name)
191 .kind(CompletionItemKind::TypeAlias) 191 .kind(SymbolKind::TypeAlias)
192 .set_documentation(type_alias.docs(ctx.db)) 192 .set_documentation(type_alias.docs(ctx.db))
193 .add_to(acc); 193 .add_to(acc);
194} 194}
@@ -211,7 +211,7 @@ fn add_const_impl(
211 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone()) 211 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
212 .text_edit(TextEdit::replace(range, snippet)) 212 .text_edit(TextEdit::replace(range, snippet))
213 .lookup_by(const_name) 213 .lookup_by(const_name)
214 .kind(CompletionItemKind::Const) 214 .kind(SymbolKind::Const)
215 .set_documentation(const_.docs(ctx.db)) 215 .set_documentation(const_.docs(ctx.db))
216 .add_to(acc); 216 .add_to(acc);
217 } 217 }
@@ -679,11 +679,6 @@ impl Test for () {
679 #[test] 679 #[test]
680 fn complete_without_name() { 680 fn complete_without_name() {
681 let test = |completion: &str, hint: &str, completed: &str, next_sibling: &str| { 681 let test = |completion: &str, hint: &str, completed: &str, next_sibling: &str| {
682 println!(
683 "completion='{}', hint='{}', next_sibling='{}'",
684 completion, hint, next_sibling
685 );
686
687 check_edit( 682 check_edit(
688 completion, 683 completion,
689 &format!( 684 &format!(
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs
index 809e1645a..5d62fab97 100644
--- a/crates/completion/src/completions/unqualified_path.rs
+++ b/crates/completion/src/completions/unqualified_path.rs
@@ -165,9 +165,9 @@ fn quux(x: i32) {
165} 165}
166"#, 166"#,
167 expect![[r#" 167 expect![[r#"
168 bn y i32 168 lc y i32
169 bn x i32 169 lc x i32
170 fn quux(…) fn quux(x: i32) 170 fn quux(…) -> ()
171 "#]], 171 "#]],
172 ); 172 );
173 } 173 }
@@ -187,9 +187,9 @@ fn quux() {
187} 187}
188"#, 188"#,
189 expect![[r#" 189 expect![[r#"
190 bn b i32 190 lc b i32
191 bn a 191 lc a
192 fn quux() fn quux() 192 fn quux() -> ()
193 "#]], 193 "#]],
194 ); 194 );
195 } 195 }
@@ -203,8 +203,8 @@ fn quux() {
203} 203}
204"#, 204"#,
205 expect![[r#" 205 expect![[r#"
206 bn x 206 lc x
207 fn quux() fn quux() 207 fn quux() -> ()
208 "#]], 208 "#]],
209 ); 209 );
210 } 210 }
@@ -235,14 +235,14 @@ fn main() {
235 r#"fn quux<T>() { $0 }"#, 235 r#"fn quux<T>() { $0 }"#,
236 expect![[r#" 236 expect![[r#"
237 tp T 237 tp T
238 fn quux() fn quux<T>() 238 fn quux() -> ()
239 "#]], 239 "#]],
240 ); 240 );
241 check( 241 check(
242 r#"fn quux<const C: usize>() { $0 }"#, 242 r#"fn quux<const C: usize>() { $0 }"#,
243 expect![[r#" 243 expect![[r#"
244 tp C 244 cp C
245 fn quux() fn quux<const C: usize>() 245 fn quux() -> ()
246 "#]], 246 "#]],
247 ); 247 );
248 } 248 }
@@ -253,7 +253,7 @@ fn main() {
253 check( 253 check(
254 r#"fn quux<'a>() { $0 }"#, 254 r#"fn quux<'a>() { $0 }"#,
255 expect![[r#" 255 expect![[r#"
256 fn quux() fn quux<'a>() 256 fn quux() -> ()
257 "#]], 257 "#]],
258 ); 258 );
259 } 259 }
@@ -263,7 +263,7 @@ fn main() {
263 check( 263 check(
264 r#"struct S<T> { x: $0}"#, 264 r#"struct S<T> { x: $0}"#,
265 expect![[r#" 265 expect![[r#"
266 tp Self 266 sp Self
267 tp T 267 tp T
268 st S<…> 268 st S<…>
269 "#]], 269 "#]],
@@ -275,7 +275,7 @@ fn main() {
275 check( 275 check(
276 r#"enum X { Y($0) }"#, 276 r#"enum X { Y($0) }"#,
277 expect![[r#" 277 expect![[r#"
278 tp Self 278 sp Self
279 en X 279 en X
280 "#]], 280 "#]],
281 ); 281 );
@@ -291,7 +291,7 @@ fn quux() { $0 }
291"#, 291"#,
292 expect![[r#" 292 expect![[r#"
293 st S 293 st S
294 fn quux() fn quux() 294 fn quux() -> ()
295 en E 295 en E
296 "#]], 296 "#]],
297 ); 297 );
@@ -344,7 +344,7 @@ mod m {
344} 344}
345"#, 345"#,
346 expect![[r#" 346 expect![[r#"
347 fn quux() fn quux() 347 fn quux() -> ()
348 st Bar 348 st Bar
349 "#]], 349 "#]],
350 ); 350 );
@@ -359,7 +359,7 @@ fn x() -> $0
359"#, 359"#,
360 expect![[r#" 360 expect![[r#"
361 st Foo 361 st Foo
362 fn x() fn x() 362 fn x() -> ()
363 "#]], 363 "#]],
364 ); 364 );
365 } 365 }
@@ -378,9 +378,9 @@ fn foo() {
378"#, 378"#,
379 // FIXME: should be only one bar here 379 // FIXME: should be only one bar here
380 expect![[r#" 380 expect![[r#"
381 bn bar i32 381 lc bar i32
382 bn bar i32 382 lc bar i32
383 fn foo() fn foo() 383 fn foo() -> ()
384 "#]], 384 "#]],
385 ); 385 );
386 } 386 }
@@ -390,8 +390,8 @@ fn foo() {
390 check( 390 check(
391 r#"impl S { fn foo(&self) { $0 } }"#, 391 r#"impl S { fn foo(&self) { $0 } }"#,
392 expect![[r#" 392 expect![[r#"
393 bn self &{unknown} 393 lc self &{unknown}
394 tp Self 394 sp Self
395 "#]], 395 "#]],
396 ); 396 );
397 } 397 }
@@ -410,7 +410,7 @@ use prelude::*;
410mod prelude { struct Option; } 410mod prelude { struct Option; }
411"#, 411"#,
412 expect![[r#" 412 expect![[r#"
413 fn foo() fn foo() 413 fn foo() -> ()
414 md std 414 md std
415 st Option 415 st Option
416 "#]], 416 "#]],
@@ -440,7 +440,7 @@ mod macros {
440} 440}
441"#, 441"#,
442 expect![[r##" 442 expect![[r##"
443 fn f() fn f() 443 fn f() -> ()
444 ma concat!(…) #[macro_export] macro_rules! concat 444 ma concat!(…) #[macro_export] macro_rules! concat
445 md std 445 md std
446 "##]], 446 "##]],
@@ -467,7 +467,7 @@ use prelude::*;
467mod prelude { struct String; } 467mod prelude { struct String; }
468"#, 468"#,
469 expect![[r#" 469 expect![[r#"
470 fn foo() fn foo() 470 fn foo() -> ()
471 md std 471 md std
472 md core 472 md core
473 st String 473 st String
@@ -498,7 +498,7 @@ fn main() { let v = $0 }
498 expect![[r##" 498 expect![[r##"
499 md m1 499 md m1
500 ma baz!(…) #[macro_export] macro_rules! baz 500 ma baz!(…) #[macro_export] macro_rules! baz
501 fn main() fn main() 501 fn main() -> ()
502 md m2 502 md m2
503 ma bar!(…) macro_rules! bar 503 ma bar!(…) macro_rules! bar
504 ma foo!(…) macro_rules! foo 504 ma foo!(…) macro_rules! foo
@@ -514,7 +514,7 @@ macro_rules! foo { () => {} }
514fn foo() { $0 } 514fn foo() { $0 }
515"#, 515"#,
516 expect![[r#" 516 expect![[r#"
517 fn foo() fn foo() 517 fn foo() -> ()
518 ma foo!(…) macro_rules! foo 518 ma foo!(…) macro_rules! foo
519 "#]], 519 "#]],
520 ); 520 );
@@ -528,7 +528,7 @@ macro_rules! foo { () => {} }
528fn main() { let x: $0 } 528fn main() { let x: $0 }
529"#, 529"#,
530 expect![[r#" 530 expect![[r#"
531 fn main() fn main() 531 fn main() -> ()
532 ma foo!(…) macro_rules! foo 532 ma foo!(…) macro_rules! foo
533 "#]], 533 "#]],
534 ); 534 );
@@ -542,7 +542,7 @@ macro_rules! foo { () => {} }
542fn main() { $0 } 542fn main() { $0 }
543"#, 543"#,
544 expect![[r#" 544 expect![[r#"
545 fn main() fn main() 545 fn main() -> ()
546 ma foo!(…) macro_rules! foo 546 ma foo!(…) macro_rules! foo
547 "#]], 547 "#]],
548 ); 548 );
@@ -558,8 +558,8 @@ fn main() {
558} 558}
559"#, 559"#,
560 expect![[r#" 560 expect![[r#"
561 fn frobnicate() fn frobnicate() 561 fn frobnicate() -> ()
562 fn main() fn main() 562 fn main() -> ()
563 "#]], 563 "#]],
564 ); 564 );
565 } 565 }
@@ -575,9 +575,9 @@ fn quux(x: i32) {
575} 575}
576"#, 576"#,
577 expect![[r#" 577 expect![[r#"
578 bn y i32 578 lc y i32
579 bn x i32 579 lc x i32
580 fn quux(…) fn quux(x: i32) 580 fn quux(…) -> ()
581 ma m!(…) macro_rules! m 581 ma m!(…) macro_rules! m
582 "#]], 582 "#]],
583 ); 583 );
@@ -594,9 +594,9 @@ fn quux(x: i32) {
594} 594}
595", 595",
596 expect![[r#" 596 expect![[r#"
597 bn y i32 597 lc y i32
598 bn x i32 598 lc x i32
599 fn quux(…) fn quux(x: i32) 599 fn quux(…) -> ()
600 ma m!(…) macro_rules! m 600 ma m!(…) macro_rules! m
601 "#]], 601 "#]],
602 ); 602 );
@@ -613,9 +613,9 @@ fn quux(x: i32) {
613} 613}
614"#, 614"#,
615 expect![[r#" 615 expect![[r#"
616 bn y i32 616 lc y i32
617 bn x i32 617 lc x i32
618 fn quux(…) fn quux(x: i32) 618 fn quux(…) -> ()
619 ma m!(…) macro_rules! m 619 ma m!(…) macro_rules! m
620 "#]], 620 "#]],
621 ); 621 );
@@ -630,7 +630,7 @@ use spam::Quux;
630fn main() { $0 } 630fn main() { $0 }
631"#, 631"#,
632 expect![[r#" 632 expect![[r#"
633 fn main() fn main() 633 fn main() -> ()
634 ?? Quux 634 ?? Quux
635 "#]], 635 "#]],
636 ); 636 );
@@ -708,7 +708,7 @@ fn main() { let foo: Foo = Q$0 }
708 ev Foo::Baz () 708 ev Foo::Baz ()
709 ev Foo::Quux () 709 ev Foo::Quux ()
710 en Foo 710 en Foo
711 fn main() fn main() 711 fn main() -> ()
712 "#]], 712 "#]],
713 ) 713 )
714 } 714 }
@@ -723,7 +723,7 @@ fn f() -> m::E { V$0 }
723 expect![[r#" 723 expect![[r#"
724 ev m::E::V () 724 ev m::E::V ()
725 md m 725 md m
726 fn f() fn f() -> m::E 726 fn f() -> E
727 "#]], 727 "#]],
728 ) 728 )
729 } 729 }
@@ -750,7 +750,7 @@ struct MyStruct {}
750impl My$0 750impl My$0
751"#, 751"#,
752 expect![[r#" 752 expect![[r#"
753 tp Self 753 sp Self
754 tt MyTrait 754 tt MyTrait
755 st MyStruct 755 st MyStruct
756 "#]], 756 "#]],
diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs
index 4147853e7..eeb952ec3 100644
--- a/crates/completion/src/item.rs
+++ b/crates/completion/src/item.rs
@@ -3,11 +3,14 @@
3use std::fmt; 3use std::fmt;
4 4
5use hir::{Documentation, ModPath, Mutability}; 5use hir::{Documentation, ModPath, Mutability};
6use ide_db::helpers::{ 6use ide_db::{
7 insert_use::{self, ImportScope, MergeBehavior}, 7 helpers::{
8 mod_path_to_ast, SnippetCap, 8 insert_use::{self, ImportScope, MergeBehavior},
9 mod_path_to_ast, SnippetCap,
10 },
11 SymbolKind,
9}; 12};
10use stdx::assert_never; 13use stdx::{assert_never, impl_from};
11use syntax::{algo, TextRange}; 14use syntax::{algo, TextRange};
12use text_edit::TextEdit; 15use text_edit::TextEdit;
13 16
@@ -117,49 +120,50 @@ pub enum CompletionScore {
117 120
118#[derive(Debug, Clone, Copy, PartialEq, Eq)] 121#[derive(Debug, Clone, Copy, PartialEq, Eq)]
119pub enum CompletionItemKind { 122pub enum CompletionItemKind {
120 Snippet, 123 SymbolKind(SymbolKind),
121 Keyword, 124 Attribute,
122 Module,
123 Function,
124 BuiltinType,
125 Struct,
126 Enum,
127 EnumVariant,
128 Binding, 125 Binding,
129 Field, 126 BuiltinType,
130 Static, 127 Keyword,
131 Const,
132 Trait,
133 TypeAlias,
134 Method, 128 Method,
135 TypeParam, 129 Snippet,
136 Macro,
137 Attribute,
138 UnresolvedReference, 130 UnresolvedReference,
139} 131}
140 132
133impl_from!(SymbolKind for CompletionItemKind);
134
141impl CompletionItemKind { 135impl CompletionItemKind {
142 #[cfg(test)] 136 #[cfg(test)]
143 pub(crate) fn tag(&self) -> &'static str { 137 pub(crate) fn tag(&self) -> &'static str {
144 match self { 138 match self {
139 CompletionItemKind::SymbolKind(kind) => match kind {
140 SymbolKind::Const => "ct",
141 SymbolKind::ConstParam => "cp",
142 SymbolKind::Enum => "en",
143 SymbolKind::Field => "fd",
144 SymbolKind::Function => "fn",
145 SymbolKind::Impl => "im",
146 SymbolKind::Label => "lb",
147 SymbolKind::LifetimeParam => "lt",
148 SymbolKind::Local => "lc",
149 SymbolKind::Macro => "ma",
150 SymbolKind::Module => "md",
151 SymbolKind::SelfParam => "sp",
152 SymbolKind::Static => "sc",
153 SymbolKind::Struct => "st",
154 SymbolKind::Trait => "tt",
155 SymbolKind::TypeAlias => "ta",
156 SymbolKind::TypeParam => "tp",
157 SymbolKind::Union => "un",
158 SymbolKind::ValueParam => "vp",
159 SymbolKind::Variant => "ev",
160 },
145 CompletionItemKind::Attribute => "at", 161 CompletionItemKind::Attribute => "at",
146 CompletionItemKind::Binding => "bn", 162 CompletionItemKind::Binding => "bn",
147 CompletionItemKind::BuiltinType => "bt", 163 CompletionItemKind::BuiltinType => "bt",
148 CompletionItemKind::Const => "ct",
149 CompletionItemKind::Enum => "en",
150 CompletionItemKind::EnumVariant => "ev",
151 CompletionItemKind::Field => "fd",
152 CompletionItemKind::Function => "fn",
153 CompletionItemKind::Keyword => "kw", 164 CompletionItemKind::Keyword => "kw",
154 CompletionItemKind::Macro => "ma",
155 CompletionItemKind::Method => "me", 165 CompletionItemKind::Method => "me",
156 CompletionItemKind::Module => "md",
157 CompletionItemKind::Snippet => "sn", 166 CompletionItemKind::Snippet => "sn",
158 CompletionItemKind::Static => "sc",
159 CompletionItemKind::Struct => "st",
160 CompletionItemKind::Trait => "tt",
161 CompletionItemKind::TypeAlias => "ta",
162 CompletionItemKind::TypeParam => "tp",
163 CompletionItemKind::UnresolvedReference => "??", 167 CompletionItemKind::UnresolvedReference => "??",
164 } 168 }
165 } 169 }
@@ -382,8 +386,8 @@ impl Builder {
382 self.insert_text_format = InsertTextFormat::Snippet; 386 self.insert_text_format = InsertTextFormat::Snippet;
383 self.insert_text(snippet) 387 self.insert_text(snippet)
384 } 388 }
385 pub(crate) fn kind(mut self, kind: CompletionItemKind) -> Builder { 389 pub(crate) fn kind(mut self, kind: impl Into<CompletionItemKind>) -> Builder {
386 self.kind = Some(kind); 390 self.kind = Some(kind.into());
387 self 391 self
388 } 392 }
389 pub(crate) fn text_edit(mut self, edit: TextEdit) -> Builder { 393 pub(crate) fn text_edit(mut self, edit: TextEdit) -> Builder {
@@ -394,14 +398,13 @@ impl Builder {
394 self.insert_text_format = InsertTextFormat::Snippet; 398 self.insert_text_format = InsertTextFormat::Snippet;
395 self.text_edit(edit) 399 self.text_edit(edit)
396 } 400 }
397 #[allow(unused)]
398 pub(crate) fn detail(self, detail: impl Into<String>) -> Builder { 401 pub(crate) fn detail(self, detail: impl Into<String>) -> Builder {
399 self.set_detail(Some(detail)) 402 self.set_detail(Some(detail))
400 } 403 }
401 pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder { 404 pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder {
402 self.detail = detail.map(Into::into); 405 self.detail = detail.map(Into::into);
403 if let Some(detail) = &self.detail { 406 if let Some(detail) = &self.detail {
404 if assert_never!(detail.contains('\n'), "multiline detail: {}", detail) { 407 if assert_never!(detail.contains('\n'), "multiline detail:\n{}", detail) {
405 self.detail = Some(detail.splitn(2, '\n').next().unwrap().to_string()); 408 self.detail = Some(detail.splitn(2, '\n').next().unwrap().to_string());
406 } 409 }
407 } 410 }
diff --git a/crates/completion/src/lib.rs b/crates/completion/src/lib.rs
index 2c4e54524..db8bfbbc3 100644
--- a/crates/completion/src/lib.rs
+++ b/crates/completion/src/lib.rs
@@ -209,25 +209,24 @@ mod tests {
209 fn test_completion_detail_from_macro_generated_struct_fn_doc_attr() { 209 fn test_completion_detail_from_macro_generated_struct_fn_doc_attr() {
210 check_detail_and_documentation( 210 check_detail_and_documentation(
211 r#" 211 r#"
212 //- /lib.rs 212macro_rules! bar {
213 macro_rules! bar { 213 () => {
214 () => { 214 struct Bar;
215 struct Bar; 215 impl Bar {
216 impl Bar { 216 #[doc = "Do the foo"]
217 #[doc = "Do the foo"] 217 fn foo(&self) {}
218 fn foo(&self) {} 218 }
219 } 219 }
220 } 220}
221 }
222 221
223 bar!(); 222bar!();
224 223
225 fn foo() { 224fn foo() {
226 let bar = Bar; 225 let bar = Bar;
227 bar.fo$0; 226 bar.fo$0;
228 } 227}
229 "#, 228"#,
230 DetailAndDocumentation { detail: "fn foo(&self)", documentation: "Do the foo" }, 229 DetailAndDocumentation { detail: "-> ()", documentation: "Do the foo" },
231 ); 230 );
232 } 231 }
233 232
@@ -235,52 +234,42 @@ mod tests {
235 fn test_completion_detail_from_macro_generated_struct_fn_doc_comment() { 234 fn test_completion_detail_from_macro_generated_struct_fn_doc_comment() {
236 check_detail_and_documentation( 235 check_detail_and_documentation(
237 r#" 236 r#"
238 //- /lib.rs 237macro_rules! bar {
239 macro_rules! bar { 238 () => {
240 () => { 239 struct Bar;
241 struct Bar; 240 impl Bar {
242 impl Bar { 241 /// Do the foo
243 /// Do the foo 242 fn foo(&self) {}
244 fn foo(&self) {} 243 }
245 } 244 }
246 } 245}
247 }
248 246
249 bar!(); 247bar!();
250 248
251 fn foo() { 249fn foo() {
252 let bar = Bar; 250 let bar = Bar;
253 bar.fo$0; 251 bar.fo$0;
254 } 252}
255 "#, 253"#,
256 DetailAndDocumentation { detail: "fn foo(&self)", documentation: " Do the foo" }, 254 DetailAndDocumentation { detail: "-> ()", documentation: " Do the foo" },
257 ); 255 );
258 } 256 }
259 257
260 #[test] 258 #[test]
261 fn test_no_completions_required() { 259 fn test_no_completions_required() {
262 // There must be no hint for 'in' keyword. 260 // There must be no hint for 'in' keyword.
263 check_no_completion( 261 check_no_completion(r#"fn foo() { for i i$0 }"#);
264 r#"
265 fn foo() {
266 for i i$0
267 }
268 "#,
269 );
270 // After 'in' keyword hints may be spawned. 262 // After 'in' keyword hints may be spawned.
271 check_detail_and_documentation( 263 check_detail_and_documentation(
272 r#" 264 r#"
273 /// Do the foo 265/// Do the foo
274 fn foo() -> &'static str { "foo" } 266fn foo() -> &'static str { "foo" }
275 267
276 fn bar() { 268fn bar() {
277 for c in fo$0 269 for c in fo$0
278 } 270}
279 "#, 271"#,
280 DetailAndDocumentation { 272 DetailAndDocumentation { detail: "-> &str", documentation: "Do the foo" },
281 detail: "fn foo() -> &'static str",
282 documentation: "Do the foo",
283 },
284 ); 273 );
285 } 274 }
286} 275}
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs
index 4f622d28a..e11b881ca 100644
--- a/crates/completion/src/render.rs
+++ b/crates/completion/src/render.rs
@@ -13,7 +13,7 @@ mod builder_ext;
13use hir::{ 13use hir::{
14 AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type, 14 AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type,
15}; 15};
16use ide_db::{helpers::SnippetCap, RootDatabase}; 16use ide_db::{helpers::SnippetCap, RootDatabase, SymbolKind};
17use syntax::TextRange; 17use syntax::TextRange;
18use test_utils::mark; 18use test_utils::mark;
19 19
@@ -146,7 +146,7 @@ impl<'a> Render<'a> {
146 self.ctx.source_range(), 146 self.ctx.source_range(),
147 name.to_string(), 147 name.to_string(),
148 ) 148 )
149 .kind(CompletionItemKind::Field) 149 .kind(SymbolKind::Field)
150 .detail(ty.display(self.ctx.db()).to_string()) 150 .detail(ty.display(self.ctx.db()).to_string())
151 .set_documentation(field.docs(self.ctx.db())) 151 .set_documentation(field.docs(self.ctx.db()))
152 .set_deprecated(is_deprecated); 152 .set_deprecated(is_deprecated);
@@ -160,7 +160,7 @@ impl<'a> Render<'a> {
160 160
161 fn add_tuple_field(&mut self, field: usize, ty: &Type) -> CompletionItem { 161 fn add_tuple_field(&mut self, field: usize, ty: &Type) -> CompletionItem {
162 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), field.to_string()) 162 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), field.to_string())
163 .kind(CompletionItemKind::Field) 163 .kind(SymbolKind::Field)
164 .detail(ty.display(self.ctx.db()).to_string()) 164 .detail(ty.display(self.ctx.db()).to_string())
165 .build() 165 .build()
166 } 166 }
@@ -187,7 +187,7 @@ impl<'a> Render<'a> {
187 if self.ctx.completion.is_pat_binding_or_const 187 if self.ctx.completion.is_pat_binding_or_const
188 | self.ctx.completion.is_irrefutable_pat_binding => 188 | self.ctx.completion.is_irrefutable_pat_binding =>
189 { 189 {
190 CompletionItemKind::EnumVariant 190 CompletionItemKind::SymbolKind(SymbolKind::Variant)
191 } 191 }
192 ScopeDef::ModuleDef(Variant(var)) => { 192 ScopeDef::ModuleDef(Variant(var)) => {
193 let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None); 193 let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None);
@@ -198,20 +198,28 @@ impl<'a> Render<'a> {
198 return item; 198 return item;
199 } 199 }
200 200
201 ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::Module, 201 ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module),
202 ScopeDef::ModuleDef(Adt(hir::Adt::Struct(_))) => CompletionItemKind::Struct, 202 ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt {
203 // FIXME: add CompletionItemKind::Union 203 hir::Adt::Struct(_) => SymbolKind::Struct,
204 ScopeDef::ModuleDef(Adt(hir::Adt::Union(_))) => CompletionItemKind::Struct, 204 hir::Adt::Union(_) => SymbolKind::Union,
205 ScopeDef::ModuleDef(Adt(hir::Adt::Enum(_))) => CompletionItemKind::Enum, 205 hir::Adt::Enum(_) => SymbolKind::Enum,
206 ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::Const, 206 }),
207 ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::Static, 207 ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const),
208 ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::Trait, 208 ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static),
209 ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::TypeAlias, 209 ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait),
210 ScopeDef::ModuleDef(TypeAlias(..)) => {
211 CompletionItemKind::SymbolKind(SymbolKind::TypeAlias)
212 }
210 ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType, 213 ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
211 ScopeDef::GenericParam(..) => CompletionItemKind::TypeParam, 214 ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
212 ScopeDef::Local(..) => CompletionItemKind::Binding, 215 hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
213 // (does this need its own kind?) 216 hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
214 ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => CompletionItemKind::TypeParam, 217 hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
218 }),
219 ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
220 ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => {
221 CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
222 }
215 ScopeDef::Unknown => { 223 ScopeDef::Unknown => {
216 let item = CompletionItem::new( 224 let item = CompletionItem::new(
217 CompletionKind::Reference, 225 CompletionKind::Reference,
@@ -400,7 +408,9 @@ fn main() { Foo::Fo$0 }
400 source_range: 54..56, 408 source_range: 54..56,
401 delete: 54..56, 409 delete: 54..56,
402 insert: "Foo", 410 insert: "Foo",
403 kind: EnumVariant, 411 kind: SymbolKind(
412 Variant,
413 ),
404 detail: "{ x: i32, y: i32 }", 414 detail: "{ x: i32, y: i32 }",
405 }, 415 },
406 ] 416 ]
@@ -423,7 +433,9 @@ fn main() { Foo::Fo$0 }
423 source_range: 46..48, 433 source_range: 46..48,
424 delete: 46..48, 434 delete: 46..48,
425 insert: "Foo($0)", 435 insert: "Foo($0)",
426 kind: EnumVariant, 436 kind: SymbolKind(
437 Variant,
438 ),
427 lookup: "Foo", 439 lookup: "Foo",
428 detail: "(i32, i32)", 440 detail: "(i32, i32)",
429 trigger_call_info: true, 441 trigger_call_info: true,
@@ -448,7 +460,9 @@ fn main() { Foo::Fo$0 }
448 source_range: 35..37, 460 source_range: 35..37,
449 delete: 35..37, 461 delete: 35..37,
450 insert: "Foo", 462 insert: "Foo",
451 kind: EnumVariant, 463 kind: SymbolKind(
464 Variant,
465 ),
452 detail: "()", 466 detail: "()",
453 }, 467 },
454 ] 468 ]
@@ -472,7 +486,9 @@ fn main() { let _: m::Spam = S$0 }
472 source_range: 75..76, 486 source_range: 75..76,
473 delete: 75..76, 487 delete: 75..76,
474 insert: "Spam::Bar($0)", 488 insert: "Spam::Bar($0)",
475 kind: EnumVariant, 489 kind: SymbolKind(
490 Variant,
491 ),
476 lookup: "Spam::Bar", 492 lookup: "Spam::Bar",
477 detail: "(i32)", 493 detail: "(i32)",
478 trigger_call_info: true, 494 trigger_call_info: true,
@@ -482,14 +498,18 @@ fn main() { let _: m::Spam = S$0 }
482 source_range: 75..76, 498 source_range: 75..76,
483 delete: 75..76, 499 delete: 75..76,
484 insert: "m", 500 insert: "m",
485 kind: Module, 501 kind: SymbolKind(
502 Module,
503 ),
486 }, 504 },
487 CompletionItem { 505 CompletionItem {
488 label: "m::Spam::Foo", 506 label: "m::Spam::Foo",
489 source_range: 75..76, 507 source_range: 75..76,
490 delete: 75..76, 508 delete: 75..76,
491 insert: "m::Spam::Foo", 509 insert: "m::Spam::Foo",
492 kind: EnumVariant, 510 kind: SymbolKind(
511 Variant,
512 ),
493 lookup: "Spam::Foo", 513 lookup: "Spam::Foo",
494 detail: "()", 514 detail: "()",
495 }, 515 },
@@ -498,9 +518,11 @@ fn main() { let _: m::Spam = S$0 }
498 source_range: 75..76, 518 source_range: 75..76,
499 delete: 75..76, 519 delete: 75..76,
500 insert: "main()$0", 520 insert: "main()$0",
501 kind: Function, 521 kind: SymbolKind(
522 Function,
523 ),
502 lookup: "main", 524 lookup: "main",
503 detail: "fn main()", 525 detail: "-> ()",
504 }, 526 },
505 ] 527 ]
506 "#]], 528 "#]],
@@ -525,18 +547,22 @@ fn main() { som$0 }
525 source_range: 127..130, 547 source_range: 127..130,
526 delete: 127..130, 548 delete: 127..130,
527 insert: "main()$0", 549 insert: "main()$0",
528 kind: Function, 550 kind: SymbolKind(
551 Function,
552 ),
529 lookup: "main", 553 lookup: "main",
530 detail: "fn main()", 554 detail: "-> ()",
531 }, 555 },
532 CompletionItem { 556 CompletionItem {
533 label: "something_deprecated()", 557 label: "something_deprecated()",
534 source_range: 127..130, 558 source_range: 127..130,
535 delete: 127..130, 559 delete: 127..130,
536 insert: "something_deprecated()$0", 560 insert: "something_deprecated()$0",
537 kind: Function, 561 kind: SymbolKind(
562 Function,
563 ),
538 lookup: "something_deprecated", 564 lookup: "something_deprecated",
539 detail: "fn something_deprecated()", 565 detail: "-> ()",
540 deprecated: true, 566 deprecated: true,
541 }, 567 },
542 CompletionItem { 568 CompletionItem {
@@ -544,9 +570,11 @@ fn main() { som$0 }
544 source_range: 127..130, 570 source_range: 127..130,
545 delete: 127..130, 571 delete: 127..130,
546 insert: "something_else_deprecated()$0", 572 insert: "something_else_deprecated()$0",
547 kind: Function, 573 kind: SymbolKind(
574 Function,
575 ),
548 lookup: "something_else_deprecated", 576 lookup: "something_else_deprecated",
549 detail: "fn something_else_deprecated()", 577 detail: "-> ()",
550 deprecated: true, 578 deprecated: true,
551 }, 579 },
552 ] 580 ]
@@ -565,7 +593,9 @@ fn foo() { A { the$0 } }
565 source_range: 57..60, 593 source_range: 57..60,
566 delete: 57..60, 594 delete: 57..60,
567 insert: "the_field", 595 insert: "the_field",
568 kind: Field, 596 kind: SymbolKind(
597 Field,
598 ),
569 detail: "u32", 599 detail: "u32",
570 deprecated: true, 600 deprecated: true,
571 }, 601 },
@@ -595,7 +625,7 @@ impl S {
595 insert: "bar()$0", 625 insert: "bar()$0",
596 kind: Method, 626 kind: Method,
597 lookup: "bar", 627 lookup: "bar",
598 detail: "fn bar(self)", 628 detail: "-> ()",
599 documentation: Documentation( 629 documentation: Documentation(
600 "Method docs", 630 "Method docs",
601 ), 631 ),
@@ -605,7 +635,9 @@ impl S {
605 source_range: 94..94, 635 source_range: 94..94,
606 delete: 94..94, 636 delete: 94..94,
607 insert: "foo", 637 insert: "foo",
608 kind: Field, 638 kind: SymbolKind(
639 Field,
640 ),
609 detail: "{unknown}", 641 detail: "{unknown}",
610 documentation: Documentation( 642 documentation: Documentation(
611 "Field docs", 643 "Field docs",
@@ -636,7 +668,9 @@ use self::E::*;
636 source_range: 10..12, 668 source_range: 10..12,
637 delete: 10..12, 669 delete: 10..12,
638 insert: "E", 670 insert: "E",
639 kind: Enum, 671 kind: SymbolKind(
672 Enum,
673 ),
640 documentation: Documentation( 674 documentation: Documentation(
641 "enum docs", 675 "enum docs",
642 ), 676 ),
@@ -646,7 +680,9 @@ use self::E::*;
646 source_range: 10..12, 680 source_range: 10..12,
647 delete: 10..12, 681 delete: 10..12,
648 insert: "V", 682 insert: "V",
649 kind: EnumVariant, 683 kind: SymbolKind(
684 Variant,
685 ),
650 detail: "()", 686 detail: "()",
651 documentation: Documentation( 687 documentation: Documentation(
652 "variant docs", 688 "variant docs",
@@ -657,7 +693,9 @@ use self::E::*;
657 source_range: 10..12, 693 source_range: 10..12,
658 delete: 10..12, 694 delete: 10..12,
659 insert: "my", 695 insert: "my",
660 kind: Module, 696 kind: SymbolKind(
697 Module,
698 ),
661 documentation: Documentation( 699 documentation: Documentation(
662 "mod docs", 700 "mod docs",
663 ), 701 ),
@@ -687,7 +725,7 @@ fn foo(s: S) { s.$0 }
687 insert: "the_method()$0", 725 insert: "the_method()$0",
688 kind: Method, 726 kind: Method,
689 lookup: "the_method", 727 lookup: "the_method",
690 detail: "fn the_method(&self)", 728 detail: "-> ()",
691 }, 729 },
692 ] 730 ]
693 "#]], 731 "#]],
@@ -883,7 +921,7 @@ struct WorldSnapshot { _f: () };
883fn go(world: &WorldSnapshot) { go(w$0) } 921fn go(world: &WorldSnapshot) { go(w$0) }
884"#, 922"#,
885 expect![[r#" 923 expect![[r#"
886 bn world [type+name] 924 lc world [type+name]
887 st WorldSnapshot [] 925 st WorldSnapshot []
888 fn go(…) [] 926 fn go(…) []
889 "#]], 927 "#]],
@@ -900,7 +938,7 @@ fn f(foo: &Foo) { f(foo, w$0) }
900 expect![[r#" 938 expect![[r#"
901 st Foo [] 939 st Foo []
902 fn f(…) [] 940 fn f(…) []
903 bn foo [] 941 lc foo []
904 "#]], 942 "#]],
905 ); 943 );
906 } 944 }
diff --git a/crates/completion/src/render/const_.rs b/crates/completion/src/render/const_.rs
index e46452d4e..5010b642a 100644
--- a/crates/completion/src/render/const_.rs
+++ b/crates/completion/src/render/const_.rs
@@ -1,13 +1,14 @@
1//! Renderer for `const` fields. 1//! Renderer for `const` fields.
2 2
3use hir::HasSource; 3use hir::HasSource;
4use ide_db::SymbolKind;
4use syntax::{ 5use syntax::{
5 ast::{Const, NameOwner}, 6 ast::{Const, NameOwner},
6 display::const_label, 7 display::const_label,
7}; 8};
8 9
9use crate::{ 10use crate::{
10 item::{CompletionItem, CompletionItemKind, CompletionKind}, 11 item::{CompletionItem, CompletionKind},
11 render::RenderContext, 12 render::RenderContext,
12}; 13};
13 14
@@ -36,7 +37,7 @@ impl<'a> ConstRender<'a> {
36 let detail = self.detail(); 37 let detail = self.detail();
37 38
38 let item = CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name) 39 let item = CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name)
39 .kind(CompletionItemKind::Const) 40 .kind(SymbolKind::Const)
40 .set_documentation(self.ctx.docs(self.const_)) 41 .set_documentation(self.ctx.docs(self.const_))
41 .set_deprecated( 42 .set_deprecated(
42 self.ctx.is_deprecated(self.const_) 43 self.ctx.is_deprecated(self.const_)
diff --git a/crates/completion/src/render/enum_variant.rs b/crates/completion/src/render/enum_variant.rs
index 89fb49773..adcddebd1 100644
--- a/crates/completion/src/render/enum_variant.rs
+++ b/crates/completion/src/render/enum_variant.rs
@@ -1,11 +1,12 @@
1//! Renderer for `enum` variants. 1//! Renderer for `enum` variants.
2 2
3use hir::{HasAttrs, HirDisplay, ModPath, StructKind}; 3use hir::{HasAttrs, HirDisplay, ModPath, StructKind};
4use ide_db::SymbolKind;
4use itertools::Itertools; 5use itertools::Itertools;
5use test_utils::mark; 6use test_utils::mark;
6 7
7use crate::{ 8use crate::{
8 item::{CompletionItem, CompletionItemKind, CompletionKind, ImportEdit}, 9 item::{CompletionItem, CompletionKind, ImportEdit},
9 render::{builder_ext::Params, RenderContext}, 10 render::{builder_ext::Params, RenderContext},
10}; 11};
11 12
@@ -60,7 +61,7 @@ impl<'a> EnumRender<'a> {
60 self.ctx.source_range(), 61 self.ctx.source_range(),
61 self.qualified_name.clone(), 62 self.qualified_name.clone(),
62 ) 63 )
63 .kind(CompletionItemKind::EnumVariant) 64 .kind(SymbolKind::Variant)
64 .set_documentation(self.variant.docs(self.ctx.db())) 65 .set_documentation(self.variant.docs(self.ctx.db()))
65 .set_deprecated(self.ctx.is_deprecated(self.variant)) 66 .set_deprecated(self.ctx.is_deprecated(self.variant))
66 .add_import(import_to_add) 67 .add_import(import_to_add)
diff --git a/crates/completion/src/render/function.rs b/crates/completion/src/render/function.rs
index 8f4c66211..e46e21d24 100644
--- a/crates/completion/src/render/function.rs
+++ b/crates/completion/src/render/function.rs
@@ -1,7 +1,8 @@
1//! Renderer for function calls. 1//! Renderer for function calls.
2 2
3use hir::{HasSource, Type}; 3use hir::{HasSource, HirDisplay, Type};
4use syntax::{ast::Fn, display::function_declaration}; 4use ide_db::SymbolKind;
5use syntax::ast::Fn;
5use test_utils::mark; 6use test_utils::mark;
6 7
7use crate::{ 8use crate::{
@@ -54,7 +55,8 @@ impl<'a> FunctionRender<'a> {
54 } 55 }
55 56
56 fn detail(&self) -> String { 57 fn detail(&self) -> String {
57 function_declaration(&self.ast_node) 58 let ty = self.func.ret_type(self.ctx.db());
59 format!("-> {}", ty.display(self.ctx.db()))
58 } 60 }
59 61
60 fn add_arg(&self, arg: &str, ty: &Type) -> String { 62 fn add_arg(&self, arg: &str, ty: &Type) -> String {
@@ -105,7 +107,7 @@ impl<'a> FunctionRender<'a> {
105 if self.func.self_param(self.ctx.db()).is_some() { 107 if self.func.self_param(self.ctx.db()).is_some() {
106 CompletionItemKind::Method 108 CompletionItemKind::Method
107 } else { 109 } else {
108 CompletionItemKind::Function 110 SymbolKind::Function.into()
109 } 111 }
110 } 112 }
111} 113}
diff --git a/crates/completion/src/render/macro_.rs b/crates/completion/src/render/macro_.rs
index f893e420a..a4535786f 100644
--- a/crates/completion/src/render/macro_.rs
+++ b/crates/completion/src/render/macro_.rs
@@ -1,11 +1,12 @@
1//! Renderer for macro invocations. 1//! Renderer for macro invocations.
2 2
3use hir::{Documentation, HasSource}; 3use hir::{Documentation, HasSource};
4use ide_db::SymbolKind;
4use syntax::display::macro_label; 5use syntax::display::macro_label;
5use test_utils::mark; 6use test_utils::mark;
6 7
7use crate::{ 8use crate::{
8 item::{CompletionItem, CompletionItemKind, CompletionKind, ImportEdit}, 9 item::{CompletionItem, CompletionKind, ImportEdit},
9 render::RenderContext, 10 render::RenderContext,
10}; 11};
11 12
@@ -41,7 +42,7 @@ impl<'a> MacroRender<'a> {
41 fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> { 42 fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> {
42 let mut builder = 43 let mut builder =
43 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label()) 44 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label())
44 .kind(CompletionItemKind::Macro) 45 .kind(SymbolKind::Macro)
45 .set_documentation(self.docs.clone()) 46 .set_documentation(self.docs.clone())
46 .set_deprecated(self.ctx.is_deprecated(self.macro_)) 47 .set_deprecated(self.ctx.is_deprecated(self.macro_))
47 .add_import(import_to_add) 48 .add_import(import_to_add)
diff --git a/crates/completion/src/render/type_alias.rs b/crates/completion/src/render/type_alias.rs
index 29287143a..bd97c3692 100644
--- a/crates/completion/src/render/type_alias.rs
+++ b/crates/completion/src/render/type_alias.rs
@@ -1,13 +1,14 @@
1//! Renderer for type aliases. 1//! Renderer for type aliases.
2 2
3use hir::HasSource; 3use hir::HasSource;
4use ide_db::SymbolKind;
4use syntax::{ 5use syntax::{
5 ast::{NameOwner, TypeAlias}, 6 ast::{NameOwner, TypeAlias},
6 display::type_label, 7 display::type_label,
7}; 8};
8 9
9use crate::{ 10use crate::{
10 item::{CompletionItem, CompletionItemKind, CompletionKind}, 11 item::{CompletionItem, CompletionKind},
11 render::RenderContext, 12 render::RenderContext,
12}; 13};
13 14
@@ -36,7 +37,7 @@ impl<'a> TypeAliasRender<'a> {
36 let detail = self.detail(); 37 let detail = self.detail();
37 38
38 let item = CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name) 39 let item = CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name)
39 .kind(CompletionItemKind::TypeAlias) 40 .kind(SymbolKind::TypeAlias)
40 .set_documentation(self.ctx.docs(self.type_alias)) 41 .set_documentation(self.ctx.docs(self.type_alias))
41 .set_deprecated( 42 .set_deprecated(
42 self.ctx.is_deprecated(self.type_alias) 43 self.ctx.is_deprecated(self.type_alias)
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index aaa7013b6..e9bb4f541 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -18,8 +18,8 @@ use hir_def::{
18 type_ref::{Mutability, TypeRef}, 18 type_ref::{Mutability, TypeRef},
19 AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, 19 AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId,
20 DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, 20 DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId,
21 LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId, TraitId, 21 LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
22 TypeAliasId, TypeParamId, UnionId, 22 TypeParamId, UnionId,
23}; 23};
24use hir_def::{find_path::PrefixKind, item_scope::ItemInNs, visibility::Visibility}; 24use hir_def::{find_path::PrefixKind, item_scope::ItemInNs, visibility::Visibility};
25use hir_expand::{ 25use hir_expand::{
@@ -90,8 +90,8 @@ impl Crate {
90 } 90 }
91 91
92 pub fn root_module(self, db: &dyn HirDatabase) -> Module { 92 pub fn root_module(self, db: &dyn HirDatabase) -> Module {
93 let module_id = db.crate_def_map(self.id).root(); 93 let def_map = db.crate_def_map(self.id);
94 Module::new(self, module_id) 94 Module { id: def_map.module_id(def_map.root()) }
95 } 95 }
96 96
97 pub fn root_file(self, db: &dyn HirDatabase) -> FileId { 97 pub fn root_file(self, db: &dyn HirDatabase) -> FileId {
@@ -270,18 +270,14 @@ impl ModuleDef {
270 None => return, 270 None => return,
271 }; 271 };
272 272
273 hir_ty::diagnostics::validate_module_item(db, module.id.krate, id, sink) 273 hir_ty::diagnostics::validate_module_item(db, module.id.krate(), id, sink)
274 } 274 }
275} 275}
276 276
277impl Module { 277impl Module {
278 pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module {
279 Module { id: ModuleId { krate: krate.id, local_id: crate_module_id } }
280 }
281
282 /// Name of this module. 278 /// Name of this module.
283 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 279 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
284 let def_map = db.crate_def_map(self.id.krate); 280 let def_map = self.id.def_map(db.upcast());
285 let parent = def_map[self.id.local_id].parent?; 281 let parent = def_map[self.id.local_id].parent?;
286 def_map[parent].children.iter().find_map(|(name, module_id)| { 282 def_map[parent].children.iter().find_map(|(name, module_id)| {
287 if *module_id == self.id.local_id { 283 if *module_id == self.id.local_id {
@@ -294,33 +290,34 @@ impl Module {
294 290
295 /// Returns the crate this module is part of. 291 /// Returns the crate this module is part of.
296 pub fn krate(self) -> Crate { 292 pub fn krate(self) -> Crate {
297 Crate { id: self.id.krate } 293 Crate { id: self.id.krate() }
298 } 294 }
299 295
300 /// Topmost parent of this module. Every module has a `crate_root`, but some 296 /// Topmost parent of this module. Every module has a `crate_root`, but some
301 /// might be missing `krate`. This can happen if a module's file is not included 297 /// might be missing `krate`. This can happen if a module's file is not included
302 /// in the module tree of any target in `Cargo.toml`. 298 /// in the module tree of any target in `Cargo.toml`.
303 pub fn crate_root(self, db: &dyn HirDatabase) -> Module { 299 pub fn crate_root(self, db: &dyn HirDatabase) -> Module {
304 let def_map = db.crate_def_map(self.id.krate); 300 let def_map = db.crate_def_map(self.id.krate());
305 self.with_module_id(def_map.root()) 301 Module { id: def_map.module_id(def_map.root()) }
306 } 302 }
307 303
308 /// Iterates over all child modules. 304 /// Iterates over all child modules.
309 pub fn children(self, db: &dyn HirDatabase) -> impl Iterator<Item = Module> { 305 pub fn children(self, db: &dyn HirDatabase) -> impl Iterator<Item = Module> {
310 let def_map = db.crate_def_map(self.id.krate); 306 let def_map = self.id.def_map(db.upcast());
311 let children = def_map[self.id.local_id] 307 let children = def_map[self.id.local_id]
312 .children 308 .children
313 .iter() 309 .iter()
314 .map(|(_, module_id)| self.with_module_id(*module_id)) 310 .map(|(_, module_id)| Module { id: def_map.module_id(*module_id) })
315 .collect::<Vec<_>>(); 311 .collect::<Vec<_>>();
316 children.into_iter() 312 children.into_iter()
317 } 313 }
318 314
319 /// Finds a parent module. 315 /// Finds a parent module.
320 pub fn parent(self, db: &dyn HirDatabase) -> Option<Module> { 316 pub fn parent(self, db: &dyn HirDatabase) -> Option<Module> {
321 let def_map = db.crate_def_map(self.id.krate); 317 // FIXME: handle block expressions as modules (their parent is in a different DefMap)
318 let def_map = self.id.def_map(db.upcast());
322 let parent_id = def_map[self.id.local_id].parent?; 319 let parent_id = def_map[self.id.local_id].parent?;
323 Some(self.with_module_id(parent_id)) 320 Some(Module { id: def_map.module_id(parent_id) })
324 } 321 }
325 322
326 pub fn path_to_root(self, db: &dyn HirDatabase) -> Vec<Module> { 323 pub fn path_to_root(self, db: &dyn HirDatabase) -> Vec<Module> {
@@ -339,7 +336,7 @@ impl Module {
339 db: &dyn HirDatabase, 336 db: &dyn HirDatabase,
340 visible_from: Option<Module>, 337 visible_from: Option<Module>,
341 ) -> Vec<(Name, ScopeDef)> { 338 ) -> Vec<(Name, ScopeDef)> {
342 db.crate_def_map(self.id.krate)[self.id.local_id] 339 self.id.def_map(db.upcast())[self.id.local_id]
343 .scope 340 .scope
344 .entries() 341 .entries()
345 .filter_map(|(name, def)| { 342 .filter_map(|(name, def)| {
@@ -362,14 +359,14 @@ impl Module {
362 } 359 }
363 360
364 pub fn visibility_of(self, db: &dyn HirDatabase, def: &ModuleDef) -> Option<Visibility> { 361 pub fn visibility_of(self, db: &dyn HirDatabase, def: &ModuleDef) -> Option<Visibility> {
365 db.crate_def_map(self.id.krate)[self.id.local_id].scope.visibility_of(def.clone().into()) 362 self.id.def_map(db.upcast())[self.id.local_id].scope.visibility_of(def.clone().into())
366 } 363 }
367 364
368 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { 365 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
369 let _p = profile::span("Module::diagnostics").detail(|| { 366 let _p = profile::span("Module::diagnostics").detail(|| {
370 format!("{:?}", self.name(db).map_or("<unknown>".into(), |name| name.to_string())) 367 format!("{:?}", self.name(db).map_or("<unknown>".into(), |name| name.to_string()))
371 }); 368 });
372 let crate_def_map = db.crate_def_map(self.id.krate); 369 let crate_def_map = self.id.def_map(db.upcast());
373 crate_def_map.add_diagnostics(db.upcast(), self.id.local_id, sink); 370 crate_def_map.add_diagnostics(db.upcast(), self.id.local_id, sink);
374 for decl in self.declarations(db) { 371 for decl in self.declarations(db) {
375 match decl { 372 match decl {
@@ -396,19 +393,15 @@ impl Module {
396 } 393 }
397 394
398 pub fn declarations(self, db: &dyn HirDatabase) -> Vec<ModuleDef> { 395 pub fn declarations(self, db: &dyn HirDatabase) -> Vec<ModuleDef> {
399 let def_map = db.crate_def_map(self.id.krate); 396 let def_map = self.id.def_map(db.upcast());
400 def_map[self.id.local_id].scope.declarations().map(ModuleDef::from).collect() 397 def_map[self.id.local_id].scope.declarations().map(ModuleDef::from).collect()
401 } 398 }
402 399
403 pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> { 400 pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> {
404 let def_map = db.crate_def_map(self.id.krate); 401 let def_map = self.id.def_map(db.upcast());
405 def_map[self.id.local_id].scope.impls().map(Impl::from).collect() 402 def_map[self.id.local_id].scope.impls().map(Impl::from).collect()
406 } 403 }
407 404
408 pub(crate) fn with_module_id(self, module_id: LocalModuleId) -> Module {
409 Module::new(self.krate(), module_id)
410 }
411
412 /// Finds a path that can be used to refer to the given item from within 405 /// Finds a path that can be used to refer to the given item from within
413 /// this module, if possible. 406 /// this module, if possible.
414 pub fn find_use_path(self, db: &dyn DefDatabase, item: impl Into<ItemInNs>) -> Option<ModPath> { 407 pub fn find_use_path(self, db: &dyn DefDatabase, item: impl Into<ItemInNs>) -> Option<ModPath> {
@@ -457,7 +450,7 @@ impl Field {
457 }; 450 };
458 let substs = Substs::type_params(db, generic_def_id); 451 let substs = Substs::type_params(db, generic_def_id);
459 let ty = db.field_types(var_id)[self.id].clone().subst(&substs); 452 let ty = db.field_types(var_id)[self.id].clone().subst(&substs);
460 Type::new(db, self.parent.module(db).id.krate, var_id, ty) 453 Type::new(db, self.parent.module(db).id.krate(), var_id, ty)
461 } 454 }
462 455
463 pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef { 456 pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
@@ -502,7 +495,11 @@ impl Struct {
502 } 495 }
503 496
504 pub fn ty(self, db: &dyn HirDatabase) -> Type { 497 pub fn ty(self, db: &dyn HirDatabase) -> Type {
505 Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id) 498 Type::from_def(
499 db,
500 self.id.lookup(db.upcast()).container.module(db.upcast()).krate(),
501 self.id,
502 )
506 } 503 }
507 504
508 pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> { 505 pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> {
@@ -533,7 +530,11 @@ impl Union {
533 } 530 }
534 531
535 pub fn ty(self, db: &dyn HirDatabase) -> Type { 532 pub fn ty(self, db: &dyn HirDatabase) -> Type {
536 Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id) 533 Type::from_def(
534 db,
535 self.id.lookup(db.upcast()).container.module(db.upcast()).krate(),
536 self.id,
537 )
537 } 538 }
538 539
539 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> { 540 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
@@ -573,7 +574,11 @@ impl Enum {
573 } 574 }
574 575
575 pub fn ty(self, db: &dyn HirDatabase) -> Type { 576 pub fn ty(self, db: &dyn HirDatabase) -> Type {
576 Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id) 577 Type::from_def(
578 db,
579 self.id.lookup(db.upcast()).container.module(db.upcast()).krate(),
580 self.id,
581 )
577 } 582 }
578} 583}
579 584
@@ -632,7 +637,7 @@ impl Adt {
632 /// general set of completions, but will not look very nice when printed. 637 /// general set of completions, but will not look very nice when printed.
633 pub fn ty(self, db: &dyn HirDatabase) -> Type { 638 pub fn ty(self, db: &dyn HirDatabase) -> Type {
634 let id = AdtId::from(self); 639 let id = AdtId::from(self);
635 Type::from_def(db, id.module(db.upcast()).krate, id) 640 Type::from_def(db, id.module(db.upcast()).krate(), id)
636 } 641 }
637 642
638 pub fn module(self, db: &dyn HirDatabase) -> Module { 643 pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -750,7 +755,7 @@ impl Function {
750 let ctx = hir_ty::TyLoweringContext::new(db, &resolver); 755 let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
751 let environment = TraitEnvironment::lower(db, &resolver); 756 let environment = TraitEnvironment::lower(db, &resolver);
752 Type { 757 Type {
753 krate: self.id.lookup(db.upcast()).container.module(db.upcast()).krate, 758 krate: self.id.lookup(db.upcast()).container.module(db.upcast()).krate(),
754 ty: InEnvironment { value: Ty::from_hir_ext(&ctx, ret_type).0, environment }, 759 ty: InEnvironment { value: Ty::from_hir_ext(&ctx, ret_type).0, environment },
755 } 760 }
756 } 761 }
@@ -771,7 +776,7 @@ impl Function {
771 .iter() 776 .iter()
772 .map(|type_ref| { 777 .map(|type_ref| {
773 let ty = Type { 778 let ty = Type {
774 krate: self.id.lookup(db.upcast()).container.module(db.upcast()).krate, 779 krate: self.id.lookup(db.upcast()).container.module(db.upcast()).krate(),
775 ty: InEnvironment { 780 ty: InEnvironment {
776 value: Ty::from_hir_ext(&ctx, type_ref).0, 781 value: Ty::from_hir_ext(&ctx, type_ref).0,
777 environment: environment.clone(), 782 environment: environment.clone(),
@@ -795,7 +800,7 @@ impl Function {
795 } 800 }
796 801
797 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { 802 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
798 let krate = self.module(db).id.krate; 803 let krate = self.module(db).id.krate();
799 hir_def::diagnostics::validate_body(db.upcast(), self.id.into(), sink); 804 hir_def::diagnostics::validate_body(db.upcast(), self.id.into(), sink);
800 hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); 805 hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink);
801 hir_ty::diagnostics::validate_body(db, self.id.into(), sink); 806 hir_ty::diagnostics::validate_body(db, self.id.into(), sink);
@@ -973,7 +978,7 @@ impl TypeAlias {
973 } 978 }
974 979
975 pub fn ty(self, db: &dyn HirDatabase) -> Type { 980 pub fn ty(self, db: &dyn HirDatabase) -> Type {
976 Type::from_def(db, self.id.lookup(db.upcast()).module(db.upcast()).krate, self.id) 981 Type::from_def(db, self.id.lookup(db.upcast()).module(db.upcast()).krate(), self.id)
977 } 982 }
978 983
979 pub fn name(self, db: &dyn HirDatabase) -> Name { 984 pub fn name(self, db: &dyn HirDatabase) -> Name {
@@ -1000,8 +1005,9 @@ impl MacroDef {
1000 /// early, in `hir_expand`, where modules simply do not exist yet. 1005 /// early, in `hir_expand`, where modules simply do not exist yet.
1001 pub fn module(self, db: &dyn HirDatabase) -> Option<Module> { 1006 pub fn module(self, db: &dyn HirDatabase) -> Option<Module> {
1002 let krate = self.id.krate; 1007 let krate = self.id.krate;
1003 let module_id = db.crate_def_map(krate).root(); 1008 let def_map = db.crate_def_map(krate);
1004 Some(Module::new(Crate { id: krate }, module_id)) 1009 let module_id = def_map.root();
1010 Some(Module { id: def_map.module_id(module_id) })
1005 } 1011 }
1006 1012
1007 /// XXX: this parses the file 1013 /// XXX: this parses the file
@@ -1230,7 +1236,7 @@ impl Local {
1230 let def = DefWithBodyId::from(self.parent); 1236 let def = DefWithBodyId::from(self.parent);
1231 let infer = db.infer(def); 1237 let infer = db.infer(def);
1232 let ty = infer[self.pat_id].clone(); 1238 let ty = infer[self.pat_id].clone();
1233 let krate = def.module(db.upcast()).krate; 1239 let krate = def.module(db.upcast()).krate();
1234 Type::new(db, krate, def, ty) 1240 Type::new(db, krate, def, ty)
1235 } 1241 }
1236 1242
@@ -1318,7 +1324,7 @@ impl TypeParam {
1318 let environment = TraitEnvironment::lower(db, &resolver); 1324 let environment = TraitEnvironment::lower(db, &resolver);
1319 let ty = Ty::Placeholder(self.id); 1325 let ty = Ty::Placeholder(self.id);
1320 Type { 1326 Type {
1321 krate: self.id.parent.module(db.upcast()).krate, 1327 krate: self.id.parent.module(db.upcast()).krate(),
1322 ty: InEnvironment { value: ty, environment }, 1328 ty: InEnvironment { value: ty, environment },
1323 } 1329 }
1324 } 1330 }
@@ -1344,7 +1350,7 @@ impl TypeParam {
1344 let subst = Substs::type_params(db, self.id.parent); 1350 let subst = Substs::type_params(db, self.id.parent);
1345 let ty = ty.subst(&subst.prefix(local_idx)); 1351 let ty = ty.subst(&subst.prefix(local_idx));
1346 Some(Type { 1352 Some(Type {
1347 krate: self.id.parent.module(db.upcast()).krate, 1353 krate: self.id.parent.module(db.upcast()).krate(),
1348 ty: InEnvironment { value: ty, environment }, 1354 ty: InEnvironment { value: ty, environment },
1349 }) 1355 })
1350 } 1356 }
@@ -1405,7 +1411,7 @@ impl ConstParam {
1405 1411
1406 pub fn ty(self, db: &dyn HirDatabase) -> Type { 1412 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1407 let def = self.id.parent; 1413 let def = self.id.parent;
1408 let krate = def.module(db.upcast()).krate; 1414 let krate = def.module(db.upcast()).krate();
1409 Type::new(db, krate, def, db.const_param_ty(self.id)) 1415 Type::new(db, krate, def, db.const_param_ty(self.id))
1410 } 1416 }
1411} 1417}
@@ -1440,7 +1446,7 @@ impl Impl {
1440 let environment = TraitEnvironment::lower(db, &resolver); 1446 let environment = TraitEnvironment::lower(db, &resolver);
1441 let ty = Ty::from_hir(&ctx, &impl_data.target_type); 1447 let ty = Ty::from_hir(&ctx, &impl_data.target_type);
1442 Type { 1448 Type {
1443 krate: self.id.lookup(db.upcast()).container.module(db.upcast()).krate, 1449 krate: self.id.lookup(db.upcast()).container.module(db.upcast()).krate(),
1444 ty: InEnvironment { value: ty, environment }, 1450 ty: InEnvironment { value: ty, environment },
1445 } 1451 }
1446 } 1452 }
@@ -1458,7 +1464,7 @@ impl Impl {
1458 } 1464 }
1459 1465
1460 pub fn krate(self, db: &dyn HirDatabase) -> Crate { 1466 pub fn krate(self, db: &dyn HirDatabase) -> Crate {
1461 Crate { id: self.module(db).id.krate } 1467 Crate { id: self.module(db).id.krate() }
1462 } 1468 }
1463 1469
1464 pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> { 1470 pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 447faa04f..5343a036c 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -5,5 +5,5 @@ pub use hir_expand::diagnostics::{
5}; 5};
6pub use hir_ty::diagnostics::{ 6pub use hir_ty::diagnostics::{
7 IncorrectCase, MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr, 7 IncorrectCase, MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr,
8 NoSuchField, RemoveThisSemicolon, 8 NoSuchField, RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap,
9}; 9};
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs
index 7c57d8378..262002671 100644
--- a/crates/hir/src/has_source.rs
+++ b/crates/hir/src/has_source.rs
@@ -24,12 +24,12 @@ pub trait HasSource {
24impl Module { 24impl Module {
25 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. 25 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
26 pub fn definition_source(self, db: &dyn HirDatabase) -> InFile<ModuleSource> { 26 pub fn definition_source(self, db: &dyn HirDatabase) -> InFile<ModuleSource> {
27 let def_map = db.crate_def_map(self.id.krate); 27 let def_map = self.id.def_map(db.upcast());
28 def_map[self.id.local_id].definition_source(db.upcast()) 28 def_map[self.id.local_id].definition_source(db.upcast())
29 } 29 }
30 30
31 pub fn is_mod_rs(self, db: &dyn HirDatabase) -> bool { 31 pub fn is_mod_rs(self, db: &dyn HirDatabase) -> bool {
32 let def_map = db.crate_def_map(self.id.krate); 32 let def_map = self.id.def_map(db.upcast());
33 match def_map[self.id.local_id].origin { 33 match def_map[self.id.local_id].origin {
34 ModuleOrigin::File { is_mod_rs, .. } => is_mod_rs, 34 ModuleOrigin::File { is_mod_rs, .. } => is_mod_rs,
35 _ => false, 35 _ => false,
@@ -39,7 +39,7 @@ impl Module {
39 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. 39 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
40 /// `None` for the crate root. 40 /// `None` for the crate root.
41 pub fn declaration_source(self, db: &dyn HirDatabase) -> Option<InFile<ast::Module>> { 41 pub fn declaration_source(self, db: &dyn HirDatabase) -> Option<InFile<ast::Module>> {
42 let def_map = db.crate_def_map(self.id.krate); 42 let def_map = self.id.def_map(db.upcast());
43 def_map[self.id.local_id].declaration_source(db.upcast()) 43 def_map[self.id.local_id].declaration_source(db.upcast())
44 } 44 }
45} 45}
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index 9bf60c72a..6c612ee86 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -30,12 +30,12 @@ pub(super) struct SourceToDefCtx<'a, 'b> {
30impl SourceToDefCtx<'_, '_> { 30impl SourceToDefCtx<'_, '_> {
31 pub(super) fn file_to_def(&mut self, file: FileId) -> Option<ModuleId> { 31 pub(super) fn file_to_def(&mut self, file: FileId) -> Option<ModuleId> {
32 let _p = profile::span("SourceBinder::to_module_def"); 32 let _p = profile::span("SourceBinder::to_module_def");
33 let (krate, local_id) = self.db.relevant_crates(file).iter().find_map(|&crate_id| { 33 self.db.relevant_crates(file).iter().find_map(|&crate_id| {
34 // FIXME: inner items
34 let crate_def_map = self.db.crate_def_map(crate_id); 35 let crate_def_map = self.db.crate_def_map(crate_id);
35 let local_id = crate_def_map.modules_for_file(file).next()?; 36 let local_id = crate_def_map.modules_for_file(file).next()?;
36 Some((crate_id, local_id)) 37 Some(crate_def_map.module_id(local_id))
37 })?; 38 })
38 Some(ModuleId { krate, local_id })
39 } 39 }
40 40
41 pub(super) fn module_to_def(&mut self, src: InFile<ast::Module>) -> Option<ModuleId> { 41 pub(super) fn module_to_def(&mut self, src: InFile<ast::Module>) -> Option<ModuleId> {
@@ -60,9 +60,9 @@ impl SourceToDefCtx<'_, '_> {
60 }?; 60 }?;
61 61
62 let child_name = src.value.name()?.as_name(); 62 let child_name = src.value.name()?.as_name();
63 let def_map = self.db.crate_def_map(parent_module.krate); 63 let def_map = parent_module.def_map(self.db.upcast());
64 let child_id = *def_map[parent_module.local_id].children.get(&child_name)?; 64 let child_id = *def_map[parent_module.local_id].children.get(&child_name)?;
65 Some(ModuleId { krate: parent_module.krate, local_id: child_id }) 65 Some(def_map.module_id(child_id))
66 } 66 }
67 67
68 pub(super) fn trait_to_def(&mut self, src: InFile<ast::Trait>) -> Option<TraitId> { 68 pub(super) fn trait_to_def(&mut self, src: InFile<ast::Trait>) -> Option<TraitId> {
@@ -185,7 +185,7 @@ impl SourceToDefCtx<'_, '_> {
185 ) -> Option<MacroDefId> { 185 ) -> Option<MacroDefId> {
186 let kind = MacroDefKind::Declarative; 186 let kind = MacroDefKind::Declarative;
187 let file_id = src.file_id.original_file(self.db.upcast()); 187 let file_id = src.file_id.original_file(self.db.upcast());
188 let krate = self.file_to_def(file_id)?.krate; 188 let krate = self.file_to_def(file_id)?.krate();
189 let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); 189 let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value);
190 let ast_id = Some(AstId::new(src.file_id, file_ast_id.upcast())); 190 let ast_id = Some(AstId::new(src.file_id, file_ast_id.upcast()));
191 Some(MacroDefId { krate, ast_id, kind, local_inner: false }) 191 Some(MacroDefId { krate, ast_id, kind, local_inner: false })
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index c72649c41..6513daec8 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -196,7 +196,7 @@ impl Attrs {
196 pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { 196 pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs {
197 let raw_attrs = match def { 197 let raw_attrs = match def {
198 AttrDefId::ModuleId(module) => { 198 AttrDefId::ModuleId(module) => {
199 let def_map = db.crate_def_map(module.krate); 199 let def_map = module.def_map(db);
200 let mod_data = &def_map[module.local_id]; 200 let mod_data = &def_map[module.local_id];
201 match mod_data.declaration_source(db) { 201 match mod_data.declaration_source(db) {
202 Some(it) => { 202 Some(it) => {
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index 2c2c999dd..d0c84ab0b 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -86,7 +86,7 @@ impl Expander {
86 module: ModuleId, 86 module: ModuleId,
87 ) -> Expander { 87 ) -> Expander {
88 let cfg_expander = CfgExpander::new(db, current_file_id, module.krate); 88 let cfg_expander = CfgExpander::new(db, current_file_id, module.krate);
89 let crate_def_map = db.crate_def_map(module.krate); 89 let crate_def_map = module.def_map(db);
90 let ast_id_map = db.ast_id_map(current_file_id); 90 let ast_id_map = db.ast_id_map(current_file_id);
91 Expander { 91 Expander {
92 cfg_expander, 92 cfg_expander,
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs
index dcb00a1d9..65d85c86a 100644
--- a/crates/hir_def/src/child_by_source.rs
+++ b/crates/hir_def/src/child_by_source.rs
@@ -74,7 +74,7 @@ impl ChildBySource for ImplId {
74 74
75impl ChildBySource for ModuleId { 75impl ChildBySource for ModuleId {
76 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { 76 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
77 let crate_def_map = db.crate_def_map(self.krate); 77 let crate_def_map = self.def_map(db);
78 let module_data = &crate_def_map[self.local_id]; 78 let module_data = &crate_def_map[self.local_id];
79 module_data.scope.child_by_source(db) 79 module_data.scope.child_by_source(db)
80 } 80 }
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs
index a87c80b8a..aef7e1f6c 100644
--- a/crates/hir_def/src/db.rs
+++ b/crates/hir_def/src/db.rs
@@ -2,9 +2,9 @@
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use base_db::{salsa, CrateId, SourceDatabase, Upcast}; 4use base_db::{salsa, CrateId, SourceDatabase, Upcast};
5use hir_expand::{db::AstDatabase, AstId, HirFileId}; 5use hir_expand::{db::AstDatabase, HirFileId};
6use la_arena::ArenaMap; 6use la_arena::ArenaMap;
7use syntax::{ast, SmolStr}; 7use syntax::SmolStr;
8 8
9use crate::{ 9use crate::{
10 adt::{EnumData, StructData}, 10 adt::{EnumData, StructData},
@@ -16,9 +16,10 @@ use crate::{
16 item_tree::ItemTree, 16 item_tree::ItemTree,
17 lang_item::{LangItemTarget, LangItems}, 17 lang_item::{LangItemTarget, LangItems},
18 nameres::DefMap, 18 nameres::DefMap,
19 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, 19 AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId,
20 GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId, StaticLoc, StructId, 20 FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId,
21 StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId, 21 StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId,
22 UnionLoc, VariantId,
22}; 23};
23 24
24#[salsa::query_group(InternDatabaseStorage)] 25#[salsa::query_group(InternDatabaseStorage)]
@@ -41,6 +42,8 @@ pub trait InternDatabase: SourceDatabase {
41 fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId; 42 fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId;
42 #[salsa::interned] 43 #[salsa::interned]
43 fn intern_impl(&self, loc: ImplLoc) -> ImplId; 44 fn intern_impl(&self, loc: ImplLoc) -> ImplId;
45 #[salsa::interned]
46 fn intern_block(&self, loc: BlockLoc) -> BlockId;
44} 47}
45 48
46#[salsa::query_group(DefDatabaseStorage)] 49#[salsa::query_group(DefDatabaseStorage)]
@@ -56,7 +59,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
56 fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>; 59 fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>;
57 60
58 #[salsa::invoke(DefMap::block_def_map_query)] 61 #[salsa::invoke(DefMap::block_def_map_query)]
59 fn block_def_map(&self, krate: CrateId, block: AstId<ast::BlockExpr>) -> Arc<DefMap>; 62 fn block_def_map(&self, block: BlockId) -> Arc<DefMap>;
60 63
61 #[salsa::invoke(StructData::struct_data_query)] 64 #[salsa::invoke(StructData::struct_data_query)]
62 fn struct_data(&self, id: StructId) -> Arc<StructData>; 65 fn struct_data(&self, id: StructId) -> Arc<StructData>;
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs
index db2d125ae..94a1d567d 100644
--- a/crates/hir_def/src/find_path.rs
+++ b/crates/hir_def/src/find_path.rs
@@ -53,12 +53,8 @@ fn check_self_super(def_map: &DefMap, item: ItemInNs, from: ModuleId) -> Option<
53 Some(ModPath::from_segments(PathKind::Super(0), Vec::new())) 53 Some(ModPath::from_segments(PathKind::Super(0), Vec::new()))
54 } else if let Some(parent_id) = def_map[from.local_id].parent { 54 } else if let Some(parent_id) = def_map[from.local_id].parent {
55 // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly) 55 // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly)
56 if item 56 let parent_id = def_map.module_id(parent_id);
57 == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { 57 if item == ItemInNs::Types(ModuleDefId::ModuleId(parent_id)) {
58 krate: from.krate,
59 local_id: parent_id,
60 }))
61 {
62 Some(ModPath::from_segments(PathKind::Super(1), Vec::new())) 58 Some(ModPath::from_segments(PathKind::Super(1), Vec::new()))
63 } else { 59 } else {
64 None 60 None
@@ -110,7 +106,7 @@ fn find_path_inner(
110 // Base cases: 106 // Base cases:
111 107
112 // - if the item is already in scope, return the name under which it is 108 // - if the item is already in scope, return the name under which it is
113 let def_map = db.crate_def_map(from.krate); 109 let def_map = from.def_map(db);
114 let from_scope: &crate::item_scope::ItemScope = &def_map[from.local_id].scope; 110 let from_scope: &crate::item_scope::ItemScope = &def_map[from.local_id].scope;
115 let scope_name = 111 let scope_name =
116 if let Some((name, _)) = from_scope.name_of(item) { Some(name.clone()) } else { None }; 112 if let Some((name, _)) = from_scope.name_of(item) { Some(name.clone()) } else { None };
@@ -120,12 +116,8 @@ fn find_path_inner(
120 } 116 }
121 117
122 // - if the item is the crate root, return `crate` 118 // - if the item is the crate root, return `crate`
123 if item 119 let root = def_map.module_id(def_map.root());
124 == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { 120 if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) {
125 krate: from.krate,
126 local_id: def_map.root(),
127 }))
128 {
129 return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); 121 return Some(ModPath::from_segments(PathKind::Crate, Vec::new()));
130 } 122 }
131 123
@@ -145,7 +137,7 @@ fn find_path_inner(
145 137
146 // - if the item is in the prelude, return the name from there 138 // - if the item is in the prelude, return the name from there
147 if let Some(prelude_module) = def_map.prelude() { 139 if let Some(prelude_module) = def_map.prelude() {
148 let prelude_def_map = db.crate_def_map(prelude_module.krate); 140 let prelude_def_map = prelude_module.def_map(db);
149 let prelude_scope: &crate::item_scope::ItemScope = 141 let prelude_scope: &crate::item_scope::ItemScope =
150 &prelude_def_map[prelude_module.local_id].scope; 142 &prelude_def_map[prelude_module.local_id].scope;
151 if let Some((name, vis)) = prelude_scope.name_of(item) { 143 if let Some((name, vis)) = prelude_scope.name_of(item) {
@@ -175,7 +167,7 @@ fn find_path_inner(
175 167
176 // - otherwise, look for modules containing (reexporting) it and import it from one of those 168 // - otherwise, look for modules containing (reexporting) it and import it from one of those
177 169
178 let crate_root = ModuleId { local_id: def_map.root(), krate: from.krate }; 170 let crate_root = def_map.module_id(def_map.root());
179 let crate_attrs = db.attrs(crate_root.into()); 171 let crate_attrs = db.attrs(crate_root.into());
180 let prefer_no_std = crate_attrs.by_key("no_std").exists(); 172 let prefer_no_std = crate_attrs.by_key("no_std").exists();
181 let mut best_path = None; 173 let mut best_path = None;
@@ -283,19 +275,16 @@ fn find_local_import_locations(
283 // above `from` with any visibility. That means we do not need to descend into private siblings 275 // above `from` with any visibility. That means we do not need to descend into private siblings
284 // of `from` (and similar). 276 // of `from` (and similar).
285 277
286 let def_map = db.crate_def_map(from.krate); 278 let def_map = from.def_map(db);
287 279
288 // Compute the initial worklist. We start with all direct child modules of `from` as well as all 280 // Compute the initial worklist. We start with all direct child modules of `from` as well as all
289 // of its (recursive) parent modules. 281 // of its (recursive) parent modules.
290 let data = &def_map[from.local_id]; 282 let data = &def_map[from.local_id];
291 let mut worklist = data 283 let mut worklist =
292 .children 284 data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>();
293 .values()
294 .map(|child| ModuleId { krate: from.krate, local_id: *child })
295 .collect::<Vec<_>>();
296 let mut parent = data.parent; 285 let mut parent = data.parent;
297 while let Some(p) = parent { 286 while let Some(p) = parent {
298 worklist.push(ModuleId { krate: from.krate, local_id: p }); 287 worklist.push(def_map.module_id(p));
299 parent = def_map[p].parent; 288 parent = def_map[p].parent;
300 } 289 }
301 290
@@ -312,7 +301,7 @@ fn find_local_import_locations(
312 &def_map[module.local_id] 301 &def_map[module.local_id]
313 } else { 302 } else {
314 // The crate might reexport a module defined in another crate. 303 // The crate might reexport a module defined in another crate.
315 ext_def_map = db.crate_def_map(module.krate); 304 ext_def_map = module.def_map(db);
316 &ext_def_map[module.local_id] 305 &ext_def_map[module.local_id]
317 }; 306 };
318 307
@@ -375,7 +364,7 @@ mod tests {
375 parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap(); 364 parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap();
376 let mod_path = ModPath::from_src(ast_path, &Hygiene::new_unhygienic()).unwrap(); 365 let mod_path = ModPath::from_src(ast_path, &Hygiene::new_unhygienic()).unwrap();
377 366
378 let crate_def_map = db.crate_def_map(module.krate); 367 let crate_def_map = module.def_map(&db);
379 let resolved = crate_def_map 368 let resolved = crate_def_map
380 .resolve_path( 369 .resolve_path(
381 &db, 370 &db,
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs
index 0251d016b..0a3dc7956 100644
--- a/crates/hir_def/src/import_map.rs
+++ b/crates/hir_def/src/import_map.rs
@@ -75,7 +75,7 @@ impl ImportMap {
75 75
76 // We look only into modules that are public(ly reexported), starting with the crate root. 76 // We look only into modules that are public(ly reexported), starting with the crate root.
77 let empty = ImportPath { segments: vec![] }; 77 let empty = ImportPath { segments: vec![] };
78 let root = ModuleId { krate, local_id: def_map.root() }; 78 let root = def_map.module_id(def_map.root());
79 let mut worklist = vec![(root, empty)]; 79 let mut worklist = vec![(root, empty)];
80 while let Some((module, mod_path)) = worklist.pop() { 80 while let Some((module, mod_path)) = worklist.pop() {
81 let ext_def_map; 81 let ext_def_map;
@@ -83,7 +83,7 @@ impl ImportMap {
83 &def_map[module.local_id] 83 &def_map[module.local_id]
84 } else { 84 } else {
85 // The crate might reexport a module defined in another crate. 85 // The crate might reexport a module defined in another crate.
86 ext_def_map = db.crate_def_map(module.krate); 86 ext_def_map = module.def_map(db);
87 &ext_def_map[module.local_id] 87 &ext_def_map[module.local_id]
88 }; 88 };
89 89
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index b8d7608e7..1e5c94660 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -66,7 +66,7 @@ impl GenericParamsId {
66} 66}
67 67
68/// The item tree of a source file. 68/// The item tree of a source file.
69#[derive(Debug, Eq, PartialEq)] 69#[derive(Debug, Default, Eq, PartialEq)]
70pub struct ItemTree { 70pub struct ItemTree {
71 _c: Count<Self>, 71 _c: Count<Self>,
72 72
@@ -82,7 +82,7 @@ impl ItemTree {
82 let syntax = if let Some(node) = db.parse_or_expand(file_id) { 82 let syntax = if let Some(node) = db.parse_or_expand(file_id) {
83 node 83 node
84 } else { 84 } else {
85 return Arc::new(Self::empty()); 85 return Default::default();
86 }; 86 };
87 87
88 let hygiene = Hygiene::new(db.upcast(), file_id); 88 let hygiene = Hygiene::new(db.upcast(), file_id);
@@ -118,15 +118,6 @@ impl ItemTree {
118 Arc::new(item_tree) 118 Arc::new(item_tree)
119 } 119 }
120 120
121 fn empty() -> Self {
122 Self {
123 _c: Count::new(),
124 top_level: Default::default(),
125 attrs: Default::default(),
126 data: Default::default(),
127 }
128 }
129
130 fn shrink_to_fit(&mut self) { 121 fn shrink_to_fit(&mut self) {
131 if let Some(data) = &mut self.data { 122 if let Some(data) = &mut self.data {
132 let ItemTreeData { 123 let ItemTreeData {
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index ce470fc3b..8a71376b9 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -43,7 +43,7 @@ pub(super) struct Ctx {
43impl Ctx { 43impl Ctx {
44 pub(super) fn new(db: &dyn DefDatabase, hygiene: Hygiene, file: HirFileId) -> Self { 44 pub(super) fn new(db: &dyn DefDatabase, hygiene: Hygiene, file: HirFileId) -> Self {
45 Self { 45 Self {
46 tree: ItemTree::empty(), 46 tree: ItemTree::default(),
47 hygiene, 47 hygiene,
48 file, 48 file,
49 source_ast_id_map: db.ast_id_map(file), 49 source_ast_id_map: db.ast_id_map(file),
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index 08ed920c6..42b50b5b7 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -50,7 +50,10 @@ pub mod import_map;
50#[cfg(test)] 50#[cfg(test)]
51mod test_db; 51mod test_db;
52 52
53use std::hash::{Hash, Hasher}; 53use std::{
54 hash::{Hash, Hasher},
55 sync::Arc,
56};
54 57
55use base_db::{impl_intern_key, salsa, CrateId}; 58use base_db::{impl_intern_key, salsa, CrateId};
56use hir_expand::{ 59use hir_expand::{
@@ -58,6 +61,7 @@ use hir_expand::{
58 MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 61 MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
59}; 62};
60use la_arena::Idx; 63use la_arena::Idx;
64use nameres::DefMap;
61use syntax::ast; 65use syntax::ast;
62 66
63use crate::builtin_type::BuiltinType; 67use crate::builtin_type::BuiltinType;
@@ -69,10 +73,24 @@ use stdx::impl_from;
69 73
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 74#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
71pub struct ModuleId { 75pub struct ModuleId {
72 pub krate: CrateId, 76 krate: CrateId,
77 block: Option<BlockId>,
73 pub local_id: LocalModuleId, 78 pub local_id: LocalModuleId,
74} 79}
75 80
81impl ModuleId {
82 pub fn def_map(&self, db: &dyn db::DefDatabase) -> Arc<DefMap> {
83 match self.block {
84 Some(block) => db.block_def_map(block),
85 None => db.crate_def_map(self.krate),
86 }
87 }
88
89 pub fn krate(&self) -> CrateId {
90 self.krate
91 }
92}
93
76/// An ID of a module, **local** to a specific crate 94/// An ID of a module, **local** to a specific crate
77pub type LocalModuleId = Idx<nameres::ModuleData>; 95pub type LocalModuleId = Idx<nameres::ModuleData>;
78 96
@@ -216,6 +234,15 @@ pub struct ImplId(salsa::InternId);
216type ImplLoc = ItemLoc<Impl>; 234type ImplLoc = ItemLoc<Impl>;
217impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); 235impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl);
218 236
237#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
238pub struct BlockId(salsa::InternId);
239#[derive(Debug, Hash, PartialEq, Eq, Clone)]
240pub struct BlockLoc {
241 ast_id: AstId<ast::BlockExpr>,
242 module: ModuleId,
243}
244impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block);
245
219#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 246#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
220pub struct TypeParamId { 247pub struct TypeParamId {
221 pub parent: GenericDefId, 248 pub parent: GenericDefId,
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index bd3ea9b8b..199771e9a 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -62,7 +62,7 @@ use la_arena::Arena;
62use profile::Count; 62use profile::Count;
63use rustc_hash::FxHashMap; 63use rustc_hash::FxHashMap;
64use stdx::format_to; 64use stdx::format_to;
65use syntax::{ast, AstNode}; 65use syntax::ast;
66 66
67use crate::{ 67use crate::{
68 db::DefDatabase, 68 db::DefDatabase,
@@ -70,14 +70,14 @@ use crate::{
70 nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, 70 nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
71 path::ModPath, 71 path::ModPath,
72 per_ns::PerNs, 72 per_ns::PerNs,
73 AstId, LocalModuleId, ModuleDefId, ModuleId, 73 AstId, BlockId, BlockLoc, LocalModuleId, ModuleDefId, ModuleId,
74}; 74};
75 75
76/// Contains all top-level defs from a macro-expanded crate 76/// Contains all top-level defs from a macro-expanded crate
77#[derive(Debug, PartialEq, Eq)] 77#[derive(Debug, PartialEq, Eq)]
78pub struct DefMap { 78pub struct DefMap {
79 _c: Count<Self>, 79 _c: Count<Self>,
80 parent: Option<Arc<DefMap>>, 80 block: Option<BlockInfo>,
81 root: LocalModuleId, 81 root: LocalModuleId,
82 modules: Arena<ModuleData>, 82 modules: Arena<ModuleData>,
83 krate: CrateId, 83 krate: CrateId,
@@ -91,6 +91,13 @@ pub struct DefMap {
91 diagnostics: Vec<DefDiagnostic>, 91 diagnostics: Vec<DefDiagnostic>,
92} 92}
93 93
94#[derive(Debug, PartialEq, Eq)]
95struct BlockInfo {
96 block: BlockId,
97 parent: Arc<DefMap>,
98 parent_module: LocalModuleId,
99}
100
94impl std::ops::Index<LocalModuleId> for DefMap { 101impl std::ops::Index<LocalModuleId> for DefMap {
95 type Output = ModuleData; 102 type Output = ModuleData;
96 fn index(&self, id: LocalModuleId) -> &ModuleData { 103 fn index(&self, id: LocalModuleId) -> &ModuleData {
@@ -190,15 +197,12 @@ impl DefMap {
190 Arc::new(def_map) 197 Arc::new(def_map)
191 } 198 }
192 199
193 pub(crate) fn block_def_map_query( 200 pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> {
194 db: &dyn DefDatabase, 201 let block: BlockLoc = db.lookup_intern_block(block_id);
195 krate: CrateId, 202 let item_tree = db.item_tree(block.ast_id.file_id);
196 block: AstId<ast::BlockExpr>, 203 let block_items = item_tree.inner_items_of_block(block.ast_id.value);
197 ) -> Arc<DefMap> {
198 let item_tree = db.item_tree(block.file_id);
199 let block_items = item_tree.inner_items_of_block(block.value);
200 204
201 let parent = parent_def_map(db, krate, block); 205 let parent = block.module.def_map(db);
202 206
203 if block_items.is_empty() { 207 if block_items.is_empty() {
204 // If there are no inner items, nothing new is brought into scope, so we can just return 208 // If there are no inner items, nothing new is brought into scope, so we can just return
@@ -206,10 +210,13 @@ impl DefMap {
206 return parent; 210 return parent;
207 } 211 }
208 212
209 let mut def_map = DefMap::empty(krate, parent.edition); 213 let block_info =
210 def_map.parent = Some(parent); 214 BlockInfo { block: block_id, parent, parent_module: block.module.local_id };
215
216 let mut def_map = DefMap::empty(block.module.krate, block_info.parent.edition);
217 def_map.block = Some(block_info);
211 218
212 let def_map = collector::collect_defs(db, def_map, Some(block.value)); 219 let def_map = collector::collect_defs(db, def_map, Some(block.ast_id.value));
213 Arc::new(def_map) 220 Arc::new(def_map)
214 } 221 }
215 222
@@ -218,7 +225,7 @@ impl DefMap {
218 let root = modules.alloc(ModuleData::default()); 225 let root = modules.alloc(ModuleData::default());
219 DefMap { 226 DefMap {
220 _c: Count::new(), 227 _c: Count::new(),
221 parent: None, 228 block: None,
222 krate, 229 krate,
223 edition, 230 edition,
224 extern_prelude: FxHashMap::default(), 231 extern_prelude: FxHashMap::default(),
@@ -265,6 +272,11 @@ impl DefMap {
265 self.extern_prelude.iter() 272 self.extern_prelude.iter()
266 } 273 }
267 274
275 pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId {
276 let block = self.block.as_ref().map(|b| b.block);
277 ModuleId { krate: self.krate, local_id, block }
278 }
279
268 pub(crate) fn resolve_path( 280 pub(crate) fn resolve_path(
269 &self, 281 &self,
270 db: &dyn DefDatabase, 282 db: &dyn DefDatabase,
@@ -282,9 +294,9 @@ impl DefMap {
282 pub fn dump(&self) -> String { 294 pub fn dump(&self) -> String {
283 let mut buf = String::new(); 295 let mut buf = String::new();
284 let mut current_map = self; 296 let mut current_map = self;
285 while let Some(parent) = &current_map.parent { 297 while let Some(block) = &current_map.block {
286 go(&mut buf, current_map, "block scope", current_map.root); 298 go(&mut buf, current_map, "block scope", current_map.root);
287 current_map = &**parent; 299 current_map = &*block.parent;
288 } 300 }
289 go(&mut buf, current_map, "crate", current_map.root); 301 go(&mut buf, current_map, "crate", current_map.root);
290 return buf; 302 return buf;
@@ -338,35 +350,6 @@ impl ModuleData {
338 } 350 }
339} 351}
340 352
341fn parent_def_map(
342 db: &dyn DefDatabase,
343 krate: CrateId,
344 block: AstId<ast::BlockExpr>,
345) -> Arc<DefMap> {
346 // FIXME: store this info in the item tree instead of reparsing here
347 let ast_id_map = db.ast_id_map(block.file_id);
348 let block_ptr = ast_id_map.get(block.value);
349 let root = match db.parse_or_expand(block.file_id) {
350 Some(it) => it,
351 None => {
352 return Arc::new(DefMap::empty(krate, Edition::Edition2018));
353 }
354 };
355 let ast = block_ptr.to_node(&root);
356
357 for ancestor in ast.syntax().ancestors().skip(1) {
358 if let Some(block_expr) = ast::BlockExpr::cast(ancestor) {
359 let ancestor_id = ast_id_map.ast_id(&block_expr);
360 let ast_id = InFile::new(block.file_id, ancestor_id);
361 let parent_map = db.block_def_map(krate, ast_id);
362 return parent_map;
363 }
364 }
365
366 // No enclosing block scope, so the parent is the crate-level DefMap.
367 db.crate_def_map(krate)
368}
369
370#[derive(Debug, Clone, PartialEq, Eq)] 353#[derive(Debug, Clone, PartialEq, Eq)]
371pub enum ModuleSource { 354pub enum ModuleSource {
372 SourceFile(ast::SourceFile), 355 SourceFile(ast::SourceFile),
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index cd68efbe6..393170b32 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -37,8 +37,8 @@ use crate::{
37 per_ns::PerNs, 37 per_ns::PerNs,
38 visibility::{RawVisibility, Visibility}, 38 visibility::{RawVisibility, Visibility},
39 AdtId, AsMacroCall, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, 39 AdtId, AsMacroCall, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId,
40 FunctionLoc, ImplLoc, Intern, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, 40 FunctionLoc, ImplLoc, Intern, LocalModuleId, ModuleDefId, StaticLoc, StructLoc, TraitLoc,
41 TraitLoc, TypeAliasLoc, UnionLoc, 41 TypeAliasLoc, UnionLoc,
42}; 42};
43 43
44const GLOB_RECURSION_LIMIT: usize = 100; 44const GLOB_RECURSION_LIMIT: usize = 100;
@@ -56,10 +56,9 @@ pub(super) fn collect_defs(
56 for dep in &crate_graph[def_map.krate].dependencies { 56 for dep in &crate_graph[def_map.krate].dependencies {
57 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); 57 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
58 let dep_def_map = db.crate_def_map(dep.crate_id); 58 let dep_def_map = db.crate_def_map(dep.crate_id);
59 def_map.extern_prelude.insert( 59 def_map
60 dep.as_name(), 60 .extern_prelude
61 ModuleId { krate: dep.crate_id, local_id: dep_def_map.root }.into(), 61 .insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into());
62 );
63 62
64 // look for the prelude 63 // look for the prelude
65 // If the dependency defines a prelude, we overwrite an already defined 64 // If the dependency defines a prelude, we overwrite an already defined
@@ -332,11 +331,9 @@ impl DefCollector<'_> {
332 // exported in type/value namespace. This function reduces the visibility of all items 331 // exported in type/value namespace. This function reduces the visibility of all items
333 // in the crate root that aren't proc macros. 332 // in the crate root that aren't proc macros.
334 let root = self.def_map.root; 333 let root = self.def_map.root;
334 let module_id = self.def_map.module_id(root);
335 let root = &mut self.def_map.modules[root]; 335 let root = &mut self.def_map.modules[root];
336 root.scope.censor_non_proc_macros(ModuleId { 336 root.scope.censor_non_proc_macros(module_id);
337 krate: self.def_map.krate,
338 local_id: self.def_map.root,
339 });
340 } 337 }
341 } 338 }
342 339
@@ -578,7 +575,7 @@ impl DefCollector<'_> {
578 } else if m.krate != self.def_map.krate { 575 } else if m.krate != self.def_map.krate {
579 mark::hit!(glob_across_crates); 576 mark::hit!(glob_across_crates);
580 // glob import from other crate => we can just import everything once 577 // glob import from other crate => we can just import everything once
581 let item_map = self.db.crate_def_map(m.krate); 578 let item_map = m.def_map(self.db);
582 let scope = &item_map[m.local_id].scope; 579 let scope = &item_map[m.local_id].scope;
583 580
584 // Module scoped macros is included 581 // Module scoped macros is included
@@ -1029,8 +1026,7 @@ impl ModCollector<'_, '_> {
1029 continue; 1026 continue;
1030 } 1027 }
1031 } 1028 }
1032 let module = 1029 let module = self.def_collector.def_map.module_id(self.module_id);
1033 ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id };
1034 let container = ContainerId::ModuleId(module); 1030 let container = ContainerId::ModuleId(module);
1035 1031
1036 let mut def = None; 1032 let mut def = None;
@@ -1097,10 +1093,7 @@ impl ModCollector<'_, '_> {
1097 } 1093 }
1098 } 1094 }
1099 ModItem::Impl(imp) => { 1095 ModItem::Impl(imp) => {
1100 let module = ModuleId { 1096 let module = self.def_collector.def_map.module_id(self.module_id);
1101 krate: self.def_collector.def_map.krate,
1102 local_id: self.module_id,
1103 };
1104 let container = ContainerId::ModuleId(module); 1097 let container = ContainerId::ModuleId(module);
1105 let impl_id = ImplLoc { container, id: ItemTreeId::new(self.file_id, imp) } 1098 let impl_id = ImplLoc { container, id: ItemTreeId::new(self.file_id, imp) }
1106 .intern(self.def_collector.db); 1099 .intern(self.def_collector.db);
@@ -1343,7 +1336,7 @@ impl ModCollector<'_, '_> {
1343 modules[res].scope.define_legacy_macro(name, mac) 1336 modules[res].scope.define_legacy_macro(name, mac)
1344 } 1337 }
1345 modules[self.module_id].children.insert(name.clone(), res); 1338 modules[self.module_id].children.insert(name.clone(), res);
1346 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; 1339 let module = self.def_collector.def_map.module_id(res);
1347 let def: ModuleDefId = module.into(); 1340 let def: ModuleDefId = module.into();
1348 self.def_collector.def_map.modules[self.module_id].scope.define_def(def); 1341 self.def_collector.def_map.modules[self.module_id].scope.define_def(def);
1349 self.def_collector.update( 1342 self.def_collector.update(
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index ec90f4e65..419e465ed 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -10,9 +10,8 @@
10//! 10//!
11//! `ReachedFixedPoint` signals about this. 11//! `ReachedFixedPoint` signals about this.
12 12
13use std::iter::successors;
14
15use base_db::Edition; 13use base_db::Edition;
14use hir_expand::name;
16use hir_expand::name::Name; 15use hir_expand::name::Name;
17use test_utils::mark; 16use test_utils::mark;
18 17
@@ -23,7 +22,7 @@ use crate::{
23 path::{ModPath, PathKind}, 22 path::{ModPath, PathKind},
24 per_ns::PerNs, 23 per_ns::PerNs,
25 visibility::{RawVisibility, Visibility}, 24 visibility::{RawVisibility, Visibility},
26 AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, 25 AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId,
27}; 26};
28 27
29#[derive(Debug, Clone, Copy, PartialEq, Eq)] 28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -63,6 +62,10 @@ impl ResolvePathResult {
63 62
64impl DefMap { 63impl DefMap {
65 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { 64 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs {
65 if name == &name!(self) {
66 mark::hit!(extern_crate_self_as);
67 return PerNs::types(self.module_id(self.root).into(), Visibility::Public);
68 }
66 self.extern_prelude 69 self.extern_prelude
67 .get(name) 70 .get(name)
68 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)) 71 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public))
@@ -126,8 +129,8 @@ impl DefMap {
126 result.krate = result.krate.or(new.krate); 129 result.krate = result.krate.or(new.krate);
127 result.segment_index = result.segment_index.min(new.segment_index); 130 result.segment_index = result.segment_index.min(new.segment_index);
128 131
129 match &current_map.parent { 132 match &current_map.block {
130 Some(map) => current_map = map, 133 Some(block) => current_map = &block.parent,
131 None => return result, 134 None => return result,
132 } 135 }
133 } 136 }
@@ -146,21 +149,15 @@ impl DefMap {
146 PathKind::DollarCrate(krate) => { 149 PathKind::DollarCrate(krate) => {
147 if krate == self.krate { 150 if krate == self.krate {
148 mark::hit!(macro_dollar_crate_self); 151 mark::hit!(macro_dollar_crate_self);
149 PerNs::types( 152 PerNs::types(self.module_id(self.root).into(), Visibility::Public)
150 ModuleId { krate: self.krate, local_id: self.root }.into(),
151 Visibility::Public,
152 )
153 } else { 153 } else {
154 let def_map = db.crate_def_map(krate); 154 let def_map = db.crate_def_map(krate);
155 let module = ModuleId { krate, local_id: def_map.root }; 155 let module = def_map.module_id(def_map.root);
156 mark::hit!(macro_dollar_crate_other); 156 mark::hit!(macro_dollar_crate_other);
157 PerNs::types(module.into(), Visibility::Public) 157 PerNs::types(module.into(), Visibility::Public)
158 } 158 }
159 } 159 }
160 PathKind::Crate => PerNs::types( 160 PathKind::Crate => PerNs::types(self.module_id(self.root).into(), Visibility::Public),
161 ModuleId { krate: self.krate, local_id: self.root }.into(),
162 Visibility::Public,
163 ),
164 // plain import or absolute path in 2015: crate-relative with 161 // plain import or absolute path in 2015: crate-relative with
165 // fallback to extern prelude (with the simplification in 162 // fallback to extern prelude (with the simplification in
166 // rust-lang/rust#57745) 163 // rust-lang/rust#57745)
@@ -194,17 +191,35 @@ impl DefMap {
194 self.resolve_name_in_module(db, original_module, &segment, prefer_module) 191 self.resolve_name_in_module(db, original_module, &segment, prefer_module)
195 } 192 }
196 PathKind::Super(lvl) => { 193 PathKind::Super(lvl) => {
197 let m = successors(Some(original_module), |m| self.modules[*m].parent) 194 let mut module = original_module;
198 .nth(lvl as usize); 195 for i in 0..lvl {
199 if let Some(local_id) = m { 196 match self.modules[module].parent {
200 PerNs::types( 197 Some(it) => module = it,
201 ModuleId { krate: self.krate, local_id }.into(), 198 None => match &self.block {
202 Visibility::Public, 199 Some(block) => {
203 ) 200 // Look up remaining path in parent `DefMap`
204 } else { 201 let new_path = ModPath {
205 log::debug!("super path in root module"); 202 kind: PathKind::Super(lvl - i),
206 return ResolvePathResult::empty(ReachedFixedPoint::Yes); 203 segments: path.segments.clone(),
204 };
205 log::debug!("`super` path: {} -> {} in parent map", path, new_path);
206 return block.parent.resolve_path_fp_with_macro(
207 db,
208 mode,
209 block.parent_module,
210 &new_path,
211 shadow,
212 );
213 }
214 None => {
215 log::debug!("super path in root module");
216 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
217 }
218 },
219 }
207 } 220 }
221
222 PerNs::types(self.module_id(module).into(), Visibility::Public)
208 } 223 }
209 PathKind::Abs => { 224 PathKind::Abs => {
210 // 2018-style absolute path -- only extern prelude 225 // 2018-style absolute path -- only extern prelude
@@ -243,7 +258,7 @@ impl DefMap {
243 kind: PathKind::Super(0), 258 kind: PathKind::Super(0),
244 }; 259 };
245 log::debug!("resolving {:?} in other crate", path); 260 log::debug!("resolving {:?} in other crate", path);
246 let defp_map = db.crate_def_map(module.krate); 261 let defp_map = module.def_map(db);
247 let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow); 262 let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow);
248 return ResolvePathResult::with( 263 return ResolvePathResult::with(
249 def, 264 def,
@@ -356,7 +371,7 @@ impl DefMap {
356 self 371 self
357 } else { 372 } else {
358 // Extend lifetime 373 // Extend lifetime
359 keep = db.crate_def_map(prelude.krate); 374 keep = prelude.def_map(db);
360 &keep 375 &keep
361 }; 376 };
362 def_map[prelude.local_id].scope.get(name) 377 def_map[prelude.local_id].scope.get(name)
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs
index 73e3a4702..b36d0b59b 100644
--- a/crates/hir_def/src/nameres/tests.rs
+++ b/crates/hir_def/src/nameres/tests.rs
@@ -8,12 +8,12 @@ mod block;
8 8
9use std::sync::Arc; 9use std::sync::Arc;
10 10
11use base_db::{fixture::WithFixture, SourceDatabase}; 11use base_db::{fixture::WithFixture, FilePosition, SourceDatabase};
12use expect_test::{expect, Expect}; 12use expect_test::{expect, Expect};
13use hir_expand::db::AstDatabase; 13use syntax::AstNode;
14use test_utils::mark; 14use test_utils::mark;
15 15
16use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; 16use crate::{db::DefDatabase, nameres::*, test_db::TestDB, Lookup};
17 17
18fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { 18fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> {
19 let db = TestDB::with_files(ra_fixture); 19 let db = TestDB::with_files(ra_fixture);
@@ -23,14 +23,58 @@ fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> {
23 23
24fn compute_block_def_map(ra_fixture: &str) -> Arc<DefMap> { 24fn compute_block_def_map(ra_fixture: &str) -> Arc<DefMap> {
25 let (db, position) = TestDB::with_position(ra_fixture); 25 let (db, position) = TestDB::with_position(ra_fixture);
26
27 // FIXME: perhaps we should make this use body lowering tests instead?
28
26 let module = db.module_for_file(position.file_id); 29 let module = db.module_for_file(position.file_id);
27 let ast_map = db.ast_id_map(position.file_id.into()); 30 let mut def_map = db.crate_def_map(module.krate);
28 let ast = db.parse(position.file_id); 31 while let Some(new_def_map) = descend_def_map_at_position(&db, position, def_map.clone()) {
29 let block: ast::BlockExpr = 32 def_map = new_def_map;
30 syntax::algo::find_node_at_offset(&ast.syntax_node(), position.offset).unwrap(); 33 }
31 let block_id = ast_map.ast_id(&block); 34
35 // FIXME: select the right module, not the root
36
37 def_map
38}
39
40fn descend_def_map_at_position(
41 db: &dyn DefDatabase,
42 position: FilePosition,
43 def_map: Arc<DefMap>,
44) -> Option<Arc<DefMap>> {
45 for (local_id, module_data) in def_map.modules() {
46 let mod_def = module_data.origin.definition_source(db);
47 let ast_map = db.ast_id_map(mod_def.file_id);
48 let item_tree = db.item_tree(mod_def.file_id);
49 let root = db.parse_or_expand(mod_def.file_id).unwrap();
50 for item in module_data.scope.declarations() {
51 match item {
52 ModuleDefId::FunctionId(it) => {
53 // Technically blocks can be inside any type (due to arrays and const generics),
54 // and also in const/static initializers. For tests we only really care about
55 // functions though.
56
57 let ast = ast_map.get(item_tree[it.lookup(db).id.value].ast_id).to_node(&root);
58
59 if ast.syntax().text_range().contains(position.offset) {
60 // Cursor inside function, descend into its body's DefMap.
61 // Note that we don't handle block *expressions* inside function bodies.
62 let ast_map = db.ast_id_map(position.file_id.into());
63 let ast_id = ast_map.ast_id(&ast.body().unwrap());
64 let block = BlockLoc {
65 ast_id: InFile::new(position.file_id.into(), ast_id),
66 module: def_map.module_id(local_id),
67 };
68 let block_id = db.intern_block(block);
69 return Some(db.block_def_map(block_id));
70 }
71 }
72 _ => continue,
73 }
74 }
75 }
32 76
33 db.block_def_map(module.krate, InFile::new(position.file_id.into(), block_id)) 77 None
34} 78}
35 79
36fn check(ra_fixture: &str, expect: Expect) { 80fn check(ra_fixture: &str, expect: Expect) {
diff --git a/crates/hir_def/src/nameres/tests/block.rs b/crates/hir_def/src/nameres/tests/block.rs
index 01d6326a7..470ca593e 100644
--- a/crates/hir_def/src/nameres/tests/block.rs
+++ b/crates/hir_def/src/nameres/tests/block.rs
@@ -95,3 +95,29 @@ fn outer() {
95 "#]], 95 "#]],
96 ); 96 );
97} 97}
98
99#[test]
100fn super_imports() {
101 check_at(
102 r#"
103mod module {
104 fn f() {
105 use super::Struct;
106 $0
107 }
108}
109
110struct Struct {}
111"#,
112 expect![[r#"
113 block scope
114 Struct: t
115 crate
116 Struct: t
117 module: t
118
119 crate::module
120 f: v
121 "#]],
122 );
123}
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index 58d69d3c6..e8e72e5ef 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -62,6 +62,22 @@ fn unresolved_extern_crate() {
62} 62}
63 63
64#[test] 64#[test]
65fn extern_crate_self_as() {
66 mark::check!(extern_crate_self_as);
67 check_diagnostics(
68 r"
69 //- /lib.rs
70 extern crate doesnotexist;
71 //^^^^^^^^^^^^^^^^^^^^^^^^^^ unresolved extern crate
72 // Should not error.
73 extern crate self as foo;
74 struct Foo;
75 use foo::Foo as Bar;
76 ",
77 );
78}
79
80#[test]
65fn dedup_unresolved_import_from_unresolved_crate() { 81fn dedup_unresolved_import_from_unresolved_crate() {
66 check_diagnostics( 82 check_diagnostics(
67 r" 83 r"
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index e34cd7f2f..84ea09b53 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -304,6 +304,7 @@ pub use hir_expand::name as __name;
304#[macro_export] 304#[macro_export]
305macro_rules! __known_path { 305macro_rules! __known_path {
306 (core::iter::IntoIterator) => {}; 306 (core::iter::IntoIterator) => {};
307 (core::iter::Iterator) => {};
307 (core::result::Result) => {}; 308 (core::result::Result) => {};
308 (core::option::Option) => {}; 309 (core::option::Option) => {};
309 (core::ops::Range) => {}; 310 (core::ops::Range) => {};
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index b2f577649..9021ea712 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -430,7 +430,7 @@ impl Resolver {
430 for scope in &self.scopes { 430 for scope in &self.scopes {
431 if let Scope::ModuleScope(m) = scope { 431 if let Scope::ModuleScope(m) = scope {
432 if let Some(prelude) = m.crate_def_map.prelude() { 432 if let Some(prelude) = m.crate_def_map.prelude() {
433 let prelude_def_map = db.crate_def_map(prelude.krate); 433 let prelude_def_map = prelude.def_map(db);
434 traits.extend(prelude_def_map[prelude.local_id].scope.traits()); 434 traits.extend(prelude_def_map[prelude.local_id].scope.traits());
435 } 435 }
436 traits.extend(m.crate_def_map[m.module_id].scope.traits()); 436 traits.extend(m.crate_def_map[m.module_id].scope.traits());
@@ -459,7 +459,7 @@ impl Resolver {
459 459
460 pub fn module(&self) -> Option<ModuleId> { 460 pub fn module(&self) -> Option<ModuleId> {
461 let (def_map, local_id) = self.module_scope()?; 461 let (def_map, local_id) = self.module_scope()?;
462 Some(ModuleId { krate: def_map.krate(), local_id }) 462 Some(def_map.module_id(local_id))
463 } 463 }
464 464
465 pub fn krate(&self) -> Option<CrateId> { 465 pub fn krate(&self) -> Option<CrateId> {
@@ -529,7 +529,7 @@ impl Scope {
529 f(name.clone(), ScopeDef::PerNs(def)); 529 f(name.clone(), ScopeDef::PerNs(def));
530 }); 530 });
531 if let Some(prelude) = m.crate_def_map.prelude() { 531 if let Some(prelude) = m.crate_def_map.prelude() {
532 let prelude_def_map = db.crate_def_map(prelude.krate); 532 let prelude_def_map = prelude.def_map(db);
533 prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| { 533 prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| {
534 let seen_tuple = (name.clone(), def); 534 let seen_tuple = (name.clone(), def);
535 if !seen.contains(&seen_tuple) { 535 if !seen.contains(&seen_tuple) {
@@ -633,7 +633,7 @@ pub trait HasResolver: Copy {
633 633
634impl HasResolver for ModuleId { 634impl HasResolver for ModuleId {
635 fn resolver(self, db: &dyn DefDatabase) -> Resolver { 635 fn resolver(self, db: &dyn DefDatabase) -> Resolver {
636 let def_map = db.crate_def_map(self.krate); 636 let def_map = self.def_map(db);
637 Resolver::default().push_module_scope(def_map, self.local_id) 637 Resolver::default().push_module_scope(def_map, self.local_id)
638 } 638 }
639} 639}
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs
index 4ff219fb7..c4e36eda5 100644
--- a/crates/hir_def/src/test_db.rs
+++ b/crates/hir_def/src/test_db.rs
@@ -15,7 +15,7 @@ use rustc_hash::FxHashSet;
15use syntax::{TextRange, TextSize}; 15use syntax::{TextRange, TextSize};
16use test_utils::extract_annotations; 16use test_utils::extract_annotations;
17 17
18use crate::{db::DefDatabase, ModuleDefId}; 18use crate::{db::DefDatabase, ModuleDefId, ModuleId};
19 19
20#[salsa::database( 20#[salsa::database(
21 base_db::SourceDatabaseExtStorage, 21 base_db::SourceDatabaseExtStorage,
@@ -72,12 +72,12 @@ impl FileLoader for TestDB {
72} 72}
73 73
74impl TestDB { 74impl TestDB {
75 pub(crate) fn module_for_file(&self, file_id: FileId) -> crate::ModuleId { 75 pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId {
76 for &krate in self.relevant_crates(file_id).iter() { 76 for &krate in self.relevant_crates(file_id).iter() {
77 let crate_def_map = self.crate_def_map(krate); 77 let crate_def_map = self.crate_def_map(krate);
78 for (local_id, data) in crate_def_map.modules() { 78 for (local_id, data) in crate_def_map.modules() {
79 if data.origin.file_id() == Some(file_id) { 79 if data.origin.file_id() == Some(file_id) {
80 return crate::ModuleId { krate, local_id }; 80 return crate_def_map.module_id(local_id);
81 } 81 }
82 } 82 }
83 } 83 }
diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs
index 3134fa43d..e79a91102 100644
--- a/crates/hir_def/src/visibility.rs
+++ b/crates/hir_def/src/visibility.rs
@@ -103,7 +103,7 @@ impl Visibility {
103 if from_module.krate != to_module.krate { 103 if from_module.krate != to_module.krate {
104 return false; 104 return false;
105 } 105 }
106 let def_map = db.crate_def_map(from_module.krate); 106 let def_map = from_module.def_map(db);
107 self.is_visible_from_def_map(&def_map, from_module.local_id) 107 self.is_visible_from_def_map(&def_map, from_module.local_id)
108 } 108 }
109 109
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 80b60d59f..57bc6fbd7 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -327,17 +327,14 @@ fn concat_expand(
327 // concat works with string and char literals, so remove any quotes. 327 // concat works with string and char literals, so remove any quotes.
328 // It also works with integer, float and boolean literals, so just use the rest 328 // It also works with integer, float and boolean literals, so just use the rest
329 // as-is. 329 // as-is.
330 330 let component = unquote_str(&it).unwrap_or_else(|| it.text.to_string());
331 text += it 331 text.push_str(&component);
332 .text 332 }
333 .trim_start_matches(|c| match c { 333 // handle boolean literals
334 'r' | '#' | '\'' | '"' => true, 334 tt::TokenTree::Leaf(tt::Leaf::Ident(id))
335 _ => false, 335 if i % 2 == 0 && (id.text == "true" || id.text == "false") =>
336 }) 336 {
337 .trim_end_matches(|c| match c { 337 text.push_str(id.text.as_str());
338 '#' | '\'' | '"' => true,
339 _ => false,
340 });
341 } 338 }
342 tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (), 339 tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
343 _ => { 340 _ => {
@@ -345,7 +342,6 @@ fn concat_expand(
345 } 342 }
346 } 343 }
347 } 344 }
348
349 ExpandResult { value: Some((quote!(#text), FragmentKind::Expr)), err } 345 ExpandResult { value: Some((quote!(#text), FragmentKind::Expr)), err }
350} 346}
351 347
@@ -745,12 +741,10 @@ mod tests {
745 r##" 741 r##"
746 #[rustc_builtin_macro] 742 #[rustc_builtin_macro]
747 macro_rules! concat {} 743 macro_rules! concat {}
748 concat!("foo", 0, r#"bar"#); 744 concat!("foo", "r", 0, r#"bar"#, false);
749 "##, 745 "##,
750 ); 746 );
751 747
752 assert_eq!(expanded, r#""foo0bar""#); 748 assert_eq!(expanded, r#""foor0barfalse""#);
753
754 // FIXME: `true`/`false` literals don't work.
755 } 749 }
756} 750}
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs
index d692cec14..c7609e90d 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -186,6 +186,9 @@ pub mod known {
186 Neg, 186 Neg,
187 Not, 187 Not,
188 Index, 188 Index,
189 // Components of known path (function name)
190 filter_map,
191 next,
189 // Builtin macros 192 // Builtin macros
190 file, 193 file,
191 column, 194 column,
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs
index 247da43f2..323c5f963 100644
--- a/crates/hir_ty/src/diagnostics.rs
+++ b/crates/hir_ty/src/diagnostics.rs
@@ -247,7 +247,7 @@ impl Diagnostic for RemoveThisSemicolon {
247 247
248// Diagnostic: break-outside-of-loop 248// Diagnostic: break-outside-of-loop
249// 249//
250// This diagnostic is triggered if `break` keyword is used outside of a loop. 250// This diagnostic is triggered if the `break` keyword is used outside of a loop.
251#[derive(Debug)] 251#[derive(Debug)]
252pub struct BreakOutsideOfLoop { 252pub struct BreakOutsideOfLoop {
253 pub file: HirFileId, 253 pub file: HirFileId,
@@ -271,7 +271,7 @@ impl Diagnostic for BreakOutsideOfLoop {
271 271
272// Diagnostic: missing-unsafe 272// Diagnostic: missing-unsafe
273// 273//
274// This diagnostic is triggered if operation marked as `unsafe` is used outside of `unsafe` function or block. 274// This diagnostic is triggered if an operation marked as `unsafe` is used outside of an `unsafe` function or block.
275#[derive(Debug)] 275#[derive(Debug)]
276pub struct MissingUnsafe { 276pub struct MissingUnsafe {
277 pub file: HirFileId, 277 pub file: HirFileId,
@@ -295,7 +295,7 @@ impl Diagnostic for MissingUnsafe {
295 295
296// Diagnostic: mismatched-arg-count 296// Diagnostic: mismatched-arg-count
297// 297//
298// This diagnostic is triggered if function is invoked with an incorrect amount of arguments. 298// This diagnostic is triggered if a function is invoked with an incorrect amount of arguments.
299#[derive(Debug)] 299#[derive(Debug)]
300pub struct MismatchedArgCount { 300pub struct MismatchedArgCount {
301 pub file: HirFileId, 301 pub file: HirFileId,
@@ -347,7 +347,7 @@ impl fmt::Display for CaseType {
347 347
348// Diagnostic: incorrect-ident-case 348// Diagnostic: incorrect-ident-case
349// 349//
350// This diagnostic is triggered if item name doesn't follow https://doc.rust-lang.org/1.0.0/style/style/naming/README.html[Rust naming convention]. 350// This diagnostic is triggered if an item name doesn't follow https://doc.rust-lang.org/1.0.0/style/style/naming/README.html[Rust naming convention].
351#[derive(Debug)] 351#[derive(Debug)]
352pub struct IncorrectCase { 352pub struct IncorrectCase {
353 pub file: HirFileId, 353 pub file: HirFileId,
@@ -386,6 +386,31 @@ impl Diagnostic for IncorrectCase {
386 } 386 }
387} 387}
388 388
389// Diagnostic: replace-filter-map-next-with-find-map
390//
391// This diagnostic is triggered when `.filter_map(..).next()` is used, rather than the more concise `.find_map(..)`.
392#[derive(Debug)]
393pub struct ReplaceFilterMapNextWithFindMap {
394 pub file: HirFileId,
395 /// This expression is the whole method chain up to and including `.filter_map(..).next()`.
396 pub next_expr: AstPtr<ast::Expr>,
397}
398
399impl Diagnostic for ReplaceFilterMapNextWithFindMap {
400 fn code(&self) -> DiagnosticCode {
401 DiagnosticCode("replace-filter-map-next-with-find-map")
402 }
403 fn message(&self) -> String {
404 "replace filter_map(..).next() with find_map(..)".to_string()
405 }
406 fn display_source(&self) -> InFile<SyntaxNodePtr> {
407 InFile { file_id: self.file, value: self.next_expr.clone().into() }
408 }
409 fn as_any(&self) -> &(dyn Any + Send + 'static) {
410 self
411 }
412}
413
389#[cfg(test)] 414#[cfg(test)]
390mod tests { 415mod tests {
391 use base_db::{fixture::WithFixture, FileId, SourceDatabase, SourceDatabaseExt}; 416 use base_db::{fixture::WithFixture, FileId, SourceDatabase, SourceDatabaseExt};
@@ -644,4 +669,87 @@ fn foo() { break; }
644 "#, 669 "#,
645 ); 670 );
646 } 671 }
672
673 // Register the required standard library types to make the tests work
674 fn add_filter_map_with_find_next_boilerplate(body: &str) -> String {
675 let prefix = r#"
676 //- /main.rs crate:main deps:core
677 use core::iter::Iterator;
678 use core::option::Option::{self, Some, None};
679 "#;
680 let suffix = r#"
681 //- /core/lib.rs crate:core
682 pub mod option {
683 pub enum Option<T> { Some(T), None }
684 }
685 pub mod iter {
686 pub trait Iterator {
687 type Item;
688 fn filter_map<B, F>(self, f: F) -> FilterMap where F: FnMut(Self::Item) -> Option<B> { FilterMap }
689 fn next(&mut self) -> Option<Self::Item>;
690 }
691 pub struct FilterMap {}
692 impl Iterator for FilterMap {
693 type Item = i32;
694 fn next(&mut self) -> i32 { 7 }
695 }
696 }
697 "#;
698 format!("{}{}{}", prefix, body, suffix)
699 }
700
701 #[test]
702 fn replace_filter_map_next_with_find_map2() {
703 check_diagnostics(&add_filter_map_with_find_next_boilerplate(
704 r#"
705 fn foo() {
706 let m = [1, 2, 3].iter().filter_map(|x| if *x == 2 { Some (4) } else { None }).next();
707 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ replace filter_map(..).next() with find_map(..)
708 }
709 "#,
710 ));
711 }
712
713 #[test]
714 fn replace_filter_map_next_with_find_map_no_diagnostic_without_next() {
715 check_diagnostics(&add_filter_map_with_find_next_boilerplate(
716 r#"
717 fn foo() {
718 let m = [1, 2, 3]
719 .iter()
720 .filter_map(|x| if *x == 2 { Some (4) } else { None })
721 .len();
722 }
723 "#,
724 ));
725 }
726
727 #[test]
728 fn replace_filter_map_next_with_find_map_no_diagnostic_with_intervening_methods() {
729 check_diagnostics(&add_filter_map_with_find_next_boilerplate(
730 r#"
731 fn foo() {
732 let m = [1, 2, 3]
733 .iter()
734 .filter_map(|x| if *x == 2 { Some (4) } else { None })
735 .map(|x| x + 2)
736 .len();
737 }
738 "#,
739 ));
740 }
741
742 #[test]
743 fn replace_filter_map_next_with_find_map_no_diagnostic_if_not_in_chain() {
744 check_diagnostics(&add_filter_map_with_find_next_boilerplate(
745 r#"
746 fn foo() {
747 let m = [1, 2, 3]
748 .iter()
749 .filter_map(|x| if *x == 2 { Some (4) } else { None });
750 let n = m.next();
751 }
752 "#,
753 ));
754 }
647} 755}
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index 107417c27..d740b7265 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -2,8 +2,10 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{expr::Statement, path::path, resolver::HasResolver, AdtId, DefWithBodyId}; 5use hir_def::{
6use hir_expand::diagnostics::DiagnosticSink; 6 expr::Statement, path::path, resolver::HasResolver, AdtId, AssocItemId, DefWithBodyId,
7};
8use hir_expand::{diagnostics::DiagnosticSink, name};
7use rustc_hash::FxHashSet; 9use rustc_hash::FxHashSet;
8use syntax::{ast, AstPtr}; 10use syntax::{ast, AstPtr};
9 11
@@ -24,6 +26,8 @@ pub(crate) use hir_def::{
24 LocalFieldId, VariantId, 26 LocalFieldId, VariantId,
25}; 27};
26 28
29use super::ReplaceFilterMapNextWithFindMap;
30
27pub(super) struct ExprValidator<'a, 'b: 'a> { 31pub(super) struct ExprValidator<'a, 'b: 'a> {
28 owner: DefWithBodyId, 32 owner: DefWithBodyId,
29 infer: Arc<InferenceResult>, 33 infer: Arc<InferenceResult>,
@@ -40,6 +44,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
40 } 44 }
41 45
42 pub(super) fn validate_body(&mut self, db: &dyn HirDatabase) { 46 pub(super) fn validate_body(&mut self, db: &dyn HirDatabase) {
47 self.check_for_filter_map_next(db);
48
43 let body = db.body(self.owner.into()); 49 let body = db.body(self.owner.into());
44 50
45 for (id, expr) in body.exprs.iter() { 51 for (id, expr) in body.exprs.iter() {
@@ -150,20 +156,76 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
150 } 156 }
151 } 157 }
152 158
153 fn validate_call(&mut self, db: &dyn HirDatabase, call_id: ExprId, expr: &Expr) -> Option<()> { 159 fn check_for_filter_map_next(&mut self, db: &dyn HirDatabase) {
160 // Find the FunctionIds for Iterator::filter_map and Iterator::next
161 let iterator_path = path![core::iter::Iterator];
162 let resolver = self.owner.resolver(db.upcast());
163 let iterator_trait_id = match resolver.resolve_known_trait(db.upcast(), &iterator_path) {
164 Some(id) => id,
165 None => return,
166 };
167 let iterator_trait_items = &db.trait_data(iterator_trait_id).items;
168 let filter_map_function_id =
169 match iterator_trait_items.iter().find(|item| item.0 == name![filter_map]) {
170 Some((_, AssocItemId::FunctionId(id))) => id,
171 _ => return,
172 };
173 let next_function_id = match iterator_trait_items.iter().find(|item| item.0 == name![next])
174 {
175 Some((_, AssocItemId::FunctionId(id))) => id,
176 _ => return,
177 };
178
179 // Search function body for instances of .filter_map(..).next()
180 let body = db.body(self.owner.into());
181 let mut prev = None;
182 for (id, expr) in body.exprs.iter() {
183 if let Expr::MethodCall { receiver, .. } = expr {
184 let function_id = match self.infer.method_resolution(id) {
185 Some(id) => id,
186 None => continue,
187 };
188
189 if function_id == *filter_map_function_id {
190 prev = Some(id);
191 continue;
192 }
193
194 if function_id == *next_function_id {
195 if let Some(filter_map_id) = prev {
196 if *receiver == filter_map_id {
197 let (_, source_map) = db.body_with_source_map(self.owner.into());
198 if let Ok(next_source_ptr) = source_map.expr_syntax(id) {
199 self.sink.push(ReplaceFilterMapNextWithFindMap {
200 file: next_source_ptr.file_id,
201 next_expr: next_source_ptr.value,
202 });
203 }
204 }
205 }
206 }
207 }
208 prev = None;
209 }
210 }
211
212 fn validate_call(&mut self, db: &dyn HirDatabase, call_id: ExprId, expr: &Expr) {
154 // Check that the number of arguments matches the number of parameters. 213 // Check that the number of arguments matches the number of parameters.
155 214
156 // FIXME: Due to shortcomings in the current type system implementation, only emit this 215 // FIXME: Due to shortcomings in the current type system implementation, only emit this
157 // diagnostic if there are no type mismatches in the containing function. 216 // diagnostic if there are no type mismatches in the containing function.
158 if self.infer.type_mismatches.iter().next().is_some() { 217 if self.infer.type_mismatches.iter().next().is_some() {
159 return None; 218 return;
160 } 219 }
161 220
162 let is_method_call = matches!(expr, Expr::MethodCall { .. }); 221 let is_method_call = matches!(expr, Expr::MethodCall { .. });
163 let (sig, args) = match expr { 222 let (sig, args) = match expr {
164 Expr::Call { callee, args } => { 223 Expr::Call { callee, args } => {
165 let callee = &self.infer.type_of_expr[*callee]; 224 let callee = &self.infer.type_of_expr[*callee];
166 let sig = callee.callable_sig(db)?; 225 let sig = match callee.callable_sig(db) {
226 Some(sig) => sig,
227 None => return,
228 };
167 (sig, args.clone()) 229 (sig, args.clone())
168 } 230 }
169 Expr::MethodCall { receiver, args, .. } => { 231 Expr::MethodCall { receiver, args, .. } => {
@@ -175,22 +237,25 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
175 // if the receiver is of unknown type, it's very likely we 237 // if the receiver is of unknown type, it's very likely we
176 // don't know enough to correctly resolve the method call. 238 // don't know enough to correctly resolve the method call.
177 // This is kind of a band-aid for #6975. 239 // This is kind of a band-aid for #6975.
178 return None; 240 return;
179 } 241 }
180 242
181 // FIXME: note that we erase information about substs here. This 243 // FIXME: note that we erase information about substs here. This
182 // is not right, but, luckily, doesn't matter as we care only 244 // is not right, but, luckily, doesn't matter as we care only
183 // about the number of params 245 // about the number of params
184 let callee = self.infer.method_resolution(call_id)?; 246 let callee = match self.infer.method_resolution(call_id) {
247 Some(callee) => callee,
248 None => return,
249 };
185 let sig = db.callable_item_signature(callee.into()).value; 250 let sig = db.callable_item_signature(callee.into()).value;
186 251
187 (sig, args) 252 (sig, args)
188 } 253 }
189 _ => return None, 254 _ => return,
190 }; 255 };
191 256
192 if sig.is_varargs { 257 if sig.is_varargs {
193 return None; 258 return;
194 } 259 }
195 260
196 let params = sig.params(); 261 let params = sig.params();
@@ -213,8 +278,6 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
213 }); 278 });
214 } 279 }
215 } 280 }
216
217 None
218 } 281 }
219 282
220 fn validate_match( 283 fn validate_match(
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index d2f1b4014..38a043c48 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -617,7 +617,7 @@ impl HirDisplay for FnSig {
617} 617}
618 618
619fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> { 619fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> {
620 let krate = trait_.lookup(db).container.module(db).krate; 620 let krate = trait_.lookup(db).container.module(db).krate();
621 let fn_traits = [ 621 let fn_traits = [
622 db.lang_item(krate, "fn".into()), 622 db.lang_item(krate, "fn".into()),
623 db.lang_item(krate, "fn_mut".into()), 623 db.lang_item(krate, "fn_mut".into()),
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index e00c7e176..d47f975d2 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -211,19 +211,21 @@ impl TypeCtor {
211 | TypeCtor::Tuple { .. } => None, 211 | TypeCtor::Tuple { .. } => None,
212 // Closure's krate is irrelevant for coherence I would think? 212 // Closure's krate is irrelevant for coherence I would think?
213 TypeCtor::Closure { .. } => None, 213 TypeCtor::Closure { .. } => None,
214 TypeCtor::Adt(adt) => Some(adt.module(db.upcast()).krate), 214 TypeCtor::Adt(adt) => Some(adt.module(db.upcast()).krate()),
215 TypeCtor::FnDef(callable) => Some(callable.krate(db)), 215 TypeCtor::FnDef(callable) => Some(callable.krate(db)),
216 TypeCtor::AssociatedType(type_alias) => { 216 TypeCtor::AssociatedType(type_alias) => {
217 Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate) 217 Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate())
218 } 218 }
219 TypeCtor::ForeignType(type_alias) => { 219 TypeCtor::ForeignType(type_alias) => {
220 Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate) 220 Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate())
221 } 221 }
222 TypeCtor::OpaqueType(opaque_ty_id) => match opaque_ty_id { 222 TypeCtor::OpaqueType(opaque_ty_id) => match opaque_ty_id {
223 OpaqueTyId::ReturnTypeImplTrait(func, _) => { 223 OpaqueTyId::ReturnTypeImplTrait(func, _) => {
224 Some(func.lookup(db.upcast()).module(db.upcast()).krate) 224 Some(func.lookup(db.upcast()).module(db.upcast()).krate())
225 }
226 OpaqueTyId::AsyncBlockTypeImplTrait(def, _) => {
227 Some(def.module(db.upcast()).krate())
225 } 228 }
226 OpaqueTyId::AsyncBlockTypeImplTrait(def, _) => Some(def.module(db.upcast()).krate),
227 }, 229 },
228 } 230 }
229 } 231 }
@@ -870,7 +872,7 @@ impl Ty {
870 Ty::Apply(ApplicationTy { ctor: TypeCtor::OpaqueType(opaque_ty_id), .. }) => { 872 Ty::Apply(ApplicationTy { ctor: TypeCtor::OpaqueType(opaque_ty_id), .. }) => {
871 match opaque_ty_id { 873 match opaque_ty_id {
872 OpaqueTyId::AsyncBlockTypeImplTrait(def, _expr) => { 874 OpaqueTyId::AsyncBlockTypeImplTrait(def, _expr) => {
873 let krate = def.module(db.upcast()).krate; 875 let krate = def.module(db.upcast()).krate();
874 if let Some(future_trait) = db 876 if let Some(future_trait) = db
875 .lang_item(krate, "future_trait".into()) 877 .lang_item(krate, "future_trait".into())
876 .and_then(|item| item.as_trait()) 878 .and_then(|item| item.as_trait())
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 7a734c8b9..dfb573ff3 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -1147,7 +1147,7 @@ impl CallableDefId {
1147 CallableDefId::StructId(s) => s.lookup(db).container.module(db), 1147 CallableDefId::StructId(s) => s.lookup(db).container.module(db),
1148 CallableDefId::EnumVariantId(e) => e.parent.lookup(db).container.module(db), 1148 CallableDefId::EnumVariantId(e) => e.parent.lookup(db).container.module(db),
1149 } 1149 }
1150 .krate 1150 .krate()
1151 } 1151 }
1152} 1152}
1153 1153
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index f06aeeb42..a302456b0 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -248,12 +248,12 @@ impl Ty {
248 let lang_item_targets = match self { 248 let lang_item_targets = match self {
249 Ty::Apply(a_ty) => match a_ty.ctor { 249 Ty::Apply(a_ty) => match a_ty.ctor {
250 TypeCtor::Adt(def_id) => { 250 TypeCtor::Adt(def_id) => {
251 return Some(std::iter::once(def_id.module(db.upcast()).krate).collect()) 251 return Some(std::iter::once(def_id.module(db.upcast()).krate()).collect())
252 } 252 }
253 TypeCtor::ForeignType(type_alias_id) => { 253 TypeCtor::ForeignType(type_alias_id) => {
254 return Some( 254 return Some(
255 std::iter::once( 255 std::iter::once(
256 type_alias_id.lookup(db.upcast()).module(db.upcast()).krate, 256 type_alias_id.lookup(db.upcast()).module(db.upcast()).krate(),
257 ) 257 )
258 .collect(), 258 .collect(),
259 ) 259 )
@@ -280,7 +280,7 @@ impl Ty {
280 LangItemTarget::ImplDefId(it) => Some(it), 280 LangItemTarget::ImplDefId(it) => Some(it),
281 _ => None, 281 _ => None,
282 }) 282 })
283 .map(|it| it.lookup(db.upcast()).container.module(db.upcast()).krate) 283 .map(|it| it.lookup(db.upcast()).container.module(db.upcast()).krate())
284 .collect(); 284 .collect();
285 Some(res) 285 Some(res)
286 } 286 }
diff --git a/crates/hir_ty/src/test_db.rs b/crates/hir_ty/src/test_db.rs
index 3bbcbc242..381b98ba8 100644
--- a/crates/hir_ty/src/test_db.rs
+++ b/crates/hir_ty/src/test_db.rs
@@ -83,7 +83,7 @@ impl TestDB {
83 let crate_def_map = self.crate_def_map(krate); 83 let crate_def_map = self.crate_def_map(krate);
84 for (local_id, data) in crate_def_map.modules() { 84 for (local_id, data) in crate_def_map.modules() {
85 if data.origin.file_id() == Some(file_id) { 85 if data.origin.file_id() == Some(file_id) {
86 return ModuleId { krate, local_id }; 86 return crate_def_map.module_id(local_id);
87 } 87 }
88 } 88 }
89 } 89 }
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs
index 4a3fcea8d..7386a4e7b 100644
--- a/crates/hir_ty/src/tests.rs
+++ b/crates/hir_ty/src/tests.rs
@@ -188,10 +188,10 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
188 }; 188 };
189 189
190 let module = db.module_for_file(file_id); 190 let module = db.module_for_file(file_id);
191 let crate_def_map = db.crate_def_map(module.krate); 191 let def_map = module.def_map(&db);
192 192
193 let mut defs: Vec<DefWithBodyId> = Vec::new(); 193 let mut defs: Vec<DefWithBodyId> = Vec::new();
194 visit_module(&db, &crate_def_map, module.local_id, &mut |it| defs.push(it)); 194 visit_module(&db, &def_map, module.local_id, &mut |it| defs.push(it));
195 defs.sort_by_key(|def| match def { 195 defs.sort_by_key(|def| match def {
196 DefWithBodyId::FunctionId(it) => { 196 DefWithBodyId::FunctionId(it) => {
197 let loc = it.lookup(&db); 197 let loc = it.lookup(&db);
@@ -321,7 +321,7 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
321 { 321 {
322 let events = db.log_executed(|| { 322 let events = db.log_executed(|| {
323 let module = db.module_for_file(pos.file_id); 323 let module = db.module_for_file(pos.file_id);
324 let crate_def_map = db.crate_def_map(module.krate); 324 let crate_def_map = module.def_map(&db);
325 visit_module(&db, &crate_def_map, module.local_id, &mut |def| { 325 visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
326 db.infer(def); 326 db.infer(def);
327 }); 327 });
@@ -343,7 +343,7 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
343 { 343 {
344 let events = db.log_executed(|| { 344 let events = db.log_executed(|| {
345 let module = db.module_for_file(pos.file_id); 345 let module = db.module_for_file(pos.file_id);
346 let crate_def_map = db.crate_def_map(module.krate); 346 let crate_def_map = module.def_map(&db);
347 visit_module(&db, &crate_def_map, module.local_id, &mut |def| { 347 visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
348 db.infer(def); 348 db.infer(def);
349 }); 349 });
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs
index 2196af677..cfb756158 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -426,7 +426,7 @@ pub(crate) fn trait_datum_query(
426 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 426 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST);
427 let flags = rust_ir::TraitFlags { 427 let flags = rust_ir::TraitFlags {
428 auto: trait_data.auto, 428 auto: trait_data.auto,
429 upstream: trait_.lookup(db.upcast()).container.module(db.upcast()).krate != krate, 429 upstream: trait_.lookup(db.upcast()).container.module(db.upcast()).krate() != krate,
430 non_enumerable: true, 430 non_enumerable: true,
431 coinductive: false, // only relevant for Chalk testing 431 coinductive: false, // only relevant for Chalk testing
432 // FIXME: set these flags correctly 432 // FIXME: set these flags correctly
@@ -549,7 +549,7 @@ fn impl_def_datum(
549 let generic_params = generics(db.upcast(), impl_id.into()); 549 let generic_params = generics(db.upcast(), impl_id.into());
550 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 550 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST);
551 let trait_ = trait_ref.trait_; 551 let trait_ = trait_ref.trait_;
552 let impl_type = if impl_id.lookup(db.upcast()).container.module(db.upcast()).krate == krate { 552 let impl_type = if impl_id.lookup(db.upcast()).container.module(db.upcast()).krate() == krate {
553 rust_ir::ImplType::Local 553 rust_ir::ImplType::Local
554 } else { 554 } else {
555 rust_ir::ImplType::External 555 rust_ir::ImplType::External
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index b35bc2bae..8607139ba 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -136,6 +136,9 @@ pub(crate) fn diagnostics(
136 .on::<hir::diagnostics::IncorrectCase, _>(|d| { 136 .on::<hir::diagnostics::IncorrectCase, _>(|d| {
137 res.borrow_mut().push(warning_with_fix(d, &sema)); 137 res.borrow_mut().push(warning_with_fix(d, &sema));
138 }) 138 })
139 .on::<hir::diagnostics::ReplaceFilterMapNextWithFindMap, _>(|d| {
140 res.borrow_mut().push(warning_with_fix(d, &sema));
141 })
139 .on::<hir::diagnostics::InactiveCode, _>(|d| { 142 .on::<hir::diagnostics::InactiveCode, _>(|d| {
140 // If there's inactive code somewhere in a macro, don't propagate to the call-site. 143 // If there's inactive code somewhere in a macro, don't propagate to the call-site.
141 if d.display_source().file_id.expansion_info(db).is_some() { 144 if d.display_source().file_id.expansion_info(db).is_some() {
diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs
index 579d5a308..cbfc66ab3 100644
--- a/crates/ide/src/diagnostics/fixes.rs
+++ b/crates/ide/src/diagnostics/fixes.rs
@@ -4,7 +4,7 @@ use hir::{
4 db::AstDatabase, 4 db::AstDatabase,
5 diagnostics::{ 5 diagnostics::{
6 Diagnostic, IncorrectCase, MissingFields, MissingOkOrSomeInTailExpr, NoSuchField, 6 Diagnostic, IncorrectCase, MissingFields, MissingOkOrSomeInTailExpr, NoSuchField,
7 RemoveThisSemicolon, UnresolvedModule, 7 RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap, UnresolvedModule,
8 }, 8 },
9 HasSource, HirDisplay, InFile, Semantics, VariantDef, 9 HasSource, HirDisplay, InFile, Semantics, VariantDef,
10}; 10};
@@ -15,8 +15,8 @@ use ide_db::{
15}; 15};
16use syntax::{ 16use syntax::{
17 algo, 17 algo,
18 ast::{self, edit::IndentLevel, make}, 18 ast::{self, edit::IndentLevel, make, ArgListOwner},
19 AstNode, 19 AstNode, TextRange,
20}; 20};
21use text_edit::TextEdit; 21use text_edit::TextEdit;
22 22
@@ -144,6 +144,33 @@ impl DiagnosticWithFix for IncorrectCase {
144 } 144 }
145} 145}
146 146
147impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap {
148 fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
149 let root = sema.db.parse_or_expand(self.file)?;
150 let next_expr = self.next_expr.to_node(&root);
151 let next_call = ast::MethodCallExpr::cast(next_expr.syntax().clone())?;
152
153 let filter_map_call = ast::MethodCallExpr::cast(next_call.receiver()?.syntax().clone())?;
154 let filter_map_name_range = filter_map_call.name_ref()?.ident_token()?.text_range();
155 let filter_map_args = filter_map_call.arg_list()?;
156
157 let range_to_replace =
158 TextRange::new(filter_map_name_range.start(), next_expr.syntax().text_range().end());
159 let replacement = format!("find_map{}", filter_map_args.syntax().text());
160 let trigger_range = next_expr.syntax().text_range();
161
162 let edit = TextEdit::replace(range_to_replace, replacement);
163
164 let source_change = SourceChange::from_text_edit(self.file.original_file(sema.db), edit);
165
166 Some(Fix::new(
167 "Replace filter_map(..).next() with find_map()",
168 source_change,
169 trigger_range,
170 ))
171 }
172}
173
147fn missing_record_expr_field_fix( 174fn missing_record_expr_field_fix(
148 sema: &Semantics<RootDatabase>, 175 sema: &Semantics<RootDatabase>,
149 usage_file_id: FileId, 176 usage_file_id: FileId,
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index 9c568c90c..23d885218 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -7,6 +7,7 @@ use hir::{AssocItem, Documentation, FieldSource, HasAttrs, HasSource, InFile, Mo
7use ide_db::{ 7use ide_db::{
8 base_db::{FileId, FileRange, SourceDatabase}, 8 base_db::{FileId, FileRange, SourceDatabase},
9 symbol_index::FileSymbolKind, 9 symbol_index::FileSymbolKind,
10 SymbolKind,
10}; 11};
11use ide_db::{defs::Definition, RootDatabase}; 12use ide_db::{defs::Definition, RootDatabase};
12use syntax::{ 13use syntax::{
@@ -18,30 +19,6 @@ use crate::FileSymbol;
18 19
19use super::short_label::ShortLabel; 20use super::short_label::ShortLabel;
20 21
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
22pub enum SymbolKind {
23 Module,
24 Impl,
25 Field,
26 TypeParam,
27 ConstParam,
28 LifetimeParam,
29 ValueParam,
30 SelfParam,
31 Local,
32 Label,
33 Function,
34 Const,
35 Static,
36 Struct,
37 Enum,
38 Variant,
39 Union,
40 TypeAlias,
41 Trait,
42 Macro,
43}
44
45/// `NavigationTarget` represents and element in the editor's UI which you can 22/// `NavigationTarget` represents and element in the editor's UI which you can
46/// click on to navigate to a particular piece of code. 23/// click on to navigate to a particular piece of code.
47/// 24///
@@ -196,6 +173,7 @@ impl ToNav for FileSymbol {
196 FileSymbolKind::Const => SymbolKind::Const, 173 FileSymbolKind::Const => SymbolKind::Const,
197 FileSymbolKind::Static => SymbolKind::Static, 174 FileSymbolKind::Static => SymbolKind::Static,
198 FileSymbolKind::Macro => SymbolKind::Macro, 175 FileSymbolKind::Macro => SymbolKind::Macro,
176 FileSymbolKind::Union => SymbolKind::Union,
199 }), 177 }),
200 full_range: self.range, 178 full_range: self.range,
201 focus_range: self.name_range, 179 focus_range: self.name_range,
@@ -457,13 +435,16 @@ impl TryToNav for hir::TypeParam {
457 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { 435 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
458 let src = self.source(db)?; 436 let src = self.source(db)?;
459 let full_range = match &src.value { 437 let full_range = match &src.value {
460 Either::Left(it) => it.syntax().text_range(), 438 Either::Left(it) => it
439 .name()
440 .map_or_else(|| it.syntax().text_range(), |name| name.syntax().text_range()),
461 Either::Right(it) => it.syntax().text_range(), 441 Either::Right(it) => it.syntax().text_range(),
462 }; 442 };
463 let focus_range = match &src.value { 443 let focus_range = match &src.value {
464 Either::Left(_) => None, 444 Either::Left(it) => it.name(),
465 Either::Right(it) => it.name().map(|it| it.syntax().text_range()), 445 Either::Right(it) => it.name(),
466 }; 446 }
447 .map(|it| it.syntax().text_range());
467 Some(NavigationTarget { 448 Some(NavigationTarget {
468 file_id: src.file_id.original_file(db), 449 file_id: src.file_id.original_file(db),
469 name: self.name(db).to_string().into(), 450 name: self.name(db).to_string().into(),
diff --git a/crates/ide/src/file_structure.rs b/crates/ide/src/file_structure.rs
index 32556dad3..26793bdb4 100644
--- a/crates/ide/src/file_structure.rs
+++ b/crates/ide/src/file_structure.rs
@@ -1,10 +1,9 @@
1use ide_db::SymbolKind;
1use syntax::{ 2use syntax::{
2 ast::{self, AttrsOwner, GenericParamsOwner, NameOwner}, 3 ast::{self, AttrsOwner, GenericParamsOwner, NameOwner},
3 match_ast, AstNode, SourceFile, SyntaxNode, TextRange, WalkEvent, 4 match_ast, AstNode, SourceFile, SyntaxNode, TextRange, WalkEvent,
4}; 5};
5 6
6use crate::SymbolKind;
7
8#[derive(Debug, Clone)] 7#[derive(Debug, Clone)]
9pub struct StructureNode { 8pub struct StructureNode {
10 pub parent: Option<usize>, 9 pub parent: Option<usize>,
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 567b8117e..989e94a31 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -65,7 +65,7 @@ use crate::display::ToNav;
65pub use crate::{ 65pub use crate::{
66 call_hierarchy::CallItem, 66 call_hierarchy::CallItem,
67 diagnostics::{Diagnostic, DiagnosticsConfig, Fix, Severity}, 67 diagnostics::{Diagnostic, DiagnosticsConfig, Fix, Severity},
68 display::navigation_target::{NavigationTarget, SymbolKind}, 68 display::navigation_target::NavigationTarget,
69 expand_macro::ExpandedMacro, 69 expand_macro::ExpandedMacro,
70 file_structure::StructureNode, 70 file_structure::StructureNode,
71 folding_ranges::{Fold, FoldKind}, 71 folding_ranges::{Fold, FoldKind},
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 3a4f4d80b..40d9487eb 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -1098,4 +1098,20 @@ fn foo<const FOO$0: usize>() -> usize {
1098 "#]], 1098 "#]],
1099 ); 1099 );
1100 } 1100 }
1101
1102 #[test]
1103 fn test_find_self_ty_in_trait_def() {
1104 check(
1105 r#"
1106trait Foo {
1107 fn f() -> Self$0;
1108}
1109"#,
1110 expect![[r#"
1111 Self TypeParam FileId(0) 6..9 6..9 Other
1112
1113 FileId(0) 26..30 Other
1114 "#]],
1115 );
1116 }
1101} 1117}
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 975abf47f..33170906d 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -3,7 +3,7 @@ use std::fmt;
3use assists::utils::test_related_attribute; 3use assists::utils::test_related_attribute;
4use cfg::CfgExpr; 4use cfg::CfgExpr;
5use hir::{AsAssocItem, HasAttrs, HasSource, Semantics}; 5use hir::{AsAssocItem, HasAttrs, HasSource, Semantics};
6use ide_db::{defs::Definition, RootDatabase}; 6use ide_db::{defs::Definition, RootDatabase, SymbolKind};
7use itertools::Itertools; 7use itertools::Itertools;
8use syntax::{ 8use syntax::{
9 ast::{self, AstNode, AttrsOwner}, 9 ast::{self, AstNode, AttrsOwner},
@@ -13,7 +13,7 @@ use test_utils::mark;
13 13
14use crate::{ 14use crate::{
15 display::{ToNav, TryToNav}, 15 display::{ToNav, TryToNav},
16 FileId, NavigationTarget, SymbolKind, 16 FileId, NavigationTarget,
17}; 17};
18 18
19#[derive(Debug, Clone)] 19#[derive(Debug, Clone)]
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index f2d4da78d..a3d4e4f77 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -13,7 +13,7 @@ mod html;
13mod tests; 13mod tests;
14 14
15use hir::{Name, Semantics}; 15use hir::{Name, Semantics};
16use ide_db::RootDatabase; 16use ide_db::{RootDatabase, SymbolKind};
17use rustc_hash::FxHashMap; 17use rustc_hash::FxHashMap;
18use syntax::{ 18use syntax::{
19 ast::{self, HasFormatSpecifier}, 19 ast::{self, HasFormatSpecifier},
@@ -27,7 +27,7 @@ use crate::{
27 format::highlight_format_string, highlights::Highlights, 27 format::highlight_format_string, highlights::Highlights,
28 macro_rules::MacroRulesHighlighter, tags::Highlight, 28 macro_rules::MacroRulesHighlighter, tags::Highlight,
29 }, 29 },
30 FileId, HlMod, HlTag, SymbolKind, 30 FileId, HlMod, HlTag,
31}; 31};
32 32
33pub(crate) use html::highlight_as_html; 33pub(crate) use html::highlight_as_html;
diff --git a/crates/ide/src/syntax_highlighting/format.rs b/crates/ide/src/syntax_highlighting/format.rs
index 8a9b5ca8c..8c67a0863 100644
--- a/crates/ide/src/syntax_highlighting/format.rs
+++ b/crates/ide/src/syntax_highlighting/format.rs
@@ -1,10 +1,11 @@
1//! Syntax highlighting for format macro strings. 1//! Syntax highlighting for format macro strings.
2use ide_db::SymbolKind;
2use syntax::{ 3use syntax::{
3 ast::{self, FormatSpecifier, HasFormatSpecifier}, 4 ast::{self, FormatSpecifier, HasFormatSpecifier},
4 AstNode, AstToken, TextRange, 5 AstNode, AstToken, TextRange,
5}; 6};
6 7
7use crate::{syntax_highlighting::highlights::Highlights, HlRange, HlTag, SymbolKind}; 8use crate::{syntax_highlighting::highlights::Highlights, HlRange, HlTag};
8 9
9pub(super) fn highlight_format_string( 10pub(super) fn highlight_format_string(
10 stack: &mut Highlights, 11 stack: &mut Highlights,
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 8625ef5df..24fcbb584 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -3,7 +3,7 @@
3use hir::{AsAssocItem, Semantics, VariantDef}; 3use hir::{AsAssocItem, Semantics, VariantDef};
4use ide_db::{ 4use ide_db::{
5 defs::{Definition, NameClass, NameRefClass}, 5 defs::{Definition, NameClass, NameRefClass},
6 RootDatabase, 6 RootDatabase, SymbolKind,
7}; 7};
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
9use syntax::{ 9use syntax::{
@@ -12,7 +12,7 @@ use syntax::{
12 SyntaxNode, SyntaxToken, T, 12 SyntaxNode, SyntaxToken, T,
13}; 13};
14 14
15use crate::{syntax_highlighting::tags::HlPunct, Highlight, HlMod, HlTag, SymbolKind}; 15use crate::{syntax_highlighting::tags::HlPunct, Highlight, HlMod, HlTag};
16 16
17pub(super) fn element( 17pub(super) fn element(
18 sema: &Semantics<RootDatabase>, 18 sema: &Semantics<RootDatabase>,
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs
index 8dd05ac52..3c02fdb11 100644
--- a/crates/ide/src/syntax_highlighting/tags.rs
+++ b/crates/ide/src/syntax_highlighting/tags.rs
@@ -3,7 +3,7 @@
3 3
4use std::{fmt, ops}; 4use std::{fmt, ops};
5 5
6use crate::SymbolKind; 6use ide_db::SymbolKind;
7 7
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 8#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
9pub struct Highlight { 9pub struct Highlight {
diff --git a/crates/ide_db/src/lib.rs b/crates/ide_db/src/lib.rs
index 118c090d7..6eb34b06b 100644
--- a/crates/ide_db/src/lib.rs
+++ b/crates/ide_db/src/lib.rs
@@ -134,3 +134,27 @@ fn line_index(db: &dyn LineIndexDatabase, file_id: FileId) -> Arc<LineIndex> {
134 let text = db.file_text(file_id); 134 let text = db.file_text(file_id);
135 Arc::new(LineIndex::new(&*text)) 135 Arc::new(LineIndex::new(&*text))
136} 136}
137
138#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
139pub enum SymbolKind {
140 Const,
141 ConstParam,
142 Enum,
143 Field,
144 Function,
145 Impl,
146 Label,
147 LifetimeParam,
148 Local,
149 Macro,
150 Module,
151 SelfParam,
152 Static,
153 Struct,
154 Trait,
155 TypeAlias,
156 TypeParam,
157 Union,
158 ValueParam,
159 Variant,
160}
diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs
index e954bd72e..9ed9568ce 100644
--- a/crates/ide_db/src/symbol_index.rs
+++ b/crates/ide_db/src/symbol_index.rs
@@ -356,15 +356,16 @@ pub struct FileSymbol {
356 356
357#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)] 357#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
358pub enum FileSymbolKind { 358pub enum FileSymbolKind {
359 Const,
360 Enum,
359 Function, 361 Function,
362 Macro,
363 Module,
364 Static,
360 Struct, 365 Struct,
361 Enum,
362 Trait, 366 Trait,
363 Module,
364 TypeAlias, 367 TypeAlias,
365 Const, 368 Union,
366 Static,
367 Macro,
368} 369}
369 370
370impl FileSymbolKind { 371impl FileSymbolKind {
@@ -375,6 +376,7 @@ impl FileSymbolKind {
375 | FileSymbolKind::Enum 376 | FileSymbolKind::Enum
376 | FileSymbolKind::Trait 377 | FileSymbolKind::Trait
377 | FileSymbolKind::TypeAlias 378 | FileSymbolKind::TypeAlias
379 | FileSymbolKind::Union
378 ) 380 )
379 } 381 }
380} 382}
@@ -425,6 +427,7 @@ fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> {
425 ast::Const(it) => decl(it), 427 ast::Const(it) => decl(it),
426 ast::Static(it) => decl(it), 428 ast::Static(it) => decl(it),
427 ast::MacroRules(it) => decl(it), 429 ast::MacroRules(it) => decl(it),
430 ast::Union(it) => decl(it),
428 _ => None, 431 _ => None,
429 } 432 }
430 } 433 }
@@ -443,6 +446,7 @@ fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option<FileSymbol> {
443 CONST => FileSymbolKind::Const, 446 CONST => FileSymbolKind::Const,
444 STATIC => FileSymbolKind::Static, 447 STATIC => FileSymbolKind::Static,
445 MACRO_RULES => FileSymbolKind::Macro, 448 MACRO_RULES => FileSymbolKind::Macro,
449 UNION => FileSymbolKind::Union,
446 kind => unreachable!("{:?}", kind), 450 kind => unreachable!("{:?}", kind),
447 }, 451 },
448 range: node.text_range(), 452 range: node.text_range(),
diff --git a/crates/ide_db/src/ty_filter.rs b/crates/ide_db/src/ty_filter.rs
index 63a945282..f8406851b 100644
--- a/crates/ide_db/src/ty_filter.rs
+++ b/crates/ide_db/src/ty_filter.rs
@@ -49,6 +49,21 @@ impl TryEnum {
49 } 49 }
50 } 50 }
51 51
52 pub fn happy_pattern(self) -> ast::Pat {
53 match self {
54 TryEnum::Result => make::tuple_struct_pat(
55 make::path_unqualified(make::path_segment(make::name_ref("Ok"))),
56 iter::once(make::wildcard_pat().into()),
57 )
58 .into(),
59 TryEnum::Option => make::tuple_struct_pat(
60 make::path_unqualified(make::path_segment(make::name_ref("Some"))),
61 iter::once(make::wildcard_pat().into()),
62 )
63 .into(),
64 }
65 }
66
52 fn type_name(self) -> &'static str { 67 fn type_name(self) -> &'static str {
53 match self { 68 match self {
54 TryEnum::Result => "Result", 69 TryEnum::Result => "Result",
diff --git a/crates/parser/src/grammar/items/consts.rs b/crates/parser/src/grammar/items/consts.rs
index eb7d1f828..12130df40 100644
--- a/crates/parser/src/grammar/items/consts.rs
+++ b/crates/parser/src/grammar/items/consts.rs
@@ -13,7 +13,7 @@ pub(super) fn konst(p: &mut Parser, m: Marker) {
13fn const_or_static(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) { 13fn const_or_static(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) {
14 assert!(p.at(kw)); 14 assert!(p.at(kw));
15 p.bump(kw); 15 p.bump(kw);
16 p.eat(T![mut]); // FIXME: validator to forbid const mut 16 p.eat(T![mut]);
17 17
18 // Allow `_` in place of an identifier in a `const`. 18 // Allow `_` in place of an identifier in a `const`.
19 let is_const_underscore = kw == T![const] && p.eat(T![_]); 19 let is_const_underscore = kw == T![const] && p.eat(T![_]);
diff --git a/crates/profile/Cargo.toml b/crates/profile/Cargo.toml
index cc7da27f7..4dd9acc98 100644
--- a/crates/profile/Cargo.toml
+++ b/crates/profile/Cargo.toml
@@ -14,7 +14,7 @@ once_cell = "1.3.1"
14cfg-if = "1" 14cfg-if = "1"
15libc = "0.2.73" 15libc = "0.2.73"
16la-arena = { version = "0.2.0", path = "../../lib/arena" } 16la-arena = { version = "0.2.0", path = "../../lib/arena" }
17countme = { version = "2.0.0-pre.2", features = ["enable"] } 17countme = { version = "2.0.0", features = ["enable"] }
18jemalloc-ctl = { version = "0.3.3", optional = true } 18jemalloc-ctl = { version = "0.3.3", optional = true }
19 19
20[target.'cfg(target_os = "linux")'.dependencies] 20[target.'cfg(target_os = "linux")'.dependencies]
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs
index 2f7f94a39..1d6e5478b 100644
--- a/crates/rust-analyzer/src/bin/main.rs
+++ b/crates/rust-analyzer/src/bin/main.rs
@@ -76,7 +76,12 @@ fn setup_logging(log_file: Option<PathBuf>) -> Result<()> {
76 profile::init(); 76 profile::init();
77 77
78 if !cfg!(debug_assertions) { 78 if !cfg!(debug_assertions) {
79 stdx::set_assert_hook(|loc, args| log::error!("assertion failed at {}: {}", loc, args)); 79 stdx::set_assert_hook(|loc, args| {
80 if env::var("RA_PROFILE").is_ok() {
81 panic!("assertion failed at {}: {}", loc, args)
82 }
83 log::error!("assertion failed at {}: {}", loc, args)
84 });
80 } 85 }
81 86
82 Ok(()) 87 Ok(())
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 3ddb9e19a..247bfe71e 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -147,6 +147,9 @@ config_data! {
147 /// Whether to show `Method References` lens. Only applies when 147 /// Whether to show `Method References` lens. Only applies when
148 /// `#rust-analyzer.lens.enable#` is set. 148 /// `#rust-analyzer.lens.enable#` is set.
149 lens_methodReferences: bool = "false", 149 lens_methodReferences: bool = "false",
150 /// Whether to show `References` lens. Only applies when
151 /// `#rust-analyzer.lens.enable#` is set.
152 lens_references: bool = "false",
150 153
151 /// Disable project auto-discovery in favor of explicitly specified set 154 /// Disable project auto-discovery in favor of explicitly specified set
152 /// of projects.\n\nElements must be paths pointing to `Cargo.toml`, 155 /// of projects.\n\nElements must be paths pointing to `Cargo.toml`,
@@ -221,6 +224,7 @@ pub struct LensConfig {
221 pub debug: bool, 224 pub debug: bool,
222 pub implementations: bool, 225 pub implementations: bool,
223 pub method_refs: bool, 226 pub method_refs: bool,
227 pub refs: bool, // for Struct, Enum, Union and Trait
224} 228}
225 229
226impl LensConfig { 230impl LensConfig {
@@ -237,7 +241,7 @@ impl LensConfig {
237 } 241 }
238 242
239 pub fn references(&self) -> bool { 243 pub fn references(&self) -> bool {
240 self.method_refs 244 self.method_refs || self.refs
241 } 245 }
242} 246}
243 247
@@ -593,6 +597,7 @@ impl Config {
593 debug: self.data.lens_enable && self.data.lens_debug, 597 debug: self.data.lens_enable && self.data.lens_debug,
594 implementations: self.data.lens_enable && self.data.lens_implementations, 598 implementations: self.data.lens_enable && self.data.lens_implementations,
595 method_refs: self.data.lens_enable && self.data.lens_methodReferences, 599 method_refs: self.data.lens_enable && self.data.lens_methodReferences,
600 refs: self.data.lens_enable && self.data.lens_references,
596 } 601 }
597 } 602 }
598 pub fn hover(&self) -> HoverConfig { 603 pub fn hover(&self) -> HoverConfig {
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 42451cd2d..07204436c 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -10,8 +10,9 @@ use std::{
10 10
11use ide::{ 11use ide::{
12 FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, LineIndex, NavigationTarget, 12 FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, LineIndex, NavigationTarget,
13 Query, RangeInfo, Runnable, RunnableKind, SearchScope, SourceChange, SymbolKind, TextEdit, 13 Query, RangeInfo, Runnable, RunnableKind, SearchScope, SourceChange, TextEdit,
14}; 14};
15use ide_db::SymbolKind;
15use itertools::Itertools; 16use itertools::Itertools;
16use lsp_server::ErrorCode; 17use lsp_server::ErrorCode;
17use lsp_types::{ 18use lsp_types::{
@@ -1111,42 +1112,48 @@ pub(crate) fn handle_code_lens(
1111 } 1112 }
1112 } 1113 }
1113 1114
1114 if lens_config.implementations { 1115 if lens_config.implementations || lens_config.refs {
1115 // Handle impls 1116 snap.analysis
1116 lenses.extend( 1117 .file_structure(file_id)?
1117 snap.analysis 1118 .into_iter()
1118 .file_structure(file_id)? 1119 .filter(|it| {
1119 .into_iter() 1120 matches!(
1120 .filter(|it| { 1121 it.kind,
1121 matches!( 1122 SymbolKind::Trait | SymbolKind::Struct | SymbolKind::Enum | SymbolKind::Union
1122 it.kind, 1123 )
1123 SymbolKind::Trait 1124 })
1124 | SymbolKind::Struct 1125 .for_each(|it| {
1125 | SymbolKind::Enum 1126 let range = to_proto::range(&line_index, it.node_range);
1126 | SymbolKind::Union 1127 let position = to_proto::position(&line_index, it.navigation_range.start());
1127 ) 1128 let doc_pos = lsp_types::TextDocumentPositionParams::new(
1128 }) 1129 params.text_document.clone(),
1129 .map(|it| { 1130 position,
1130 let range = to_proto::range(&line_index, it.node_range); 1131 );
1131 let pos = range.start; 1132 let goto_params = lsp_types::request::GotoImplementationParams {
1132 let lens_params = lsp_types::request::GotoImplementationParams { 1133 text_document_position_params: doc_pos.clone(),
1133 text_document_position_params: lsp_types::TextDocumentPositionParams::new( 1134 work_done_progress_params: Default::default(),
1134 params.text_document.clone(), 1135 partial_result_params: Default::default(),
1135 pos, 1136 };
1136 ), 1137
1137 work_done_progress_params: Default::default(), 1138 if lens_config.implementations {
1138 partial_result_params: Default::default(), 1139 lenses.push(CodeLens {
1139 };
1140 CodeLens {
1141 range, 1140 range,
1142 command: None, 1141 command: None,
1143 data: Some(to_value(CodeLensResolveData::Impls(lens_params)).unwrap()), 1142 data: Some(to_value(CodeLensResolveData::Impls(goto_params)).unwrap()),
1144 } 1143 })
1145 }), 1144 }
1146 ); 1145
1146 if lens_config.refs {
1147 lenses.push(CodeLens {
1148 range,
1149 command: None,
1150 data: Some(to_value(CodeLensResolveData::References(doc_pos)).unwrap()),
1151 })
1152 }
1153 });
1147 } 1154 }
1148 1155
1149 if lens_config.references() { 1156 if lens_config.method_refs {
1150 lenses.extend(snap.analysis.find_all_methods(file_id)?.into_iter().map(|it| { 1157 lenses.extend(snap.analysis.find_all_methods(file_id)?.into_iter().map(|it| {
1151 let range = to_proto::range(&line_index, it.range); 1158 let range = to_proto::range(&line_index, it.range);
1152 let position = to_proto::position(&line_index, it.range.start()); 1159 let position = to_proto::position(&line_index, it.range.start());
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 0e3550002..96f915f1c 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -8,8 +8,9 @@ use ide::{
8 Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation, FileId, 8 Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation, FileId,
9 FileRange, FileSystemEdit, Fold, FoldKind, Highlight, HlMod, HlPunct, HlRange, HlTag, Indel, 9 FileRange, FileSystemEdit, Fold, FoldKind, Highlight, HlMod, HlPunct, HlRange, HlTag, Indel,
10 InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup, NavigationTarget, ReferenceAccess, 10 InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup, NavigationTarget, ReferenceAccess,
11 RenameError, Runnable, Severity, SourceChange, SymbolKind, TextEdit, TextRange, TextSize, 11 RenameError, Runnable, Severity, SourceChange, TextEdit, TextRange, TextSize,
12}; 12};
13use ide_db::SymbolKind;
13use itertools::Itertools; 14use itertools::Itertools;
14 15
15use crate::{ 16use crate::{
@@ -87,25 +88,35 @@ pub(crate) fn completion_item_kind(
87 completion_item_kind: CompletionItemKind, 88 completion_item_kind: CompletionItemKind,
88) -> lsp_types::CompletionItemKind { 89) -> lsp_types::CompletionItemKind {
89 match completion_item_kind { 90 match completion_item_kind {
90 CompletionItemKind::Keyword => lsp_types::CompletionItemKind::Keyword, 91 CompletionItemKind::Attribute => lsp_types::CompletionItemKind::EnumMember,
91 CompletionItemKind::Snippet => lsp_types::CompletionItemKind::Snippet,
92 CompletionItemKind::Module => lsp_types::CompletionItemKind::Module,
93 CompletionItemKind::Function => lsp_types::CompletionItemKind::Function,
94 CompletionItemKind::Struct => lsp_types::CompletionItemKind::Struct,
95 CompletionItemKind::Enum => lsp_types::CompletionItemKind::Enum,
96 CompletionItemKind::EnumVariant => lsp_types::CompletionItemKind::EnumMember,
97 CompletionItemKind::BuiltinType => lsp_types::CompletionItemKind::Struct,
98 CompletionItemKind::Binding => lsp_types::CompletionItemKind::Variable, 92 CompletionItemKind::Binding => lsp_types::CompletionItemKind::Variable,
99 CompletionItemKind::Field => lsp_types::CompletionItemKind::Field, 93 CompletionItemKind::BuiltinType => lsp_types::CompletionItemKind::Struct,
100 CompletionItemKind::Trait => lsp_types::CompletionItemKind::Interface, 94 CompletionItemKind::Keyword => lsp_types::CompletionItemKind::Keyword,
101 CompletionItemKind::TypeAlias => lsp_types::CompletionItemKind::Struct,
102 CompletionItemKind::Const => lsp_types::CompletionItemKind::Constant,
103 CompletionItemKind::Static => lsp_types::CompletionItemKind::Value,
104 CompletionItemKind::Method => lsp_types::CompletionItemKind::Method, 95 CompletionItemKind::Method => lsp_types::CompletionItemKind::Method,
105 CompletionItemKind::TypeParam => lsp_types::CompletionItemKind::TypeParameter, 96 CompletionItemKind::Snippet => lsp_types::CompletionItemKind::Snippet,
106 CompletionItemKind::Macro => lsp_types::CompletionItemKind::Method,
107 CompletionItemKind::Attribute => lsp_types::CompletionItemKind::EnumMember,
108 CompletionItemKind::UnresolvedReference => lsp_types::CompletionItemKind::Reference, 97 CompletionItemKind::UnresolvedReference => lsp_types::CompletionItemKind::Reference,
98 CompletionItemKind::SymbolKind(symbol) => match symbol {
99 SymbolKind::Const => lsp_types::CompletionItemKind::Constant,
100 SymbolKind::ConstParam => lsp_types::CompletionItemKind::TypeParameter,
101 SymbolKind::Enum => lsp_types::CompletionItemKind::Enum,
102 SymbolKind::Field => lsp_types::CompletionItemKind::Field,
103 SymbolKind::Function => lsp_types::CompletionItemKind::Function,
104 SymbolKind::Impl => lsp_types::CompletionItemKind::Text,
105 SymbolKind::Label => lsp_types::CompletionItemKind::Variable,
106 SymbolKind::LifetimeParam => lsp_types::CompletionItemKind::TypeParameter,
107 SymbolKind::Local => lsp_types::CompletionItemKind::Variable,
108 SymbolKind::Macro => lsp_types::CompletionItemKind::Method,
109 SymbolKind::Module => lsp_types::CompletionItemKind::Module,
110 SymbolKind::SelfParam => lsp_types::CompletionItemKind::Value,
111 SymbolKind::Static => lsp_types::CompletionItemKind::Value,
112 SymbolKind::Struct => lsp_types::CompletionItemKind::Struct,
113 SymbolKind::Trait => lsp_types::CompletionItemKind::Interface,
114 SymbolKind::TypeAlias => lsp_types::CompletionItemKind::Struct,
115 SymbolKind::TypeParam => lsp_types::CompletionItemKind::TypeParameter,
116 SymbolKind::Union => lsp_types::CompletionItemKind::Struct,
117 SymbolKind::ValueParam => lsp_types::CompletionItemKind::Value,
118 SymbolKind::Variant => lsp_types::CompletionItemKind::EnumMember,
119 },
109 } 120 }
110} 121}
111 122
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs
index 73b121f8a..d42817078 100644
--- a/crates/stdx/src/lib.rs
+++ b/crates/stdx/src/lib.rs
@@ -196,6 +196,7 @@ impl ops::DerefMut for JodChild {
196impl Drop for JodChild { 196impl Drop for JodChild {
197 fn drop(&mut self) { 197 fn drop(&mut self) {
198 let _ = self.0.kill(); 198 let _ = self.0.kill();
199 let _ = self.0.wait();
199 } 200 }
200} 201}
201 202
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index 24298fbfa..e70fbba9c 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
12 12
13[dependencies] 13[dependencies]
14itertools = "0.10.0" 14itertools = "0.10.0"
15rowan = "0.12" 15rowan = "0.12.2"
16rustc_lexer = { version = "700.0.0", package = "rustc-ap-rustc_lexer" } 16rustc_lexer = { version = "700.0.0", package = "rustc-ap-rustc_lexer" }
17rustc-hash = "1.1.0" 17rustc-hash = "1.1.0"
18arrayvec = "0.5.1" 18arrayvec = "0.5.1"
diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs
index 7694e8834..3e216fb70 100644
--- a/crates/syntax/src/validation.rs
+++ b/crates/syntax/src/validation.rs
@@ -1,4 +1,6 @@
1//! FIXME: write short doc here 1//! This module implements syntax validation that the parser doesn't handle.
2//!
3//! A failed validation emits a diagnostic.
2 4
3mod block; 5mod block;
4 6
@@ -92,6 +94,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
92 match_ast! { 94 match_ast! {
93 match node { 95 match node {
94 ast::Literal(it) => validate_literal(it, &mut errors), 96 ast::Literal(it) => validate_literal(it, &mut errors),
97 ast::Const(it) => validate_const(it, &mut errors),
95 ast::BlockExpr(it) => block::validate_block_expr(it, &mut errors), 98 ast::BlockExpr(it) => block::validate_block_expr(it, &mut errors),
96 ast::FieldExpr(it) => validate_numeric_name(it.name_ref(), &mut errors), 99 ast::FieldExpr(it) => validate_numeric_name(it.name_ref(), &mut errors),
97 ast::RecordExprField(it) => validate_numeric_name(it.name_ref(), &mut errors), 100 ast::RecordExprField(it) => validate_numeric_name(it.name_ref(), &mut errors),
@@ -362,3 +365,14 @@ fn validate_macro_rules(mac: ast::MacroRules, errors: &mut Vec<SyntaxError>) {
362 )); 365 ));
363 } 366 }
364} 367}
368
369fn validate_const(const_: ast::Const, errors: &mut Vec<SyntaxError>) {
370 if let Some(mut_token) = const_
371 .const_token()
372 .and_then(|t| t.next_token())
373 .and_then(|t| algo::skip_trivia_token(t, Direction::Next))
374 .filter(|t| t.kind() == T![mut])
375 {
376 errors.push(SyntaxError::new("const globals cannot be mutable", mut_token.text_range()));
377 }
378}
diff --git a/crates/syntax/test_data/parser/err/0047_mutable_const_item.rast b/crates/syntax/test_data/parser/err/0047_mutable_const_item.rast
new file mode 100644
index 000000000..c7eb312c9
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0047_mutable_const_item.rast
@@ -0,0 +1,22 @@
1[email protected]
2 [email protected]
3 [email protected] "const"
4 [email protected] " "
5 [email protected] "mut"
6 [email protected] " "
7 [email protected]
8 [email protected] "FOO"
9 [email protected] ":"
10 [email protected] " "
11 [email protected]
12 [email protected] "("
13 [email protected] ")"
14 [email protected] " "
15 [email protected] "="
16 [email protected] " "
17 [email protected]
18 [email protected] "("
19 [email protected] ")"
20 [email protected] ";"
21 [email protected] "\n"
22error 6..9: const globals cannot be mutable
diff --git a/crates/syntax/test_data/parser/err/0047_mutable_const_item.rs b/crates/syntax/test_data/parser/err/0047_mutable_const_item.rs
new file mode 100644
index 000000000..b34336f3f
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0047_mutable_const_item.rs
@@ -0,0 +1 @@
const mut FOO: () = ();
diff --git a/crates/syntax/test_data/parser/ok/0024_const_item.rast b/crates/syntax/test_data/parser/ok/0024_const_item.rast
index dd1b9c9a0..b89ed6f98 100644
--- a/crates/syntax/test_data/parser/ok/0024_const_item.rast
+++ b/crates/syntax/test_data/parser/ok/0024_const_item.rast
@@ -1,4 +1,4 @@
1SOURCE_FILE@0..64 1SOURCE_FILE@0..39
2 [email protected] 2 [email protected]
3 [email protected] "const" 3 [email protected] "const"
4 [email protected] " " 4 [email protected] " "
@@ -36,24 +36,3 @@ [email protected]
36 [email protected] "92" 36 [email protected] "92"
37 [email protected] ";" 37 [email protected] ";"
38 [email protected] "\n" 38 [email protected] "\n"
39 [email protected]
40 [email protected] "const"
41 [email protected] " "
42 [email protected] "mut"
43 [email protected] " "
44 [email protected]
45 [email protected] "BAR"
46 [email protected] ":"
47 [email protected] " "
48 [email protected]
49 [email protected]
50 [email protected]
51 [email protected]
52 [email protected] "u32"
53 [email protected] " "
54 [email protected] "="
55 [email protected] " "
56 [email protected]
57 [email protected] "62"
58 [email protected] ";"
59 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/ok/0024_const_item.rs b/crates/syntax/test_data/parser/ok/0024_const_item.rs
index a806a209d..1f2ffa0da 100644
--- a/crates/syntax/test_data/parser/ok/0024_const_item.rs
+++ b/crates/syntax/test_data/parser/ok/0024_const_item.rs
@@ -1,3 +1,2 @@
1const _: u32 = 0; 1const _: u32 = 0;
2const FOO: u32 = 92; 2const FOO: u32 = 92;
3const mut BAR: u32 = 62;