diff options
author | Florian Diebold <[email protected]> | 2018-12-24 18:07:48 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2018-12-25 14:16:42 +0000 |
commit | b5b68f2094d49cacde6d7f0c49f521a0b25f34bd (patch) | |
tree | 5439bb80896c211b3cadb2c037383243fe1fc140 | |
parent | 5fb426cb9eeefa69a53d7c8c3367f7c6b714b9b8 (diff) |
Add basic HIR and types for structs/enums
-rw-r--r-- | crates/ra_analysis/src/db.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/adt.rs | 114 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir/src/mock.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/query_definitions.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 72 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/0004_struct.txt | 10 |
9 files changed, 244 insertions, 29 deletions
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs index 780a84291..7043a0f4d 100644 --- a/crates/ra_analysis/src/db.rs +++ b/crates/ra_analysis/src/db.rs | |||
@@ -95,6 +95,8 @@ salsa::database_storage! { | |||
95 | fn submodules() for hir::db::SubmodulesQuery; | 95 | fn submodules() for hir::db::SubmodulesQuery; |
96 | fn infer() for hir::db::InferQuery; | 96 | fn infer() for hir::db::InferQuery; |
97 | fn type_for_def() for hir::db::TypeForDefQuery; | 97 | fn type_for_def() for hir::db::TypeForDefQuery; |
98 | fn struct_data() for db::StructDataQuery; | ||
99 | fn enum_data() for db::EnumDataQuery; | ||
98 | } | 100 | } |
99 | } | 101 | } |
100 | } | 102 | } |
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs new file mode 100644 index 000000000..a2d228593 --- /dev/null +++ b/crates/ra_hir/src/adt.rs | |||
@@ -0,0 +1,114 @@ | |||
1 | use ra_syntax::{SmolStr, ast::{self, NameOwner}}; | ||
2 | |||
3 | use crate::{ | ||
4 | DefId, Cancelable, | ||
5 | db::{HirDatabase}, | ||
6 | ty::{Ty}, | ||
7 | }; | ||
8 | |||
9 | pub struct Struct { | ||
10 | def_id: DefId, | ||
11 | } | ||
12 | |||
13 | impl Struct { | ||
14 | pub(crate) fn new(def_id: DefId) -> Self { | ||
15 | Struct { def_id } | ||
16 | } | ||
17 | |||
18 | pub fn name(&self, db: &impl HirDatabase) -> Cancelable<SmolStr> { | ||
19 | Ok(db.struct_data(self.def_id)?.name.clone()) | ||
20 | } | ||
21 | } | ||
22 | |||
23 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
24 | pub struct StructData { | ||
25 | name: SmolStr, | ||
26 | variant_data: VariantData, | ||
27 | } | ||
28 | |||
29 | impl StructData { | ||
30 | pub(crate) fn new(struct_def: ast::StructDef) -> StructData { | ||
31 | let name = struct_def | ||
32 | .name() | ||
33 | .map(|n| n.text()) | ||
34 | .unwrap_or(SmolStr::new("[error]")); | ||
35 | let variant_data = VariantData::Unit; // TODO implement this | ||
36 | StructData { name, variant_data } | ||
37 | } | ||
38 | } | ||
39 | |||
40 | pub struct Enum { | ||
41 | def_id: DefId, | ||
42 | } | ||
43 | |||
44 | impl Enum { | ||
45 | pub(crate) fn new(def_id: DefId) -> Self { | ||
46 | Enum { def_id } | ||
47 | } | ||
48 | |||
49 | pub fn name(&self, db: &impl HirDatabase) -> Cancelable<SmolStr> { | ||
50 | Ok(db.enum_data(self.def_id)?.name.clone()) | ||
51 | } | ||
52 | } | ||
53 | |||
54 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
55 | pub struct EnumData { | ||
56 | name: SmolStr, | ||
57 | variants: Vec<(SmolStr, VariantData)>, | ||
58 | } | ||
59 | |||
60 | impl EnumData { | ||
61 | pub(crate) fn new(enum_def: ast::EnumDef) -> Self { | ||
62 | let name = enum_def | ||
63 | .name() | ||
64 | .map(|n| n.text()) | ||
65 | .unwrap_or(SmolStr::new("[error]")); | ||
66 | let variants = Vec::new(); // TODO implement this | ||
67 | EnumData { name, variants } | ||
68 | } | ||
69 | } | ||
70 | |||
71 | /// A single field of an enum variant or struct | ||
72 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
73 | pub struct StructField { | ||
74 | name: SmolStr, | ||
75 | ty: Ty, | ||
76 | } | ||
77 | |||
78 | /// Fields of an enum variant or struct | ||
79 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
80 | pub enum VariantData { | ||
81 | Struct(Vec<StructField>), | ||
82 | Tuple(Vec<StructField>), | ||
83 | Unit, | ||
84 | } | ||
85 | |||
86 | impl VariantData { | ||
87 | pub fn fields(&self) -> &[StructField] { | ||
88 | match *self { | ||
89 | VariantData::Struct(ref fields) | VariantData::Tuple(ref fields) => fields, | ||
90 | _ => &[], | ||
91 | } | ||
92 | } | ||
93 | pub fn is_struct(&self) -> bool { | ||
94 | if let VariantData::Struct(..) = *self { | ||
95 | true | ||
96 | } else { | ||
97 | false | ||
98 | } | ||
99 | } | ||
100 | pub fn is_tuple(&self) -> bool { | ||
101 | if let VariantData::Tuple(..) = *self { | ||
102 | true | ||
103 | } else { | ||
104 | false | ||
105 | } | ||
106 | } | ||
107 | pub fn is_unit(&self) -> bool { | ||
108 | if let VariantData::Unit = *self { | ||
109 | true | ||
110 | } else { | ||
111 | false | ||
112 | } | ||
113 | } | ||
114 | } | ||
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index d94f75857..113790ee9 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -15,6 +15,7 @@ use crate::{ | |||
15 | module::{ModuleId, ModuleTree, ModuleSource, | 15 | module::{ModuleId, ModuleTree, ModuleSource, |
16 | nameres::{ItemMap, InputModuleItems}}, | 16 | nameres::{ItemMap, InputModuleItems}}, |
17 | ty::{InferenceResult, Ty}, | 17 | ty::{InferenceResult, Ty}, |
18 | adt::{StructData, EnumData}, | ||
18 | }; | 19 | }; |
19 | 20 | ||
20 | salsa::query_group! { | 21 | salsa::query_group! { |
@@ -31,6 +32,16 @@ pub trait HirDatabase: SyntaxDatabase | |||
31 | use fn query_definitions::fn_syntax; | 32 | use fn query_definitions::fn_syntax; |
32 | } | 33 | } |
33 | 34 | ||
35 | fn struct_data(def_id: DefId) -> Cancelable<Arc<StructData>> { | ||
36 | type StructDataQuery; | ||
37 | use fn query_definitions::struct_data; | ||
38 | } | ||
39 | |||
40 | fn enum_data(def_id: DefId) -> Cancelable<Arc<EnumData>> { | ||
41 | type EnumDataQuery; | ||
42 | use fn query_definitions::enum_data; | ||
43 | } | ||
44 | |||
34 | fn infer(fn_id: FnId) -> Cancelable<Arc<InferenceResult>> { | 45 | fn infer(fn_id: FnId) -> Cancelable<Arc<InferenceResult>> { |
35 | type InferQuery; | 46 | type InferQuery; |
36 | use fn query_definitions::infer; | 47 | use fn query_definitions::infer; |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index a0d99a84d..7e9824de9 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -25,6 +25,7 @@ pub mod source_binder; | |||
25 | mod krate; | 25 | mod krate; |
26 | mod module; | 26 | mod module; |
27 | mod function; | 27 | mod function; |
28 | mod adt; | ||
28 | mod ty; | 29 | mod ty; |
29 | 30 | ||
30 | use std::ops::Index; | 31 | use std::ops::Index; |
@@ -42,6 +43,7 @@ pub use self::{ | |||
42 | krate::Crate, | 43 | krate::Crate, |
43 | module::{Module, ModuleId, Problem, nameres::ItemMap, ModuleScope, Resolution}, | 44 | module::{Module, ModuleId, Problem, nameres::ItemMap, ModuleScope, Resolution}, |
44 | function::{Function, FnScopes}, | 45 | function::{Function, FnScopes}, |
46 | adt::{Struct, Enum}, | ||
45 | }; | 47 | }; |
46 | 48 | ||
47 | pub use self::function::FnSignatureInfo; | 49 | pub use self::function::FnSignatureInfo; |
@@ -56,6 +58,8 @@ ra_db::impl_numeric_id!(DefId); | |||
56 | pub(crate) enum DefKind { | 58 | pub(crate) enum DefKind { |
57 | Module, | 59 | Module, |
58 | Function, | 60 | Function, |
61 | Struct, | ||
62 | Enum, | ||
59 | Item, | 63 | Item, |
60 | } | 64 | } |
61 | 65 | ||
@@ -73,8 +77,8 @@ impl DefKind { | |||
73 | SyntaxKind::FN_DEF => Some(DefKind::Function), | 77 | SyntaxKind::FN_DEF => Some(DefKind::Function), |
74 | SyntaxKind::MODULE => Some(DefKind::Module), | 78 | SyntaxKind::MODULE => Some(DefKind::Module), |
75 | // These define items, but don't have their own DefKinds yet: | 79 | // These define items, but don't have their own DefKinds yet: |
76 | SyntaxKind::STRUCT_DEF => Some(DefKind::Item), | 80 | SyntaxKind::STRUCT_DEF => Some(DefKind::Struct), |
77 | SyntaxKind::ENUM_DEF => Some(DefKind::Item), | 81 | SyntaxKind::ENUM_DEF => Some(DefKind::Enum), |
78 | SyntaxKind::TRAIT_DEF => Some(DefKind::Item), | 82 | SyntaxKind::TRAIT_DEF => Some(DefKind::Item), |
79 | SyntaxKind::TYPE_DEF => Some(DefKind::Item), | 83 | SyntaxKind::TYPE_DEF => Some(DefKind::Item), |
80 | SyntaxKind::CONST_DEF => Some(DefKind::Item), | 84 | SyntaxKind::CONST_DEF => Some(DefKind::Item), |
@@ -99,6 +103,8 @@ impl DefLoc { | |||
99 | pub enum Def { | 103 | pub enum Def { |
100 | Module(Module), | 104 | Module(Module), |
101 | Function(Function), | 105 | Function(Function), |
106 | Struct(Struct), | ||
107 | Enum(Enum), | ||
102 | Item, | 108 | Item, |
103 | } | 109 | } |
104 | 110 | ||
@@ -114,6 +120,14 @@ impl DefId { | |||
114 | let function = Function::new(self); | 120 | let function = Function::new(self); |
115 | Def::Function(function) | 121 | Def::Function(function) |
116 | } | 122 | } |
123 | DefKind::Struct => { | ||
124 | let struct_def = Struct::new(self); | ||
125 | Def::Struct(struct_def) | ||
126 | } | ||
127 | DefKind::Enum => { | ||
128 | let enum_def = Enum::new(self); | ||
129 | Def::Enum(enum_def) | ||
130 | } | ||
117 | DefKind::Item => Def::Item, | 131 | DefKind::Item => Def::Item, |
118 | }; | 132 | }; |
119 | Ok(res) | 133 | Ok(res) |
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index b5a997170..ead2b8414 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs | |||
@@ -193,6 +193,8 @@ salsa::database_storage! { | |||
193 | fn submodules() for db::SubmodulesQuery; | 193 | fn submodules() for db::SubmodulesQuery; |
194 | fn infer() for db::InferQuery; | 194 | fn infer() for db::InferQuery; |
195 | fn type_for_def() for db::TypeForDefQuery; | 195 | fn type_for_def() for db::TypeForDefQuery; |
196 | fn struct_data() for db::StructDataQuery; | ||
197 | fn enum_data() for db::EnumDataQuery; | ||
196 | } | 198 | } |
197 | } | 199 | } |
198 | } | 200 | } |
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index b654af920..72440d1d6 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs | |||
@@ -19,7 +19,8 @@ use crate::{ | |||
19 | imp::Submodule, | 19 | imp::Submodule, |
20 | nameres::{InputModuleItems, ItemMap, Resolver}, | 20 | nameres::{InputModuleItems, ItemMap, Resolver}, |
21 | }, | 21 | }, |
22 | ty::{self, InferenceResult, Ty} | 22 | ty::{self, InferenceResult, Ty}, |
23 | adt::{StructData, EnumData}, | ||
23 | }; | 24 | }; |
24 | 25 | ||
25 | /// Resolve `FnId` to the corresponding `SyntaxNode` | 26 | /// Resolve `FnId` to the corresponding `SyntaxNode` |
@@ -45,6 +46,24 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<T | |||
45 | ty::type_for_def(db, def_id) | 46 | ty::type_for_def(db, def_id) |
46 | } | 47 | } |
47 | 48 | ||
49 | pub(super) fn struct_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<StructData>> { | ||
50 | let def_loc = def_id.loc(db); | ||
51 | assert!(def_loc.kind == DefKind::Struct); | ||
52 | let syntax = db.file_item(def_loc.source_item_id); | ||
53 | let struct_def = | ||
54 | ast::StructDef::cast(syntax.borrowed()).expect("struct def should point to StructDef node"); | ||
55 | Ok(Arc::new(StructData::new(struct_def.borrowed()))) | ||
56 | } | ||
57 | |||
58 | pub(super) fn enum_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<EnumData>> { | ||
59 | let def_loc = def_id.loc(db); | ||
60 | assert!(def_loc.kind == DefKind::Enum); | ||
61 | let syntax = db.file_item(def_loc.source_item_id); | ||
62 | let enum_def = | ||
63 | ast::EnumDef::cast(syntax.borrowed()).expect("enum def should point to EnumDef node"); | ||
64 | Ok(Arc::new(EnumData::new(enum_def.borrowed()))) | ||
65 | } | ||
66 | |||
48 | pub(super) fn file_items(db: &impl HirDatabase, file_id: FileId) -> Arc<SourceFileItems> { | 67 | pub(super) fn file_items(db: &impl HirDatabase, file_id: FileId) -> Arc<SourceFileItems> { |
49 | let mut res = SourceFileItems::new(file_id); | 68 | let mut res = SourceFileItems::new(file_id); |
50 | let source_file = db.source_file(file_id); | 69 | let source_file = db.source_file(file_id); |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index c759d4c8b..f86b749ec 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -17,7 +17,7 @@ use ra_syntax::{ | |||
17 | 17 | ||
18 | use crate::{Def, DefId, FnScopes, Module, Function, Path, db::HirDatabase}; | 18 | use crate::{Def, DefId, FnScopes, Module, Function, Path, db::HirDatabase}; |
19 | 19 | ||
20 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | 20 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
21 | pub enum Ty { | 21 | pub enum Ty { |
22 | /// The primitive boolean type. Written as `bool`. | 22 | /// The primitive boolean type. Written as `bool`. |
23 | Bool, | 23 | Bool, |
@@ -35,8 +35,15 @@ pub enum Ty { | |||
35 | /// A primitive floating-point type. For example, `f64`. | 35 | /// A primitive floating-point type. For example, `f64`. |
36 | Float(primitive::FloatTy), | 36 | Float(primitive::FloatTy), |
37 | 37 | ||
38 | // Structures, enumerations and unions. | 38 | /// Structures, enumerations and unions. |
39 | // Adt(AdtDef, Substs), | 39 | Adt { |
40 | /// The DefId of the struct/enum. | ||
41 | def_id: DefId, | ||
42 | /// The name, for displaying. | ||
43 | name: SmolStr, | ||
44 | // later we'll need generic substitutions here | ||
45 | }, | ||
46 | |||
40 | /// The pointee of a string slice. Written as `str`. | 47 | /// The pointee of a string slice. Written as `str`. |
41 | Str, | 48 | Str, |
42 | 49 | ||
@@ -107,45 +114,48 @@ pub enum Ty { | |||
107 | 114 | ||
108 | type TyRef = Arc<Ty>; | 115 | type TyRef = Arc<Ty>; |
109 | 116 | ||
110 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | 117 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
111 | pub struct FnSig { | 118 | pub struct FnSig { |
112 | input: Vec<Ty>, | 119 | input: Vec<Ty>, |
113 | output: Ty, | 120 | output: Ty, |
114 | } | 121 | } |
115 | 122 | ||
116 | impl Ty { | 123 | impl Ty { |
117 | pub fn new(_db: &impl HirDatabase, node: ast::TypeRef) -> Cancelable<Self> { | 124 | pub(crate) fn new( |
125 | db: &impl HirDatabase, | ||
126 | module: &Module, | ||
127 | node: ast::TypeRef, | ||
128 | ) -> Cancelable<Self> { | ||
118 | use ra_syntax::ast::TypeRef::*; | 129 | use ra_syntax::ast::TypeRef::*; |
119 | Ok(match node { | 130 | Ok(match node { |
120 | ParenType(_inner) => Ty::Unknown, // TODO | 131 | ParenType(_inner) => Ty::Unknown, // TODO |
121 | TupleType(_inner) => Ty::Unknown, // TODO | 132 | TupleType(_inner) => Ty::Unknown, // TODO |
122 | NeverType(..) => Ty::Never, | 133 | NeverType(..) => Ty::Never, |
123 | PathType(inner) => { | 134 | PathType(inner) => { |
124 | let path = if let Some(p) = inner.path() { | 135 | let path = if let Some(p) = inner.path().and_then(Path::from_ast) { |
125 | p | 136 | p |
126 | } else { | 137 | } else { |
127 | return Ok(Ty::Unknown); | 138 | return Ok(Ty::Unknown); |
128 | }; | 139 | }; |
129 | if path.qualifier().is_none() { | 140 | if path.is_ident() { |
130 | let name = path | 141 | let name = &path.segments[0]; |
131 | .segment() | ||
132 | .and_then(|s| s.name_ref()) | ||
133 | .map(|n| n.text()) | ||
134 | .unwrap_or(SmolStr::new("")); | ||
135 | if let Some(int_ty) = primitive::IntTy::from_string(&name) { | 142 | if let Some(int_ty) = primitive::IntTy::from_string(&name) { |
136 | Ty::Int(int_ty) | 143 | return Ok(Ty::Int(int_ty)); |
137 | } else if let Some(uint_ty) = primitive::UintTy::from_string(&name) { | 144 | } else if let Some(uint_ty) = primitive::UintTy::from_string(&name) { |
138 | Ty::Uint(uint_ty) | 145 | return Ok(Ty::Uint(uint_ty)); |
139 | } else if let Some(float_ty) = primitive::FloatTy::from_string(&name) { | 146 | } else if let Some(float_ty) = primitive::FloatTy::from_string(&name) { |
140 | Ty::Float(float_ty) | 147 | return Ok(Ty::Float(float_ty)); |
141 | } else { | ||
142 | // TODO | ||
143 | Ty::Unknown | ||
144 | } | 148 | } |
145 | } else { | ||
146 | // TODO | ||
147 | Ty::Unknown | ||
148 | } | 149 | } |
150 | |||
151 | // Resolve in module (in type namespace) | ||
152 | let resolved = if let Some(r) = module.resolve_path(db, path)? { | ||
153 | r | ||
154 | } else { | ||
155 | return Ok(Ty::Unknown); | ||
156 | }; | ||
157 | let ty = db.type_for_def(resolved)?; | ||
158 | ty | ||
149 | } | 159 | } |
150 | PointerType(_inner) => Ty::Unknown, // TODO | 160 | PointerType(_inner) => Ty::Unknown, // TODO |
151 | ArrayType(_inner) => Ty::Unknown, // TODO | 161 | ArrayType(_inner) => Ty::Unknown, // TODO |
@@ -189,6 +199,7 @@ impl fmt::Display for Ty { | |||
189 | } | 199 | } |
190 | write!(f, ") -> {}", sig.output) | 200 | write!(f, ") -> {}", sig.output) |
191 | } | 201 | } |
202 | Ty::Adt { name, .. } => write!(f, "{}", name), | ||
192 | Ty::Unknown => write!(f, "[unknown]"), | 203 | Ty::Unknown => write!(f, "[unknown]"), |
193 | } | 204 | } |
194 | } | 205 | } |
@@ -196,6 +207,7 @@ impl fmt::Display for Ty { | |||
196 | 207 | ||
197 | pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { | 208 | pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { |
198 | let syntax = f.syntax(db); | 209 | let syntax = f.syntax(db); |
210 | let module = f.module(db)?; | ||
199 | let node = syntax.borrowed(); | 211 | let node = syntax.borrowed(); |
200 | // TODO we ignore type parameters for now | 212 | // TODO we ignore type parameters for now |
201 | let input = node | 213 | let input = node |
@@ -204,7 +216,7 @@ pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { | |||
204 | pl.params() | 216 | pl.params() |
205 | .map(|p| { | 217 | .map(|p| { |
206 | p.type_ref() | 218 | p.type_ref() |
207 | .map(|t| Ty::new(db, t)) | 219 | .map(|t| Ty::new(db, &module, t)) |
208 | .unwrap_or(Ok(Ty::Unknown)) | 220 | .unwrap_or(Ok(Ty::Unknown)) |
209 | }) | 221 | }) |
210 | .collect() | 222 | .collect() |
@@ -213,7 +225,7 @@ pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { | |||
213 | let output = node | 225 | let output = node |
214 | .ret_type() | 226 | .ret_type() |
215 | .and_then(|rt| rt.type_ref()) | 227 | .and_then(|rt| rt.type_ref()) |
216 | .map(|t| Ty::new(db, t)) | 228 | .map(|t| Ty::new(db, &module, t)) |
217 | .unwrap_or(Ok(Ty::Unknown))?; | 229 | .unwrap_or(Ok(Ty::Unknown))?; |
218 | let sig = FnSig { input, output }; | 230 | let sig = FnSig { input, output }; |
219 | Ok(Ty::FnPtr(Arc::new(sig))) | 231 | Ok(Ty::FnPtr(Arc::new(sig))) |
@@ -232,6 +244,14 @@ pub fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> { | |||
232 | Ok(Ty::Unknown) | 244 | Ok(Ty::Unknown) |
233 | } | 245 | } |
234 | Def::Function(f) => type_for_fn(db, f), | 246 | Def::Function(f) => type_for_fn(db, f), |
247 | Def::Struct(s) => Ok(Ty::Adt { | ||
248 | def_id, | ||
249 | name: s.name(db)?, | ||
250 | }), | ||
251 | Def::Enum(e) => Ok(Ty::Adt { | ||
252 | def_id, | ||
253 | name: e.name(db)?, | ||
254 | }), | ||
235 | Def::Item => { | 255 | Def::Item => { |
236 | log::debug!("trying to get type for item of unknown type {:?}", def_id); | 256 | log::debug!("trying to get type for item of unknown type {:?}", def_id); |
237 | Ok(Ty::Unknown) | 257 | Ok(Ty::Unknown) |
@@ -492,7 +512,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
492 | }; | 512 | }; |
493 | let cast_ty = e | 513 | let cast_ty = e |
494 | .type_ref() | 514 | .type_ref() |
495 | .map(|t| Ty::new(self.db, t)) | 515 | .map(|t| Ty::new(self.db, &self.module, t)) |
496 | .unwrap_or(Ok(Ty::Unknown))?; | 516 | .unwrap_or(Ok(Ty::Unknown))?; |
497 | // TODO do the coercion... | 517 | // TODO do the coercion... |
498 | cast_ty | 518 | cast_ty |
@@ -526,7 +546,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
526 | match stmt { | 546 | match stmt { |
527 | ast::Stmt::LetStmt(stmt) => { | 547 | ast::Stmt::LetStmt(stmt) => { |
528 | let decl_ty = if let Some(type_ref) = stmt.type_ref() { | 548 | let decl_ty = if let Some(type_ref) = stmt.type_ref() { |
529 | Ty::new(self.db, type_ref)? | 549 | Ty::new(self.db, &self.module, type_ref)? |
530 | } else { | 550 | } else { |
531 | Ty::Unknown | 551 | Ty::Unknown |
532 | }; | 552 | }; |
@@ -576,7 +596,7 @@ pub fn infer(db: &impl HirDatabase, function: Function) -> Cancelable<InferenceR | |||
576 | continue; | 596 | continue; |
577 | }; | 597 | }; |
578 | if let Some(type_ref) = param.type_ref() { | 598 | if let Some(type_ref) = param.type_ref() { |
579 | let ty = Ty::new(db, type_ref)?; | 599 | let ty = Ty::new(db, &ctx.module, type_ref)?; |
580 | ctx.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty); | 600 | ctx.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty); |
581 | } else { | 601 | } else { |
582 | // TODO self param | 602 | // TODO self param |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index b6c02cd80..170eef147 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -68,6 +68,29 @@ fn test() { | |||
68 | ); | 68 | ); |
69 | } | 69 | } |
70 | 70 | ||
71 | #[test] | ||
72 | fn infer_struct() { | ||
73 | check_inference( | ||
74 | r#" | ||
75 | struct A { | ||
76 | b: B, | ||
77 | c: C, | ||
78 | } | ||
79 | struct B; | ||
80 | struct C(usize); | ||
81 | |||
82 | fn test() { | ||
83 | let c = C(1); | ||
84 | B; | ||
85 | let a: A = A { b: B, c: C() }; | ||
86 | a.b; | ||
87 | a.c; | ||
88 | } | ||
89 | "#, | ||
90 | "0004_struct.txt", | ||
91 | ); | ||
92 | } | ||
93 | |||
71 | fn infer(content: &str) -> String { | 94 | fn infer(content: &str) -> String { |
72 | let (db, _, file_id) = MockDatabase::with_single_file(content); | 95 | let (db, _, file_id) = MockDatabase::with_single_file(content); |
73 | let source_file = db.source_file(file_id); | 96 | let source_file = db.source_file(file_id); |
diff --git a/crates/ra_hir/src/ty/tests/data/0004_struct.txt b/crates/ra_hir/src/ty/tests/data/0004_struct.txt new file mode 100644 index 000000000..70ad055ff --- /dev/null +++ b/crates/ra_hir/src/ty/tests/data/0004_struct.txt | |||
@@ -0,0 +1,10 @@ | |||
1 | [86; 90) 'C(1)': [unknown] | ||
2 | [72; 153) '{ ...a.c; }': () | ||
3 | [86; 87) 'C': C | ||
4 | [107; 108) 'a': A | ||
5 | [114; 132) 'A { b:... C() }': [unknown] | ||
6 | [138; 141) 'a.b': [unknown] | ||
7 | [147; 150) 'a.c': [unknown] | ||
8 | [96; 97) 'B': B | ||
9 | [88; 89) '1': [unknown] | ||
10 | [82; 83) 'c': [unknown] | ||