aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/adt.rs5
-rw-r--r--crates/ra_hir/src/code_model_api.rs21
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs81
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/generics.rs48
-rw-r--r--crates/ra_hir/src/ids.rs9
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/mock.rs1
-rw-r--r--crates/ra_hir/src/nameres.rs24
-rw-r--r--crates/ra_hir/src/path.rs68
-rw-r--r--crates/ra_hir/src/ty.rs378
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs17
-rw-r--r--crates/ra_hir/src/ty/tests.rs103
-rw-r--r--crates/ra_hir/src/ty/tests/data/function_generics.txt14
-rw-r--r--crates/ra_hir/src/ty/tests/data/generic_chain.txt29
-rw-r--r--crates/ra_hir/src/ty/tests/data/generics_in_patterns.txt17
-rw-r--r--crates/ra_hir/src/ty/tests/data/no_panic_on_field_of_enum.txt4
-rw-r--r--crates/ra_hir/src/ty/tests/data/struct_generics.txt15
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs6
-rw-r--r--crates/ra_ide_api/src/db.rs1
-rw-r--r--crates/ra_ide_api/src/extend_selection.rs2
-rw-r--r--crates/ra_ide_api/src/lib.rs32
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs17
-rw-r--r--crates/ra_syntax/src/ast/generated.rs128
-rw-r--r--crates/ra_syntax/src/grammar.ron10
25 files changed, 882 insertions, 153 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index d87fe7049..ab1c428db 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -1,3 +1,6 @@
1//! This module contains the implementation details of the HIR for ADTs, i.e.
2//! structs and enums (and unions).
3
1use std::sync::Arc; 4use std::sync::Arc;
2 5
3use ra_syntax::{ 6use ra_syntax::{
@@ -62,7 +65,7 @@ fn get_def_id(
62 }; 65 };
63 let loc = DefLoc { 66 let loc = DefLoc {
64 kind: expected_kind, 67 kind: expected_kind,
65 source_item_id: source_item_id, 68 source_item_id,
66 ..*same_file_loc 69 ..*same_file_loc
67 }; 70 };
68 loc.id(db) 71 loc.id(db)
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 11e919c1a..88eda5ed0 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -12,6 +12,7 @@ use crate::{
12 expr::BodySyntaxMapping, 12 expr::BodySyntaxMapping,
13 ty::InferenceResult, 13 ty::InferenceResult,
14 adt::VariantData, 14 adt::VariantData,
15 generics::GenericParams,
15 code_model_impl::def_id_to_ast, 16 code_model_impl::def_id_to_ast,
16}; 17};
17 18
@@ -201,6 +202,10 @@ impl Struct {
201 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) { 202 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) {
202 def_id_to_ast(db, self.def_id) 203 def_id_to_ast(db, self.def_id)
203 } 204 }
205
206 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
207 db.generic_params(self.def_id)
208 }
204} 209}
205 210
206#[derive(Debug, Clone, PartialEq, Eq, Hash)] 211#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -228,6 +233,10 @@ impl Enum {
228 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) { 233 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) {
229 def_id_to_ast(db, self.def_id) 234 def_id_to_ast(db, self.def_id)
230 } 235 }
236
237 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
238 db.generic_params(self.def_id)
239 }
231} 240}
232 241
233#[derive(Debug, Clone, PartialEq, Eq, Hash)] 242#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -339,6 +348,10 @@ impl Function {
339 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> { 348 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
340 db.infer(self.def_id) 349 db.infer(self.def_id)
341 } 350 }
351
352 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
353 db.generic_params(self.def_id)
354 }
342} 355}
343 356
344#[derive(Debug, Clone, PartialEq, Eq, Hash)] 357#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -384,6 +397,10 @@ impl Trait {
384 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TraitDef>) { 397 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TraitDef>) {
385 def_id_to_ast(db, self.def_id) 398 def_id_to_ast(db, self.def_id)
386 } 399 }
400
401 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
402 db.generic_params(self.def_id)
403 }
387} 404}
388 405
389#[derive(Debug, Clone, PartialEq, Eq, Hash)] 406#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -399,4 +416,8 @@ impl Type {
399 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TypeDef>) { 416 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TypeDef>) {
400 def_id_to_ast(db, self.def_id) 417 def_id_to_ast(db, self.def_id)
401 } 418 }
419
420 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
421 db.generic_params(self.def_id)
422 }
402} 423}
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index e5394d440..73c212de8 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -95,7 +95,7 @@ impl Module {
95 } 95 }
96 96
97 /// Finds a child module with the specified name. 97 /// Finds a child module with the specified name.
98 pub fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Option<Module> { 98 pub(crate) fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Option<Module> {
99 let loc = self.def_id.loc(db); 99 let loc = self.def_id.loc(db);
100 let module_tree = db.module_tree(loc.source_root_id); 100 let module_tree = db.module_tree(loc.source_root_id);
101 let child_id = loc.module_id.child(&module_tree, name)?; 101 let child_id = loc.module_id.child(&module_tree, name)?;
@@ -103,7 +103,7 @@ impl Module {
103 } 103 }
104 104
105 /// Iterates over all child modules. 105 /// Iterates over all child modules.
106 pub fn children_impl(&self, db: &impl HirDatabase) -> impl Iterator<Item = Module> { 106 pub(crate) fn children_impl(&self, db: &impl HirDatabase) -> impl Iterator<Item = Module> {
107 // FIXME this should be implementable without collecting into a vec, but 107 // FIXME this should be implementable without collecting into a vec, but
108 // it's kind of hard since the iterator needs to keep a reference to the 108 // it's kind of hard since the iterator needs to keep a reference to the
109 // module tree. 109 // module tree.
@@ -117,7 +117,7 @@ impl Module {
117 children.into_iter() 117 children.into_iter()
118 } 118 }
119 119
120 pub fn parent_impl(&self, db: &impl HirDatabase) -> Option<Module> { 120 pub(crate) fn parent_impl(&self, db: &impl HirDatabase) -> Option<Module> {
121 let loc = self.def_id.loc(db); 121 let loc = self.def_id.loc(db);
122 let module_tree = db.module_tree(loc.source_root_id); 122 let module_tree = db.module_tree(loc.source_root_id);
123 let parent_id = loc.module_id.parent(&module_tree)?; 123 let parent_id = loc.module_id.parent(&module_tree)?;
@@ -125,13 +125,13 @@ impl Module {
125 } 125 }
126 126
127 /// Returns a `ModuleScope`: a set of items, visible in this module. 127 /// Returns a `ModuleScope`: a set of items, visible in this module.
128 pub fn scope_impl(&self, db: &impl HirDatabase) -> ModuleScope { 128 pub(crate) fn scope_impl(&self, db: &impl HirDatabase) -> ModuleScope {
129 let loc = self.def_id.loc(db); 129 let loc = self.def_id.loc(db);
130 let item_map = db.item_map(loc.source_root_id); 130 let item_map = db.item_map(loc.source_root_id);
131 item_map.per_module[&loc.module_id].clone() 131 item_map.per_module[&loc.module_id].clone()
132 } 132 }
133 133
134 pub fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> PerNs<DefId> { 134 pub(crate) fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> PerNs<DefId> {
135 let mut curr_per_ns = PerNs::types( 135 let mut curr_per_ns = PerNs::types(
136 match path.kind { 136 match path.kind {
137 PathKind::Crate => self.crate_root(db), 137 PathKind::Crate => self.crate_root(db),
@@ -147,47 +147,54 @@ impl Module {
147 .def_id, 147 .def_id,
148 ); 148 );
149 149
150 let segments = &path.segments; 150 for segment in path.segments.iter() {
151 for (idx, name) in segments.iter().enumerate() { 151 let curr = match curr_per_ns.as_ref().take_types() {
152 let curr = if let Some(r) = curr_per_ns.as_ref().take_types() { 152 Some(r) => r,
153 r 153 None => {
154 } else { 154 // we still have path segments left, but the path so far
155 return PerNs::none(); 155 // didn't resolve in the types namespace => no resolution
156 // (don't break here because curr_per_ns might contain
157 // something in the value namespace, and it would be wrong
158 // to return that)
159 return PerNs::none();
160 }
156 }; 161 };
157 let module = match curr.resolve(db) { 162 // resolve segment in curr
158 Def::Module(it) => it, 163 curr_per_ns = match curr.resolve(db) {
164 Def::Module(m) => {
165 let scope = m.scope(db);
166 match scope.get(&segment.name) {
167 Some(r) => r.def_id,
168 None => PerNs::none(),
169 }
170 }
159 Def::Enum(e) => { 171 Def::Enum(e) => {
160 if segments.len() == idx + 1 { 172 // enum variant
161 // enum variant 173 let matching_variant = e
162 let matching_variant = 174 .variants(db)
163 e.variants(db).into_iter().find(|(n, _variant)| n == name); 175 .into_iter()
164 176 .find(|(n, _variant)| n == &segment.name);
165 if let Some((_n, variant)) = matching_variant { 177
166 return PerNs::both(variant.def_id(), e.def_id()); 178 match matching_variant {
167 } else { 179 Some((_n, variant)) => PerNs::both(variant.def_id(), e.def_id()),
168 return PerNs::none(); 180 None => PerNs::none(),
169 }
170 } else if segments.len() == idx {
171 // enum
172 return PerNs::types(e.def_id());
173 } else {
174 // malformed enum?
175 return PerNs::none();
176 } 181 }
177 } 182 }
178 _ => return PerNs::none(), 183 _ => {
179 }; 184 // could be an inherent method call in UFCS form
180 let scope = module.scope(db); 185 // (`Struct::method`), or some other kind of associated
181 curr_per_ns = if let Some(r) = scope.get(&name) { 186 // item... Which we currently don't handle (TODO)
182 r.def_id 187 PerNs::none()
183 } else { 188 }
184 return PerNs::none();
185 }; 189 };
186 } 190 }
187 curr_per_ns 191 curr_per_ns
188 } 192 }
189 193
190 pub fn problems_impl(&self, db: &impl HirDatabase) -> Vec<(TreeArc<SyntaxNode>, Problem)> { 194 pub(crate) fn problems_impl(
195 &self,
196 db: &impl HirDatabase,
197 ) -> Vec<(TreeArc<SyntaxNode>, Problem)> {
191 let loc = self.def_id.loc(db); 198 let loc = self.def_id.loc(db);
192 let module_tree = db.module_tree(loc.source_root_id); 199 let module_tree = db.module_tree(loc.source_root_id);
193 loc.module_id.problems(&module_tree, db) 200 loc.module_id.problems(&module_tree, db)
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 60065cf6a..f383701d7 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -14,6 +14,7 @@ use crate::{
14 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks}, 14 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks},
15 adt::{StructData, EnumData, EnumVariantData}, 15 adt::{StructData, EnumData, EnumVariantData},
16 impl_block::ModuleImplBlocks, 16 impl_block::ModuleImplBlocks,
17 generics::GenericParams,
17}; 18};
18 19
19#[salsa::query_group] 20#[salsa::query_group]
@@ -101,6 +102,9 @@ pub trait HirDatabase:
101 #[salsa::invoke(crate::expr::body_syntax_mapping)] 102 #[salsa::invoke(crate::expr::body_syntax_mapping)]
102 fn body_syntax_mapping(&self, def_id: DefId) -> Arc<crate::expr::BodySyntaxMapping>; 103 fn body_syntax_mapping(&self, def_id: DefId) -> Arc<crate::expr::BodySyntaxMapping>;
103 104
105 #[salsa::invoke(crate::generics::GenericParams::generic_params_query)]
106 fn generic_params(&self, def_id: DefId) -> Arc<GenericParams>;
107
104 #[salsa::invoke(crate::FnSignature::fn_signature_query)] 108 #[salsa::invoke(crate::FnSignature::fn_signature_query)]
105 fn fn_signature(&self, def_id: DefId) -> Arc<FnSignature>; 109 fn fn_signature(&self, def_id: DefId) -> Arc<FnSignature>;
106} 110}
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
new file mode 100644
index 000000000..d8248ad49
--- /dev/null
+++ b/crates/ra_hir/src/generics.rs
@@ -0,0 +1,48 @@
1//! Many kinds of items or constructs can have generic parameters: functions,
2//! structs, impls, traits, etc. This module provides a common HIR for these
3//! generic parameters. See also the `Generics` type and the `generics_of` query
4//! in rustc.
5
6use std::sync::Arc;
7
8use ra_syntax::ast::{TypeParamList, AstNode, NameOwner};
9
10use crate::{db::HirDatabase, DefId, Name, AsName};
11
12/// Data about a generic parameter (to a function, struct, impl, ...).
13#[derive(Clone, PartialEq, Eq, Debug)]
14pub struct GenericParam {
15 pub(crate) idx: u32,
16 pub(crate) name: Name,
17}
18
19/// Data about the generic parameters of a function, struct, impl, etc.
20#[derive(Clone, PartialEq, Eq, Debug, Default)]
21pub struct GenericParams {
22 pub(crate) params: Vec<GenericParam>,
23}
24
25impl GenericParams {
26 pub(crate) fn generic_params_query(db: &impl HirDatabase, def_id: DefId) -> Arc<GenericParams> {
27 let (_file_id, node) = def_id.source(db);
28 let mut generics = GenericParams::default();
29 if let Some(type_param_list) = node.children().find_map(TypeParamList::cast) {
30 for (idx, type_param) in type_param_list.type_params().enumerate() {
31 let name = type_param
32 .name()
33 .map(AsName::as_name)
34 .unwrap_or_else(Name::missing);
35 let param = GenericParam {
36 idx: idx as u32,
37 name,
38 };
39 generics.params.push(param);
40 }
41 }
42 Arc::new(generics)
43 }
44
45 pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
46 self.params.iter().find(|p| &p.name == name)
47 }
48}
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 0d8e67547..c5408e277 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -151,6 +151,15 @@ pub(crate) enum DefKind {
151 Type, 151 Type,
152 Item, 152 Item,
153 153
154 /// The constructor of a struct. E.g. if we have `struct Foo(usize)`, the
155 /// name `Foo` needs to resolve to different types depending on whether we
156 /// are in the types or values namespace: As a type, `Foo` of course refers
157 /// to the struct `Foo`; as a value, `Foo` is a callable type with signature
158 /// `(usize) -> Foo`. The cleanest approach to handle this seems to be to
159 /// have different defs in the two namespaces.
160 ///
161 /// rustc does the same; note that it even creates a struct constructor if
162 /// the struct isn't a tuple struct (see `CtorKind::Fictive` in rustc).
154 StructCtor, 163 StructCtor,
155} 164}
156 165
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index f1402a286..361d39f03 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -24,6 +24,7 @@ mod type_ref;
24mod ty; 24mod ty;
25mod impl_block; 25mod impl_block;
26mod expr; 26mod expr;
27mod generics;
27 28
28mod code_model_api; 29mod code_model_api;
29mod code_model_impl; 30mod code_model_impl;
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index 018e5e0d4..6e6f2f04b 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -243,6 +243,7 @@ salsa::database_storage! {
243 fn body_hir() for db::BodyHirQuery; 243 fn body_hir() for db::BodyHirQuery;
244 fn body_syntax_mapping() for db::BodySyntaxMappingQuery; 244 fn body_syntax_mapping() for db::BodySyntaxMappingQuery;
245 fn fn_signature() for db::FnSignatureQuery; 245 fn fn_signature() for db::FnSignatureQuery;
246 fn generic_params() for db::GenericParamsQuery;
246 } 247 }
247 } 248 }
248} 249}
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 4efafd409..4874e82f3 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -221,10 +221,10 @@ where
221 }; 221 };
222 } 222 }
223 for (import_id, import_data) in input.imports.iter() { 223 for (import_id, import_data) in input.imports.iter() {
224 if let Some(name) = import_data.path.segments.iter().last() { 224 if let Some(segment) = import_data.path.segments.iter().last() {
225 if !import_data.is_glob { 225 if !import_data.is_glob {
226 module_items.items.insert( 226 module_items.items.insert(
227 name.clone(), 227 segment.name.clone(),
228 Resolution { 228 Resolution {
229 def_id: PerNs::none(), 229 def_id: PerNs::none(),
230 import: Some(import_id), 230 import: Some(import_id),
@@ -319,13 +319,13 @@ where
319 PathKind::Crate => module_id.crate_root(&self.module_tree), 319 PathKind::Crate => module_id.crate_root(&self.module_tree),
320 }; 320 };
321 321
322 for (i, name) in import.path.segments.iter().enumerate() { 322 for (i, segment) in import.path.segments.iter().enumerate() {
323 let is_last = i == import.path.segments.len() - 1; 323 let is_last = i == import.path.segments.len() - 1;
324 324
325 let def_id = match self.result.per_module[&curr].items.get(name) { 325 let def_id = match self.result.per_module[&curr].items.get(&segment.name) {
326 Some(res) if !res.def_id.is_none() => res.def_id, 326 Some(res) if !res.def_id.is_none() => res.def_id,
327 _ => { 327 _ => {
328 log::debug!("path segment {:?} not found", name); 328 log::debug!("path segment {:?} not found", segment.name);
329 return false; 329 return false;
330 } 330 }
331 }; 331 };
@@ -336,7 +336,7 @@ where
336 } else { 336 } else {
337 log::debug!( 337 log::debug!(
338 "path segment {:?} resolved to value only, but is not last", 338 "path segment {:?} resolved to value only, but is not last",
339 name 339 segment.name
340 ); 340 );
341 return false; 341 return false;
342 }; 342 };
@@ -358,17 +358,17 @@ where
358 log::debug!("resolving {:?} in other source root", path); 358 log::debug!("resolving {:?} in other source root", path);
359 let def_id = module.resolve_path(self.db, &path); 359 let def_id = module.resolve_path(self.db, &path);
360 if !def_id.is_none() { 360 if !def_id.is_none() {
361 let name = path.segments.last().unwrap(); 361 let last_segment = path.segments.last().unwrap();
362 self.update(module_id, |items| { 362 self.update(module_id, |items| {
363 let res = Resolution { 363 let res = Resolution {
364 def_id, 364 def_id,
365 import: Some(import_id), 365 import: Some(import_id),
366 }; 366 };
367 items.items.insert(name.clone(), res); 367 items.items.insert(last_segment.name.clone(), res);
368 }); 368 });
369 log::debug!( 369 log::debug!(
370 "resolved import {:?} ({:?}) cross-source root to {:?}", 370 "resolved import {:?} ({:?}) cross-source root to {:?}",
371 name, 371 last_segment.name,
372 import, 372 import,
373 def_id.map(|did| did.loc(self.db)) 373 def_id.map(|did| did.loc(self.db))
374 ); 374 );
@@ -382,7 +382,7 @@ where
382 _ => { 382 _ => {
383 log::debug!( 383 log::debug!(
384 "path segment {:?} resolved to non-module {:?}, but is not last", 384 "path segment {:?} resolved to non-module {:?}, but is not last",
385 name, 385 segment.name,
386 type_def_id.loc(self.db) 386 type_def_id.loc(self.db)
387 ); 387 );
388 return true; // this resolved to a non-module, so the path won't ever resolve 388 return true; // this resolved to a non-module, so the path won't ever resolve
@@ -391,7 +391,7 @@ where
391 } else { 391 } else {
392 log::debug!( 392 log::debug!(
393 "resolved import {:?} ({:?}) within source root to {:?}", 393 "resolved import {:?} ({:?}) within source root to {:?}",
394 name, 394 segment.name,
395 import, 395 import,
396 def_id.map(|did| did.loc(self.db)) 396 def_id.map(|did| did.loc(self.db))
397 ); 397 );
@@ -400,7 +400,7 @@ where
400 def_id, 400 def_id,
401 import: Some(import_id), 401 import: Some(import_id),
402 }; 402 };
403 items.items.insert(name.clone(), res); 403 items.items.insert(segment.name.clone(), res);
404 }) 404 })
405 } 405 }
406 } 406 }
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs
index 7b0ce3b61..c3d14c689 100644
--- a/crates/ra_hir/src/path.rs
+++ b/crates/ra_hir/src/path.rs
@@ -1,11 +1,35 @@
1use std::sync::Arc;
2
1use ra_syntax::{ast, AstNode}; 3use ra_syntax::{ast, AstNode};
2 4
3use crate::{Name, AsName}; 5use crate::{Name, AsName, type_ref::TypeRef};
4 6
5#[derive(Debug, Clone, PartialEq, Eq, Hash)] 7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
6pub struct Path { 8pub struct Path {
7 pub kind: PathKind, 9 pub kind: PathKind,
8 pub segments: Vec<Name>, 10 pub segments: Vec<PathSegment>,
11}
12
13#[derive(Debug, Clone, PartialEq, Eq, Hash)]
14pub struct PathSegment {
15 pub name: Name,
16 pub args_and_bindings: Option<Arc<GenericArgs>>,
17}
18
19/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This
20/// can (in the future) also include bindings of associated types, like in
21/// `Iterator<Item = Foo>`.
22#[derive(Debug, Clone, PartialEq, Eq, Hash)]
23pub struct GenericArgs {
24 pub args: Vec<GenericArg>,
25 // someday also bindings
26}
27
28/// A single generic argument.
29#[derive(Debug, Clone, PartialEq, Eq, Hash)]
30pub enum GenericArg {
31 Type(TypeRef),
32 // or lifetime...
9} 33}
10 34
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 35#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -34,7 +58,17 @@ impl Path {
34 loop { 58 loop {
35 let segment = path.segment()?; 59 let segment = path.segment()?;
36 match segment.kind()? { 60 match segment.kind()? {
37 ast::PathSegmentKind::Name(name) => segments.push(name.as_name()), 61 ast::PathSegmentKind::Name(name) => {
62 let args = segment
63 .type_arg_list()
64 .and_then(GenericArgs::from_ast)
65 .map(Arc::new);
66 let segment = PathSegment {
67 name: name.as_name(),
68 args_and_bindings: args,
69 };
70 segments.push(segment);
71 }
38 ast::PathSegmentKind::CrateKw => { 72 ast::PathSegmentKind::CrateKw => {
39 kind = PathKind::Crate; 73 kind = PathKind::Crate;
40 break; 74 break;
@@ -88,7 +122,23 @@ impl Path {
88 if self.kind != PathKind::Plain || self.segments.len() > 1 { 122 if self.kind != PathKind::Plain || self.segments.len() > 1 {
89 return None; 123 return None;
90 } 124 }
91 self.segments.first() 125 self.segments.first().map(|s| &s.name)
126 }
127}
128
129impl GenericArgs {
130 fn from_ast(node: &ast::TypeArgList) -> Option<GenericArgs> {
131 let mut args = Vec::new();
132 for type_arg in node.type_args() {
133 let type_ref = TypeRef::from_ast_opt(type_arg.type_ref());
134 args.push(GenericArg::Type(type_ref));
135 }
136 // lifetimes and assoc type args ignored for now
137 if args.len() > 0 {
138 Some(GenericArgs { args })
139 } else {
140 None
141 }
92 } 142 }
93} 143}
94 144
@@ -96,7 +146,10 @@ impl From<Name> for Path {
96 fn from(name: Name) -> Path { 146 fn from(name: Name) -> Path {
97 Path { 147 Path {
98 kind: PathKind::Plain, 148 kind: PathKind::Plain,
99 segments: vec![name], 149 segments: vec![PathSegment {
150 name,
151 args_and_bindings: None,
152 }],
100 } 153 }
101 } 154 }
102} 155}
@@ -160,7 +213,10 @@ fn convert_path(prefix: Option<Path>, path: &ast::Path) -> Option<Path> {
160 kind: PathKind::Plain, 213 kind: PathKind::Plain,
161 segments: Vec::with_capacity(1), 214 segments: Vec::with_capacity(1),
162 }); 215 });
163 res.segments.push(name.as_name()); 216 res.segments.push(PathSegment {
217 name: name.as_name(),
218 args_and_bindings: None, // no type args in use
219 });
164 res 220 res
165 } 221 }
166 ast::PathSegmentKind::CrateKw => { 222 ast::PathSegmentKind::CrateKw => {
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 8d6493887..c602450e1 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -37,6 +37,8 @@ use crate::{
37 type_ref::{TypeRef, Mutability}, 37 type_ref::{TypeRef, Mutability},
38 name::KnownName, 38 name::KnownName,
39 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, 39 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat},
40 generics::GenericParams,
41 path::GenericArg,
40}; 42};
41 43
42/// The ID of a type variable. 44/// The ID of a type variable.
@@ -151,10 +153,20 @@ impl Expectation {
151 } 153 }
152} 154}
153 155
156/// A list of substitutions for generic parameters.
157#[derive(Clone, PartialEq, Eq, Debug)]
158pub struct Substs(Arc<[Ty]>);
159
160impl Substs {
161 pub fn empty() -> Substs {
162 Substs(Arc::new([]))
163 }
164}
165
154/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). 166/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs).
155/// 167///
156/// This should be cheap to clone. 168/// This should be cheap to clone.
157#[derive(Clone, PartialEq, Eq, Hash, Debug)] 169#[derive(Clone, PartialEq, Eq, Debug)]
158pub enum Ty { 170pub enum Ty {
159 /// The primitive boolean type. Written as `bool`. 171 /// The primitive boolean type. Written as `bool`.
160 Bool, 172 Bool,
@@ -175,7 +187,8 @@ pub enum Ty {
175 def_id: DefId, 187 def_id: DefId,
176 /// The name, for displaying. 188 /// The name, for displaying.
177 name: Name, 189 name: Name,
178 // later we'll need generic substitutions here 190 /// Substitutions for the generic parameters of the type.
191 substs: Substs,
179 }, 192 },
180 193
181 /// The pointee of a string slice. Written as `str`. 194 /// The pointee of a string slice. Written as `str`.
@@ -234,9 +247,15 @@ pub enum Ty {
234 247
235 // Opaque (`impl Trait`) type found in a return type. 248 // Opaque (`impl Trait`) type found in a return type.
236 // Opaque(DefId, Substs), 249 // Opaque(DefId, Substs),
250 /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
251 Param {
252 /// The index of the parameter (starting with parameters from the
253 /// surrounding impl, then the current function).
254 idx: u32,
255 /// The name of the parameter, for displaying.
256 name: Name,
257 },
237 258
238 // A type parameter; for example, `T` in `fn f<T>(x: T) {}
239 // Param(ParamTy),
240 /// A type variable used during type checking. Not to be confused with a 259 /// A type variable used during type checking. Not to be confused with a
241 /// type parameter. 260 /// type parameter.
242 Infer(InferTy), 261 Infer(InferTy),
@@ -250,7 +269,7 @@ pub enum Ty {
250} 269}
251 270
252/// A function signature. 271/// A function signature.
253#[derive(Clone, PartialEq, Eq, Hash, Debug)] 272#[derive(Clone, PartialEq, Eq, Debug)]
254pub struct FnSig { 273pub struct FnSig {
255 input: Vec<Ty>, 274 input: Vec<Ty>,
256 output: Ty, 275 output: Ty,
@@ -259,8 +278,12 @@ pub struct FnSig {
259impl Ty { 278impl Ty {
260 pub(crate) fn from_hir( 279 pub(crate) fn from_hir(
261 db: &impl HirDatabase, 280 db: &impl HirDatabase,
281 // TODO: the next three parameters basically describe the scope for name
282 // resolution; this should be refactored into something like a general
283 // resolver architecture
262 module: &Module, 284 module: &Module,
263 impl_block: Option<&ImplBlock>, 285 impl_block: Option<&ImplBlock>,
286 generics: &GenericParams,
264 type_ref: &TypeRef, 287 type_ref: &TypeRef,
265 ) -> Self { 288 ) -> Self {
266 match type_ref { 289 match type_ref {
@@ -268,32 +291,32 @@ impl Ty {
268 TypeRef::Tuple(inner) => { 291 TypeRef::Tuple(inner) => {
269 let inner_tys = inner 292 let inner_tys = inner
270 .iter() 293 .iter()
271 .map(|tr| Ty::from_hir(db, module, impl_block, tr)) 294 .map(|tr| Ty::from_hir(db, module, impl_block, generics, tr))
272 .collect::<Vec<_>>(); 295 .collect::<Vec<_>>();
273 Ty::Tuple(inner_tys.into()) 296 Ty::Tuple(inner_tys.into())
274 } 297 }
275 TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, path), 298 TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, generics, path),
276 TypeRef::RawPtr(inner, mutability) => { 299 TypeRef::RawPtr(inner, mutability) => {
277 let inner_ty = Ty::from_hir(db, module, impl_block, inner); 300 let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner);
278 Ty::RawPtr(Arc::new(inner_ty), *mutability) 301 Ty::RawPtr(Arc::new(inner_ty), *mutability)
279 } 302 }
280 TypeRef::Array(inner) => { 303 TypeRef::Array(inner) => {
281 let inner_ty = Ty::from_hir(db, module, impl_block, inner); 304 let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner);
282 Ty::Array(Arc::new(inner_ty)) 305 Ty::Array(Arc::new(inner_ty))
283 } 306 }
284 TypeRef::Slice(inner) => { 307 TypeRef::Slice(inner) => {
285 let inner_ty = Ty::from_hir(db, module, impl_block, inner); 308 let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner);
286 Ty::Slice(Arc::new(inner_ty)) 309 Ty::Slice(Arc::new(inner_ty))
287 } 310 }
288 TypeRef::Reference(inner, mutability) => { 311 TypeRef::Reference(inner, mutability) => {
289 let inner_ty = Ty::from_hir(db, module, impl_block, inner); 312 let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner);
290 Ty::Ref(Arc::new(inner_ty), *mutability) 313 Ty::Ref(Arc::new(inner_ty), *mutability)
291 } 314 }
292 TypeRef::Placeholder => Ty::Unknown, 315 TypeRef::Placeholder => Ty::Unknown,
293 TypeRef::Fn(params) => { 316 TypeRef::Fn(params) => {
294 let mut inner_tys = params 317 let mut inner_tys = params
295 .iter() 318 .iter()
296 .map(|tr| Ty::from_hir(db, module, impl_block, tr)) 319 .map(|tr| Ty::from_hir(db, module, impl_block, generics, tr))
297 .collect::<Vec<_>>(); 320 .collect::<Vec<_>>();
298 let return_ty = inner_tys 321 let return_ty = inner_tys
299 .pop() 322 .pop()
@@ -312,15 +335,19 @@ impl Ty {
312 db: &impl HirDatabase, 335 db: &impl HirDatabase,
313 module: &Module, 336 module: &Module,
314 impl_block: Option<&ImplBlock>, 337 impl_block: Option<&ImplBlock>,
338 generics: &GenericParams,
315 type_ref: Option<&TypeRef>, 339 type_ref: Option<&TypeRef>,
316 ) -> Self { 340 ) -> Self {
317 type_ref.map_or(Ty::Unknown, |t| Ty::from_hir(db, module, impl_block, t)) 341 type_ref.map_or(Ty::Unknown, |t| {
342 Ty::from_hir(db, module, impl_block, generics, t)
343 })
318 } 344 }
319 345
320 pub(crate) fn from_hir_path( 346 pub(crate) fn from_hir_path(
321 db: &impl HirDatabase, 347 db: &impl HirDatabase,
322 module: &Module, 348 module: &Module,
323 impl_block: Option<&ImplBlock>, 349 impl_block: Option<&ImplBlock>,
350 generics: &GenericParams,
324 path: &Path, 351 path: &Path,
325 ) -> Self { 352 ) -> Self {
326 if let Some(name) = path.as_ident() { 353 if let Some(name) = path.as_ident() {
@@ -329,7 +356,15 @@ impl Ty {
329 } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) { 356 } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) {
330 return Ty::Float(float_ty); 357 return Ty::Float(float_ty);
331 } else if name.as_known_name() == Some(KnownName::SelfType) { 358 } else if name.as_known_name() == Some(KnownName::SelfType) {
332 return Ty::from_hir_opt(db, module, None, impl_block.map(|i| i.target_type())); 359 // TODO pass the impl block's generics?
360 let generics = &GenericParams::default();
361 return Ty::from_hir_opt(
362 db,
363 module,
364 None,
365 generics,
366 impl_block.map(|i| i.target_type()),
367 );
333 } else if let Some(known) = name.as_known_name() { 368 } else if let Some(known) = name.as_known_name() {
334 match known { 369 match known {
335 KnownName::Bool => return Ty::Bool, 370 KnownName::Bool => return Ty::Bool,
@@ -337,16 +372,89 @@ impl Ty {
337 KnownName::Str => return Ty::Str, 372 KnownName::Str => return Ty::Str,
338 _ => {} 373 _ => {}
339 } 374 }
375 } else if let Some(generic_param) = generics.find_by_name(&name) {
376 return Ty::Param {
377 idx: generic_param.idx,
378 name: generic_param.name.clone(),
379 };
340 } 380 }
341 } 381 }
342 382
343 // Resolve in module (in type namespace) 383 // Resolve in module (in type namespace)
344 let resolved = if let Some(r) = module.resolve_path(db, path).take_types() { 384 let resolved = match module.resolve_path(db, path).take_types() {
345 r 385 Some(r) => r,
346 } else { 386 None => return Ty::Unknown,
347 return Ty::Unknown;
348 }; 387 };
349 db.type_for_def(resolved) 388 let ty = db.type_for_def(resolved);
389 let substs = Ty::substs_from_path(db, module, impl_block, generics, path, resolved);
390 ty.apply_substs(substs)
391 }
392
393 /// Collect generic arguments from a path into a `Substs`. See also
394 /// `create_substs_for_ast_path` and `def_to_ty` in rustc.
395 fn substs_from_path(
396 db: &impl HirDatabase,
397 // the scope of the segment...
398 module: &Module,
399 impl_block: Option<&ImplBlock>,
400 outer_generics: &GenericParams,
401 path: &Path,
402 resolved: DefId,
403 ) -> Substs {
404 let mut substs = Vec::new();
405 let def = resolved.resolve(db);
406 let last = path
407 .segments
408 .last()
409 .expect("path should have at least one segment");
410 let (def_generics, segment) = match def {
411 Def::Struct(s) => (s.generic_params(db), last),
412 Def::Enum(e) => (e.generic_params(db), last),
413 Def::Function(f) => (f.generic_params(db), last),
414 Def::Trait(t) => (t.generic_params(db), last),
415 Def::EnumVariant(ev) => {
416 // the generic args for an enum variant may be either specified
417 // on the segment referring to the enum, or on the segment
418 // referring to the variant. So `Option::<T>::None` and
419 // `Option::None::<T>` are both allowed (though the former is
420 // preferred). See also `def_ids_for_path_segments` in rustc.
421 let len = path.segments.len();
422 let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() {
423 // Option::<T>::None
424 &path.segments[len - 2]
425 } else {
426 // Option::None::<T>
427 last
428 };
429 (ev.parent_enum(db).generic_params(db), segment)
430 }
431 _ => return Substs::empty(),
432 };
433 // substs_from_path
434 if let Some(generic_args) = &segment.args_and_bindings {
435 // if args are provided, it should be all of them, but we can't rely on that
436 let param_count = def_generics.params.len();
437 for arg in generic_args.args.iter().take(param_count) {
438 match arg {
439 GenericArg::Type(type_ref) => {
440 let ty = Ty::from_hir(db, module, impl_block, outer_generics, type_ref);
441 substs.push(ty);
442 }
443 }
444 }
445 }
446 // add placeholders for args that were not provided
447 // TODO: handle defaults
448 for _ in segment
449 .args_and_bindings
450 .as_ref()
451 .map(|ga| ga.args.len())
452 .unwrap_or(0)..def_generics.params.len()
453 {
454 substs.push(Ty::Unknown);
455 }
456 assert_eq!(substs.len(), def_generics.params.len());
457 Substs(substs.into())
350 } 458 }
351 459
352 pub fn unit() -> Self { 460 pub fn unit() -> Self {
@@ -374,7 +482,14 @@ impl Ty {
374 } 482 }
375 sig_mut.output.walk_mut(f); 483 sig_mut.output.walk_mut(f);
376 } 484 }
377 Ty::Adt { .. } => {} // need to walk type parameters later 485 Ty::Adt { substs, .. } => {
486 // Without an Arc::make_mut_slice, we can't avoid the clone here:
487 let mut v: Vec<_> = substs.0.iter().cloned().collect();
488 for t in &mut v {
489 t.walk_mut(f);
490 }
491 substs.0 = v.into();
492 }
378 _ => {} 493 _ => {}
379 } 494 }
380 } 495 }
@@ -394,6 +509,49 @@ impl Ty {
394 _ => None, 509 _ => None,
395 } 510 }
396 } 511 }
512
513 /// If this is a type with type parameters (an ADT or function), replaces
514 /// the `Substs` for these type parameters with the given ones. (So e.g. if
515 /// `self` is `Option<_>` and the substs contain `u32`, we'll have
516 /// `Option<u32>` afterwards.)
517 pub fn apply_substs(self, substs: Substs) -> Ty {
518 match self {
519 Ty::Adt { def_id, name, .. } => Ty::Adt {
520 def_id,
521 name,
522 substs,
523 },
524 _ => self,
525 }
526 }
527
528 /// Replaces type parameters in this type using the given `Substs`. (So e.g.
529 /// if `self` is `&[T]`, where type parameter T has index 0, and the
530 /// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.)
531 pub fn subst(self, substs: &Substs) -> Ty {
532 self.fold(&mut |ty| match ty {
533 Ty::Param { idx, name } => {
534 if (idx as usize) < substs.0.len() {
535 substs.0[idx as usize].clone()
536 } else {
537 // TODO: does this indicate a bug? i.e. should we always
538 // have substs for all type params? (they might contain the
539 // params themselves again...)
540 Ty::Param { idx, name }
541 }
542 }
543 ty => ty,
544 })
545 }
546
547 /// Returns the type parameters of this type if it has some (i.e. is an ADT
548 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
549 fn substs(&self) -> Option<Substs> {
550 match self {
551 Ty::Adt { substs, .. } => Some(substs.clone()),
552 _ => None,
553 }
554 }
397} 555}
398 556
399impl fmt::Display for Ty { 557impl fmt::Display for Ty {
@@ -425,7 +583,17 @@ impl fmt::Display for Ty {
425 .to_fmt(f)?; 583 .to_fmt(f)?;
426 write!(f, " -> {}", sig.output) 584 write!(f, " -> {}", sig.output)
427 } 585 }
428 Ty::Adt { name, .. } => write!(f, "{}", name), 586 Ty::Adt { name, substs, .. } => {
587 write!(f, "{}", name)?;
588 if substs.0.len() > 0 {
589 join(substs.0.iter())
590 .surround_with("<", ">")
591 .separator(", ")
592 .to_fmt(f)?;
593 }
594 Ok(())
595 }
596 Ty::Param { name, .. } => write!(f, "{}", name),
429 Ty::Unknown => write!(f, "[unknown]"), 597 Ty::Unknown => write!(f, "[unknown]"),
430 Ty::Infer(..) => write!(f, "_"), 598 Ty::Infer(..) => write!(f, "_"),
431 } 599 }
@@ -440,28 +608,49 @@ fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty {
440 let signature = f.signature(db); 608 let signature = f.signature(db);
441 let module = f.module(db); 609 let module = f.module(db);
442 let impl_block = f.impl_block(db); 610 let impl_block = f.impl_block(db);
443 // TODO we ignore type parameters for now 611 let generics = f.generic_params(db);
444 let input = signature 612 let input = signature
445 .params() 613 .params()
446 .iter() 614 .iter()
447 .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), tr)) 615 .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), &generics, tr))
448 .collect::<Vec<_>>(); 616 .collect::<Vec<_>>();
449 let output = Ty::from_hir(db, &module, impl_block.as_ref(), signature.ret_type()); 617 let output = Ty::from_hir(
618 db,
619 &module,
620 impl_block.as_ref(),
621 &generics,
622 signature.ret_type(),
623 );
450 let sig = FnSig { input, output }; 624 let sig = FnSig { input, output };
451 Ty::FnPtr(Arc::new(sig)) 625 Ty::FnPtr(Arc::new(sig))
452} 626}
453 627
628fn make_substs(generics: &GenericParams) -> Substs {
629 Substs(
630 generics
631 .params
632 .iter()
633 .map(|_p| Ty::Unknown)
634 .collect::<Vec<_>>()
635 .into(),
636 )
637}
638
454fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { 639fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
640 let generics = s.generic_params(db);
455 Ty::Adt { 641 Ty::Adt {
456 def_id: s.def_id(), 642 def_id: s.def_id(),
457 name: s.name(db).unwrap_or_else(Name::missing), 643 name: s.name(db).unwrap_or_else(Name::missing),
644 substs: make_substs(&generics),
458 } 645 }
459} 646}
460 647
461pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { 648pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
649 let generics = s.generic_params(db);
462 Ty::Adt { 650 Ty::Adt {
463 def_id: s.def_id(), 651 def_id: s.def_id(),
464 name: s.name(db).unwrap_or_else(Name::missing), 652 name: s.name(db).unwrap_or_else(Name::missing),
653 substs: make_substs(&generics),
465 } 654 }
466} 655}
467 656
@@ -495,19 +684,29 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Ty {
495 684
496pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Option<Ty> { 685pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Option<Ty> {
497 let def = def_id.resolve(db); 686 let def = def_id.resolve(db);
498 let variant_data = match def { 687 let (variant_data, generics) = match def {
499 Def::Struct(s) => s.variant_data(db), 688 Def::Struct(s) => (s.variant_data(db), s.generic_params(db)),
500 Def::EnumVariant(ev) => ev.variant_data(db), 689 Def::EnumVariant(ev) => (ev.variant_data(db), ev.parent_enum(db).generic_params(db)),
501 // TODO: unions 690 // TODO: unions
691 Def::Enum(_) => {
692 // this can happen in (invalid) code, but enums don't have fields themselves
693 return None;
694 }
502 _ => panic!( 695 _ => panic!(
503 "trying to get type for field in non-struct/variant {:?}", 696 "trying to get type for field {:?} in non-struct/variant {:?}",
504 def_id 697 field, def_id
505 ), 698 ),
506 }; 699 };
507 let module = def_id.module(db); 700 let module = def_id.module(db);
508 let impl_block = def_id.impl_block(db); 701 let impl_block = def_id.impl_block(db);
509 let type_ref = variant_data.get_field_type_ref(&field)?; 702 let type_ref = variant_data.get_field_type_ref(&field)?;
510 Some(Ty::from_hir(db, &module, impl_block.as_ref(), &type_ref)) 703 Some(Ty::from_hir(
704 db,
705 &module,
706 impl_block.as_ref(),
707 &generics,
708 &type_ref,
709 ))
511} 710}
512 711
513/// The result of type inference: A mapping from expressions and patterns to types. 712/// The result of type inference: A mapping from expressions and patterns to types.
@@ -684,8 +883,26 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
684 self.type_of_pat.insert(pat, ty); 883 self.type_of_pat.insert(pat, ty);
685 } 884 }
686 885
687 fn make_ty(&self, type_ref: &TypeRef) -> Ty { 886 fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
688 Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref) 887 // TODO provide generics of function
888 let generics = GenericParams::default();
889 let ty = Ty::from_hir(
890 self.db,
891 &self.module,
892 self.impl_block.as_ref(),
893 &generics,
894 type_ref,
895 );
896 let ty = self.insert_type_vars(ty);
897 ty
898 }
899
900 fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs) -> bool {
901 substs1
902 .0
903 .iter()
904 .zip(substs2.0.iter())
905 .all(|(t1, t2)| self.unify(t1, t2))
689 } 906 }
690 907
691 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 908 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
@@ -708,12 +925,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
708 (Ty::Bool, _) | (Ty::Str, _) | (Ty::Never, _) | (Ty::Char, _) => ty1 == ty2, 925 (Ty::Bool, _) | (Ty::Str, _) | (Ty::Never, _) | (Ty::Char, _) => ty1 == ty2,
709 ( 926 (
710 Ty::Adt { 927 Ty::Adt {
711 def_id: def_id1, .. 928 def_id: def_id1,
929 substs: substs1,
930 ..
712 }, 931 },
713 Ty::Adt { 932 Ty::Adt {
714 def_id: def_id2, .. 933 def_id: def_id2,
934 substs: substs2,
935 ..
715 }, 936 },
716 ) if def_id1 == def_id2 => true, 937 ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2),
717 (Ty::Slice(t1), Ty::Slice(t2)) => self.unify(t1, t2), 938 (Ty::Slice(t1), Ty::Slice(t2)) => self.unify(t1, t2),
718 (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => self.unify(t1, t2), 939 (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => self.unify(t1, t2),
719 (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify(t1, t2), 940 (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify(t1, t2),
@@ -848,73 +1069,100 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
848 Some(ty) 1069 Some(ty)
849 } 1070 }
850 1071
851 fn resolve_variant(&self, path: Option<&Path>) -> (Ty, Option<DefId>) { 1072 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<DefId>) {
852 let path = if let Some(path) = path { 1073 let path = match path {
853 path 1074 Some(path) => path,
854 } else { 1075 None => return (Ty::Unknown, None),
855 return (Ty::Unknown, None);
856 }; 1076 };
857 let def_id = if let Some(def_id) = self.module.resolve_path(self.db, &path).take_types() { 1077 let def_id = match self.module.resolve_path(self.db, &path).take_types() {
858 def_id 1078 Some(def_id) => def_id,
859 } else { 1079 _ => return (Ty::Unknown, None),
860 return (Ty::Unknown, None);
861 }; 1080 };
1081 // TODO remove the duplication between here and `Ty::from_path`?
1082 // TODO provide generics of function
1083 let generics = GenericParams::default();
1084 let substs = Ty::substs_from_path(
1085 self.db,
1086 &self.module,
1087 self.impl_block.as_ref(),
1088 &generics,
1089 path,
1090 def_id,
1091 );
862 match def_id.resolve(self.db) { 1092 match def_id.resolve(self.db) {
863 Def::Struct(s) => { 1093 Def::Struct(s) => {
864 let ty = type_for_struct(self.db, s); 1094 let ty = type_for_struct(self.db, s);
1095 let ty = self.insert_type_vars(ty.apply_substs(substs));
865 (ty, Some(def_id)) 1096 (ty, Some(def_id))
866 } 1097 }
867 Def::EnumVariant(ev) => { 1098 Def::EnumVariant(ev) => {
868 let ty = type_for_enum_variant(self.db, ev); 1099 let ty = type_for_enum_variant(self.db, ev);
1100 let ty = self.insert_type_vars(ty.apply_substs(substs));
869 (ty, Some(def_id)) 1101 (ty, Some(def_id))
870 } 1102 }
871 _ => (Ty::Unknown, None), 1103 _ => (Ty::Unknown, None),
872 } 1104 }
873 } 1105 }
874 1106
875 fn resolve_fields(&self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { 1107 fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> {
876 let def_id = self.module.resolve_path(self.db, path?).take_types()?; 1108 let (ty, def_id) = self.resolve_variant(path);
1109 let def_id = def_id?;
877 let def = def_id.resolve(self.db); 1110 let def = def_id.resolve(self.db);
878 1111
879 match def { 1112 match def {
880 Def::Struct(s) => { 1113 Def::Struct(s) => {
881 let fields = s.fields(self.db); 1114 let fields = s.fields(self.db);
882 Some((type_for_struct(self.db, s), fields)) 1115 Some((ty, fields))
883 } 1116 }
884 Def::EnumVariant(ev) => { 1117 Def::EnumVariant(ev) => {
885 let fields = ev.fields(self.db); 1118 let fields = ev.fields(self.db);
886 Some((type_for_enum_variant(self.db, ev), fields)) 1119 Some((ty, fields))
887 } 1120 }
888 _ => None, 1121 _ => None,
889 } 1122 }
890 } 1123 }
891 1124
892 fn infer_tuple_struct_pat(&mut self, path: Option<&Path>, subpats: &[PatId]) -> Ty { 1125 fn infer_tuple_struct_pat(
1126 &mut self,
1127 path: Option<&Path>,
1128 subpats: &[PatId],
1129 expected: &Ty,
1130 ) -> Ty {
893 let (ty, fields) = self 1131 let (ty, fields) = self
894 .resolve_fields(path) 1132 .resolve_fields(path)
895 .unwrap_or((Ty::Unknown, Vec::new())); 1133 .unwrap_or((Ty::Unknown, Vec::new()));
896 1134
1135 self.unify(&ty, expected);
1136
1137 let substs = ty.substs().expect("adt should have substs");
1138
897 for (i, &subpat) in subpats.iter().enumerate() { 1139 for (i, &subpat) in subpats.iter().enumerate() {
898 let expected_ty = fields 1140 let expected_ty = fields
899 .get(i) 1141 .get(i)
900 .and_then(|field| field.ty(self.db)) 1142 .and_then(|field| field.ty(self.db))
901 .unwrap_or(Ty::Unknown); 1143 .unwrap_or(Ty::Unknown)
1144 .subst(&substs);
902 self.infer_pat(subpat, &expected_ty); 1145 self.infer_pat(subpat, &expected_ty);
903 } 1146 }
904 1147
905 ty 1148 ty
906 } 1149 }
907 1150
908 fn infer_struct_pat(&mut self, path: Option<&Path>, subpats: &[FieldPat]) -> Ty { 1151 fn infer_struct_pat(&mut self, path: Option<&Path>, subpats: &[FieldPat], expected: &Ty) -> Ty {
909 let (ty, fields) = self 1152 let (ty, fields) = self
910 .resolve_fields(path) 1153 .resolve_fields(path)
911 .unwrap_or((Ty::Unknown, Vec::new())); 1154 .unwrap_or((Ty::Unknown, Vec::new()));
912 1155
1156 self.unify(&ty, expected);
1157
1158 let substs = ty.substs().expect("adt should have substs");
1159
913 for subpat in subpats { 1160 for subpat in subpats {
914 let matching_field = fields.iter().find(|field| field.name() == &subpat.name); 1161 let matching_field = fields.iter().find(|field| field.name() == &subpat.name);
915 let expected_ty = matching_field 1162 let expected_ty = matching_field
916 .and_then(|field| field.ty(self.db)) 1163 .and_then(|field| field.ty(self.db))
917 .unwrap_or(Ty::Unknown); 1164 .unwrap_or(Ty::Unknown)
1165 .subst(&substs);
918 self.infer_pat(subpat.pat, &expected_ty); 1166 self.infer_pat(subpat.pat, &expected_ty);
919 } 1167 }
920 1168
@@ -959,11 +1207,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
959 Pat::TupleStruct { 1207 Pat::TupleStruct {
960 path: ref p, 1208 path: ref p,
961 args: ref subpats, 1209 args: ref subpats,
962 } => self.infer_tuple_struct_pat(p.as_ref(), subpats), 1210 } => self.infer_tuple_struct_pat(p.as_ref(), subpats, expected),
963 Pat::Struct { 1211 Pat::Struct {
964 path: ref p, 1212 path: ref p,
965 args: ref fields, 1213 args: ref fields,
966 } => self.infer_struct_pat(p.as_ref(), fields), 1214 } => self.infer_struct_pat(p.as_ref(), fields, expected),
967 Pat::Path(path) => self 1215 Pat::Path(path) => self
968 .module 1216 .module
969 .resolve_path(self.db, &path) 1217 .resolve_path(self.db, &path)
@@ -1155,11 +1403,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1155 spread, 1403 spread,
1156 } => { 1404 } => {
1157 let (ty, def_id) = self.resolve_variant(path.as_ref()); 1405 let (ty, def_id) = self.resolve_variant(path.as_ref());
1406 let substs = ty.substs().expect("adt should have substs");
1158 for field in fields { 1407 for field in fields {
1159 let field_ty = if let Some(def_id) = def_id { 1408 let field_ty = if let Some(def_id) = def_id {
1160 self.db 1409 self.db
1161 .type_for_field(def_id, field.name.clone()) 1410 .type_for_field(def_id, field.name.clone())
1162 .unwrap_or(Ty::Unknown) 1411 .unwrap_or(Ty::Unknown)
1412 .subst(&substs)
1163 } else { 1413 } else {
1164 Ty::Unknown 1414 Ty::Unknown
1165 }; 1415 };
@@ -1180,7 +1430,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1180 let i = name.to_string().parse::<usize>().ok(); 1430 let i = name.to_string().parse::<usize>().ok();
1181 i.and_then(|i| fields.get(i).cloned()) 1431 i.and_then(|i| fields.get(i).cloned())
1182 } 1432 }
1183 Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, name.clone()), 1433 Ty::Adt {
1434 def_id, ref substs, ..
1435 } => self
1436 .db
1437 .type_for_field(def_id, name.clone())
1438 .map(|ty| ty.subst(substs)),
1184 _ => None, 1439 _ => None,
1185 }) 1440 })
1186 .unwrap_or(Ty::Unknown); 1441 .unwrap_or(Ty::Unknown);
@@ -1193,7 +1448,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1193 Expr::Cast { expr, type_ref } => { 1448 Expr::Cast { expr, type_ref } => {
1194 let _inner_ty = self.infer_expr(*expr, &Expectation::none()); 1449 let _inner_ty = self.infer_expr(*expr, &Expectation::none());
1195 let cast_ty = self.make_ty(type_ref); 1450 let cast_ty = self.make_ty(type_ref);
1196 let cast_ty = self.insert_type_vars(cast_ty);
1197 // TODO check the cast... 1451 // TODO check the cast...
1198 cast_ty 1452 cast_ty
1199 } 1453 }
@@ -1305,12 +1559,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1305 type_ref, 1559 type_ref,
1306 initializer, 1560 initializer,
1307 } => { 1561 } => {
1308 let decl_ty = Ty::from_hir_opt( 1562 let decl_ty = type_ref
1309 self.db, 1563 .as_ref()
1310 &self.module, 1564 .map(|tr| self.make_ty(tr))
1311 self.impl_block.as_ref(), 1565 .unwrap_or(Ty::Unknown);
1312 type_ref.as_ref(),
1313 );
1314 let decl_ty = self.insert_type_vars(decl_ty); 1566 let decl_ty = self.insert_type_vars(decl_ty);
1315 let ty = if let Some(expr) = initializer { 1567 let ty = if let Some(expr) = initializer {
1316 let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty)); 1568 let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty));
@@ -1338,13 +1590,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1338 let body = Arc::clone(&self.body); // avoid borrow checker problem 1590 let body = Arc::clone(&self.body); // avoid borrow checker problem
1339 for (type_ref, pat) in signature.params().iter().zip(body.params()) { 1591 for (type_ref, pat) in signature.params().iter().zip(body.params()) {
1340 let ty = self.make_ty(type_ref); 1592 let ty = self.make_ty(type_ref);
1341 let ty = self.insert_type_vars(ty);
1342 1593
1343 self.infer_pat(*pat, &ty); 1594 self.infer_pat(*pat, &ty);
1344 } 1595 }
1345 self.return_ty = { 1596 self.return_ty = {
1346 let ty = self.make_ty(signature.ret_type()); 1597 let ty = self.make_ty(signature.ret_type());
1347 let ty = self.insert_type_vars(ty);
1348 ty 1598 ty
1349 }; 1599 };
1350 } 1600 }
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index b221bd142..9f65c5fe1 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -8,7 +8,11 @@ use rustc_hash::FxHashMap;
8 8
9use ra_db::SourceRootId; 9use ra_db::SourceRootId;
10 10
11use crate::{HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, impl_block::{ImplId, ImplBlock, ImplItem}}; 11use crate::{
12 HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function,
13 impl_block::{ImplId, ImplBlock, ImplItem},
14 generics::GenericParams
15};
12use super::Ty; 16use super::Ty;
13 17
14/// This is used as a key for indexing impls. 18/// This is used as a key for indexing impls.
@@ -64,8 +68,15 @@ impl CrateImplBlocks {
64 if let Some(_target_trait) = impl_data.target_trait() { 68 if let Some(_target_trait) = impl_data.target_trait() {
65 // ignore for now 69 // ignore for now
66 } else { 70 } else {
67 let target_ty = 71 // TODO provide generics of impl
68 Ty::from_hir(db, &module, Some(&impl_block), impl_data.target_type()); 72 let generics = GenericParams::default();
73 let target_ty = Ty::from_hir(
74 db,
75 &module,
76 Some(&impl_block),
77 &generics,
78 impl_data.target_type(),
79 );
69 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { 80 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
70 self.impls 81 self.impls
71 .entry(target_ty_fp) 82 .entry(target_ty_fp)
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index fc4054159..5aa24a29b 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -418,6 +418,109 @@ fn test() {
418 ); 418 );
419} 419}
420 420
421#[test]
422fn infer_struct_generics() {
423 check_inference(
424 r#"
425struct A<T> {
426 x: T,
427}
428
429fn test(a1: A<u32>, i: i32) {
430 a1.x;
431 let a2 = A { x: i };
432 a2.x;
433 let a3 = A::<i128> { x: 1 };
434 a3.x;
435}
436"#,
437 "struct_generics.txt",
438 );
439}
440
441#[test]
442fn infer_generics_in_patterns() {
443 check_inference(
444 r#"
445struct A<T> {
446 x: T,
447}
448
449enum Option<T> {
450 Some(T),
451 None,
452}
453
454fn test(a1: A<u32>, o: Option<u64>) {
455 let A { x: x2 } = a1;
456 let A::<i64> { x: x3 } = A { x: 1 };
457 match o {
458 Option::Some(t) => t,
459 _ => 1,
460 };
461}
462"#,
463 "generics_in_patterns.txt",
464 );
465}
466
467#[test]
468fn infer_function_generics() {
469 check_inference(
470 r#"
471fn id<T>(t: T) -> T { t }
472
473fn test() {
474 id(1u32);
475 id::<i128>(1);
476 let x: u64 = id(1);
477}
478"#,
479 "function_generics.txt",
480 );
481}
482
483#[test]
484fn infer_generic_chain() {
485 check_inference(
486 r#"
487struct A<T> {
488 x: T,
489}
490impl<T2> A<T2> {
491 fn x(self) -> T2 {
492 self.x
493 }
494}
495fn id<T>(t: T) -> T { t }
496
497fn test() -> i128 {
498 let x = 1;
499 let y = id(x);
500 let a = A { x: id(y) };
501 let z = id(a.x);
502 let b = A { x: z };
503 b.x()
504}
505"#,
506 "generic_chain.txt",
507 );
508}
509
510#[test]
511fn no_panic_on_field_of_enum() {
512 check_inference(
513 r#"
514enum X {}
515
516fn test(x: X) {
517 x.some_field;
518}
519"#,
520 "no_panic_on_field_of_enum.txt",
521 );
522}
523
421fn infer(content: &str) -> String { 524fn infer(content: &str) -> String {
422 let (db, _, file_id) = MockDatabase::with_single_file(content); 525 let (db, _, file_id) = MockDatabase::with_single_file(content);
423 let source_file = db.source_file(file_id); 526 let source_file = db.source_file(file_id);
diff --git a/crates/ra_hir/src/ty/tests/data/function_generics.txt b/crates/ra_hir/src/ty/tests/data/function_generics.txt
new file mode 100644
index 000000000..e44d26cfd
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/data/function_generics.txt
@@ -0,0 +1,14 @@
1[10; 11) 't': [unknown]
2[21; 26) '{ t }': [unknown]
3[23; 24) 't': [unknown]
4[38; 98) '{ ...(1); }': ()
5[44; 46) 'id': fn(T) -> T
6[44; 52) 'id(1u32)': T
7[47; 51) '1u32': u32
8[58; 68) 'id::<i128>': fn(T) -> T
9[58; 71) 'id::<i128>(1)': T
10[69; 70) '1': T
11[81; 82) 'x': T
12[90; 92) 'id': fn(T) -> T
13[90; 95) 'id(1)': T
14[93; 94) '1': T
diff --git a/crates/ra_hir/src/ty/tests/data/generic_chain.txt b/crates/ra_hir/src/ty/tests/data/generic_chain.txt
new file mode 100644
index 000000000..568e00846
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/data/generic_chain.txt
@@ -0,0 +1,29 @@
1[53; 57) 'self': A<[unknown]>
2[65; 87) '{ ... }': [unknown]
3[75; 79) 'self': A<[unknown]>
4[75; 81) 'self.x': [unknown]
5[99; 100) 't': [unknown]
6[110; 115) '{ t }': [unknown]
7[112; 113) 't': [unknown]
8[135; 261) '{ ....x() }': i128
9[146; 147) 'x': T
10[150; 151) '1': T
11[162; 163) 'y': T
12[166; 168) 'id': fn(T) -> T
13[166; 171) 'id(x)': T
14[169; 170) 'x': T
15[182; 183) 'a': A<T>
16[186; 200) 'A { x: id(y) }': A<T>
17[193; 195) 'id': fn(T) -> T
18[193; 198) 'id(y)': T
19[196; 197) 'y': T
20[211; 212) 'z': T
21[215; 217) 'id': fn(T) -> T
22[215; 222) 'id(a.x)': T
23[218; 219) 'a': A<T>
24[218; 221) 'a.x': T
25[233; 234) 'b': A<T>
26[237; 247) 'A { x: z }': A<T>
27[244; 245) 'z': T
28[254; 255) 'b': A<T>
29[254; 259) 'b.x()': i128
diff --git a/crates/ra_hir/src/ty/tests/data/generics_in_patterns.txt b/crates/ra_hir/src/ty/tests/data/generics_in_patterns.txt
new file mode 100644
index 000000000..1b01ef19e
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/data/generics_in_patterns.txt
@@ -0,0 +1,17 @@
1[79; 81) 'a1': A<u32>
2[91; 92) 'o': Option<u64>
3[107; 244) '{ ... }; }': ()
4[117; 128) 'A { x: x2 }': A<u32>
5[124; 126) 'x2': u32
6[131; 133) 'a1': A<u32>
7[143; 161) 'A::<i6...: x3 }': A<i64>
8[157; 159) 'x3': i64
9[164; 174) 'A { x: 1 }': A<i64>
10[171; 172) '1': i64
11[180; 241) 'match ... }': u64
12[186; 187) 'o': Option<u64>
13[198; 213) 'Option::Some(t)': Option<u64>
14[211; 212) 't': u64
15[217; 218) 't': u64
16[228; 229) '_': Option<u64>
17[233; 234) '1': u64
diff --git a/crates/ra_hir/src/ty/tests/data/no_panic_on_field_of_enum.txt b/crates/ra_hir/src/ty/tests/data/no_panic_on_field_of_enum.txt
new file mode 100644
index 000000000..4dca0b7f4
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/data/no_panic_on_field_of_enum.txt
@@ -0,0 +1,4 @@
1[20; 21) 'x': X
2[26; 47) '{ ...eld; }': ()
3[32; 33) 'x': X
4[32; 44) 'x.some_field': [unknown]
diff --git a/crates/ra_hir/src/ty/tests/data/struct_generics.txt b/crates/ra_hir/src/ty/tests/data/struct_generics.txt
new file mode 100644
index 000000000..1024a39a9
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/data/struct_generics.txt
@@ -0,0 +1,15 @@
1[36; 38) 'a1': A<u32>
2[48; 49) 'i': i32
3[56; 147) '{ ...3.x; }': ()
4[62; 64) 'a1': A<u32>
5[62; 66) 'a1.x': u32
6[76; 78) 'a2': A<i32>
7[81; 91) 'A { x: i }': A<i32>
8[88; 89) 'i': i32
9[97; 99) 'a2': A<i32>
10[97; 101) 'a2.x': i32
11[111; 113) 'a3': A<i128>
12[116; 134) 'A::<i1...x: 1 }': A<i128>
13[131; 132) '1': i128
14[140; 142) 'a3': A<i128>
15[140; 144) 'a3.x': i128
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index fb8b2fc88..32fd497be 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -25,7 +25,9 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
25fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { 25fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
26 for receiver in receiver.autoderef(ctx.db) { 26 for receiver in receiver.autoderef(ctx.db) {
27 match receiver { 27 match receiver {
28 Ty::Adt { def_id, .. } => { 28 Ty::Adt {
29 def_id, ref substs, ..
30 } => {
29 match def_id.resolve(ctx.db) { 31 match def_id.resolve(ctx.db) {
30 Def::Struct(s) => { 32 Def::Struct(s) => {
31 for field in s.fields(ctx.db) { 33 for field in s.fields(ctx.db) {
@@ -35,7 +37,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
35 field.name().to_string(), 37 field.name().to_string(),
36 ) 38 )
37 .kind(CompletionItemKind::Field) 39 .kind(CompletionItemKind::Field)
38 .set_detail(field.ty(ctx.db).map(|ty| ty.to_string())) 40 .set_detail(field.ty(ctx.db).map(|ty| ty.subst(substs).to_string()))
39 .add_to(acc); 41 .add_to(acc);
40 } 42 }
41 } 43 }
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs
index c2978f909..a1b666899 100644
--- a/crates/ra_ide_api/src/db.rs
+++ b/crates/ra_ide_api/src/db.rs
@@ -129,6 +129,7 @@ salsa::database_storage! {
129 fn body_hir() for hir::db::BodyHirQuery; 129 fn body_hir() for hir::db::BodyHirQuery;
130 fn body_syntax_mapping() for hir::db::BodySyntaxMappingQuery; 130 fn body_syntax_mapping() for hir::db::BodySyntaxMappingQuery;
131 fn fn_signature() for hir::db::FnSignatureQuery; 131 fn fn_signature() for hir::db::FnSignatureQuery;
132 fn generic_params() for hir::db::GenericParamsQuery;
132 } 133 }
133 } 134 }
134} 135}
diff --git a/crates/ra_ide_api/src/extend_selection.rs b/crates/ra_ide_api/src/extend_selection.rs
index 9f0ab2f1c..718b4def5 100644
--- a/crates/ra_ide_api/src/extend_selection.rs
+++ b/crates/ra_ide_api/src/extend_selection.rs
@@ -51,7 +51,7 @@ mod tests {
51 } 51 }
52 ", 52 ",
53 ); 53 );
54 let r = analysis.extend_selection(frange); 54 let r = analysis.extend_selection(frange).unwrap();
55 assert_eq!(r, TextRange::from_to(51.into(), 56.into())); 55 assert_eq!(r, TextRange::from_to(51.into(), 56.into()));
56 } 56 }
57} 57}
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index fb0821ff6..a09a8f926 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -299,7 +299,7 @@ impl Analysis {
299 } 299 }
300 300
301 /// Gets the syntax tree of the file. 301 /// Gets the syntax tree of the file.
302 pub fn file_syntax(&self, file_id: FileId) -> TreeArc<SourceFile> { 302 pub fn parse(&self, file_id: FileId) -> TreeArc<SourceFile> {
303 self.db.source_file(file_id).clone() 303 self.db.source_file(file_id).clone()
304 } 304 }
305 305
@@ -310,14 +310,15 @@ impl Analysis {
310 } 310 }
311 311
312 /// Selects the next syntactic nodes encopasing the range. 312 /// Selects the next syntactic nodes encopasing the range.
313 pub fn extend_selection(&self, frange: FileRange) -> TextRange { 313 pub fn extend_selection(&self, frange: FileRange) -> Cancelable<TextRange> {
314 extend_selection::extend_selection(&self.db, frange) 314 self.with_db(|db| extend_selection::extend_selection(db, frange))
315 } 315 }
316 316
317 /// Returns position of the mathcing brace (all types of braces are 317 /// Returns position of the mathcing brace (all types of braces are
318 /// supported). 318 /// supported).
319 pub fn matching_brace(&self, file: &SourceFile, offset: TextUnit) -> Option<TextUnit> { 319 pub fn matching_brace(&self, position: FilePosition) -> Option<TextUnit> {
320 ra_ide_api_light::matching_brace(file, offset) 320 let file = self.db.source_file(position.file_id);
321 ra_ide_api_light::matching_brace(&file, position.offset)
321 } 322 }
322 323
323 /// Returns a syntax tree represented as `String`, for debug purposes. 324 /// Returns a syntax tree represented as `String`, for debug purposes.
@@ -388,8 +389,7 @@ impl Analysis {
388 &self, 389 &self,
389 position: FilePosition, 390 position: FilePosition,
390 ) -> Cancelable<Option<RangeInfo<Vec<NavigationTarget>>>> { 391 ) -> Cancelable<Option<RangeInfo<Vec<NavigationTarget>>>> {
391 self.db 392 self.with_db(|db| goto_definition::goto_definition(db, position))
392 .catch_canceled(|db| goto_definition::goto_definition(db, position))
393 } 393 }
394 394
395 /// Finds all usages of the reference at point. 395 /// Finds all usages of the reference at point.
@@ -404,8 +404,7 @@ impl Analysis {
404 404
405 /// Computes parameter information for the given call expression. 405 /// Computes parameter information for the given call expression.
406 pub fn call_info(&self, position: FilePosition) -> Cancelable<Option<CallInfo>> { 406 pub fn call_info(&self, position: FilePosition) -> Cancelable<Option<CallInfo>> {
407 self.db 407 self.with_db(|db| call_info::call_info(db, position))
408 .catch_canceled(|db| call_info::call_info(db, position))
409 } 408 }
410 409
411 /// Returns a `mod name;` declaration which created the current module. 410 /// Returns a `mod name;` declaration which created the current module.
@@ -420,33 +419,28 @@ impl Analysis {
420 419
421 /// Returns the root file of the given crate. 420 /// Returns the root file of the given crate.
422 pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> { 421 pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> {
423 Ok(self.db.crate_graph().crate_root(crate_id)) 422 self.with_db(|db| db.crate_graph().crate_root(crate_id))
424 } 423 }
425 424
426 /// Returns the set of possible targets to run for the current file. 425 /// Returns the set of possible targets to run for the current file.
427 pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> { 426 pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> {
428 self.db 427 self.with_db(|db| runnables::runnables(db, file_id))
429 .catch_canceled(|db| runnables::runnables(db, file_id))
430 } 428 }
431 429
432 /// Computes syntax highlighting for the given file. 430 /// Computes syntax highlighting for the given file.
433 pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> { 431 pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> {
434 self.db 432 self.with_db(|db| syntax_highlighting::highlight(db, file_id))
435 .catch_canceled(|db| syntax_highlighting::highlight(db, file_id))
436 } 433 }
437 434
438 /// Computes completions at the given position. 435 /// Computes completions at the given position.
439 pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> { 436 pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> {
440 let completions = self 437 self.with_db(|db| completion::completions(db, position).map(Into::into))
441 .db
442 .catch_canceled(|db| completion::completions(db, position))?;
443 Ok(completions.map(|it| it.into()))
444 } 438 }
445 439
446 /// Computes assists (aks code actons aka intentions) for the given 440 /// Computes assists (aks code actons aka intentions) for the given
447 /// position. 441 /// position.
448 pub fn assists(&self, frange: FileRange) -> Cancelable<Vec<SourceChange>> { 442 pub fn assists(&self, frange: FileRange) -> Cancelable<Vec<SourceChange>> {
449 Ok(self.db.assists(frange)) 443 self.with_db(|db| db.assists(frange))
450 } 444 }
451 445
452 /// Computes the set of diagnostics for the given file. 446 /// Computes the set of diagnostics for the given file.
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index d1e8c5774..497f819be 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -8,7 +8,7 @@ use lsp_types::{
8 WorkspaceEdit 8 WorkspaceEdit
9}; 9};
10use ra_ide_api::{ 10use ra_ide_api::{
11 FileId, FilePosition, FileRange, FoldKind, Query, RangeInfo, RunnableKind, Severity, 11 FileId, FilePosition, FileRange, FoldKind, Query, RangeInfo, RunnableKind, Severity, Cancelable,
12}; 12};
13use ra_syntax::{AstNode, TextUnit}; 13use ra_syntax::{AstNode, TextUnit};
14use rustc_hash::FxHashMap; 14use rustc_hash::FxHashMap;
@@ -40,9 +40,13 @@ pub fn handle_extend_selection(
40 .into_iter() 40 .into_iter()
41 .map_conv_with(&line_index) 41 .map_conv_with(&line_index)
42 .map(|range| FileRange { file_id, range }) 42 .map(|range| FileRange { file_id, range })
43 .map(|frange| world.analysis().extend_selection(frange)) 43 .map(|frange| {
44 .map_conv_with(&line_index) 44 world
45 .collect(); 45 .analysis()
46 .extend_selection(frange)
47 .map(|it| it.conv_with(&line_index))
48 })
49 .collect::<Cancelable<Vec<_>>>()?;
46 Ok(req::ExtendSelectionResult { selections }) 50 Ok(req::ExtendSelectionResult { selections })
47} 51}
48 52
@@ -51,7 +55,6 @@ pub fn handle_find_matching_brace(
51 params: req::FindMatchingBraceParams, 55 params: req::FindMatchingBraceParams,
52) -> Result<Vec<Position>> { 56) -> Result<Vec<Position>> {
53 let file_id = params.text_document.try_conv_with(&world)?; 57 let file_id = params.text_document.try_conv_with(&world)?;
54 let file = world.analysis().file_syntax(file_id);
55 let line_index = world.analysis().file_line_index(file_id); 58 let line_index = world.analysis().file_line_index(file_id);
56 let res = params 59 let res = params
57 .offsets 60 .offsets
@@ -60,7 +63,7 @@ pub fn handle_find_matching_brace(
60 .map(|offset| { 63 .map(|offset| {
61 world 64 world
62 .analysis() 65 .analysis()
63 .matching_brace(&file, offset) 66 .matching_brace(FilePosition { file_id, offset })
64 .unwrap_or(offset) 67 .unwrap_or(offset)
65 }) 68 })
66 .map_conv_with(&line_index) 69 .map_conv_with(&line_index)
@@ -315,7 +318,7 @@ pub fn handle_completion(
315 let mut res = false; 318 let mut res = false;
316 if let Some(ctx) = params.context { 319 if let Some(ctx) = params.context {
317 if ctx.trigger_character.unwrap_or_default() == ":" { 320 if ctx.trigger_character.unwrap_or_default() == ":" {
318 let source_file = world.analysis().file_syntax(position.file_id); 321 let source_file = world.analysis().parse(position.file_id);
319 let syntax = source_file.syntax(); 322 let syntax = source_file.syntax();
320 let text = syntax.text(); 323 let text = syntax.text();
321 if let Some(next_char) = text.char_at(position.offset) { 324 if let Some(next_char) = text.char_at(position.offset) {
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 271040bf4..9fe946172 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -105,6 +105,38 @@ impl ArrayType {
105 } 105 }
106} 106}
107 107
108// AssocTypeArg
109#[derive(Debug, PartialEq, Eq, Hash)]
110#[repr(transparent)]
111pub struct AssocTypeArg {
112 pub(crate) syntax: SyntaxNode,
113}
114unsafe impl TransparentNewType for AssocTypeArg {
115 type Repr = rowan::SyntaxNode<RaTypes>;
116}
117
118impl AstNode for AssocTypeArg {
119 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
120 match syntax.kind() {
121 ASSOC_TYPE_ARG => Some(AssocTypeArg::from_repr(syntax.into_repr())),
122 _ => None,
123 }
124 }
125 fn syntax(&self) -> &SyntaxNode { &self.syntax }
126 fn to_owned(&self) -> TreeArc<AssocTypeArg> { TreeArc::cast(self.syntax.to_owned()) }
127}
128
129
130impl AssocTypeArg {
131 pub fn name_ref(&self) -> Option<&NameRef> {
132 super::child_opt(self)
133 }
134
135 pub fn type_ref(&self) -> Option<&TypeRef> {
136 super::child_opt(self)
137 }
138}
139
108// Attr 140// Attr
109#[derive(Debug, PartialEq, Eq, Hash)] 141#[derive(Debug, PartialEq, Eq, Hash)]
110#[repr(transparent)] 142#[repr(transparent)]
@@ -1397,6 +1429,34 @@ impl AstNode for Lifetime {
1397impl ast::AstToken for Lifetime {} 1429impl ast::AstToken for Lifetime {}
1398impl Lifetime {} 1430impl Lifetime {}
1399 1431
1432// LifetimeArg
1433#[derive(Debug, PartialEq, Eq, Hash)]
1434#[repr(transparent)]
1435pub struct LifetimeArg {
1436 pub(crate) syntax: SyntaxNode,
1437}
1438unsafe impl TransparentNewType for LifetimeArg {
1439 type Repr = rowan::SyntaxNode<RaTypes>;
1440}
1441
1442impl AstNode for LifetimeArg {
1443 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
1444 match syntax.kind() {
1445 LIFETIME_ARG => Some(LifetimeArg::from_repr(syntax.into_repr())),
1446 _ => None,
1447 }
1448 }
1449 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1450 fn to_owned(&self) -> TreeArc<LifetimeArg> { TreeArc::cast(self.syntax.to_owned()) }
1451}
1452
1453
1454impl LifetimeArg {
1455 pub fn lifetime(&self) -> Option<&Lifetime> {
1456 super::child_opt(self)
1457 }
1458}
1459
1400// LifetimeParam 1460// LifetimeParam
1401#[derive(Debug, PartialEq, Eq, Hash)] 1461#[derive(Debug, PartialEq, Eq, Hash)]
1402#[repr(transparent)] 1462#[repr(transparent)]
@@ -2355,6 +2415,10 @@ impl PathSegment {
2355 pub fn name_ref(&self) -> Option<&NameRef> { 2415 pub fn name_ref(&self) -> Option<&NameRef> {
2356 super::child_opt(self) 2416 super::child_opt(self)
2357 } 2417 }
2418
2419 pub fn type_arg_list(&self) -> Option<&TypeArgList> {
2420 super::child_opt(self)
2421 }
2358} 2422}
2359 2423
2360// PathType 2424// PathType
@@ -3335,6 +3399,70 @@ impl TupleType {
3335 } 3399 }
3336} 3400}
3337 3401
3402// TypeArg
3403#[derive(Debug, PartialEq, Eq, Hash)]
3404#[repr(transparent)]
3405pub struct TypeArg {
3406 pub(crate) syntax: SyntaxNode,
3407}
3408unsafe impl TransparentNewType for TypeArg {
3409 type Repr = rowan::SyntaxNode<RaTypes>;
3410}
3411
3412impl AstNode for TypeArg {
3413 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3414 match syntax.kind() {
3415 TYPE_ARG => Some(TypeArg::from_repr(syntax.into_repr())),
3416 _ => None,
3417 }
3418 }
3419 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3420 fn to_owned(&self) -> TreeArc<TypeArg> { TreeArc::cast(self.syntax.to_owned()) }
3421}
3422
3423
3424impl TypeArg {
3425 pub fn type_ref(&self) -> Option<&TypeRef> {
3426 super::child_opt(self)
3427 }
3428}
3429
3430// TypeArgList
3431#[derive(Debug, PartialEq, Eq, Hash)]
3432#[repr(transparent)]
3433pub struct TypeArgList {
3434 pub(crate) syntax: SyntaxNode,
3435}
3436unsafe impl TransparentNewType for TypeArgList {
3437 type Repr = rowan::SyntaxNode<RaTypes>;
3438}
3439
3440impl AstNode for TypeArgList {
3441 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3442 match syntax.kind() {
3443 TYPE_ARG_LIST => Some(TypeArgList::from_repr(syntax.into_repr())),
3444 _ => None,
3445 }
3446 }
3447 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3448 fn to_owned(&self) -> TreeArc<TypeArgList> { TreeArc::cast(self.syntax.to_owned()) }
3449}
3450
3451
3452impl TypeArgList {
3453 pub fn type_args(&self) -> impl Iterator<Item = &TypeArg> {
3454 super::children(self)
3455 }
3456
3457 pub fn lifetime_args(&self) -> impl Iterator<Item = &LifetimeArg> {
3458 super::children(self)
3459 }
3460
3461 pub fn assoc_type_args(&self) -> impl Iterator<Item = &AssocTypeArg> {
3462 super::children(self)
3463 }
3464}
3465
3338// TypeDef 3466// TypeDef
3339#[derive(Debug, PartialEq, Eq, Hash)] 3467#[derive(Debug, PartialEq, Eq, Hash)]
3340#[repr(transparent)] 3468#[repr(transparent)]
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index fc47c36d3..0385183fd 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -597,8 +597,16 @@ Grammar(
597 ] 597 ]
598 ), 598 ),
599 "PathSegment": ( 599 "PathSegment": (
600 options: [ "NameRef" ] 600 options: [ "NameRef", "TypeArgList" ]
601 ), 601 ),
602 "TypeArgList": (collections: [
603 ["type_args", "TypeArg"],
604 ["lifetime_args", "LifetimeArg"],
605 ["assoc_type_args", "AssocTypeArg"],
606 ]),
607 "TypeArg": (options: ["TypeRef"]),
608 "AssocTypeArg": (options: ["NameRef", "TypeRef"]),
609 "LifetimeArg": (options: ["Lifetime"]),
602 "Comment": ( traits: ["AstToken"] ), 610 "Comment": ( traits: ["AstToken"] ),
603 "Whitespace": ( traits: ["AstToken"] ), 611 "Whitespace": ( traits: ["AstToken"] ),
604 }, 612 },