aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-01-19 18:03:36 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-01-19 18:03:36 +0000
commit1c296d54e3dcc36c1a778873f26035000a352ba2 (patch)
tree0a6ce660ee32080287284c93bffaaaada91f3584 /crates
parentbade91db081a3465dea3547ab8ab669f78fde9dc (diff)
parent5f3509e140d19b989db418a00ac6778c622cde5d (diff)
Merge #576
576: Beginnings of generics r=matklad a=flodiebold This implements the beginnings of the generics infrastructure; generic parameters for structs work and are correctly substituted in fields. Functions and methods aren't handled at all yet (as the tests show). The name resolution in `ty` really needs refactoring now, I hope to do that next ;) Co-authored-by: Florian Diebold <[email protected]>
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.rs25
-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.rs370
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs17
-rw-r--r--crates/ra_hir/src/ty/tests.rs89
-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/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_syntax/src/ast/generated.rs128
-rw-r--r--crates/ra_syntax/src/grammar.ron10
21 files changed, 805 insertions, 97 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 7215236f9..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,7 +147,7 @@ impl Module {
147 .def_id, 147 .def_id,
148 ); 148 );
149 149
150 for name in path.segments.iter() { 150 for segment in path.segments.iter() {
151 let curr = match curr_per_ns.as_ref().take_types() { 151 let curr = match curr_per_ns.as_ref().take_types() {
152 Some(r) => r, 152 Some(r) => r,
153 None => { 153 None => {
@@ -163,15 +163,17 @@ impl Module {
163 curr_per_ns = match curr.resolve(db) { 163 curr_per_ns = match curr.resolve(db) {
164 Def::Module(m) => { 164 Def::Module(m) => {
165 let scope = m.scope(db); 165 let scope = m.scope(db);
166 match scope.get(&name) { 166 match scope.get(&segment.name) {
167 Some(r) => r.def_id, 167 Some(r) => r.def_id,
168 None => PerNs::none(), 168 None => PerNs::none(),
169 } 169 }
170 } 170 }
171 Def::Enum(e) => { 171 Def::Enum(e) => {
172 // enum variant 172 // enum variant
173 let matching_variant = 173 let matching_variant = e
174 e.variants(db).into_iter().find(|(n, _variant)| n == name); 174 .variants(db)
175 .into_iter()
176 .find(|(n, _variant)| n == &segment.name);
175 177
176 match matching_variant { 178 match matching_variant {
177 Some((_n, variant)) => PerNs::both(variant.def_id(), e.def_id()), 179 Some((_n, variant)) => PerNs::both(variant.def_id(), e.def_id()),
@@ -189,7 +191,10 @@ impl Module {
189 curr_per_ns 191 curr_per_ns
190 } 192 }
191 193
192 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)> {
193 let loc = self.def_id.loc(db); 198 let loc = self.def_id.loc(db);
194 let module_tree = db.module_tree(loc.source_root_id); 199 let module_tree = db.module_tree(loc.source_root_id);
195 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..9b7182485 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,9 +684,9 @@ 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
502 _ => panic!( 691 _ => panic!(
503 "trying to get type for field in non-struct/variant {:?}", 692 "trying to get type for field in non-struct/variant {:?}",
@@ -507,7 +696,13 @@ pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name)
507 let module = def_id.module(db); 696 let module = def_id.module(db);
508 let impl_block = def_id.impl_block(db); 697 let impl_block = def_id.impl_block(db);
509 let type_ref = variant_data.get_field_type_ref(&field)?; 698 let type_ref = variant_data.get_field_type_ref(&field)?;
510 Some(Ty::from_hir(db, &module, impl_block.as_ref(), &type_ref)) 699 Some(Ty::from_hir(
700 db,
701 &module,
702 impl_block.as_ref(),
703 &generics,
704 &type_ref,
705 ))
511} 706}
512 707
513/// The result of type inference: A mapping from expressions and patterns to types. 708/// The result of type inference: A mapping from expressions and patterns to types.
@@ -684,8 +879,26 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
684 self.type_of_pat.insert(pat, ty); 879 self.type_of_pat.insert(pat, ty);
685 } 880 }
686 881
687 fn make_ty(&self, type_ref: &TypeRef) -> Ty { 882 fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
688 Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref) 883 // TODO provide generics of function
884 let generics = GenericParams::default();
885 let ty = Ty::from_hir(
886 self.db,
887 &self.module,
888 self.impl_block.as_ref(),
889 &generics,
890 type_ref,
891 );
892 let ty = self.insert_type_vars(ty);
893 ty
894 }
895
896 fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs) -> bool {
897 substs1
898 .0
899 .iter()
900 .zip(substs2.0.iter())
901 .all(|(t1, t2)| self.unify(t1, t2))
689 } 902 }
690 903
691 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 904 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
@@ -708,12 +921,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
708 (Ty::Bool, _) | (Ty::Str, _) | (Ty::Never, _) | (Ty::Char, _) => ty1 == ty2, 921 (Ty::Bool, _) | (Ty::Str, _) | (Ty::Never, _) | (Ty::Char, _) => ty1 == ty2,
709 ( 922 (
710 Ty::Adt { 923 Ty::Adt {
711 def_id: def_id1, .. 924 def_id: def_id1,
925 substs: substs1,
926 ..
712 }, 927 },
713 Ty::Adt { 928 Ty::Adt {
714 def_id: def_id2, .. 929 def_id: def_id2,
930 substs: substs2,
931 ..
715 }, 932 },
716 ) if def_id1 == def_id2 => true, 933 ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2),
717 (Ty::Slice(t1), Ty::Slice(t2)) => self.unify(t1, t2), 934 (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), 935 (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), 936 (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify(t1, t2),
@@ -848,73 +1065,100 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
848 Some(ty) 1065 Some(ty)
849 } 1066 }
850 1067
851 fn resolve_variant(&self, path: Option<&Path>) -> (Ty, Option<DefId>) { 1068 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<DefId>) {
852 let path = if let Some(path) = path { 1069 let path = match path {
853 path 1070 Some(path) => path,
854 } else { 1071 None => return (Ty::Unknown, None),
855 return (Ty::Unknown, None);
856 }; 1072 };
857 let def_id = if let Some(def_id) = self.module.resolve_path(self.db, &path).take_types() { 1073 let def_id = match self.module.resolve_path(self.db, &path).take_types() {
858 def_id 1074 Some(def_id) => def_id,
859 } else { 1075 _ => return (Ty::Unknown, None),
860 return (Ty::Unknown, None);
861 }; 1076 };
1077 // TODO remove the duplication between here and `Ty::from_path`?
1078 // TODO provide generics of function
1079 let generics = GenericParams::default();
1080 let substs = Ty::substs_from_path(
1081 self.db,
1082 &self.module,
1083 self.impl_block.as_ref(),
1084 &generics,
1085 path,
1086 def_id,
1087 );
862 match def_id.resolve(self.db) { 1088 match def_id.resolve(self.db) {
863 Def::Struct(s) => { 1089 Def::Struct(s) => {
864 let ty = type_for_struct(self.db, s); 1090 let ty = type_for_struct(self.db, s);
1091 let ty = self.insert_type_vars(ty.apply_substs(substs));
865 (ty, Some(def_id)) 1092 (ty, Some(def_id))
866 } 1093 }
867 Def::EnumVariant(ev) => { 1094 Def::EnumVariant(ev) => {
868 let ty = type_for_enum_variant(self.db, ev); 1095 let ty = type_for_enum_variant(self.db, ev);
1096 let ty = self.insert_type_vars(ty.apply_substs(substs));
869 (ty, Some(def_id)) 1097 (ty, Some(def_id))
870 } 1098 }
871 _ => (Ty::Unknown, None), 1099 _ => (Ty::Unknown, None),
872 } 1100 }
873 } 1101 }
874 1102
875 fn resolve_fields(&self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { 1103 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()?; 1104 let (ty, def_id) = self.resolve_variant(path);
1105 let def_id = def_id?;
877 let def = def_id.resolve(self.db); 1106 let def = def_id.resolve(self.db);
878 1107
879 match def { 1108 match def {
880 Def::Struct(s) => { 1109 Def::Struct(s) => {
881 let fields = s.fields(self.db); 1110 let fields = s.fields(self.db);
882 Some((type_for_struct(self.db, s), fields)) 1111 Some((ty, fields))
883 } 1112 }
884 Def::EnumVariant(ev) => { 1113 Def::EnumVariant(ev) => {
885 let fields = ev.fields(self.db); 1114 let fields = ev.fields(self.db);
886 Some((type_for_enum_variant(self.db, ev), fields)) 1115 Some((ty, fields))
887 } 1116 }
888 _ => None, 1117 _ => None,
889 } 1118 }
890 } 1119 }
891 1120
892 fn infer_tuple_struct_pat(&mut self, path: Option<&Path>, subpats: &[PatId]) -> Ty { 1121 fn infer_tuple_struct_pat(
1122 &mut self,
1123 path: Option<&Path>,
1124 subpats: &[PatId],
1125 expected: &Ty,
1126 ) -> Ty {
893 let (ty, fields) = self 1127 let (ty, fields) = self
894 .resolve_fields(path) 1128 .resolve_fields(path)
895 .unwrap_or((Ty::Unknown, Vec::new())); 1129 .unwrap_or((Ty::Unknown, Vec::new()));
896 1130
1131 self.unify(&ty, expected);
1132
1133 let substs = ty.substs().expect("adt should have substs");
1134
897 for (i, &subpat) in subpats.iter().enumerate() { 1135 for (i, &subpat) in subpats.iter().enumerate() {
898 let expected_ty = fields 1136 let expected_ty = fields
899 .get(i) 1137 .get(i)
900 .and_then(|field| field.ty(self.db)) 1138 .and_then(|field| field.ty(self.db))
901 .unwrap_or(Ty::Unknown); 1139 .unwrap_or(Ty::Unknown)
1140 .subst(&substs);
902 self.infer_pat(subpat, &expected_ty); 1141 self.infer_pat(subpat, &expected_ty);
903 } 1142 }
904 1143
905 ty 1144 ty
906 } 1145 }
907 1146
908 fn infer_struct_pat(&mut self, path: Option<&Path>, subpats: &[FieldPat]) -> Ty { 1147 fn infer_struct_pat(&mut self, path: Option<&Path>, subpats: &[FieldPat], expected: &Ty) -> Ty {
909 let (ty, fields) = self 1148 let (ty, fields) = self
910 .resolve_fields(path) 1149 .resolve_fields(path)
911 .unwrap_or((Ty::Unknown, Vec::new())); 1150 .unwrap_or((Ty::Unknown, Vec::new()));
912 1151
1152 self.unify(&ty, expected);
1153
1154 let substs = ty.substs().expect("adt should have substs");
1155
913 for subpat in subpats { 1156 for subpat in subpats {
914 let matching_field = fields.iter().find(|field| field.name() == &subpat.name); 1157 let matching_field = fields.iter().find(|field| field.name() == &subpat.name);
915 let expected_ty = matching_field 1158 let expected_ty = matching_field
916 .and_then(|field| field.ty(self.db)) 1159 .and_then(|field| field.ty(self.db))
917 .unwrap_or(Ty::Unknown); 1160 .unwrap_or(Ty::Unknown)
1161 .subst(&substs);
918 self.infer_pat(subpat.pat, &expected_ty); 1162 self.infer_pat(subpat.pat, &expected_ty);
919 } 1163 }
920 1164
@@ -959,11 +1203,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
959 Pat::TupleStruct { 1203 Pat::TupleStruct {
960 path: ref p, 1204 path: ref p,
961 args: ref subpats, 1205 args: ref subpats,
962 } => self.infer_tuple_struct_pat(p.as_ref(), subpats), 1206 } => self.infer_tuple_struct_pat(p.as_ref(), subpats, expected),
963 Pat::Struct { 1207 Pat::Struct {
964 path: ref p, 1208 path: ref p,
965 args: ref fields, 1209 args: ref fields,
966 } => self.infer_struct_pat(p.as_ref(), fields), 1210 } => self.infer_struct_pat(p.as_ref(), fields, expected),
967 Pat::Path(path) => self 1211 Pat::Path(path) => self
968 .module 1212 .module
969 .resolve_path(self.db, &path) 1213 .resolve_path(self.db, &path)
@@ -1155,11 +1399,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1155 spread, 1399 spread,
1156 } => { 1400 } => {
1157 let (ty, def_id) = self.resolve_variant(path.as_ref()); 1401 let (ty, def_id) = self.resolve_variant(path.as_ref());
1402 let substs = ty.substs().expect("adt should have substs");
1158 for field in fields { 1403 for field in fields {
1159 let field_ty = if let Some(def_id) = def_id { 1404 let field_ty = if let Some(def_id) = def_id {
1160 self.db 1405 self.db
1161 .type_for_field(def_id, field.name.clone()) 1406 .type_for_field(def_id, field.name.clone())
1162 .unwrap_or(Ty::Unknown) 1407 .unwrap_or(Ty::Unknown)
1408 .subst(&substs)
1163 } else { 1409 } else {
1164 Ty::Unknown 1410 Ty::Unknown
1165 }; 1411 };
@@ -1180,7 +1426,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1180 let i = name.to_string().parse::<usize>().ok(); 1426 let i = name.to_string().parse::<usize>().ok();
1181 i.and_then(|i| fields.get(i).cloned()) 1427 i.and_then(|i| fields.get(i).cloned())
1182 } 1428 }
1183 Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, name.clone()), 1429 Ty::Adt {
1430 def_id, ref substs, ..
1431 } => self
1432 .db
1433 .type_for_field(def_id, name.clone())
1434 .map(|ty| ty.subst(substs)),
1184 _ => None, 1435 _ => None,
1185 }) 1436 })
1186 .unwrap_or(Ty::Unknown); 1437 .unwrap_or(Ty::Unknown);
@@ -1193,7 +1444,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1193 Expr::Cast { expr, type_ref } => { 1444 Expr::Cast { expr, type_ref } => {
1194 let _inner_ty = self.infer_expr(*expr, &Expectation::none()); 1445 let _inner_ty = self.infer_expr(*expr, &Expectation::none());
1195 let cast_ty = self.make_ty(type_ref); 1446 let cast_ty = self.make_ty(type_ref);
1196 let cast_ty = self.insert_type_vars(cast_ty);
1197 // TODO check the cast... 1447 // TODO check the cast...
1198 cast_ty 1448 cast_ty
1199 } 1449 }
@@ -1305,12 +1555,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1305 type_ref, 1555 type_ref,
1306 initializer, 1556 initializer,
1307 } => { 1557 } => {
1308 let decl_ty = Ty::from_hir_opt( 1558 let decl_ty = type_ref
1309 self.db, 1559 .as_ref()
1310 &self.module, 1560 .map(|tr| self.make_ty(tr))
1311 self.impl_block.as_ref(), 1561 .unwrap_or(Ty::Unknown);
1312 type_ref.as_ref(),
1313 );
1314 let decl_ty = self.insert_type_vars(decl_ty); 1562 let decl_ty = self.insert_type_vars(decl_ty);
1315 let ty = if let Some(expr) = initializer { 1563 let ty = if let Some(expr) = initializer {
1316 let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty)); 1564 let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty));
@@ -1338,13 +1586,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1338 let body = Arc::clone(&self.body); // avoid borrow checker problem 1586 let body = Arc::clone(&self.body); // avoid borrow checker problem
1339 for (type_ref, pat) in signature.params().iter().zip(body.params()) { 1587 for (type_ref, pat) in signature.params().iter().zip(body.params()) {
1340 let ty = self.make_ty(type_ref); 1588 let ty = self.make_ty(type_ref);
1341 let ty = self.insert_type_vars(ty);
1342 1589
1343 self.infer_pat(*pat, &ty); 1590 self.infer_pat(*pat, &ty);
1344 } 1591 }
1345 self.return_ty = { 1592 self.return_ty = {
1346 let ty = self.make_ty(signature.ret_type()); 1593 let ty = self.make_ty(signature.ret_type());
1347 let ty = self.insert_type_vars(ty);
1348 ty 1594 ty
1349 }; 1595 };
1350 } 1596 }
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..06e32df59 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -418,6 +418,95 @@ 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
421fn infer(content: &str) -> String { 510fn infer(content: &str) -> String {
422 let (db, _, file_id) = MockDatabase::with_single_file(content); 511 let (db, _, file_id) = MockDatabase::with_single_file(content);
423 let source_file = db.source_file(file_id); 512 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/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 473edc50e..76c2f8173 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -24,7 +24,9 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
24fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { 24fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
25 for receiver in receiver.autoderef(ctx.db) { 25 for receiver in receiver.autoderef(ctx.db) {
26 match receiver { 26 match receiver {
27 Ty::Adt { def_id, .. } => { 27 Ty::Adt {
28 def_id, ref substs, ..
29 } => {
28 match def_id.resolve(ctx.db) { 30 match def_id.resolve(ctx.db) {
29 Def::Struct(s) => { 31 Def::Struct(s) => {
30 for field in s.fields(ctx.db) { 32 for field in s.fields(ctx.db) {
@@ -33,7 +35,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
33 field.name().to_string(), 35 field.name().to_string(),
34 ) 36 )
35 .kind(CompletionItemKind::Field) 37 .kind(CompletionItemKind::Field)
36 .set_detail(field.ty(ctx.db).map(|ty| ty.to_string())) 38 .set_detail(field.ty(ctx.db).map(|ty| ty.subst(substs).to_string()))
37 .add_to(acc); 39 .add_to(acc);
38 } 40 }
39 } 41 }
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_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 },