aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/ast_transform.rs7
-rw-r--r--crates/ra_cargo_watch/Cargo.toml2
-rw-r--r--crates/ra_hir/src/semantics.rs7
-rw-r--r--crates/ra_hir/src/source_analyzer.rs27
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs36
-rw-r--r--crates/ra_hir_def/src/path/lower.rs4
-rw-r--r--crates/ra_hir_def/src/path/lower/lower_use.rs11
-rw-r--r--crates/ra_hir_ty/Cargo.toml8
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs13
-rw-r--r--crates/ra_hir_ty/src/infer/unify.rs15
-rw-r--r--crates/ra_hir_ty/src/lib.rs4
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs13
-rw-r--r--crates/ra_hir_ty/src/tests/method_resolution.rs19
-rw-r--r--crates/ra_hir_ty/src/tests/patterns.rs93
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs41
-rw-r--r--crates/ra_ide/src/completion/complete_dot.rs39
-rw-r--r--crates/ra_ide/src/goto_definition.rs6
-rw-r--r--crates/ra_ide/src/hover.rs2
-rw-r--r--crates/ra_ide/src/references.rs8
-rw-r--r--crates/ra_ide/src/references/classify.rs39
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs30
-rw-r--r--crates/ra_ide_db/src/defs.rs30
-rw-r--r--crates/rust-analyzer/Cargo.toml2
-rw-r--r--crates/rust-analyzer/src/caps.rs4
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs4
-rw-r--r--crates/rust-analyzer/src/req.rs18
-rw-r--r--crates/rust-analyzer/src/semantic_tokens.rs3
27 files changed, 369 insertions, 116 deletions
diff --git a/crates/ra_assists/src/ast_transform.rs b/crates/ra_assists/src/ast_transform.rs
index 0e53c1eee..42856f0ca 100644
--- a/crates/ra_assists/src/ast_transform.rs
+++ b/crates/ra_assists/src/ast_transform.rs
@@ -178,5 +178,10 @@ impl<'a> AstTransform<'a> for QualifyPaths<'a> {
178 178
179pub(crate) fn path_to_ast(path: hir::ModPath) -> ast::Path { 179pub(crate) fn path_to_ast(path: hir::ModPath) -> ast::Path {
180 let parse = ast::SourceFile::parse(&path.to_string()); 180 let parse = ast::SourceFile::parse(&path.to_string());
181 parse.tree().syntax().descendants().find_map(ast::Path::cast).unwrap() 181 parse
182 .tree()
183 .syntax()
184 .descendants()
185 .find_map(ast::Path::cast)
186 .unwrap_or_else(|| panic!("failed to parse path {:?}, `{}`", path, path))
182} 187}
diff --git a/crates/ra_cargo_watch/Cargo.toml b/crates/ra_cargo_watch/Cargo.toml
index 1fdbffea1..731d50371 100644
--- a/crates/ra_cargo_watch/Cargo.toml
+++ b/crates/ra_cargo_watch/Cargo.toml
@@ -6,7 +6,7 @@ authors = ["rust-analyzer developers"]
6 6
7[dependencies] 7[dependencies]
8crossbeam-channel = "0.4.0" 8crossbeam-channel = "0.4.0"
9lsp-types = { version = "0.71.0", features = ["proposed"] } 9lsp-types = { version = "0.72.0", features = ["proposed"] }
10log = "0.4.8" 10log = "0.4.8"
11cargo_metadata = "0.9.1" 11cargo_metadata = "0.9.1"
12serde_json = "1.0.48" 12serde_json = "1.0.48"
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index a0853957c..afc7f7ee7 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -107,8 +107,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
107 self.analyze(field.syntax()).resolve_field(field) 107 self.analyze(field.syntax()).resolve_field(field)
108 } 108 }
109 109
110 pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<StructField> { 110 pub fn resolve_record_field(
111 self.analyze(field.syntax()).resolve_record_field(field) 111 &self,
112 field: &ast::RecordField,
113 ) -> Option<(StructField, Option<Local>)> {
114 self.analyze(field.syntax()).resolve_record_field(self.db, field)
112 } 115 }
113 116
114 pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<VariantDef> { 117 pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<VariantDef> {
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 4c121eb73..015389fb0 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -5,7 +5,7 @@
5//! 5//!
6//! So, this modules should not be used during hir construction, it exists 6//! So, this modules should not be used during hir construction, it exists
7//! purely for "IDE needs". 7//! purely for "IDE needs".
8use std::sync::Arc; 8use std::{iter::once, sync::Arc};
9 9
10use either::Either; 10use either::Either;
11use hir_def::{ 11use hir_def::{
@@ -25,8 +25,8 @@ use ra_syntax::{
25}; 25};
26 26
27use crate::{ 27use crate::{
28 db::HirDatabase, Adt, Const, EnumVariant, Function, Local, MacroDef, ModuleDef, Path, Static, 28 db::HirDatabase, Adt, Const, EnumVariant, Function, Local, MacroDef, ModPath, ModuleDef, Path,
29 Struct, Trait, Type, TypeAlias, TypeParam, 29 PathKind, Static, Struct, Trait, Type, TypeAlias, TypeParam,
30}; 30};
31 31
32/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of 32/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
@@ -162,16 +162,27 @@ impl SourceAnalyzer {
162 162
163 pub(crate) fn resolve_record_field( 163 pub(crate) fn resolve_record_field(
164 &self, 164 &self,
165 db: &impl HirDatabase,
165 field: &ast::RecordField, 166 field: &ast::RecordField,
166 ) -> Option<crate::StructField> { 167 ) -> Option<(crate::StructField, Option<Local>)> {
167 let expr_id = match field.expr() { 168 let (expr_id, local) = match field.expr() {
168 Some(it) => self.expr_id(&it)?, 169 Some(it) => (self.expr_id(&it)?, None),
169 None => { 170 None => {
170 let src = InFile { file_id: self.file_id, value: field }; 171 let src = InFile { file_id: self.file_id, value: field };
171 self.body_source_map.as_ref()?.field_init_shorthand_expr(src)? 172 let expr_id = self.body_source_map.as_ref()?.field_init_shorthand_expr(src)?;
173 let local_name = field.name_ref()?.as_name();
174 let path = ModPath::from_segments(PathKind::Plain, once(local_name));
175 let local = match self.resolver.resolve_path_in_value_ns_fully(db, &path) {
176 Some(ValueNs::LocalBinding(pat_id)) => {
177 Some(Local { pat_id, parent: self.resolver.body_owner()? })
178 }
179 _ => None,
180 };
181 (expr_id, local)
172 } 182 }
173 }; 183 };
174 self.infer.as_ref()?.record_field_resolution(expr_id).map(|it| it.into()) 184 let struct_field = self.infer.as_ref()?.record_field_resolution(expr_id)?;
185 Some((struct_field.into(), local))
175 } 186 }
176 187
177 pub(crate) fn resolve_record_literal( 188 pub(crate) fn resolve_record_literal(
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs
index 82f0f835c..dda5ed699 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -66,6 +66,42 @@ fn crate_def_map_smoke_test() {
66} 66}
67 67
68#[test] 68#[test]
69fn crate_def_map_super_super() {
70 let map = def_map(
71 "
72 //- /lib.rs
73 mod a {
74 const A: usize = 0;
75
76 mod b {
77 const B: usize = 0;
78
79 mod c {
80 use super::super::*;
81 }
82 }
83 }
84 ",
85 );
86 assert_snapshot!(map, @r###"
87 ⋮crate
88 ⋮a: t
89
90 ⋮crate::a
91 ⋮A: v
92 ⋮b: t
93
94 ⋮crate::a::b
95 ⋮B: v
96 ⋮c: t
97
98 ⋮crate::a::b::c
99 ⋮A: v
100 ⋮b: t
101 "###)
102}
103
104#[test]
69fn bogus_paths() { 105fn bogus_paths() {
70 covers!(bogus_paths); 106 covers!(bogus_paths);
71 let map = def_map( 107 let map = def_map(
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs
index 62aafd508..4900000fe 100644
--- a/crates/ra_hir_def/src/path/lower.rs
+++ b/crates/ra_hir_def/src/path/lower.rs
@@ -101,8 +101,8 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
101 break; 101 break;
102 } 102 }
103 ast::PathSegmentKind::SuperKw => { 103 ast::PathSegmentKind::SuperKw => {
104 kind = PathKind::Super(1); 104 let nested_super_count = if let PathKind::Super(n) = kind { n } else { 0 };
105 break; 105 kind = PathKind::Super(nested_super_count + 1);
106 } 106 }
107 } 107 }
108 path = match qualifier(&path) { 108 path = match qualifier(&path) {
diff --git a/crates/ra_hir_def/src/path/lower/lower_use.rs b/crates/ra_hir_def/src/path/lower/lower_use.rs
index b6d1125e2..278d5196e 100644
--- a/crates/ra_hir_def/src/path/lower/lower_use.rs
+++ b/crates/ra_hir_def/src/path/lower/lower_use.rs
@@ -103,10 +103,13 @@ fn convert_path(prefix: Option<ModPath>, path: ast::Path, hygiene: &Hygiene) ->
103 ModPath::from_segments(PathKind::Super(0), iter::empty()) 103 ModPath::from_segments(PathKind::Super(0), iter::empty())
104 } 104 }
105 ast::PathSegmentKind::SuperKw => { 105 ast::PathSegmentKind::SuperKw => {
106 if prefix.is_some() { 106 let nested_super_count = match prefix.map(|p| p.kind) {
107 return None; 107 Some(PathKind::Super(n)) => n,
108 } 108 Some(_) => return None,
109 ModPath::from_segments(PathKind::Super(1), iter::empty()) 109 None => 0,
110 };
111
112 ModPath::from_segments(PathKind::Super(nested_super_count + 1), iter::empty())
110 } 113 }
111 ast::PathSegmentKind::Type { .. } => { 114 ast::PathSegmentKind::Type { .. } => {
112 // not allowed in imports 115 // not allowed in imports
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml
index 99e2fe1bf..f2558b579 100644
--- a/crates/ra_hir_ty/Cargo.toml
+++ b/crates/ra_hir_ty/Cargo.toml
@@ -21,11 +21,9 @@ ra_prof = { path = "../ra_prof" }
21ra_syntax = { path = "../ra_syntax" } 21ra_syntax = { path = "../ra_syntax" }
22test_utils = { path = "../test_utils" } 22test_utils = { path = "../test_utils" }
23 23
24chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "2939913fb7bb94ac2a6721087dc086be11410702" } 24chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "177d71340acc7a7204a33115fc63075d86452179" }
25chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "2939913fb7bb94ac2a6721087dc086be11410702" } 25chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "177d71340acc7a7204a33115fc63075d86452179" }
26chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "2939913fb7bb94ac2a6721087dc086be11410702" } 26chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "177d71340acc7a7204a33115fc63075d86452179" }
27
28lalrpop-intern = "0.15.1"
29 27
30[dev-dependencies] 28[dev-dependencies]
31insta = "0.13.1" 29insta = "0.13.1"
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs
index bf8ea192b..7a84e47f8 100644
--- a/crates/ra_hir_ty/src/infer/pat.rs
+++ b/crates/ra_hir_ty/src/infer/pat.rs
@@ -185,6 +185,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
185 self.write_pat_ty(pat, bound_ty); 185 self.write_pat_ty(pat, bound_ty);
186 return inner_ty; 186 return inner_ty;
187 } 187 }
188 Pat::Slice { prefix, slice: _slice, suffix } => {
189 let (container_ty, elem_ty) = match &expected {
190 ty_app!(TypeCtor::Array, st) => (TypeCtor::Array, st.as_single().clone()),
191 ty_app!(TypeCtor::Slice, st) => (TypeCtor::Slice, st.as_single().clone()),
192 _ => (TypeCtor::Slice, Ty::Unknown),
193 };
194
195 for pat_id in prefix.iter().chain(suffix) {
196 self.infer_pat(*pat_id, &elem_ty, default_bm);
197 }
198
199 Ty::apply_one(container_ty, elem_ty)
200 }
188 _ => Ty::Unknown, 201 _ => Ty::Unknown,
189 }; 202 };
190 // use a new type variable if we got Ty::Unknown here 203 // use a new type variable if we got Ty::Unknown here
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs
index aed527fe5..82b85d570 100644
--- a/crates/ra_hir_ty/src/infer/unify.rs
+++ b/crates/ra_hir_ty/src/infer/unify.rs
@@ -142,12 +142,21 @@ impl<T> Canonicalized<T> {
142 142
143pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> { 143pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> {
144 let mut table = InferenceTable::new(); 144 let mut table = InferenceTable::new();
145 let num_vars = ty1.num_vars.max(ty2.num_vars);
145 let vars = 146 let vars =
146 Substs::builder(ty1.num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build(); 147 Substs::builder(num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build();
147 let ty_with_vars = ty1.value.clone().subst_bound_vars(&vars); 148 let ty1_with_vars = ty1.value.clone().subst_bound_vars(&vars);
148 if !table.unify(&ty_with_vars, &ty2.value) { 149 let ty2_with_vars = ty2.value.clone().subst_bound_vars(&vars);
150 if !table.unify(&ty1_with_vars, &ty2_with_vars) {
149 return None; 151 return None;
150 } 152 }
153 // default any type vars that weren't unified back to their original bound vars
154 // (kind of hacky)
155 for (i, var) in vars.iter().enumerate() {
156 if &*table.resolve_ty_shallow(var) == var {
157 table.unify(var, &Ty::Bound(i as u32));
158 }
159 }
151 Some( 160 Some(
152 Substs::builder(ty1.num_vars) 161 Substs::builder(ty1.num_vars)
153 .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) 162 .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone())))
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 0009c426c..ca194f806 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -355,6 +355,10 @@ impl Substs {
355 Substs(self.0[..std::cmp::min(self.0.len(), n)].into()) 355 Substs(self.0[..std::cmp::min(self.0.len(), n)].into())
356 } 356 }
357 357
358 pub fn suffix(&self, n: usize) -> Substs {
359 Substs(self.0[self.0.len() - std::cmp::min(self.0.len(), n)..].into())
360 }
361
358 pub fn as_single(&self) -> &Ty { 362 pub fn as_single(&self) -> &Ty {
359 if self.0.len() != 1 { 363 if self.0.len() != 1 {
360 panic!("expected substs of len 1, got {:?}", self); 364 panic!("expected substs of len 1, got {:?}", self);
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index 74b908c2e..b7e8855fb 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -508,10 +508,17 @@ pub(crate) fn inherent_impl_substs(
508 impl_id: ImplId, 508 impl_id: ImplId,
509 self_ty: &Canonical<Ty>, 509 self_ty: &Canonical<Ty>,
510) -> Option<Substs> { 510) -> Option<Substs> {
511 let vars = Substs::build_for_def(db, impl_id).fill_with_bound_vars(0).build(); 511 // we create a var for each type parameter of the impl; we need to keep in
512 // mind here that `self_ty` might have vars of its own
513 let vars =
514 Substs::build_for_def(db, impl_id).fill_with_bound_vars(self_ty.num_vars as u32).build();
512 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); 515 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
513 let self_ty_with_vars = Canonical { num_vars: vars.len(), value: self_ty_with_vars }; 516 let self_ty_with_vars =
514 super::infer::unify(&self_ty_with_vars, self_ty) 517 Canonical { num_vars: vars.len() + self_ty.num_vars, value: self_ty_with_vars };
518 let substs = super::infer::unify(&self_ty_with_vars, self_ty);
519 // we only want the substs for the vars we added, not the ones from self_ty
520 let result = substs.map(|s| s.suffix(vars.len()));
521 result
515} 522}
516 523
517fn transform_receiver_ty( 524fn transform_receiver_ty(
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs
index f9b394f05..af3e5b12c 100644
--- a/crates/ra_hir_ty/src/tests/method_resolution.rs
+++ b/crates/ra_hir_ty/src/tests/method_resolution.rs
@@ -1049,6 +1049,25 @@ where
1049} 1049}
1050 1050
1051#[test] 1051#[test]
1052fn method_resolution_3373() {
1053 let t = type_at(
1054 r#"
1055//- /main.rs
1056struct A<T>(T);
1057
1058impl A<i32> {
1059 fn from(v: i32) -> A<i32> { A(v) }
1060}
1061
1062fn main() {
1063 A::from(3)<|>;
1064}
1065"#,
1066 );
1067 assert_eq!(t, "A<i32>");
1068}
1069
1070#[test]
1052fn method_resolution_slow() { 1071fn method_resolution_slow() {
1053 // this can get quite slow if we set the solver size limit too high 1072 // this can get quite slow if we set the solver size limit too high
1054 let t = type_at( 1073 let t = type_at(
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs
index 81d00c2af..76aa32024 100644
--- a/crates/ra_hir_ty/src/tests/patterns.rs
+++ b/crates/ra_hir_ty/src/tests/patterns.rs
@@ -53,8 +53,9 @@ fn test(x: &i32) {
53 [140; 141) 'g': {unknown} 53 [140; 141) 'g': {unknown}
54 [144; 145) 'e': {unknown} 54 [144; 145) 'e': {unknown}
55 [158; 205) 'if let... }': () 55 [158; 205) 'if let... }': ()
56 [165; 170) '[val]': {unknown} 56 [165; 170) '[val]': [{unknown}]
57 [173; 176) 'opt': {unknown} 57 [166; 169) 'val': {unknown}
58 [173; 176) 'opt': [{unknown}]
58 [177; 205) '{ ... }': () 59 [177; 205) '{ ... }': ()
59 [191; 192) 'h': {unknown} 60 [191; 192) 'h': {unknown}
60 [195; 198) 'val': {unknown} 61 [195; 198) 'val': {unknown}
@@ -137,6 +138,94 @@ fn test() {
137} 138}
138 139
139#[test] 140#[test]
141fn infer_pattern_match_slice() {
142 assert_snapshot!(
143 infer(r#"
144fn test() {
145 let slice: &[f64] = &[0.0];
146 match slice {
147 &[] => {},
148 &[a] => {
149 a;
150 },
151 &[b, c] => {
152 b;
153 c;
154 }
155 _ => {}
156 }
157}
158"#),
159 @r###"
160 [11; 210) '{ ... } }': ()
161 [21; 26) 'slice': &[f64]
162 [37; 43) '&[0.0]': &[f64; _]
163 [38; 43) '[0.0]': [f64; _]
164 [39; 42) '0.0': f64
165 [49; 208) 'match ... }': ()
166 [55; 60) 'slice': &[f64]
167 [71; 74) '&[]': &[f64]
168 [72; 74) '[]': [f64]
169 [78; 80) '{}': ()
170 [90; 94) '&[a]': &[f64]
171 [91; 94) '[a]': [f64]
172 [92; 93) 'a': f64
173 [98; 124) '{ ... }': ()
174 [112; 113) 'a': f64
175 [134; 141) '&[b, c]': &[f64]
176 [135; 141) '[b, c]': [f64]
177 [136; 137) 'b': f64
178 [139; 140) 'c': f64
179 [145; 186) '{ ... }': ()
180 [159; 160) 'b': f64
181 [174; 175) 'c': f64
182 [195; 196) '_': &[f64]
183 [200; 202) '{}': ()
184 "###
185 );
186}
187
188#[test]
189fn infer_pattern_match_arr() {
190 assert_snapshot!(
191 infer(r#"
192fn test() {
193 let arr: [f64; 2] = [0.0, 1.0];
194 match arr {
195 [1.0, a] => {
196 a;
197 },
198 [b, c] => {
199 b;
200 c;
201 }
202 }
203}
204"#),
205 @r###"
206 [11; 180) '{ ... } }': ()
207 [21; 24) 'arr': [f64; _]
208 [37; 47) '[0.0, 1.0]': [f64; _]
209 [38; 41) '0.0': f64
210 [43; 46) '1.0': f64
211 [53; 178) 'match ... }': ()
212 [59; 62) 'arr': [f64; _]
213 [73; 81) '[1.0, a]': [f64; _]
214 [74; 77) '1.0': f64
215 [79; 80) 'a': f64
216 [85; 111) '{ ... }': ()
217 [99; 100) 'a': f64
218 [121; 127) '[b, c]': [f64; _]
219 [122; 123) 'b': f64
220 [125; 126) 'c': f64
221 [131; 172) '{ ... }': ()
222 [145; 146) 'b': f64
223 [160; 161) 'c': f64
224 "###
225 );
226}
227
228#[test]
140fn infer_adt_pattern() { 229fn infer_adt_pattern() {
141 assert_snapshot!( 230 assert_snapshot!(
142 infer(r#" 231 infer(r#"
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index 4001aa941..62509bc29 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -18,7 +18,7 @@ use crate::{
18}; 18};
19 19
20#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] 20#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
21pub struct Interner {} 21pub struct Interner;
22 22
23impl chalk_ir::interner::Interner for Interner { 23impl chalk_ir::interner::Interner for Interner {
24 type InternedType = Box<chalk_ir::TyData<Self>>; 24 type InternedType = Box<chalk_ir::TyData<Self>>;
@@ -27,6 +27,7 @@ impl chalk_ir::interner::Interner for Interner {
27 type InternedGoal = Arc<GoalData<Self>>; 27 type InternedGoal = Arc<GoalData<Self>>;
28 type InternedGoals = Vec<Goal<Self>>; 28 type InternedGoals = Vec<Goal<Self>>;
29 type InternedSubstitution = Vec<Parameter<Self>>; 29 type InternedSubstitution = Vec<Parameter<Self>>;
30 type Identifier = TypeAliasId;
30 type DefId = InternId; 31 type DefId = InternId;
31 32
32 // FIXME: implement these 33 // FIXME: implement these
@@ -58,7 +59,7 @@ impl chalk_ir::interner::Interner for Interner {
58 None 59 None
59 } 60 }
60 61
61 fn intern_ty(ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> { 62 fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> {
62 Box::new(ty) 63 Box::new(ty)
63 } 64 }
64 65
@@ -121,7 +122,7 @@ pub type StructId = chalk_ir::StructId<Interner>;
121pub type StructDatum = chalk_rust_ir::StructDatum<Interner>; 122pub type StructDatum = chalk_rust_ir::StructDatum<Interner>;
122pub type ImplId = chalk_ir::ImplId<Interner>; 123pub type ImplId = chalk_ir::ImplId<Interner>;
123pub type ImplDatum = chalk_rust_ir::ImplDatum<Interner>; 124pub type ImplDatum = chalk_rust_ir::ImplDatum<Interner>;
124pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId; 125pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId<Interner>;
125pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<Interner>; 126pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<Interner>;
126 127
127pub(super) trait ToChalk { 128pub(super) trait ToChalk {
@@ -144,12 +145,12 @@ impl ToChalk for Ty {
144 Ty::Apply(apply_ty) => { 145 Ty::Apply(apply_ty) => {
145 let name = apply_ty.ctor.to_chalk(db); 146 let name = apply_ty.ctor.to_chalk(db);
146 let substitution = apply_ty.parameters.to_chalk(db); 147 let substitution = apply_ty.parameters.to_chalk(db);
147 chalk_ir::ApplicationTy { name, substitution }.cast().intern() 148 chalk_ir::ApplicationTy { name, substitution }.cast().intern(&Interner)
148 } 149 }
149 Ty::Projection(proj_ty) => { 150 Ty::Projection(proj_ty) => {
150 let associated_ty_id = proj_ty.associated_ty.to_chalk(db); 151 let associated_ty_id = proj_ty.associated_ty.to_chalk(db);
151 let substitution = proj_ty.parameters.to_chalk(db); 152 let substitution = proj_ty.parameters.to_chalk(db);
152 chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern() 153 chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern(&Interner)
153 } 154 }
154 Ty::Placeholder(id) => { 155 Ty::Placeholder(id) => {
155 let interned_id = db.intern_type_param_id(id); 156 let interned_id = db.intern_type_param_id(id);
@@ -157,9 +158,9 @@ impl ToChalk for Ty {
157 ui: UniverseIndex::ROOT, 158 ui: UniverseIndex::ROOT,
158 idx: interned_id.as_intern_id().as_usize(), 159 idx: interned_id.as_intern_id().as_usize(),
159 } 160 }
160 .to_ty::<Interner>() 161 .to_ty::<Interner>(&Interner)
161 } 162 }
162 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), 163 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(&Interner),
163 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), 164 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
164 Ty::Dyn(predicates) => { 165 Ty::Dyn(predicates) => {
165 let where_clauses = predicates 166 let where_clauses = predicates
@@ -169,12 +170,12 @@ impl ToChalk for Ty {
169 .map(|p| p.to_chalk(db)) 170 .map(|p| p.to_chalk(db))
170 .collect(); 171 .collect();
171 let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) }; 172 let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) };
172 chalk_ir::TyData::Dyn(bounded_ty).intern() 173 chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner)
173 } 174 }
174 Ty::Opaque(_) | Ty::Unknown => { 175 Ty::Opaque(_) | Ty::Unknown => {
175 let substitution = chalk_ir::Substitution::empty(); 176 let substitution = chalk_ir::Substitution::empty();
176 let name = TypeName::Error; 177 let name = TypeName::Error;
177 chalk_ir::ApplicationTy { name, substitution }.cast().intern() 178 chalk_ir::ApplicationTy { name, substitution }.cast().intern(&Interner)
178 } 179 }
179 } 180 }
180 } 181 }
@@ -611,6 +612,9 @@ where
611 _ => None, 612 _ => None,
612 } 613 }
613 } 614 }
615 fn interner(&self) -> &Interner {
616 &Interner
617 }
614} 618}
615 619
616pub(crate) fn associated_ty_data_query( 620pub(crate) fn associated_ty_data_query(
@@ -632,7 +636,7 @@ pub(crate) fn associated_ty_data_query(
632 let datum = AssociatedTyDatum { 636 let datum = AssociatedTyDatum {
633 trait_id: trait_.to_chalk(db), 637 trait_id: trait_.to_chalk(db),
634 id, 638 id,
635 name: lalrpop_intern::intern(&db.type_alias_data(type_alias).name.to_string()), 639 name: type_alias,
636 binders: make_binders(bound_data, generic_params.len()), 640 binders: make_binders(bound_data, generic_params.len()),
637 }; 641 };
638 Arc::new(datum) 642 Arc::new(datum)
@@ -822,13 +826,6 @@ fn type_alias_associated_ty_value(
822 Arc::new(value) 826 Arc::new(value)
823} 827}
824 828
825fn id_from_chalk<T: InternKey>(chalk_id: chalk_ir::RawId) -> T {
826 T::from_intern_id(InternId::from(chalk_id.index))
827}
828fn id_to_chalk<T: InternKey>(salsa_id: T) -> chalk_ir::RawId {
829 chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() }
830}
831
832impl From<StructId> for crate::TypeCtorId { 829impl From<StructId> for crate::TypeCtorId {
833 fn from(struct_id: StructId) -> Self { 830 fn from(struct_id: StructId) -> Self {
834 InternKey::from_intern_id(struct_id.0) 831 InternKey::from_intern_id(struct_id.0)
@@ -853,14 +850,14 @@ impl From<crate::traits::GlobalImplId> for ImplId {
853 } 850 }
854} 851}
855 852
856impl From<chalk_rust_ir::AssociatedTyValueId> for crate::traits::AssocTyValueId { 853impl From<chalk_rust_ir::AssociatedTyValueId<Interner>> for crate::traits::AssocTyValueId {
857 fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self { 854 fn from(id: chalk_rust_ir::AssociatedTyValueId<Interner>) -> Self {
858 id_from_chalk(id.0) 855 Self::from_intern_id(id.0)
859 } 856 }
860} 857}
861 858
862impl From<crate::traits::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId { 859impl From<crate::traits::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId<Interner> {
863 fn from(assoc_ty_value_id: crate::traits::AssocTyValueId) -> Self { 860 fn from(assoc_ty_value_id: crate::traits::AssocTyValueId) -> Self {
864 chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id)) 861 chalk_rust_ir::AssociatedTyValueId(assoc_ty_value_id.as_intern_id())
865 } 862 }
866} 863}
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs
index a6e0158b2..9145aa183 100644
--- a/crates/ra_ide/src/completion/complete_dot.rs
+++ b/crates/ra_ide/src/completion/complete_dot.rs
@@ -545,4 +545,43 @@ mod tests {
545 "### 545 "###
546 ) 546 )
547 } 547 }
548
549 #[test]
550 fn test_super_super_completion() {
551 assert_debug_snapshot!(
552 do_ref_completion(
553 r"
554 mod a {
555 const A: usize = 0;
556
557 mod b {
558 const B: usize = 0;
559
560 mod c {
561 use super::super::<|>
562 }
563 }
564 }
565 ",
566 ),
567 @r###"
568 [
569 CompletionItem {
570 label: "A",
571 source_range: [217; 217),
572 delete: [217; 217),
573 insert: "A",
574 kind: Const,
575 },
576 CompletionItem {
577 label: "b",
578 source_range: [217; 217),
579 delete: [217; 217),
580 insert: "b",
581 kind: Module,
582 },
583 ]
584 "###
585 );
586 }
548} 587}
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs
index e67585203..76ee232a3 100644
--- a/crates/ra_ide/src/goto_definition.rs
+++ b/crates/ra_ide/src/goto_definition.rs
@@ -76,6 +76,8 @@ pub(crate) fn reference_definition(
76 76
77 let name_kind = classify_name_ref(sema, name_ref); 77 let name_kind = classify_name_ref(sema, name_ref);
78 if let Some(def) = name_kind { 78 if let Some(def) = name_kind {
79 let def = def.definition();
80
79 return match def.try_to_nav(sema.db) { 81 return match def.try_to_nav(sema.db) {
80 Some(nav) => ReferenceResult::Exact(nav), 82 Some(nav) => ReferenceResult::Exact(nav),
81 None => ReferenceResult::Approximate(Vec::new()), 83 None => ReferenceResult::Approximate(Vec::new()),
@@ -795,8 +797,8 @@ mod tests {
795 Foo { x<|> }; 797 Foo { x<|> };
796 } 798 }
797 ", 799 ",
798 "x RECORD_FIELD_DEF FileId(1) [13; 19) [13; 14)", 800 "x BIND_PAT FileId(1) [42; 43)",
799 "x: i32|x", 801 "x",
800 ) 802 )
801 } 803 }
802} 804}
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index 5073bb1cf..b31956626 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -153,7 +153,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
153 if let Some((node, name_kind)) = match_ast! { 153 if let Some((node, name_kind)) = match_ast! {
154 match (token.parent()) { 154 match (token.parent()) {
155 ast::NameRef(name_ref) => { 155 ast::NameRef(name_ref) => {
156 classify_name_ref(&sema, &name_ref).map(|d| (name_ref.syntax().clone(), d)) 156 classify_name_ref(&sema, &name_ref).map(|d| (name_ref.syntax().clone(), d.definition()))
157 }, 157 },
158 ast::Name(name) => { 158 ast::Name(name) => {
159 classify_name(&sema, &name).map(|d| (name.syntax().clone(), d.definition())) 159 classify_name(&sema, &name).map(|d| (name.syntax().clone(), d.definition()))
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs
index f763013ae..2eb047c96 100644
--- a/crates/ra_ide/src/references.rs
+++ b/crates/ra_ide/src/references.rs
@@ -27,7 +27,10 @@ use test_utils::tested_by;
27 27
28use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo}; 28use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo};
29 29
30pub(crate) use self::{classify::classify_name_ref, rename::rename}; 30pub(crate) use self::{
31 classify::{classify_name_ref, NameRefClass},
32 rename::rename,
33};
31pub(crate) use ra_ide_db::defs::{classify_name, NameDefinition}; 34pub(crate) use ra_ide_db::defs::{classify_name, NameDefinition};
32 35
33pub use self::search_scope::SearchScope; 36pub use self::search_scope::SearchScope;
@@ -160,7 +163,7 @@ fn find_name(
160 return Some(RangeInfo::new(range, (name.text().to_string(), def))); 163 return Some(RangeInfo::new(range, (name.text().to_string(), def)));
161 } 164 }
162 let name_ref = find_node_at_offset::<ast::NameRef>(&syntax, position.offset)?; 165 let name_ref = find_node_at_offset::<ast::NameRef>(&syntax, position.offset)?;
163 let def = classify_name_ref(sema, &name_ref)?; 166 let def = classify_name_ref(sema, &name_ref)?.definition();
164 let range = name_ref.syntax().text_range(); 167 let range = name_ref.syntax().text_range();
165 Some(RangeInfo::new(range, (name_ref.text().to_string(), def))) 168 Some(RangeInfo::new(range, (name_ref.text().to_string(), def)))
166} 169}
@@ -212,6 +215,7 @@ fn process_definition(
212 // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098 215 // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098
213 216
214 if let Some(d) = classify_name_ref(&sema, &name_ref) { 217 if let Some(d) = classify_name_ref(&sema, &name_ref) {
218 let d = d.definition();
215 if d == def { 219 if d == def {
216 let kind = 220 let kind =
217 if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) { 221 if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) {
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs
index fdd07d8d1..571236fdc 100644
--- a/crates/ra_ide/src/references/classify.rs
+++ b/crates/ra_ide/src/references/classify.rs
@@ -1,18 +1,30 @@
1//! Functions that are used to classify an element from its definition or reference. 1//! Functions that are used to classify an element from its definition or reference.
2 2
3use hir::{PathResolution, Semantics}; 3use hir::{Local, PathResolution, Semantics};
4use ra_ide_db::defs::NameDefinition; 4use ra_ide_db::defs::NameDefinition;
5use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
6use ra_prof::profile; 6use ra_prof::profile;
7use ra_syntax::{ast, AstNode}; 7use ra_syntax::{ast, AstNode};
8use test_utils::tested_by; 8use test_utils::tested_by;
9 9
10pub use ra_ide_db::defs::{from_module_def, from_struct_field}; 10pub enum NameRefClass {
11 NameDefinition(NameDefinition),
12 FieldShorthand { local: Local, field: NameDefinition },
13}
14
15impl NameRefClass {
16 pub fn definition(self) -> NameDefinition {
17 match self {
18 NameRefClass::NameDefinition(def) => def,
19 NameRefClass::FieldShorthand { local, field: _ } => NameDefinition::Local(local),
20 }
21 }
22}
11 23
12pub(crate) fn classify_name_ref( 24pub(crate) fn classify_name_ref(
13 sema: &Semantics<RootDatabase>, 25 sema: &Semantics<RootDatabase>,
14 name_ref: &ast::NameRef, 26 name_ref: &ast::NameRef,
15) -> Option<NameDefinition> { 27) -> Option<NameRefClass> {
16 let _p = profile("classify_name_ref"); 28 let _p = profile("classify_name_ref");
17 29
18 let parent = name_ref.syntax().parent()?; 30 let parent = name_ref.syntax().parent()?;
@@ -20,48 +32,53 @@ pub(crate) fn classify_name_ref(
20 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { 32 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
21 tested_by!(goto_def_for_methods); 33 tested_by!(goto_def_for_methods);
22 if let Some(func) = sema.resolve_method_call(&method_call) { 34 if let Some(func) = sema.resolve_method_call(&method_call) {
23 return Some(from_module_def(func.into())); 35 return Some(NameRefClass::NameDefinition(NameDefinition::ModuleDef(func.into())));
24 } 36 }
25 } 37 }
26 38
27 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { 39 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) {
28 tested_by!(goto_def_for_fields); 40 tested_by!(goto_def_for_fields);
29 if let Some(field) = sema.resolve_field(&field_expr) { 41 if let Some(field) = sema.resolve_field(&field_expr) {
30 return Some(from_struct_field(field)); 42 return Some(NameRefClass::NameDefinition(NameDefinition::StructField(field)));
31 } 43 }
32 } 44 }
33 45
34 if let Some(record_field) = ast::RecordField::cast(parent.clone()) { 46 if let Some(record_field) = ast::RecordField::cast(parent.clone()) {
35 tested_by!(goto_def_for_record_fields); 47 tested_by!(goto_def_for_record_fields);
36 tested_by!(goto_def_for_field_init_shorthand); 48 tested_by!(goto_def_for_field_init_shorthand);
37 if let Some(field_def) = sema.resolve_record_field(&record_field) { 49 if let Some((field, local)) = sema.resolve_record_field(&record_field) {
38 return Some(from_struct_field(field_def)); 50 let field = NameDefinition::StructField(field);
51 let res = match local {
52 None => NameRefClass::NameDefinition(field),
53 Some(local) => NameRefClass::FieldShorthand { field, local },
54 };
55 return Some(res);
39 } 56 }
40 } 57 }
41 58
42 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { 59 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
43 tested_by!(goto_def_for_macros); 60 tested_by!(goto_def_for_macros);
44 if let Some(macro_def) = sema.resolve_macro_call(&macro_call) { 61 if let Some(macro_def) = sema.resolve_macro_call(&macro_call) {
45 return Some(NameDefinition::Macro(macro_def)); 62 return Some(NameRefClass::NameDefinition(NameDefinition::Macro(macro_def)));
46 } 63 }
47 } 64 }
48 65
49 let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; 66 let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
50 let resolved = sema.resolve_path(&path)?; 67 let resolved = sema.resolve_path(&path)?;
51 let res = match resolved { 68 let res = match resolved {
52 PathResolution::Def(def) => from_module_def(def), 69 PathResolution::Def(def) => NameDefinition::ModuleDef(def),
53 PathResolution::AssocItem(item) => { 70 PathResolution::AssocItem(item) => {
54 let def = match item { 71 let def = match item {
55 hir::AssocItem::Function(it) => it.into(), 72 hir::AssocItem::Function(it) => it.into(),
56 hir::AssocItem::Const(it) => it.into(), 73 hir::AssocItem::Const(it) => it.into(),
57 hir::AssocItem::TypeAlias(it) => it.into(), 74 hir::AssocItem::TypeAlias(it) => it.into(),
58 }; 75 };
59 from_module_def(def) 76 NameDefinition::ModuleDef(def)
60 } 77 }
61 PathResolution::Local(local) => NameDefinition::Local(local), 78 PathResolution::Local(local) => NameDefinition::Local(local),
62 PathResolution::TypeParam(par) => NameDefinition::TypeParam(par), 79 PathResolution::TypeParam(par) => NameDefinition::TypeParam(par),
63 PathResolution::Macro(def) => NameDefinition::Macro(def), 80 PathResolution::Macro(def) => NameDefinition::Macro(def),
64 PathResolution::SelfType(impl_def) => NameDefinition::SelfType(impl_def), 81 PathResolution::SelfType(impl_def) => NameDefinition::SelfType(impl_def),
65 }; 82 };
66 Some(res) 83 Some(NameRefClass::NameDefinition(res))
67} 84}
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index 28117b4d8..b89501aff 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -19,7 +19,11 @@ use ra_syntax::{
19}; 19};
20use rustc_hash::FxHashMap; 20use rustc_hash::FxHashMap;
21 21
22use crate::{call_info::call_info_for_token, references::classify_name_ref, Analysis, FileId}; 22use crate::{
23 call_info::call_info_for_token,
24 references::{classify_name_ref, NameRefClass},
25 Analysis, FileId,
26};
23 27
24pub(crate) use html::highlight_as_html; 28pub(crate) use html::highlight_as_html;
25pub use tags::{Highlight, HighlightModifier, HighlightModifiers, HighlightTag}; 29pub use tags::{Highlight, HighlightModifier, HighlightModifiers, HighlightTag};
@@ -186,24 +190,24 @@ fn highlight_element(
186 } 190 }
187 191
188 // Highlight references like the definitions they resolve to 192 // Highlight references like the definitions they resolve to
189
190 // Special-case field init shorthand
191 NAME_REF if element.parent().and_then(ast::RecordField::cast).is_some() => {
192 HighlightTag::Field.into()
193 }
194 NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => return None, 193 NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => return None,
195 NAME_REF => { 194 NAME_REF => {
196 let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); 195 let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap();
197 let name_kind = classify_name_ref(sema, &name_ref)?; 196 let name_kind = classify_name_ref(sema, &name_ref)?;
198 197
199 if let NameDefinition::Local(local) = &name_kind { 198 match name_kind {
200 if let Some(name) = local.name(db) { 199 NameRefClass::NameDefinition(def) => {
201 let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); 200 if let NameDefinition::Local(local) = &def {
202 binding_hash = Some(calc_binding_hash(&name, *shadow_count)) 201 if let Some(name) = local.name(db) {
202 let shadow_count =
203 bindings_shadow_count.entry(name.clone()).or_default();
204 binding_hash = Some(calc_binding_hash(&name, *shadow_count))
205 }
206 };
207 highlight_name(db, def)
203 } 208 }
204 }; 209 NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(),
205 210 }
206 highlight_name(db, name_kind)
207 } 211 }
208 212
209 // Simple token-based highlighting 213 // Simple token-based highlighting
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs
index ad4638906..7b1030a14 100644
--- a/crates/ra_ide_db/src/defs.rs
+++ b/crates/ra_ide_db/src/defs.rs
@@ -111,47 +111,47 @@ fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Opti
111 }, 111 },
112 ast::RecordFieldDef(it) => { 112 ast::RecordFieldDef(it) => {
113 let field: hir::StructField = sema.to_def(&it)?; 113 let field: hir::StructField = sema.to_def(&it)?;
114 Some(from_struct_field(field)) 114 Some(NameDefinition::StructField(field))
115 }, 115 },
116 ast::Module(it) => { 116 ast::Module(it) => {
117 let def = sema.to_def(&it)?; 117 let def = sema.to_def(&it)?;
118 Some(from_module_def(def.into())) 118 Some(NameDefinition::ModuleDef(def.into()))
119 }, 119 },
120 ast::StructDef(it) => { 120 ast::StructDef(it) => {
121 let def: hir::Struct = sema.to_def(&it)?; 121 let def: hir::Struct = sema.to_def(&it)?;
122 Some(from_module_def(def.into())) 122 Some(NameDefinition::ModuleDef(def.into()))
123 }, 123 },
124 ast::UnionDef(it) => { 124 ast::UnionDef(it) => {
125 let def: hir::Union = sema.to_def(&it)?; 125 let def: hir::Union = sema.to_def(&it)?;
126 Some(from_module_def(def.into())) 126 Some(NameDefinition::ModuleDef(def.into()))
127 }, 127 },
128 ast::EnumDef(it) => { 128 ast::EnumDef(it) => {
129 let def: hir::Enum = sema.to_def(&it)?; 129 let def: hir::Enum = sema.to_def(&it)?;
130 Some(from_module_def(def.into())) 130 Some(NameDefinition::ModuleDef(def.into()))
131 }, 131 },
132 ast::TraitDef(it) => { 132 ast::TraitDef(it) => {
133 let def: hir::Trait = sema.to_def(&it)?; 133 let def: hir::Trait = sema.to_def(&it)?;
134 Some(from_module_def(def.into())) 134 Some(NameDefinition::ModuleDef(def.into()))
135 }, 135 },
136 ast::StaticDef(it) => { 136 ast::StaticDef(it) => {
137 let def: hir::Static = sema.to_def(&it)?; 137 let def: hir::Static = sema.to_def(&it)?;
138 Some(from_module_def(def.into())) 138 Some(NameDefinition::ModuleDef(def.into()))
139 }, 139 },
140 ast::EnumVariant(it) => { 140 ast::EnumVariant(it) => {
141 let def: hir::EnumVariant = sema.to_def(&it)?; 141 let def: hir::EnumVariant = sema.to_def(&it)?;
142 Some(from_module_def(def.into())) 142 Some(NameDefinition::ModuleDef(def.into()))
143 }, 143 },
144 ast::FnDef(it) => { 144 ast::FnDef(it) => {
145 let def: hir::Function = sema.to_def(&it)?; 145 let def: hir::Function = sema.to_def(&it)?;
146 Some(from_module_def(def.into())) 146 Some(NameDefinition::ModuleDef(def.into()))
147 }, 147 },
148 ast::ConstDef(it) => { 148 ast::ConstDef(it) => {
149 let def: hir::Const = sema.to_def(&it)?; 149 let def: hir::Const = sema.to_def(&it)?;
150 Some(from_module_def(def.into())) 150 Some(NameDefinition::ModuleDef(def.into()))
151 }, 151 },
152 ast::TypeAliasDef(it) => { 152 ast::TypeAliasDef(it) => {
153 let def: hir::TypeAlias = sema.to_def(&it)?; 153 let def: hir::TypeAlias = sema.to_def(&it)?;
154 Some(from_module_def(def.into())) 154 Some(NameDefinition::ModuleDef(def.into()))
155 }, 155 },
156 ast::MacroCall(it) => { 156 ast::MacroCall(it) => {
157 let def = sema.to_def(&it)?; 157 let def = sema.to_def(&it)?;
@@ -165,11 +165,3 @@ fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Opti
165 } 165 }
166 } 166 }
167} 167}
168
169pub fn from_struct_field(field: StructField) -> NameDefinition {
170 NameDefinition::StructField(field)
171}
172
173pub fn from_module_def(def: ModuleDef) -> NameDefinition {
174 NameDefinition::ModuleDef(def)
175}
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index d00545121..b14ebb268 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -20,7 +20,7 @@ globset = "0.4.4"
20itertools = "0.8.2" 20itertools = "0.8.2"
21jod-thread = "0.1.0" 21jod-thread = "0.1.0"
22log = "0.4.8" 22log = "0.4.8"
23lsp-types = { version = "0.71.0", features = ["proposed"] } 23lsp-types = { version = "0.72.0", features = ["proposed"] }
24parking_lot = "0.10.0" 24parking_lot = "0.10.0"
25pico-args = "0.3.1" 25pico-args = "0.3.1"
26rand = { version = "0.7.3", features = ["small_rng"] } 26rand = { version = "0.7.3", features = ["small_rng"] }
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index 759bceb32..45b60768a 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -63,8 +63,8 @@ pub fn server_capabilities() -> ServerCapabilities {
63 semantic_tokens_provider: Some( 63 semantic_tokens_provider: Some(
64 SemanticTokensOptions { 64 SemanticTokensOptions {
65 legend: SemanticTokensLegend { 65 legend: SemanticTokensLegend {
66 token_types: semantic_tokens::SUPPORTED_TYPES.iter().cloned().collect(), 66 token_types: semantic_tokens::SUPPORTED_TYPES.to_vec(),
67 token_modifiers: semantic_tokens::SUPPORTED_MODIFIERS.iter().cloned().collect(), 67 token_modifiers: semantic_tokens::SUPPORTED_MODIFIERS.to_vec(),
68 }, 68 },
69 69
70 document_provider: Some(SemanticTokensDocumentProvider::Bool(true)), 70 document_provider: Some(SemanticTokensDocumentProvider::Bool(true)),
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index 6f517760f..f51263f22 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -184,6 +184,10 @@ pub fn handle_on_type_formatting(
184 // `text.char_at(position) == typed_char`. 184 // `text.char_at(position) == typed_char`.
185 position.offset -= TextUnit::of_char('.'); 185 position.offset -= TextUnit::of_char('.');
186 let char_typed = params.ch.chars().next().unwrap_or('\0'); 186 let char_typed = params.ch.chars().next().unwrap_or('\0');
187 assert!({
188 let text = world.analysis().file_text(position.file_id)?;
189 text[position.offset.to_usize()..].starts_with(char_typed)
190 });
187 191
188 // We have an assist that inserts ` ` after typing `->` in `fn foo() ->{`, 192 // We have an assist that inserts ` ` after typing `->` in `fn foo() ->{`,
189 // but it requires precise cursor positioning to work, and one can't 193 // but it requires precise cursor positioning to work, and one can't
diff --git a/crates/rust-analyzer/src/req.rs b/crates/rust-analyzer/src/req.rs
index fd6aef597..a3efe3b9f 100644
--- a/crates/rust-analyzer/src/req.rs
+++ b/crates/rust-analyzer/src/req.rs
@@ -42,14 +42,14 @@ impl Request for SyntaxTree {
42 const METHOD: &'static str = "rust-analyzer/syntaxTree"; 42 const METHOD: &'static str = "rust-analyzer/syntaxTree";
43} 43}
44 44
45#[derive(Deserialize, Debug)] 45#[derive(Deserialize, Serialize, Debug)]
46#[serde(rename_all = "camelCase")] 46#[serde(rename_all = "camelCase")]
47pub struct SyntaxTreeParams { 47pub struct SyntaxTreeParams {
48 pub text_document: TextDocumentIdentifier, 48 pub text_document: TextDocumentIdentifier,
49 pub range: Option<Range>, 49 pub range: Option<Range>,
50} 50}
51 51
52#[derive(Serialize, Debug)] 52#[derive(Deserialize, Serialize, Debug)]
53#[serde(rename_all = "camelCase")] 53#[serde(rename_all = "camelCase")]
54pub struct ExpandedMacro { 54pub struct ExpandedMacro {
55 pub name: String, 55 pub name: String,
@@ -64,7 +64,7 @@ impl Request for ExpandMacro {
64 const METHOD: &'static str = "rust-analyzer/expandMacro"; 64 const METHOD: &'static str = "rust-analyzer/expandMacro";
65} 65}
66 66
67#[derive(Deserialize, Debug)] 67#[derive(Deserialize, Serialize, Debug)]
68#[serde(rename_all = "camelCase")] 68#[serde(rename_all = "camelCase")]
69pub struct ExpandMacroParams { 69pub struct ExpandMacroParams {
70 pub text_document: TextDocumentIdentifier, 70 pub text_document: TextDocumentIdentifier,
@@ -79,7 +79,7 @@ impl Request for FindMatchingBrace {
79 const METHOD: &'static str = "rust-analyzer/findMatchingBrace"; 79 const METHOD: &'static str = "rust-analyzer/findMatchingBrace";
80} 80}
81 81
82#[derive(Deserialize, Debug)] 82#[derive(Deserialize, Serialize, Debug)]
83#[serde(rename_all = "camelCase")] 83#[serde(rename_all = "camelCase")]
84pub struct FindMatchingBraceParams { 84pub struct FindMatchingBraceParams {
85 pub text_document: TextDocumentIdentifier, 85 pub text_document: TextDocumentIdentifier,
@@ -101,14 +101,14 @@ impl Notification for PublishDecorations {
101 const METHOD: &'static str = "rust-analyzer/publishDecorations"; 101 const METHOD: &'static str = "rust-analyzer/publishDecorations";
102} 102}
103 103
104#[derive(Serialize, Debug)] 104#[derive(Deserialize, Serialize, Debug)]
105#[serde(rename_all = "camelCase")] 105#[serde(rename_all = "camelCase")]
106pub struct PublishDecorationsParams { 106pub struct PublishDecorationsParams {
107 pub uri: Url, 107 pub uri: Url,
108 pub decorations: Vec<Decoration>, 108 pub decorations: Vec<Decoration>,
109} 109}
110 110
111#[derive(Serialize, Debug)] 111#[derive(Deserialize, Serialize, Debug)]
112#[serde(rename_all = "camelCase")] 112#[serde(rename_all = "camelCase")]
113pub struct Decoration { 113pub struct Decoration {
114 pub range: Range, 114 pub range: Range,
@@ -132,7 +132,7 @@ impl Request for JoinLines {
132 const METHOD: &'static str = "rust-analyzer/joinLines"; 132 const METHOD: &'static str = "rust-analyzer/joinLines";
133} 133}
134 134
135#[derive(Deserialize, Debug)] 135#[derive(Deserialize, Serialize, Debug)]
136#[serde(rename_all = "camelCase")] 136#[serde(rename_all = "camelCase")]
137pub struct JoinLinesParams { 137pub struct JoinLinesParams {
138 pub text_document: TextDocumentIdentifier, 138 pub text_document: TextDocumentIdentifier,
@@ -162,7 +162,7 @@ pub struct RunnablesParams {
162 pub position: Option<Position>, 162 pub position: Option<Position>,
163} 163}
164 164
165#[derive(Serialize, Debug)] 165#[derive(Deserialize, Serialize, Debug)]
166#[serde(rename_all = "camelCase")] 166#[serde(rename_all = "camelCase")]
167pub struct Runnable { 167pub struct Runnable {
168 pub range: Range, 168 pub range: Range,
@@ -173,7 +173,7 @@ pub struct Runnable {
173 pub cwd: Option<String>, 173 pub cwd: Option<String>,
174} 174}
175 175
176#[derive(Serialize, Debug)] 176#[derive(Deserialize, Serialize, Debug)]
177#[serde(rename_all = "camelCase")] 177#[serde(rename_all = "camelCase")]
178pub struct SourceChange { 178pub struct SourceChange {
179 pub label: String, 179 pub label: String,
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs
index 1b146e4d8..d9ba77050 100644
--- a/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/crates/rust-analyzer/src/semantic_tokens.rs
@@ -49,12 +49,9 @@ pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[
49 SemanticTokenModifier::DOCUMENTATION, 49 SemanticTokenModifier::DOCUMENTATION,
50 SemanticTokenModifier::DECLARATION, 50 SemanticTokenModifier::DECLARATION,
51 SemanticTokenModifier::DEFINITION, 51 SemanticTokenModifier::DEFINITION,
52 SemanticTokenModifier::REFERENCE,
53 SemanticTokenModifier::STATIC, 52 SemanticTokenModifier::STATIC,
54 SemanticTokenModifier::ABSTRACT, 53 SemanticTokenModifier::ABSTRACT,
55 SemanticTokenModifier::DEPRECATED, 54 SemanticTokenModifier::DEPRECATED,
56 SemanticTokenModifier::ASYNC,
57 SemanticTokenModifier::VOLATILE,
58 SemanticTokenModifier::READONLY, 55 SemanticTokenModifier::READONLY,
59 CONSTANT, 56 CONSTANT,
60 MUTABLE, 57 MUTABLE,