aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/adt.rs26
-rw-r--r--crates/ra_hir/src/code_model_api.rs33
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs2
-rw-r--r--crates/ra_hir/src/db.rs7
-rw-r--r--crates/ra_hir/src/generics.rs15
-rw-r--r--crates/ra_hir/src/ids.rs7
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/nameres/lower.rs11
-rw-r--r--crates/ra_hir/src/ty.rs150
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs8
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap12
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs33
12 files changed, 200 insertions, 106 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index 4cca09351..3caf60ee6 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -9,19 +9,27 @@ use ra_syntax::{
9}; 9};
10 10
11use crate::{ 11use crate::{
12 DefId, DefLoc, Name, AsName, Struct, Enum, EnumVariant, 12 DefId, DefLoc, Name, AsName, Struct, Enum, EnumVariant, Module, HirFileId,
13 HirDatabase, DefKind, 13 HirDatabase, DefKind,
14 SourceItemId, 14 SourceItemId,
15 type_ref::TypeRef, 15 type_ref::TypeRef,
16 ids::{StructLoc},
16}; 17};
17 18
18impl Struct { 19impl Struct {
19 pub(crate) fn new(def_id: DefId) -> Self { 20 pub(crate) fn from_ast(
20 Struct { def_id } 21 db: &impl HirDatabase,
22 module: Module,
23 file_id: HirFileId,
24 ast: &ast::StructDef,
25 ) -> Struct {
26 let loc: StructLoc = StructLoc::from_ast(db, module, file_id, ast);
27 let id = loc.id(db);
28 Struct { id }
21 } 29 }
22 30
23 pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> { 31 pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> {
24 db.struct_data(self.def_id).variant_data.clone() 32 db.struct_data((*self).into()).variant_data.clone()
25 } 33 }
26} 34}
27 35
@@ -39,13 +47,9 @@ impl StructData {
39 StructData { name, variant_data } 47 StructData { name, variant_data }
40 } 48 }
41 49
42 pub(crate) fn struct_data_query(db: &impl HirDatabase, def_id: DefId) -> Arc<StructData> { 50 pub(crate) fn struct_data_query(db: &impl HirDatabase, struct_: Struct) -> Arc<StructData> {
43 let def_loc = def_id.loc(db); 51 let (_, struct_def) = struct_.source(db);
44 assert!(def_loc.kind == DefKind::Struct); 52 Arc::new(StructData::new(&*struct_def))
45 let syntax = db.file_item(def_loc.source_item_id);
46 let struct_def =
47 ast::StructDef::cast(&syntax).expect("struct def should point to StructDef node");
48 Arc::new(StructData::new(struct_def))
49 } 53 }
50} 54}
51 55
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 905615127..948718aa6 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -10,13 +10,13 @@ use crate::{
10 nameres::{ModuleScope, lower::ImportId}, 10 nameres::{ModuleScope, lower::ImportId},
11 db::HirDatabase, 11 db::HirDatabase,
12 expr::BodySyntaxMapping, 12 expr::BodySyntaxMapping,
13 ty::InferenceResult, 13 ty::{InferenceResult, VariantDef},
14 adt::VariantData, 14 adt::VariantData,
15 generics::GenericParams, 15 generics::GenericParams,
16 code_model_impl::def_id_to_ast, 16 code_model_impl::def_id_to_ast,
17 docs::{Documentation, Docs, docs_from_ast}, 17 docs::{Documentation, Docs, docs_from_ast},
18 module_tree::ModuleId, 18 module_tree::ModuleId,
19 ids::FunctionId, 19 ids::{FunctionId, StructId},
20}; 20};
21 21
22/// hir::Crate describes a single crate. It's the main interface with which 22/// hir::Crate describes a single crate. It's the main interface with which
@@ -68,6 +68,7 @@ pub struct Module {
68pub enum ModuleDef { 68pub enum ModuleDef {
69 Module(Module), 69 Module(Module),
70 Function(Function), 70 Function(Function),
71 Struct(Struct),
71 Def(DefId), 72 Def(DefId),
72} 73}
73 74
@@ -83,6 +84,12 @@ impl Into<ModuleDef> for Function {
83 } 84 }
84} 85}
85 86
87impl Into<ModuleDef> for Struct {
88 fn into(self) -> ModuleDef {
89 ModuleDef::Struct(self)
90 }
91}
92
86impl Into<ModuleDef> for DefId { 93impl Into<ModuleDef> for DefId {
87 fn into(self) -> ModuleDef { 94 fn into(self) -> ModuleDef {
88 ModuleDef::Def(self) 95 ModuleDef::Def(self)
@@ -187,7 +194,7 @@ impl Module {
187 194
188#[derive(Debug, Clone, PartialEq, Eq, Hash)] 195#[derive(Debug, Clone, PartialEq, Eq, Hash)]
189pub struct StructField { 196pub struct StructField {
190 parent: DefId, 197 parent: VariantDef,
191 name: Name, 198 name: Name,
192} 199}
193 200
@@ -201,38 +208,38 @@ impl StructField {
201 } 208 }
202} 209}
203 210
204#[derive(Debug, Clone, PartialEq, Eq, Hash)] 211#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
205pub struct Struct { 212pub struct Struct {
206 pub(crate) def_id: DefId, 213 pub(crate) id: StructId,
207} 214}
208 215
209impl Struct { 216impl Struct {
210 pub fn def_id(&self) -> DefId { 217 pub fn module(&self, db: &impl HirDatabase) -> Module {
211 self.def_id 218 self.id.loc(db).module
212 } 219 }
213 220
214 pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { 221 pub fn name(&self, db: &impl HirDatabase) -> Option<Name> {
215 db.struct_data(self.def_id).name.clone() 222 db.struct_data(*self).name.clone()
216 } 223 }
217 224
218 pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> { 225 pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> {
219 db.struct_data(self.def_id) 226 db.struct_data(*self)
220 .variant_data 227 .variant_data
221 .fields() 228 .fields()
222 .iter() 229 .iter()
223 .map(|it| StructField { 230 .map(|it| StructField {
224 parent: self.def_id, 231 parent: (*self).into(),
225 name: it.name.clone(), 232 name: it.name.clone(),
226 }) 233 })
227 .collect() 234 .collect()
228 } 235 }
229 236
230 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) { 237 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) {
231 def_id_to_ast(db, self.def_id) 238 self.id.loc(db).source(db)
232 } 239 }
233 240
234 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 241 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
235 db.generic_params(self.def_id.into()) 242 db.generic_params((*self).into())
236 } 243 }
237} 244}
238 245
@@ -310,7 +317,7 @@ impl EnumVariant {
310 .fields() 317 .fields()
311 .iter() 318 .iter()
312 .map(|it| StructField { 319 .map(|it| StructField {
313 parent: self.def_id, 320 parent: self.def_id.into(),
314 name: it.name.clone(), 321 name: it.name.clone(),
315 }) 322 })
316 .collect() 323 .collect()
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index b2828c7be..42f10e941 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -135,7 +135,7 @@ impl Module {
135 None => PerNs::none(), 135 None => PerNs::none(),
136 } 136 }
137 } 137 }
138 ModuleDef::Function(_) => PerNs::none(), 138 ModuleDef::Function(_) | ModuleDef::Struct(_) => PerNs::none(),
139 ModuleDef::Def(def) => { 139 ModuleDef::Def(def) => {
140 match def.resolve(db) { 140 match def.resolve(db) {
141 Def::Enum(e) => { 141 Def::Enum(e) => {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 97de7da31..75935c30f 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -8,10 +8,11 @@ use crate::{
8 SourceFileItems, SourceItemId, Crate, Module, HirInterner, 8 SourceFileItems, SourceItemId, Crate, Module, HirInterner,
9 query_definitions, 9 query_definitions,
10 Function, FnSignature, FnScopes, 10 Function, FnSignature, FnScopes,
11 Struct,
11 macros::MacroExpansion, 12 macros::MacroExpansion,
12 module_tree::ModuleTree, 13 module_tree::ModuleTree,
13 nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, 14 nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}},
14 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef}, 15 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, VariantDef},
15 adt::{StructData, EnumData, EnumVariantData}, 16 adt::{StructData, EnumData, EnumVariantData},
16 impl_block::ModuleImplBlocks, 17 impl_block::ModuleImplBlocks,
17 generics::{GenericParams, GenericDef}, 18 generics::{GenericParams, GenericDef},
@@ -29,7 +30,7 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
29 fn fn_scopes(&self, func: Function) -> Arc<FnScopes>; 30 fn fn_scopes(&self, func: Function) -> Arc<FnScopes>;
30 31
31 #[salsa::invoke(crate::adt::StructData::struct_data_query)] 32 #[salsa::invoke(crate::adt::StructData::struct_data_query)]
32 fn struct_data(&self, def_id: DefId) -> Arc<StructData>; 33 fn struct_data(&self, struct_: Struct) -> Arc<StructData>;
33 34
34 #[salsa::invoke(crate::adt::EnumData::enum_data_query)] 35 #[salsa::invoke(crate::adt::EnumData::enum_data_query)]
35 fn enum_data(&self, def_id: DefId) -> Arc<EnumData>; 36 fn enum_data(&self, def_id: DefId) -> Arc<EnumData>;
@@ -44,7 +45,7 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
44 fn type_for_def(&self, def: TypableDef) -> Ty; 45 fn type_for_def(&self, def: TypableDef) -> Ty;
45 46
46 #[salsa::invoke(crate::ty::type_for_field)] 47 #[salsa::invoke(crate::ty::type_for_field)]
47 fn type_for_field(&self, def_id: DefId, field: Name) -> Option<Ty>; 48 fn type_for_field(&self, def: VariantDef, field: Name) -> Option<Ty>;
48 49
49 #[salsa::invoke(query_definitions::file_items)] 50 #[salsa::invoke(query_definitions::file_items)]
50 fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>; 51 fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>;
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index 88c53705f..e10b85ec9 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -7,7 +7,7 @@ use std::sync::Arc;
7 7
8use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner}; 8use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner};
9 9
10use crate::{db::HirDatabase, DefId, Name, AsName, Function}; 10use crate::{db::HirDatabase, DefId, Name, AsName, Function, Struct};
11 11
12/// Data about a generic parameter (to a function, struct, impl, ...). 12/// Data about a generic parameter (to a function, struct, impl, ...).
13#[derive(Clone, PartialEq, Eq, Debug)] 13#[derive(Clone, PartialEq, Eq, Debug)]
@@ -25,6 +25,7 @@ pub struct GenericParams {
25#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] 25#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
26pub enum GenericDef { 26pub enum GenericDef {
27 Function(Function), 27 Function(Function),
28 Struct(Struct),
28 Def(DefId), 29 Def(DefId),
29} 30}
30 31
@@ -34,6 +35,12 @@ impl From<Function> for GenericDef {
34 } 35 }
35} 36}
36 37
38impl From<Struct> for GenericDef {
39 fn from(func: Struct) -> GenericDef {
40 GenericDef::Struct(func)
41 }
42}
43
37impl From<DefId> for GenericDef { 44impl From<DefId> for GenericDef {
38 fn from(def_id: DefId) -> GenericDef { 45 fn from(def_id: DefId) -> GenericDef {
39 GenericDef::Def(def_id) 46 GenericDef::Def(def_id)
@@ -53,6 +60,12 @@ impl GenericParams {
53 generics.fill(type_param_list) 60 generics.fill(type_param_list)
54 } 61 }
55 } 62 }
63 GenericDef::Struct(s) => {
64 let (_, struct_def) = s.source(db);
65 if let Some(type_param_list) = struct_def.type_param_list() {
66 generics.fill(type_param_list)
67 }
68 }
56 GenericDef::Def(def_id) => { 69 GenericDef::Def(def_id) => {
57 let (_file_id, node) = def_id.source(db); 70 let (_file_id, node) = def_id.source(db);
58 if let Some(type_param_list) = node.children().find_map(ast::TypeParamList::cast) { 71 if let Some(type_param_list) = node.children().find_map(ast::TypeParamList::cast) {
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 51e3cfb81..2791149dd 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -5,7 +5,7 @@ use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast};
5use ra_arena::{Arena, RawId, impl_arena_id}; 5use ra_arena::{Arena, RawId, impl_arena_id};
6 6
7use crate::{ 7use crate::{
8 HirDatabase, Def, Struct, Enum, EnumVariant, Crate, 8 HirDatabase, Def, Enum, EnumVariant, Crate,
9 Module, Trait, Type, Static, Const, 9 Module, Trait, Type, Static, Const,
10}; 10};
11 11
@@ -257,10 +257,7 @@ impl DefId {
257 pub fn resolve(self, db: &impl HirDatabase) -> Def { 257 pub fn resolve(self, db: &impl HirDatabase) -> Def {
258 let loc = self.loc(db); 258 let loc = self.loc(db);
259 match loc.kind { 259 match loc.kind {
260 DefKind::Struct => { 260 DefKind::Struct => unreachable!(),
261 let struct_def = Struct::new(self);
262 Def::Struct(struct_def)
263 }
264 DefKind::Enum => Def::Enum(Enum::new(self)), 261 DefKind::Enum => Def::Enum(Enum::new(self)),
265 DefKind::EnumVariant => Def::EnumVariant(EnumVariant::new(self)), 262 DefKind::EnumVariant => Def::EnumVariant(EnumVariant::new(self)),
266 DefKind::Const => { 263 DefKind::Const => {
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index a6246a5e9..5d6371892 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -43,7 +43,7 @@ pub use self::{
43 ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc, HirInterner}, 43 ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc, HirInterner},
44 macros::{MacroDef, MacroInput, MacroExpansion}, 44 macros::{MacroDef, MacroInput, MacroExpansion},
45 nameres::{ItemMap, PerNs, Namespace, Resolution}, 45 nameres::{ItemMap, PerNs, Namespace, Resolution},
46 ty::Ty, 46 ty::{Ty, AdtDef},
47 impl_block::{ImplBlock, ImplItem}, 47 impl_block::{ImplBlock, ImplItem},
48 code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping}, 48 code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping},
49 docs::{Docs, Documentation} 49 docs::{Docs, Documentation}
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs
index 1f8adc7eb..b0c4aa819 100644
--- a/crates/ra_hir/src/nameres/lower.rs
+++ b/crates/ra_hir/src/nameres/lower.rs
@@ -10,7 +10,7 @@ use rustc_hash::FxHashMap;
10use crate::{ 10use crate::{
11 SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, 11 SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems,
12 HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, Function, 12 HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, Function,
13 ModuleDef, Module, 13 ModuleDef, Module, Struct,
14}; 14};
15 15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -147,7 +147,14 @@ impl LoweredModule {
147 item: &ast::ModuleItem, 147 item: &ast::ModuleItem,
148 ) { 148 ) {
149 let name = match item.kind() { 149 let name = match item.kind() {
150 ast::ModuleItemKind::StructDef(it) => it.name(), 150 ast::ModuleItemKind::StructDef(it) => {
151 if let Some(name) = it.name() {
152 let s = Struct::from_ast(db, module, file_id, it);
153 let s: ModuleDef = s.into();
154 self.declarations.insert(name.as_name(), PerNs::both(s, s));
155 }
156 return;
157 }
151 ast::ModuleItemKind::EnumDef(it) => it.name(), 158 ast::ModuleItemKind::EnumDef(it) => it.name(),
152 ast::ModuleItemKind::FnDef(it) => { 159 ast::ModuleItemKind::FnDef(it) => {
153 if let Some(name) = it.name() { 160 if let Some(name) = it.name() {
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index f9cdbcab3..fc699a2ae 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -32,7 +32,7 @@ use rustc_hash::FxHashMap;
32 32
33use crate::{ 33use crate::{
34 Def, DefId, Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, 34 Def, DefId, Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock,
35 FnSignature, FnScopes, ModuleDef, 35 FnSignature, FnScopes, ModuleDef, Crate,
36 db::HirDatabase, 36 db::HirDatabase,
37 type_ref::{TypeRef, Mutability}, 37 type_ref::{TypeRef, Mutability},
38 name::KnownName, 38 name::KnownName,
@@ -163,6 +163,33 @@ impl Substs {
163 } 163 }
164} 164}
165 165
166#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
167pub enum AdtDef {
168 Struct(Struct),
169 Def(DefId), // Enum
170}
171
172impl From<Struct> for AdtDef {
173 fn from(struct_: Struct) -> AdtDef {
174 AdtDef::Struct(struct_)
175 }
176}
177
178impl From<DefId> for AdtDef {
179 fn from(def_id: DefId) -> AdtDef {
180 AdtDef::Def(def_id)
181 }
182}
183
184impl AdtDef {
185 fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
186 match self {
187 AdtDef::Struct(s) => s.module(db).krate(db),
188 AdtDef::Def(def_id) => def_id.krate(db),
189 }
190 }
191}
192
166/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). 193/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs).
167/// 194///
168/// This should be cheap to clone. 195/// This should be cheap to clone.
@@ -184,7 +211,7 @@ pub enum Ty {
184 /// Structures, enumerations and unions. 211 /// Structures, enumerations and unions.
185 Adt { 212 Adt {
186 /// The DefId of the struct/enum. 213 /// The DefId of the struct/enum.
187 def_id: DefId, 214 def_id: AdtDef,
188 /// The name, for displaying. 215 /// The name, for displaying.
189 name: Name, 216 name: Name,
190 /// Substitutions for the generic parameters of the type. 217 /// Substitutions for the generic parameters of the type.
@@ -384,6 +411,7 @@ impl Ty {
384 let resolved = match module.resolve_path(db, path).take_types() { 411 let resolved = match module.resolve_path(db, path).take_types() {
385 Some(ModuleDef::Def(r)) => r.into(), 412 Some(ModuleDef::Def(r)) => r.into(),
386 Some(ModuleDef::Function(f)) => f.into(), 413 Some(ModuleDef::Function(f)) => f.into(),
414 Some(ModuleDef::Struct(s)) => s.into(),
387 None | Some(ModuleDef::Module(_)) => return Ty::Unknown, 415 None | Some(ModuleDef::Module(_)) => return Ty::Unknown,
388 }; 416 };
389 let ty = db.type_for_def(resolved); 417 let ty = db.type_for_def(resolved);
@@ -409,6 +437,7 @@ impl Ty {
409 .expect("path should have at least one segment"); 437 .expect("path should have at least one segment");
410 let (def_generics, segment) = match resolved { 438 let (def_generics, segment) = match resolved {
411 TypableDef::Function(func) => (func.generic_params(db), last), 439 TypableDef::Function(func) => (func.generic_params(db), last),
440 TypableDef::Struct(s) => (s.generic_params(db), last),
412 TypableDef::Def(def_id) => match def_id.resolve(db) { 441 TypableDef::Def(def_id) => match def_id.resolve(db) {
413 Def::Struct(s) => (s.generic_params(db), last), 442 Def::Struct(s) => (s.generic_params(db), last),
414 Def::Enum(e) => (e.generic_params(db), last), 443 Def::Enum(e) => (e.generic_params(db), last),
@@ -642,7 +671,7 @@ fn make_substs(generics: &GenericParams) -> Substs {
642fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { 671fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
643 let generics = s.generic_params(db); 672 let generics = s.generic_params(db);
644 Ty::Adt { 673 Ty::Adt {
645 def_id: s.def_id(), 674 def_id: s.into(),
646 name: s.name(db).unwrap_or_else(Name::missing), 675 name: s.name(db).unwrap_or_else(Name::missing),
647 substs: make_substs(&generics), 676 substs: make_substs(&generics),
648 } 677 }
@@ -651,7 +680,7 @@ fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
651pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { 680pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
652 let generics = s.generic_params(db); 681 let generics = s.generic_params(db);
653 Ty::Adt { 682 Ty::Adt {
654 def_id: s.def_id(), 683 def_id: s.def_id().into(),
655 name: s.name(db).unwrap_or_else(Name::missing), 684 name: s.name(db).unwrap_or_else(Name::missing),
656 substs: make_substs(&generics), 685 substs: make_substs(&generics),
657 } 686 }
@@ -666,6 +695,7 @@ pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> T
666#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 695#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
667pub enum TypableDef { 696pub enum TypableDef {
668 Function(Function), 697 Function(Function),
698 Struct(Struct),
669 Def(DefId), 699 Def(DefId),
670} 700}
671 701
@@ -675,6 +705,12 @@ impl From<Function> for TypableDef {
675 } 705 }
676} 706}
677 707
708impl From<Struct> for TypableDef {
709 fn from(struct_: Struct) -> TypableDef {
710 TypableDef::Struct(struct_)
711 }
712}
713
678impl From<DefId> for TypableDef { 714impl From<DefId> for TypableDef {
679 fn from(func: DefId) -> TypableDef { 715 fn from(func: DefId) -> TypableDef {
680 TypableDef::Def(func) 716 TypableDef::Def(func)
@@ -684,8 +720,8 @@ impl From<DefId> for TypableDef {
684pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { 720pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty {
685 match def { 721 match def {
686 TypableDef::Function(f) => type_for_fn(db, f), 722 TypableDef::Function(f) => type_for_fn(db, f),
723 TypableDef::Struct(s) => type_for_struct(db, s),
687 TypableDef::Def(def_id) => match def_id.resolve(db) { 724 TypableDef::Def(def_id) => match def_id.resolve(db) {
688 Def::Struct(s) => type_for_struct(db, s),
689 Def::Enum(e) => type_for_enum(db, e), 725 Def::Enum(e) => type_for_enum(db, e),
690 Def::EnumVariant(ev) => type_for_enum_variant(db, ev), 726 Def::EnumVariant(ev) => type_for_enum_variant(db, ev),
691 _ => { 727 _ => {
@@ -700,22 +736,44 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty {
700 } 736 }
701} 737}
702 738
703pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Option<Ty> { 739#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
704 let def = def_id.resolve(db); 740pub enum VariantDef {
705 let (variant_data, generics) = match def { 741 Struct(Struct),
706 Def::Struct(s) => (s.variant_data(db), s.generic_params(db)), 742 Def(DefId), // EnumVariant
707 Def::EnumVariant(ev) => (ev.variant_data(db), ev.parent_enum(db).generic_params(db)), 743}
708 // TODO: unions 744
709 Def::Enum(_) => { 745impl From<Struct> for VariantDef {
710 // this can happen in (invalid) code, but enums don't have fields themselves 746 fn from(struct_: Struct) -> VariantDef {
711 return None; 747 VariantDef::Struct(struct_)
712 } 748 }
713 _ => panic!( 749}
714 "trying to get type for field {:?} in non-struct/variant {:?}", 750
715 field, def_id 751impl From<DefId> for VariantDef {
716 ), 752 fn from(def_id: DefId) -> VariantDef {
753 VariantDef::Def(def_id)
754 }
755}
756
757pub(super) fn type_for_field(db: &impl HirDatabase, def: VariantDef, field: Name) -> Option<Ty> {
758 let (variant_data, generics, module) = match def {
759 VariantDef::Struct(s) => (s.variant_data(db), s.generic_params(db), s.module(db)),
760 VariantDef::Def(def_id) => match def_id.resolve(db) {
761 Def::EnumVariant(ev) => (
762 ev.variant_data(db),
763 ev.parent_enum(db).generic_params(db),
764 def_id.module(db),
765 ),
766 // TODO: unions
767 Def::Enum(_) => {
768 // this can happen in (invalid) code, but enums don't have fields themselves
769 return None;
770 }
771 _ => panic!(
772 "trying to get type for field {:?} in non-struct/variant {:?}",
773 field, def_id
774 ),
775 },
717 }; 776 };
718 let module = def_id.module(db);
719 // We can't have an impl block ere, right? 777 // We can't have an impl block ere, right?
720 // let impl_block = def_id.impl_block(db); 778 // let impl_block = def_id.impl_block(db);
721 let type_ref = variant_data.get_field_type_ref(&field)?; 779 let type_ref = variant_data.get_field_type_ref(&field)?;
@@ -1076,17 +1134,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1076 }; 1134 };
1077 1135
1078 // resolve in module 1136 // resolve in module
1079 let resolved = match self.module.resolve_path(self.db, &path).take_values()? { 1137 let typable = match self.module.resolve_path(self.db, &path).take_values()? {
1080 ModuleDef::Def(it) => it.into(), 1138 ModuleDef::Def(it) => it.into(),
1081 ModuleDef::Function(func) => func.into(), 1139 ModuleDef::Function(func) => func.into(),
1140 ModuleDef::Struct(s) => s.into(),
1082 ModuleDef::Module(_) => return None, 1141 ModuleDef::Module(_) => return None,
1083 }; 1142 };
1084 let ty = self.db.type_for_def(resolved); 1143 let ty = self.db.type_for_def(typable);
1085 let ty = self.insert_type_vars(ty); 1144 let ty = self.insert_type_vars(ty);
1086 Some(ty) 1145 Some(ty)
1087 } 1146 }
1088 1147
1089 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<DefId>) { 1148 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) {
1090 let path = match path { 1149 let path = match path {
1091 Some(path) => path, 1150 Some(path) => path,
1092 None => return (Ty::Unknown, None), 1151 None => return (Ty::Unknown, None),
@@ -1094,7 +1153,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1094 let def = match self.module.resolve_path(self.db, &path).take_types() { 1153 let def = match self.module.resolve_path(self.db, &path).take_types() {
1095 Some(ModuleDef::Def(def_id)) => def_id.into(), 1154 Some(ModuleDef::Def(def_id)) => def_id.into(),
1096 Some(ModuleDef::Function(func)) => func.into(), 1155 Some(ModuleDef::Function(func)) => func.into(),
1097 _ => return (Ty::Unknown, None), 1156 Some(ModuleDef::Struct(s)) => s.into(),
1157 None | Some(ModuleDef::Module(_)) => return (Ty::Unknown, None),
1098 }; 1158 };
1099 // TODO remove the duplication between here and `Ty::from_path`? 1159 // TODO remove the duplication between here and `Ty::from_path`?
1100 // TODO provide generics of function 1160 // TODO provide generics of function
@@ -1109,37 +1169,36 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1109 ); 1169 );
1110 match def { 1170 match def {
1111 TypableDef::Def(def_id) => match def_id.resolve(self.db) { 1171 TypableDef::Def(def_id) => match def_id.resolve(self.db) {
1112 Def::Struct(s) => {
1113 let ty = type_for_struct(self.db, s);
1114 let ty = self.insert_type_vars(ty.apply_substs(substs));
1115 (ty, Some(def_id))
1116 }
1117 Def::EnumVariant(ev) => { 1172 Def::EnumVariant(ev) => {
1118 let ty = type_for_enum_variant(self.db, ev); 1173 let ty = type_for_enum_variant(self.db, ev);
1119 let ty = self.insert_type_vars(ty.apply_substs(substs)); 1174 let ty = self.insert_type_vars(ty.apply_substs(substs));
1120 (ty, Some(def_id)) 1175 (ty, Some(def_id.into()))
1121 } 1176 }
1122 _ => (Ty::Unknown, None), 1177 _ => (Ty::Unknown, None),
1123 }, 1178 },
1124 TypableDef::Function(_) => (Ty::Unknown, None), 1179 TypableDef::Function(_) => (Ty::Unknown, None),
1180 TypableDef::Struct(s) => {
1181 let ty = type_for_struct(self.db, s);
1182 let ty = self.insert_type_vars(ty.apply_substs(substs));
1183 (ty, Some(s.into()))
1184 }
1125 } 1185 }
1126 } 1186 }
1127 1187
1128 fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { 1188 fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> {
1129 let (ty, def_id) = self.resolve_variant(path); 1189 let (ty, def) = self.resolve_variant(path);
1130 let def_id = def_id?; 1190 match def? {
1131 let def = def_id.resolve(self.db); 1191 VariantDef::Struct(s) => {
1132
1133 match def {
1134 Def::Struct(s) => {
1135 let fields = s.fields(self.db); 1192 let fields = s.fields(self.db);
1136 Some((ty, fields)) 1193 Some((ty, fields))
1137 } 1194 }
1138 Def::EnumVariant(ev) => { 1195 VariantDef::Def(def_id) => match def_id.resolve(self.db) {
1139 let fields = ev.fields(self.db); 1196 Def::EnumVariant(ev) => {
1140 Some((ty, fields)) 1197 let fields = ev.fields(self.db);
1141 } 1198 Some((ty, fields))
1142 _ => None, 1199 }
1200 _ => None,
1201 },
1143 } 1202 }
1144 } 1203 }
1145 1204
@@ -1240,6 +1299,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1240 .and_then(|module_def| match module_def { 1299 .and_then(|module_def| match module_def {
1241 ModuleDef::Def(it) => Some(it.into()), 1300 ModuleDef::Def(it) => Some(it.into()),
1242 ModuleDef::Function(func) => Some(func.into()), 1301 ModuleDef::Function(func) => Some(func.into()),
1302 ModuleDef::Struct(s) => Some(s.into()),
1243 ModuleDef::Module(_) => None, 1303 ModuleDef::Module(_) => None,
1244 }) 1304 })
1245 .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), 1305 .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)),
@@ -1433,7 +1493,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1433 for field in fields { 1493 for field in fields {
1434 let field_ty = if let Some(def_id) = def_id { 1494 let field_ty = if let Some(def_id) = def_id {
1435 self.db 1495 self.db
1436 .type_for_field(def_id, field.name.clone()) 1496 .type_for_field(def_id.into(), field.name.clone())
1437 .unwrap_or(Ty::Unknown) 1497 .unwrap_or(Ty::Unknown)
1438 .subst(&substs) 1498 .subst(&substs)
1439 } else { 1499 } else {
@@ -1457,10 +1517,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1457 i.and_then(|i| fields.get(i).cloned()) 1517 i.and_then(|i| fields.get(i).cloned())
1458 } 1518 }
1459 Ty::Adt { 1519 Ty::Adt {
1460 def_id, ref substs, .. 1520 def_id: AdtDef::Struct(s),
1521 ref substs,
1522 ..
1461 } => self 1523 } => self
1462 .db 1524 .db
1463 .type_for_field(def_id, name.clone()) 1525 .type_for_field(s.into(), name.clone())
1464 .map(|ty| ty.subst(substs)), 1526 .map(|ty| ty.subst(substs)),
1465 _ => None, 1527 _ => None,
1466 }) 1528 })
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 0084b24dc..9a571c2aa 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -7,16 +7,16 @@ use std::sync::Arc;
7use rustc_hash::FxHashMap; 7use rustc_hash::FxHashMap;
8 8
9use crate::{ 9use crate::{
10 HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, 10 HirDatabase, module_tree::ModuleId, Module, Crate, Name, Function,
11 impl_block::{ImplId, ImplBlock, ImplItem}, 11 impl_block::{ImplId, ImplBlock, ImplItem},
12 generics::GenericParams 12 generics::GenericParams,
13 ty::{AdtDef, Ty}
13}; 14};
14use super::Ty;
15 15
16/// This is used as a key for indexing impls. 16/// This is used as a key for indexing impls.
17#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 17#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
18pub enum TyFingerprint { 18pub enum TyFingerprint {
19 Adt(DefId), 19 Adt(AdtDef),
20 // we'll also want to index impls for primitive types etc. 20 // we'll also want to index impls for primitive types etc.
21} 21}
22 22
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap
index c4a2d5cf8..8747fae18 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap
@@ -1,19 +1,19 @@
1--- 1---
2created: "2019-01-22T14:45:00.058678600+00:00" 2created: "2019-01-24T14:51:32.808861856+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: crates/ra_hir/src/ty/tests.rs
6--- 6---
7[72; 154) '{ ...a.c; }': () 7[72; 154) '{ ...a.c; }': ()
8[82; 83) 'c': [unknown] 8[82; 83) 'c': [unknown]
9[86; 87) 'C': [unknown] 9[86; 87) 'C': C
10[86; 90) 'C(1)': [unknown] 10[86; 90) 'C(1)': [unknown]
11[88; 89) '1': i32 11[88; 89) '1': i32
12[96; 97) 'B': [unknown] 12[96; 97) 'B': B
13[107; 108) 'a': A 13[107; 108) 'a': A
14[114; 133) 'A { b:...C(1) }': A 14[114; 133) 'A { b:...C(1) }': A
15[121; 122) 'B': B 15[121; 122) 'B': B
16[127; 128) 'C': [unknown] 16[127; 128) 'C': C
17[127; 131) 'C(1)': C 17[127; 131) 'C(1)': C
18[129; 130) '1': i32 18[129; 130) '1': i32
19[139; 140) 'a': A 19[139; 140) 'a': A
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index 32fd497be..1a2b0b2f6 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -1,4 +1,4 @@
1use hir::{Ty, Def}; 1use hir::{Ty, Def, AdtDef};
2 2
3use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind}; 3use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind};
4use crate::completion::completion_item::CompletionKind; 4use crate::completion::completion_item::CompletionKind;
@@ -28,21 +28,24 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
28 Ty::Adt { 28 Ty::Adt {
29 def_id, ref substs, .. 29 def_id, ref substs, ..
30 } => { 30 } => {
31 match def_id.resolve(ctx.db) { 31 match def_id {
32 Def::Struct(s) => { 32 AdtDef::Struct() => {}
33 for field in s.fields(ctx.db) { 33 AdtDef::Def(def_id) => match def_id.resolve(ctx.db) {
34 CompletionItem::new( 34 Def::Struct(s) => {
35 CompletionKind::Reference, 35 for field in s.fields(ctx.db) {
36 ctx.source_range(), 36 CompletionItem::new(
37 field.name().to_string(), 37 CompletionKind::Reference,
38 ) 38 ctx.source_range(),
39 .kind(CompletionItemKind::Field) 39 field.name().to_string(),
40 .set_detail(field.ty(ctx.db).map(|ty| ty.subst(substs).to_string())) 40 )
41 .add_to(acc); 41 .kind(CompletionItemKind::Field)
42 .set_detail(field.ty(ctx.db).map(|ty| ty.subst(substs).to_string()))
43 .add_to(acc);
44 }
42 } 45 }
43 } 46 // TODO unions
44 // TODO unions 47 _ => {}
45 _ => {} 48 },
46 } 49 }
47 } 50 }
48 Ty::Tuple(fields) => { 51 Ty::Tuple(fields) => {