diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-03-22 05:32:48 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-03-22 05:32:48 +0000 |
commit | 9c6c6a7cb51b701585827c1a39d36450ddb5cd51 (patch) | |
tree | c5e4c46da389accd0b03b3b285f5057265f65f65 | |
parent | 51323a852a8979a71c21725b3b2771224132b85f (diff) | |
parent | 1ee779d1f74f48d9f3098001c63108b794dbc0b5 (diff) |
Merge #988
988: Consolidate Ty variants into a new variant Ty::Apply r=matklad a=flodiebold
This gets us a lot closer to Chalk. It also introduces a lot of boilerplate, though, especially when matching :/ A lot of this can probably be refactored to be nicer, though.
Co-authored-by: Florian Diebold <[email protected]>
-rw-r--r-- | crates/ra_assists/src/fill_match_arms.rs | 14 | ||||
-rw-r--r-- | crates/ra_assists/src/fill_struct_fields.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 261 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 264 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 40 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/op.rs | 33 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_dot.rs | 27 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_struct_literal.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 14 | ||||
-rw-r--r-- | crates/ra_ide_api/src/hover.rs | 17 |
12 files changed, 377 insertions, 318 deletions
diff --git a/crates/ra_assists/src/fill_match_arms.rs b/crates/ra_assists/src/fill_match_arms.rs index 6a22b0af5..da67ab667 100644 --- a/crates/ra_assists/src/fill_match_arms.rs +++ b/crates/ra_assists/src/fill_match_arms.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use std::fmt::Write; | 1 | use std::fmt::Write; |
2 | 2 | ||
3 | use hir::{ | 3 | use hir::{ |
4 | AdtDef, Ty, FieldSource, source_binder, | 4 | AdtDef, FieldSource, source_binder, |
5 | db::HirDatabase, | 5 | db::HirDatabase, |
6 | }; | 6 | }; |
7 | use ra_syntax::ast::{self, AstNode}; | 7 | use ra_syntax::ast::{self, AstNode}; |
@@ -26,14 +26,10 @@ pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<As | |||
26 | let source_map = function.body_source_map(ctx.db); | 26 | let source_map = function.body_source_map(ctx.db); |
27 | let node_expr = source_map.node_expr(expr)?; | 27 | let node_expr = source_map.node_expr(expr)?; |
28 | let match_expr_ty = infer_result[node_expr].clone(); | 28 | let match_expr_ty = infer_result[node_expr].clone(); |
29 | let enum_def = match match_expr_ty { | 29 | let enum_def = match_expr_ty.autoderef(ctx.db).find_map(|ty| match ty.as_adt() { |
30 | Ty::Adt { def_id: AdtDef::Enum(e), .. } => e, | 30 | Some((AdtDef::Enum(e), _)) => Some(e), |
31 | Ty::Ref(adt, _) => match *adt { | 31 | _ => None, |
32 | Ty::Adt { def_id: AdtDef::Enum(e), .. } => e, | 32 | })?; |
33 | _ => return None, | ||
34 | }, | ||
35 | _ => return None, | ||
36 | }; | ||
37 | let enum_name = enum_def.name(ctx.db)?; | 33 | let enum_name = enum_def.name(ctx.db)?; |
38 | let db = ctx.db; | 34 | let db = ctx.db; |
39 | 35 | ||
diff --git a/crates/ra_assists/src/fill_struct_fields.rs b/crates/ra_assists/src/fill_struct_fields.rs index 6e61a58fc..c7790dc72 100644 --- a/crates/ra_assists/src/fill_struct_fields.rs +++ b/crates/ra_assists/src/fill_struct_fields.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use std::fmt::Write; | 1 | use std::fmt::Write; |
2 | 2 | ||
3 | use hir::{AdtDef, Ty, db::HirDatabase, source_binder::function_from_child_node}; | 3 | use hir::{AdtDef, db::HirDatabase, source_binder::function_from_child_node}; |
4 | 4 | ||
5 | use ra_syntax::ast::{self, AstNode}; | 5 | use ra_syntax::ast::{self, AstNode}; |
6 | 6 | ||
@@ -60,8 +60,8 @@ where | |||
60 | let source_map = function.body_source_map(self.ctx.db); | 60 | let source_map = function.body_source_map(self.ctx.db); |
61 | let node_expr = source_map.node_expr(self.struct_lit.into())?; | 61 | let node_expr = source_map.node_expr(self.struct_lit.into())?; |
62 | let struct_lit_ty = infer_result[node_expr].clone(); | 62 | let struct_lit_ty = infer_result[node_expr].clone(); |
63 | let struct_def = match struct_lit_ty { | 63 | let struct_def = match struct_lit_ty.as_adt() { |
64 | Ty::Adt { def_id: AdtDef::Struct(s), .. } => s, | 64 | Some((AdtDef::Struct(s), _)) => s, |
65 | _ => return None, | 65 | _ => return None, |
66 | }; | 66 | }; |
67 | self.struct_fields = struct_def | 67 | self.struct_fields = struct_def |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 75c977d32..5926b5758 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -53,7 +53,7 @@ pub use self::{ | |||
53 | name::Name, | 53 | name::Name, |
54 | ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner}, | 54 | ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner}, |
55 | nameres::{PerNs, Namespace}, | 55 | nameres::{PerNs, Namespace}, |
56 | ty::{Ty, Substs, display::HirDisplay}, | 56 | ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay}, |
57 | impl_block::{ImplBlock, ImplItem}, | 57 | impl_block::{ImplBlock, ImplItem}, |
58 | docs::{Docs, Documentation}, | 58 | docs::{Docs, Documentation}, |
59 | adt::AdtDef, | 59 | adt::AdtDef, |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 2ea3b341f..7d25ade47 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -20,11 +20,11 @@ pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, ca | |||
20 | pub(crate) use infer::{infer, InferenceResult, InferTy}; | 20 | pub(crate) use infer::{infer, InferenceResult, InferTy}; |
21 | use display::{HirDisplay, HirFormatter}; | 21 | use display::{HirDisplay, HirFormatter}; |
22 | 22 | ||
23 | /// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). | 23 | /// A type constructor or type name: this might be something like the primitive |
24 | /// | 24 | /// type `bool`, a struct like `Vec`, or things like function pointers or |
25 | /// This should be cheap to clone. | 25 | /// tuples. |
26 | #[derive(Clone, PartialEq, Eq, Debug)] | 26 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] |
27 | pub enum Ty { | 27 | pub enum TypeCtor { |
28 | /// The primitive boolean type. Written as `bool`. | 28 | /// The primitive boolean type. Written as `bool`. |
29 | Bool, | 29 | Bool, |
30 | 30 | ||
@@ -39,28 +39,23 @@ pub enum Ty { | |||
39 | Float(primitive::UncertainFloatTy), | 39 | Float(primitive::UncertainFloatTy), |
40 | 40 | ||
41 | /// Structures, enumerations and unions. | 41 | /// Structures, enumerations and unions. |
42 | Adt { | 42 | Adt(AdtDef), |
43 | /// The definition of the struct/enum. | ||
44 | def_id: AdtDef, | ||
45 | /// Substitutions for the generic parameters of the type. | ||
46 | substs: Substs, | ||
47 | }, | ||
48 | 43 | ||
49 | /// The pointee of a string slice. Written as `str`. | 44 | /// The pointee of a string slice. Written as `str`. |
50 | Str, | 45 | Str, |
51 | 46 | ||
52 | /// The pointee of an array slice. Written as `[T]`. | 47 | /// The pointee of an array slice. Written as `[T]`. |
53 | Slice(Arc<Ty>), | 48 | Slice, |
54 | 49 | ||
55 | /// An array with the given length. Written as `[T; n]`. | 50 | /// An array with the given length. Written as `[T; n]`. |
56 | Array(Arc<Ty>), | 51 | Array, |
57 | 52 | ||
58 | /// A raw pointer. Written as `*mut T` or `*const T` | 53 | /// A raw pointer. Written as `*mut T` or `*const T` |
59 | RawPtr(Arc<Ty>, Mutability), | 54 | RawPtr(Mutability), |
60 | 55 | ||
61 | /// A reference; a pointer with an associated lifetime. Written as | 56 | /// A reference; a pointer with an associated lifetime. Written as |
62 | /// `&'a mut T` or `&'a T`. | 57 | /// `&'a mut T` or `&'a T`. |
63 | Ref(Arc<Ty>, Mutability), | 58 | Ref(Mutability), |
64 | 59 | ||
65 | /// The anonymous type of a function declaration/definition. Each | 60 | /// The anonymous type of a function declaration/definition. Each |
66 | /// function has a unique type, which is output (for a function | 61 | /// function has a unique type, which is output (for a function |
@@ -74,12 +69,7 @@ pub enum Ty { | |||
74 | /// fn foo() -> i32 { 1 } | 69 | /// fn foo() -> i32 { 1 } |
75 | /// let bar = foo; // bar: fn() -> i32 {foo} | 70 | /// let bar = foo; // bar: fn() -> i32 {foo} |
76 | /// ``` | 71 | /// ``` |
77 | FnDef { | 72 | FnDef(CallableDef), |
78 | /// The definition of the function / constructor. | ||
79 | def: CallableDef, | ||
80 | /// Substitutions for the generic parameters of the type | ||
81 | substs: Substs, | ||
82 | }, | ||
83 | 73 | ||
84 | /// A pointer to a function. Written as `fn() -> i32`. | 74 | /// A pointer to a function. Written as `fn() -> i32`. |
85 | /// | 75 | /// |
@@ -89,13 +79,36 @@ pub enum Ty { | |||
89 | /// fn foo() -> i32 { 1 } | 79 | /// fn foo() -> i32 { 1 } |
90 | /// let bar: fn() -> i32 = foo; | 80 | /// let bar: fn() -> i32 = foo; |
91 | /// ``` | 81 | /// ``` |
92 | FnPtr(FnSig), | 82 | FnPtr, |
93 | 83 | ||
94 | /// The never type `!`. | 84 | /// The never type `!`. |
95 | Never, | 85 | Never, |
96 | 86 | ||
97 | /// A tuple type. For example, `(i32, bool)`. | 87 | /// A tuple type. For example, `(i32, bool)`. |
98 | Tuple(Arc<[Ty]>), | 88 | Tuple, |
89 | } | ||
90 | |||
91 | /// A nominal type with (maybe 0) type parameters. This might be a primitive | ||
92 | /// type like `bool`, a struct, tuple, function pointer, reference or | ||
93 | /// several other things. | ||
94 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
95 | pub struct ApplicationTy { | ||
96 | pub ctor: TypeCtor, | ||
97 | pub parameters: Substs, | ||
98 | } | ||
99 | |||
100 | /// A type. | ||
101 | /// | ||
102 | /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents | ||
103 | /// the same thing (but in a different way). | ||
104 | /// | ||
105 | /// This should be cheap to clone. | ||
106 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
107 | pub enum Ty { | ||
108 | /// A nominal type with (maybe 0) type parameters. This might be a primitive | ||
109 | /// type like `bool`, a struct, tuple, function pointer, reference or | ||
110 | /// several other things. | ||
111 | Apply(ApplicationTy), | ||
99 | 112 | ||
100 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {} | 113 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {} |
101 | Param { | 114 | Param { |
@@ -127,6 +140,18 @@ impl Substs { | |||
127 | Substs(Arc::new([])) | 140 | Substs(Arc::new([])) |
128 | } | 141 | } |
129 | 142 | ||
143 | pub fn single(ty: Ty) -> Substs { | ||
144 | Substs(Arc::new([ty])) | ||
145 | } | ||
146 | |||
147 | pub fn iter(&self) -> impl Iterator<Item = &Ty> { | ||
148 | self.0.iter() | ||
149 | } | ||
150 | |||
151 | pub fn len(&self) -> usize { | ||
152 | self.0.len() | ||
153 | } | ||
154 | |||
130 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 155 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
131 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | 156 | // Without an Arc::make_mut_slice, we can't avoid the clone here: |
132 | let mut v: Vec<_> = self.0.iter().cloned().collect(); | 157 | let mut v: Vec<_> = self.0.iter().cloned().collect(); |
@@ -135,9 +160,17 @@ impl Substs { | |||
135 | } | 160 | } |
136 | self.0 = v.into(); | 161 | self.0 = v.into(); |
137 | } | 162 | } |
163 | |||
164 | pub fn as_single(&self) -> &Ty { | ||
165 | if self.0.len() != 1 { | ||
166 | panic!("expected substs of len 1, got {:?}", self); | ||
167 | } | ||
168 | &self.0[0] | ||
169 | } | ||
138 | } | 170 | } |
139 | 171 | ||
140 | /// A function signature. | 172 | /// A function signature as seen by type inference: Several parameter types and |
173 | /// one return type. | ||
141 | #[derive(Clone, PartialEq, Eq, Debug)] | 174 | #[derive(Clone, PartialEq, Eq, Debug)] |
142 | pub struct FnSig { | 175 | pub struct FnSig { |
143 | params_and_return: Arc<[Ty]>, | 176 | params_and_return: Arc<[Ty]>, |
@@ -148,6 +181,11 @@ impl FnSig { | |||
148 | params.push(ret); | 181 | params.push(ret); |
149 | FnSig { params_and_return: params.into() } | 182 | FnSig { params_and_return: params.into() } |
150 | } | 183 | } |
184 | |||
185 | pub fn from_fn_ptr_substs(substs: &Substs) -> FnSig { | ||
186 | FnSig { params_and_return: Arc::clone(&substs.0) } | ||
187 | } | ||
188 | |||
151 | pub fn params(&self) -> &[Ty] { | 189 | pub fn params(&self) -> &[Ty] { |
152 | &self.params_and_return[0..self.params_and_return.len() - 1] | 190 | &self.params_and_return[0..self.params_and_return.len() - 1] |
153 | } | 191 | } |
@@ -167,80 +205,37 @@ impl FnSig { | |||
167 | } | 205 | } |
168 | 206 | ||
169 | impl Ty { | 207 | impl Ty { |
208 | pub fn simple(ctor: TypeCtor) -> Ty { | ||
209 | Ty::Apply(ApplicationTy { ctor, parameters: Substs::empty() }) | ||
210 | } | ||
211 | pub fn apply_one(ctor: TypeCtor, param: Ty) -> Ty { | ||
212 | Ty::Apply(ApplicationTy { ctor, parameters: Substs::single(param) }) | ||
213 | } | ||
214 | pub fn apply(ctor: TypeCtor, parameters: Substs) -> Ty { | ||
215 | Ty::Apply(ApplicationTy { ctor, parameters }) | ||
216 | } | ||
170 | pub fn unit() -> Self { | 217 | pub fn unit() -> Self { |
171 | Ty::Tuple(Arc::new([])) | 218 | Ty::apply(TypeCtor::Tuple, Substs::empty()) |
172 | } | 219 | } |
173 | 220 | ||
174 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | 221 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { |
175 | match self { | 222 | match self { |
176 | Ty::Slice(t) | Ty::Array(t) => t.walk(f), | 223 | Ty::Apply(a_ty) => { |
177 | Ty::RawPtr(t, _) => t.walk(f), | 224 | for t in a_ty.parameters.iter() { |
178 | Ty::Ref(t, _) => t.walk(f), | ||
179 | Ty::Tuple(ts) => { | ||
180 | for t in ts.iter() { | ||
181 | t.walk(f); | ||
182 | } | ||
183 | } | ||
184 | Ty::FnPtr(sig) => { | ||
185 | for input in sig.params() { | ||
186 | input.walk(f); | ||
187 | } | ||
188 | sig.ret().walk(f); | ||
189 | } | ||
190 | Ty::FnDef { substs, .. } => { | ||
191 | for t in substs.0.iter() { | ||
192 | t.walk(f); | 225 | t.walk(f); |
193 | } | 226 | } |
194 | } | 227 | } |
195 | Ty::Adt { substs, .. } => { | 228 | Ty::Param { .. } | Ty::Infer(_) | Ty::Unknown => {} |
196 | for t in substs.0.iter() { | ||
197 | t.walk(f); | ||
198 | } | ||
199 | } | ||
200 | Ty::Bool | ||
201 | | Ty::Char | ||
202 | | Ty::Int(_) | ||
203 | | Ty::Float(_) | ||
204 | | Ty::Str | ||
205 | | Ty::Never | ||
206 | | Ty::Param { .. } | ||
207 | | Ty::Infer(_) | ||
208 | | Ty::Unknown => {} | ||
209 | } | 229 | } |
210 | f(self); | 230 | f(self); |
211 | } | 231 | } |
212 | 232 | ||
213 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 233 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
214 | match self { | 234 | match self { |
215 | Ty::Slice(t) | Ty::Array(t) => Arc::make_mut(t).walk_mut(f), | 235 | Ty::Apply(a_ty) => { |
216 | Ty::RawPtr(t, _) => Arc::make_mut(t).walk_mut(f), | 236 | a_ty.parameters.walk_mut(f); |
217 | Ty::Ref(t, _) => Arc::make_mut(t).walk_mut(f), | ||
218 | Ty::Tuple(ts) => { | ||
219 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | ||
220 | let mut v: Vec<_> = ts.iter().cloned().collect(); | ||
221 | for t in &mut v { | ||
222 | t.walk_mut(f); | ||
223 | } | ||
224 | *ts = v.into(); | ||
225 | } | ||
226 | Ty::FnPtr(sig) => { | ||
227 | sig.walk_mut(f); | ||
228 | } | 237 | } |
229 | Ty::FnDef { substs, .. } => { | 238 | Ty::Param { .. } | Ty::Infer(_) | Ty::Unknown => {} |
230 | substs.walk_mut(f); | ||
231 | } | ||
232 | Ty::Adt { substs, .. } => { | ||
233 | substs.walk_mut(f); | ||
234 | } | ||
235 | Ty::Bool | ||
236 | | Ty::Char | ||
237 | | Ty::Int(_) | ||
238 | | Ty::Float(_) | ||
239 | | Ty::Str | ||
240 | | Ty::Never | ||
241 | | Ty::Param { .. } | ||
242 | | Ty::Infer(_) | ||
243 | | Ty::Unknown => {} | ||
244 | } | 239 | } |
245 | f(self); | 240 | f(self); |
246 | } | 241 | } |
@@ -253,10 +248,38 @@ impl Ty { | |||
253 | self | 248 | self |
254 | } | 249 | } |
255 | 250 | ||
251 | pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { | ||
252 | match self { | ||
253 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => { | ||
254 | Some((parameters.as_single(), *mutability)) | ||
255 | } | ||
256 | _ => None, | ||
257 | } | ||
258 | } | ||
259 | |||
260 | pub fn as_adt(&self) -> Option<(AdtDef, &Substs)> { | ||
261 | match self { | ||
262 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_def), parameters }) => { | ||
263 | Some((*adt_def, parameters)) | ||
264 | } | ||
265 | _ => None, | ||
266 | } | ||
267 | } | ||
268 | |||
269 | pub fn as_tuple(&self) -> Option<&Substs> { | ||
270 | match self { | ||
271 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple, parameters }) => Some(parameters), | ||
272 | _ => None, | ||
273 | } | ||
274 | } | ||
275 | |||
256 | fn builtin_deref(&self) -> Option<Ty> { | 276 | fn builtin_deref(&self) -> Option<Ty> { |
257 | match self { | 277 | match self { |
258 | Ty::Ref(t, _) => Some(Ty::clone(t)), | 278 | Ty::Apply(a_ty) => match a_ty.ctor { |
259 | Ty::RawPtr(t, _) => Some(Ty::clone(t)), | 279 | TypeCtor::Ref(..) => Some(Ty::clone(a_ty.parameters.as_single())), |
280 | TypeCtor::RawPtr(..) => Some(Ty::clone(a_ty.parameters.as_single())), | ||
281 | _ => None, | ||
282 | }, | ||
260 | _ => None, | 283 | _ => None, |
261 | } | 284 | } |
262 | } | 285 | } |
@@ -267,8 +290,10 @@ impl Ty { | |||
267 | /// `Option<u32>` afterwards.) | 290 | /// `Option<u32>` afterwards.) |
268 | pub fn apply_substs(self, substs: Substs) -> Ty { | 291 | pub fn apply_substs(self, substs: Substs) -> Ty { |
269 | match self { | 292 | match self { |
270 | Ty::Adt { def_id, .. } => Ty::Adt { def_id, substs }, | 293 | Ty::Apply(ApplicationTy { ctor, parameters: previous_substs }) => { |
271 | Ty::FnDef { def, .. } => Ty::FnDef { def, substs }, | 294 | assert_eq!(previous_substs.len(), substs.len()); |
295 | Ty::Apply(ApplicationTy { ctor, parameters: substs }) | ||
296 | } | ||
272 | _ => self, | 297 | _ => self, |
273 | } | 298 | } |
274 | } | 299 | } |
@@ -293,7 +318,7 @@ impl Ty { | |||
293 | /// or function); so if `self` is `Option<u32>`, this returns the `u32`. | 318 | /// or function); so if `self` is `Option<u32>`, this returns the `u32`. |
294 | fn substs(&self) -> Option<Substs> { | 319 | fn substs(&self) -> Option<Substs> { |
295 | match self { | 320 | match self { |
296 | Ty::Adt { substs, .. } | Ty::FnDef { substs, .. } => Some(substs.clone()), | 321 | Ty::Apply(ApplicationTy { parameters, .. }) => Some(parameters.clone()), |
297 | _ => None, | 322 | _ => None, |
298 | } | 323 | } |
299 | } | 324 | } |
@@ -305,40 +330,45 @@ impl HirDisplay for &Ty { | |||
305 | } | 330 | } |
306 | } | 331 | } |
307 | 332 | ||
308 | impl HirDisplay for Ty { | 333 | impl HirDisplay for ApplicationTy { |
309 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 334 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
310 | match self { | 335 | match self.ctor { |
311 | Ty::Bool => write!(f, "bool")?, | 336 | TypeCtor::Bool => write!(f, "bool")?, |
312 | Ty::Char => write!(f, "char")?, | 337 | TypeCtor::Char => write!(f, "char")?, |
313 | Ty::Int(t) => write!(f, "{}", t)?, | 338 | TypeCtor::Int(t) => write!(f, "{}", t)?, |
314 | Ty::Float(t) => write!(f, "{}", t)?, | 339 | TypeCtor::Float(t) => write!(f, "{}", t)?, |
315 | Ty::Str => write!(f, "str")?, | 340 | TypeCtor::Str => write!(f, "str")?, |
316 | Ty::Slice(t) | Ty::Array(t) => { | 341 | TypeCtor::Slice | TypeCtor::Array => { |
342 | let t = self.parameters.as_single(); | ||
317 | write!(f, "[{}]", t.display(f.db))?; | 343 | write!(f, "[{}]", t.display(f.db))?; |
318 | } | 344 | } |
319 | Ty::RawPtr(t, m) => { | 345 | TypeCtor::RawPtr(m) => { |
346 | let t = self.parameters.as_single(); | ||
320 | write!(f, "*{}{}", m.as_keyword_for_ptr(), t.display(f.db))?; | 347 | write!(f, "*{}{}", m.as_keyword_for_ptr(), t.display(f.db))?; |
321 | } | 348 | } |
322 | Ty::Ref(t, m) => { | 349 | TypeCtor::Ref(m) => { |
350 | let t = self.parameters.as_single(); | ||
323 | write!(f, "&{}{}", m.as_keyword_for_ref(), t.display(f.db))?; | 351 | write!(f, "&{}{}", m.as_keyword_for_ref(), t.display(f.db))?; |
324 | } | 352 | } |
325 | Ty::Never => write!(f, "!")?, | 353 | TypeCtor::Never => write!(f, "!")?, |
326 | Ty::Tuple(ts) => { | 354 | TypeCtor::Tuple => { |
327 | if ts.len() == 1 { | 355 | let ts = &self.parameters; |
328 | write!(f, "({},)", ts[0].display(f.db))?; | 356 | if ts.0.len() == 1 { |
357 | write!(f, "({},)", ts.0[0].display(f.db))?; | ||
329 | } else { | 358 | } else { |
330 | write!(f, "(")?; | 359 | write!(f, "(")?; |
331 | f.write_joined(&**ts, ", ")?; | 360 | f.write_joined(&*ts.0, ", ")?; |
332 | write!(f, ")")?; | 361 | write!(f, ")")?; |
333 | } | 362 | } |
334 | } | 363 | } |
335 | Ty::FnPtr(sig) => { | 364 | TypeCtor::FnPtr => { |
365 | let sig = FnSig::from_fn_ptr_substs(&self.parameters); | ||
336 | write!(f, "fn(")?; | 366 | write!(f, "fn(")?; |
337 | f.write_joined(sig.params(), ", ")?; | 367 | f.write_joined(sig.params(), ", ")?; |
338 | write!(f, ") -> {}", sig.ret().display(f.db))?; | 368 | write!(f, ") -> {}", sig.ret().display(f.db))?; |
339 | } | 369 | } |
340 | Ty::FnDef { def, substs, .. } => { | 370 | TypeCtor::FnDef(def) => { |
341 | let sig = f.db.callable_item_signature(*def); | 371 | let sig = f.db.callable_item_signature(def); |
342 | let name = match def { | 372 | let name = match def { |
343 | CallableDef::Function(ff) => ff.name(f.db), | 373 | CallableDef::Function(ff) => ff.name(f.db), |
344 | CallableDef::Struct(s) => s.name(f.db).unwrap_or_else(Name::missing), | 374 | CallableDef::Struct(s) => s.name(f.db).unwrap_or_else(Name::missing), |
@@ -348,28 +378,37 @@ impl HirDisplay for Ty { | |||
348 | CallableDef::Function(_) => write!(f, "fn {}", name)?, | 378 | CallableDef::Function(_) => write!(f, "fn {}", name)?, |
349 | CallableDef::Struct(_) | CallableDef::EnumVariant(_) => write!(f, "{}", name)?, | 379 | CallableDef::Struct(_) | CallableDef::EnumVariant(_) => write!(f, "{}", name)?, |
350 | } | 380 | } |
351 | if substs.0.len() > 0 { | 381 | if self.parameters.0.len() > 0 { |
352 | write!(f, "<")?; | 382 | write!(f, "<")?; |
353 | f.write_joined(&*substs.0, ", ")?; | 383 | f.write_joined(&*self.parameters.0, ", ")?; |
354 | write!(f, ">")?; | 384 | write!(f, ">")?; |
355 | } | 385 | } |
356 | write!(f, "(")?; | 386 | write!(f, "(")?; |
357 | f.write_joined(sig.params(), ", ")?; | 387 | f.write_joined(sig.params(), ", ")?; |
358 | write!(f, ") -> {}", sig.ret().display(f.db))?; | 388 | write!(f, ") -> {}", sig.ret().display(f.db))?; |
359 | } | 389 | } |
360 | Ty::Adt { def_id, substs, .. } => { | 390 | TypeCtor::Adt(def_id) => { |
361 | let name = match def_id { | 391 | let name = match def_id { |
362 | AdtDef::Struct(s) => s.name(f.db), | 392 | AdtDef::Struct(s) => s.name(f.db), |
363 | AdtDef::Enum(e) => e.name(f.db), | 393 | AdtDef::Enum(e) => e.name(f.db), |
364 | } | 394 | } |
365 | .unwrap_or_else(Name::missing); | 395 | .unwrap_or_else(Name::missing); |
366 | write!(f, "{}", name)?; | 396 | write!(f, "{}", name)?; |
367 | if substs.0.len() > 0 { | 397 | if self.parameters.0.len() > 0 { |
368 | write!(f, "<")?; | 398 | write!(f, "<")?; |
369 | f.write_joined(&*substs.0, ", ")?; | 399 | f.write_joined(&*self.parameters.0, ", ")?; |
370 | write!(f, ">")?; | 400 | write!(f, ">")?; |
371 | } | 401 | } |
372 | } | 402 | } |
403 | } | ||
404 | Ok(()) | ||
405 | } | ||
406 | } | ||
407 | |||
408 | impl HirDisplay for Ty { | ||
409 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | ||
410 | match self { | ||
411 | Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, | ||
373 | Ty::Param { name, .. } => write!(f, "{}", name)?, | 412 | Ty::Param { name, .. } => write!(f, "{}", name)?, |
374 | Ty::Unknown => write!(f, "{{unknown}}")?, | 413 | Ty::Unknown => write!(f, "{{unknown}}")?, |
375 | Ty::Infer(..) => write!(f, "_")?, | 414 | Ty::Infer(..) => write!(f, "_")?, |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 735cdecb9..bf42befbb 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -38,7 +38,7 @@ use crate::{ | |||
38 | resolve::{Resolver, Resolution}, | 38 | resolve::{Resolver, Resolution}, |
39 | nameres::Namespace | 39 | nameres::Namespace |
40 | }; | 40 | }; |
41 | use super::{Ty, TypableDef, Substs, primitive, op}; | 41 | use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; |
42 | 42 | ||
43 | /// The entry point of type inference. | 43 | /// The entry point of type inference. |
44 | pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { | 44 | pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { |
@@ -237,29 +237,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
237 | match (&*ty1, &*ty2) { | 237 | match (&*ty1, &*ty2) { |
238 | (Ty::Unknown, ..) => true, | 238 | (Ty::Unknown, ..) => true, |
239 | (.., Ty::Unknown) => true, | 239 | (.., Ty::Unknown) => true, |
240 | (Ty::Int(t1), Ty::Int(t2)) => match (t1, t2) { | 240 | (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => { |
241 | (primitive::UncertainIntTy::Unknown, _) | 241 | self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1) |
242 | | (_, primitive::UncertainIntTy::Unknown) => true, | ||
243 | _ => t1 == t2, | ||
244 | }, | ||
245 | (Ty::Float(t1), Ty::Float(t2)) => match (t1, t2) { | ||
246 | (primitive::UncertainFloatTy::Unknown, _) | ||
247 | | (_, primitive::UncertainFloatTy::Unknown) => true, | ||
248 | _ => t1 == t2, | ||
249 | }, | ||
250 | (Ty::Bool, _) | (Ty::Str, _) | (Ty::Never, _) | (Ty::Char, _) => ty1 == ty2, | ||
251 | ( | ||
252 | Ty::Adt { def_id: def_id1, substs: substs1, .. }, | ||
253 | Ty::Adt { def_id: def_id2, substs: substs2, .. }, | ||
254 | ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2, depth + 1), | ||
255 | (Ty::Slice(t1), Ty::Slice(t2)) => self.unify_inner(t1, t2, depth + 1), | ||
256 | (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => { | ||
257 | self.unify_inner(t1, t2, depth + 1) | ||
258 | } | ||
259 | (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify_inner(t1, t2, depth + 1), | ||
260 | (Ty::FnPtr(sig1), Ty::FnPtr(sig2)) if sig1 == sig2 => true, | ||
261 | (Ty::Tuple(ts1), Ty::Tuple(ts2)) if ts1.len() == ts2.len() => { | ||
262 | ts1.iter().zip(ts2.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth + 1)) | ||
263 | } | 242 | } |
264 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) | 243 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) |
265 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) | 244 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) |
@@ -298,8 +277,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
298 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { | 277 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { |
299 | match ty { | 278 | match ty { |
300 | Ty::Unknown => self.new_type_var(), | 279 | Ty::Unknown => self.new_type_var(), |
301 | Ty::Int(primitive::UncertainIntTy::Unknown) => self.new_integer_var(), | 280 | Ty::Apply(ApplicationTy { |
302 | Ty::Float(primitive::UncertainFloatTy::Unknown) => self.new_float_var(), | 281 | ctor: TypeCtor::Int(primitive::UncertainIntTy::Unknown), |
282 | .. | ||
283 | }) => self.new_integer_var(), | ||
284 | Ty::Apply(ApplicationTy { | ||
285 | ctor: TypeCtor::Float(primitive::UncertainFloatTy::Unknown), | ||
286 | .. | ||
287 | }) => self.new_float_var(), | ||
303 | _ => ty, | 288 | _ => ty, |
304 | } | 289 | } |
305 | } | 290 | } |
@@ -610,12 +595,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
610 | Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Missing => false, | 595 | Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Missing => false, |
611 | }; | 596 | }; |
612 | if is_non_ref_pat { | 597 | if is_non_ref_pat { |
613 | while let Ty::Ref(inner, mutability) = expected { | 598 | while let Some((inner, mutability)) = expected.as_reference() { |
614 | expected = inner; | 599 | expected = inner; |
615 | default_bm = match default_bm { | 600 | default_bm = match default_bm { |
616 | BindingMode::Move => BindingMode::Ref(*mutability), | 601 | BindingMode::Move => BindingMode::Ref(mutability), |
617 | BindingMode::Ref(Mutability::Shared) => BindingMode::Ref(Mutability::Shared), | 602 | BindingMode::Ref(Mutability::Shared) => BindingMode::Ref(Mutability::Shared), |
618 | BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(*mutability), | 603 | BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability), |
619 | } | 604 | } |
620 | } | 605 | } |
621 | } else if let Pat::Ref { .. } = &body[pat] { | 606 | } else if let Pat::Ref { .. } = &body[pat] { |
@@ -631,8 +616,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
631 | 616 | ||
632 | let ty = match &body[pat] { | 617 | let ty = match &body[pat] { |
633 | Pat::Tuple(ref args) => { | 618 | Pat::Tuple(ref args) => { |
634 | let expectations = match *expected { | 619 | let expectations = match expected.as_tuple() { |
635 | Ty::Tuple(ref tuple_args) => &**tuple_args, | 620 | Some(parameters) => &*parameters.0, |
636 | _ => &[], | 621 | _ => &[], |
637 | }; | 622 | }; |
638 | let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); | 623 | let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); |
@@ -644,20 +629,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
644 | .collect::<Vec<_>>() | 629 | .collect::<Vec<_>>() |
645 | .into(); | 630 | .into(); |
646 | 631 | ||
647 | Ty::Tuple(inner_tys) | 632 | Ty::apply(TypeCtor::Tuple, Substs(inner_tys)) |
648 | } | 633 | } |
649 | Pat::Ref { pat, mutability } => { | 634 | Pat::Ref { pat, mutability } => { |
650 | let expectation = match *expected { | 635 | let expectation = match expected.as_reference() { |
651 | Ty::Ref(ref sub_ty, exp_mut) => { | 636 | Some((inner_ty, exp_mut)) => { |
652 | if *mutability != exp_mut { | 637 | if *mutability != exp_mut { |
653 | // TODO: emit type error? | 638 | // TODO: emit type error? |
654 | } | 639 | } |
655 | &**sub_ty | 640 | inner_ty |
656 | } | 641 | } |
657 | _ => &Ty::Unknown, | 642 | _ => &Ty::Unknown, |
658 | }; | 643 | }; |
659 | let subty = self.infer_pat(*pat, expectation, default_bm); | 644 | let subty = self.infer_pat(*pat, expectation, default_bm); |
660 | Ty::Ref(subty.into(), *mutability) | 645 | Ty::apply_one(TypeCtor::Ref(*mutability), subty.into()) |
661 | } | 646 | } |
662 | Pat::TupleStruct { path: ref p, args: ref subpats } => { | 647 | Pat::TupleStruct { path: ref p, args: ref subpats } => { |
663 | self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm) | 648 | self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm) |
@@ -684,7 +669,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
684 | let inner_ty = self.insert_type_vars_shallow(inner_ty); | 669 | let inner_ty = self.insert_type_vars_shallow(inner_ty); |
685 | 670 | ||
686 | let bound_ty = match mode { | 671 | let bound_ty = match mode { |
687 | BindingMode::Ref(mutability) => Ty::Ref(inner_ty.clone().into(), mutability), | 672 | BindingMode::Ref(mutability) => { |
673 | Ty::apply_one(TypeCtor::Ref(mutability), inner_ty.clone().into()) | ||
674 | } | ||
688 | BindingMode::Move => inner_ty.clone(), | 675 | BindingMode::Move => inner_ty.clone(), |
689 | }; | 676 | }; |
690 | let bound_ty = self.resolve_ty_as_possible(&mut vec![], bound_ty); | 677 | let bound_ty = self.resolve_ty_as_possible(&mut vec![], bound_ty); |
@@ -738,7 +725,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
738 | Expr::Missing => Ty::Unknown, | 725 | Expr::Missing => Ty::Unknown, |
739 | Expr::If { condition, then_branch, else_branch } => { | 726 | Expr::If { condition, then_branch, else_branch } => { |
740 | // if let is desugared to match, so this is always simple if | 727 | // if let is desugared to match, so this is always simple if |
741 | self.infer_expr(*condition, &Expectation::has_type(Ty::Bool)); | 728 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); |
742 | let then_ty = self.infer_expr(*then_branch, expected); | 729 | let then_ty = self.infer_expr(*then_branch, expected); |
743 | match else_branch { | 730 | match else_branch { |
744 | Some(else_branch) => { | 731 | Some(else_branch) => { |
@@ -755,11 +742,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
755 | Expr::Loop { body } => { | 742 | Expr::Loop { body } => { |
756 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 743 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); |
757 | // TODO handle break with value | 744 | // TODO handle break with value |
758 | Ty::Never | 745 | Ty::simple(TypeCtor::Never) |
759 | } | 746 | } |
760 | Expr::While { condition, body } => { | 747 | Expr::While { condition, body } => { |
761 | // while let is desugared to a match loop, so this is always simple while | 748 | // while let is desugared to a match loop, so this is always simple while |
762 | self.infer_expr(*condition, &Expectation::has_type(Ty::Bool)); | 749 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); |
763 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 750 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); |
764 | Ty::unit() | 751 | Ty::unit() |
765 | } | 752 | } |
@@ -789,14 +776,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
789 | Expr::Call { callee, args } => { | 776 | Expr::Call { callee, args } => { |
790 | let callee_ty = self.infer_expr(*callee, &Expectation::none()); | 777 | let callee_ty = self.infer_expr(*callee, &Expectation::none()); |
791 | let (param_tys, ret_ty) = match &callee_ty { | 778 | let (param_tys, ret_ty) = match &callee_ty { |
792 | Ty::FnPtr(sig) => (sig.params().to_vec(), sig.ret().clone()), | 779 | Ty::Apply(a_ty) => match a_ty.ctor { |
793 | Ty::FnDef { substs, def, .. } => { | 780 | TypeCtor::FnPtr => { |
794 | let sig = self.db.callable_item_signature(*def); | 781 | let sig = FnSig::from_fn_ptr_substs(&a_ty.parameters); |
795 | let ret_ty = sig.ret().clone().subst(&substs); | 782 | (sig.params().to_vec(), sig.ret().clone()) |
796 | let param_tys = | 783 | } |
797 | sig.params().iter().map(|ty| ty.clone().subst(&substs)).collect(); | 784 | TypeCtor::FnDef(def) => { |
798 | (param_tys, ret_ty) | 785 | let sig = self.db.callable_item_signature(def); |
799 | } | 786 | let ret_ty = sig.ret().clone().subst(&a_ty.parameters); |
787 | let param_tys = sig | ||
788 | .params() | ||
789 | .iter() | ||
790 | .map(|ty| ty.clone().subst(&a_ty.parameters)) | ||
791 | .collect(); | ||
792 | (param_tys, ret_ty) | ||
793 | } | ||
794 | _ => (Vec::new(), Ty::Unknown), | ||
795 | }, | ||
800 | _ => { | 796 | _ => { |
801 | // not callable | 797 | // not callable |
802 | // TODO report an error? | 798 | // TODO report an error? |
@@ -821,37 +817,49 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
821 | Some(func.generic_params(self.db)), | 817 | Some(func.generic_params(self.db)), |
822 | ) | 818 | ) |
823 | } | 819 | } |
824 | None => (Ty::Unknown, receiver_ty, None), | 820 | None => (receiver_ty, Ty::Unknown, None), |
825 | }; | 821 | }; |
826 | let substs = self.substs_for_method_call(def_generics, generic_args); | 822 | let substs = self.substs_for_method_call(def_generics, generic_args); |
827 | let method_ty = method_ty.apply_substs(substs); | 823 | let method_ty = method_ty.apply_substs(substs); |
828 | let method_ty = self.insert_type_vars(method_ty); | 824 | let method_ty = self.insert_type_vars(method_ty); |
829 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { | 825 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { |
830 | Ty::FnPtr(sig) => { | 826 | Ty::Apply(a_ty) => match a_ty.ctor { |
831 | if !sig.params().is_empty() { | 827 | TypeCtor::FnPtr => { |
832 | (sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone()) | 828 | let sig = FnSig::from_fn_ptr_substs(&a_ty.parameters); |
833 | } else { | 829 | if !sig.params().is_empty() { |
834 | (Ty::Unknown, Vec::new(), sig.ret().clone()) | 830 | ( |
831 | sig.params()[0].clone(), | ||
832 | sig.params()[1..].to_vec(), | ||
833 | sig.ret().clone(), | ||
834 | ) | ||
835 | } else { | ||
836 | (Ty::Unknown, Vec::new(), sig.ret().clone()) | ||
837 | } | ||
835 | } | 838 | } |
836 | } | 839 | TypeCtor::FnDef(def) => { |
837 | Ty::FnDef { substs, def, .. } => { | 840 | let sig = self.db.callable_item_signature(def); |
838 | let sig = self.db.callable_item_signature(*def); | 841 | let ret_ty = sig.ret().clone().subst(&a_ty.parameters); |
839 | let ret_ty = sig.ret().clone().subst(&substs); | 842 | |
840 | 843 | if !sig.params().is_empty() { | |
841 | if !sig.params().is_empty() { | 844 | let mut params_iter = sig |
842 | let mut params_iter = | 845 | .params() |
843 | sig.params().iter().map(|ty| ty.clone().subst(&substs)); | 846 | .iter() |
844 | let receiver_ty = params_iter.next().unwrap(); | 847 | .map(|ty| ty.clone().subst(&a_ty.parameters)); |
845 | (receiver_ty, params_iter.collect(), ret_ty) | 848 | let receiver_ty = params_iter.next().unwrap(); |
846 | } else { | 849 | (receiver_ty, params_iter.collect(), ret_ty) |
847 | (Ty::Unknown, Vec::new(), ret_ty) | 850 | } else { |
851 | (Ty::Unknown, Vec::new(), ret_ty) | ||
852 | } | ||
848 | } | 853 | } |
849 | } | 854 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), |
855 | }, | ||
850 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), | 856 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), |
851 | }; | 857 | }; |
852 | // Apply autoref so the below unification works correctly | 858 | // Apply autoref so the below unification works correctly |
853 | let actual_receiver_ty = match expected_receiver_ty { | 859 | let actual_receiver_ty = match expected_receiver_ty.as_reference() { |
854 | Ty::Ref(_, mutability) => Ty::Ref(Arc::new(derefed_receiver_ty), mutability), | 860 | Some((_, mutability)) => { |
861 | Ty::apply_one(TypeCtor::Ref(mutability), derefed_receiver_ty) | ||
862 | } | ||
855 | _ => derefed_receiver_ty, | 863 | _ => derefed_receiver_ty, |
856 | }; | 864 | }; |
857 | self.unify(&expected_receiver_ty, &actual_receiver_ty); | 865 | self.unify(&expected_receiver_ty, &actual_receiver_ty); |
@@ -875,7 +883,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
875 | let _pat_ty = self.infer_pat(pat, &input_ty, BindingMode::default()); | 883 | let _pat_ty = self.infer_pat(pat, &input_ty, BindingMode::default()); |
876 | } | 884 | } |
877 | if let Some(guard_expr) = arm.guard { | 885 | if let Some(guard_expr) = arm.guard { |
878 | self.infer_expr(guard_expr, &Expectation::has_type(Ty::Bool)); | 886 | self.infer_expr( |
887 | guard_expr, | ||
888 | &Expectation::has_type(Ty::simple(TypeCtor::Bool)), | ||
889 | ); | ||
879 | } | 890 | } |
880 | self.infer_expr(arm.expr, &expected); | 891 | self.infer_expr(arm.expr, &expected); |
881 | } | 892 | } |
@@ -887,19 +898,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
887 | let resolver = expr::resolver_for_expr(self.body.clone(), self.db, tgt_expr); | 898 | let resolver = expr::resolver_for_expr(self.body.clone(), self.db, tgt_expr); |
888 | self.infer_path_expr(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) | 899 | self.infer_path_expr(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) |
889 | } | 900 | } |
890 | Expr::Continue => Ty::Never, | 901 | Expr::Continue => Ty::simple(TypeCtor::Never), |
891 | Expr::Break { expr } => { | 902 | Expr::Break { expr } => { |
892 | if let Some(expr) = expr { | 903 | if let Some(expr) = expr { |
893 | // TODO handle break with value | 904 | // TODO handle break with value |
894 | self.infer_expr(*expr, &Expectation::none()); | 905 | self.infer_expr(*expr, &Expectation::none()); |
895 | } | 906 | } |
896 | Ty::Never | 907 | Ty::simple(TypeCtor::Never) |
897 | } | 908 | } |
898 | Expr::Return { expr } => { | 909 | Expr::Return { expr } => { |
899 | if let Some(expr) = expr { | 910 | if let Some(expr) = expr { |
900 | self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone())); | 911 | self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone())); |
901 | } | 912 | } |
902 | Ty::Never | 913 | Ty::simple(TypeCtor::Never) |
903 | } | 914 | } |
904 | Expr::StructLit { path, fields, spread } => { | 915 | Expr::StructLit { path, fields, spread } => { |
905 | let (ty, def_id) = self.resolve_variant(path.as_ref()); | 916 | let (ty, def_id) = self.resolve_variant(path.as_ref()); |
@@ -921,16 +932,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
921 | let ty = receiver_ty | 932 | let ty = receiver_ty |
922 | .autoderef(self.db) | 933 | .autoderef(self.db) |
923 | .find_map(|derefed_ty| match derefed_ty { | 934 | .find_map(|derefed_ty| match derefed_ty { |
924 | Ty::Tuple(fields) => { | 935 | Ty::Apply(a_ty) => match a_ty.ctor { |
925 | let i = name.to_string().parse::<usize>().ok(); | 936 | TypeCtor::Tuple => { |
926 | i.and_then(|i| fields.get(i).cloned()) | 937 | let i = name.to_string().parse::<usize>().ok(); |
927 | } | 938 | i.and_then(|i| a_ty.parameters.0.get(i).cloned()) |
928 | Ty::Adt { def_id: AdtDef::Struct(s), ref substs, .. } => { | 939 | } |
929 | s.field(self.db, name).map(|field| { | 940 | TypeCtor::Adt(AdtDef::Struct(s)) => { |
930 | self.write_field_resolution(tgt_expr, field); | 941 | s.field(self.db, name).map(|field| { |
931 | field.ty(self.db).subst(substs) | 942 | self.write_field_resolution(tgt_expr, field); |
932 | }) | 943 | field.ty(self.db).subst(&a_ty.parameters) |
933 | } | 944 | }) |
945 | } | ||
946 | _ => None, | ||
947 | }, | ||
934 | _ => None, | 948 | _ => None, |
935 | }) | 949 | }) |
936 | .unwrap_or(Ty::Unknown); | 950 | .unwrap_or(Ty::Unknown); |
@@ -947,18 +961,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
947 | cast_ty | 961 | cast_ty |
948 | } | 962 | } |
949 | Expr::Ref { expr, mutability } => { | 963 | Expr::Ref { expr, mutability } => { |
950 | let expectation = if let Ty::Ref(ref subty, expected_mutability) = expected.ty { | 964 | let expectation = |
951 | if expected_mutability == Mutability::Mut && *mutability == Mutability::Shared { | 965 | if let Some((exp_inner, exp_mutability)) = &expected.ty.as_reference() { |
952 | // TODO: throw type error - expected mut reference but found shared ref, | 966 | if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared { |
953 | // which cannot be coerced | 967 | // TODO: throw type error - expected mut reference but found shared ref, |
954 | } | 968 | // which cannot be coerced |
955 | Expectation::has_type((**subty).clone()) | 969 | } |
956 | } else { | 970 | Expectation::has_type(Ty::clone(exp_inner)) |
957 | Expectation::none() | 971 | } else { |
958 | }; | 972 | Expectation::none() |
973 | }; | ||
959 | // TODO reference coercions etc. | 974 | // TODO reference coercions etc. |
960 | let inner_ty = self.infer_expr(*expr, &expectation); | 975 | let inner_ty = self.infer_expr(*expr, &expectation); |
961 | Ty::Ref(Arc::new(inner_ty), *mutability) | 976 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) |
962 | } | 977 | } |
963 | Expr::UnaryOp { expr, op } => { | 978 | Expr::UnaryOp { expr, op } => { |
964 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | 979 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); |
@@ -972,19 +987,27 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
972 | } | 987 | } |
973 | } | 988 | } |
974 | UnaryOp::Neg => { | 989 | UnaryOp::Neg => { |
975 | match inner_ty { | 990 | match &inner_ty { |
976 | Ty::Int(primitive::UncertainIntTy::Unknown) | 991 | Ty::Apply(a_ty) => match a_ty.ctor { |
977 | | Ty::Int(primitive::UncertainIntTy::Signed(..)) | 992 | TypeCtor::Int(primitive::UncertainIntTy::Unknown) |
978 | | Ty::Infer(InferTy::IntVar(..)) | 993 | | TypeCtor::Int(primitive::UncertainIntTy::Signed(..)) |
979 | | Ty::Infer(InferTy::FloatVar(..)) | 994 | | TypeCtor::Float(..) => inner_ty, |
980 | | Ty::Float(..) => inner_ty, | 995 | _ => Ty::Unknown, |
996 | }, | ||
997 | Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => { | ||
998 | inner_ty | ||
999 | } | ||
981 | // TODO: resolve ops::Neg trait | 1000 | // TODO: resolve ops::Neg trait |
982 | _ => Ty::Unknown, | 1001 | _ => Ty::Unknown, |
983 | } | 1002 | } |
984 | } | 1003 | } |
985 | UnaryOp::Not => { | 1004 | UnaryOp::Not => { |
986 | match inner_ty { | 1005 | match &inner_ty { |
987 | Ty::Bool | Ty::Int(_) | Ty::Infer(InferTy::IntVar(..)) => inner_ty, | 1006 | Ty::Apply(a_ty) => match a_ty.ctor { |
1007 | TypeCtor::Bool | TypeCtor::Int(_) => inner_ty, | ||
1008 | _ => Ty::Unknown, | ||
1009 | }, | ||
1010 | Ty::Infer(InferTy::IntVar(..)) => inner_ty, | ||
988 | // TODO: resolve ops::Not trait for inner_ty | 1011 | // TODO: resolve ops::Not trait for inner_ty |
989 | _ => Ty::Unknown, | 1012 | _ => Ty::Unknown, |
990 | } | 1013 | } |
@@ -995,7 +1018,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
995 | Some(op) => { | 1018 | Some(op) => { |
996 | let lhs_expectation = match op { | 1019 | let lhs_expectation = match op { |
997 | BinaryOp::BooleanAnd | BinaryOp::BooleanOr => { | 1020 | BinaryOp::BooleanAnd | BinaryOp::BooleanOr => { |
998 | Expectation::has_type(Ty::Bool) | 1021 | Expectation::has_type(Ty::simple(TypeCtor::Bool)) |
999 | } | 1022 | } |
1000 | _ => Expectation::none(), | 1023 | _ => Expectation::none(), |
1001 | }; | 1024 | }; |
@@ -1016,11 +1039,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1016 | ty_vec.push(self.infer_expr(*arg, &Expectation::none())); | 1039 | ty_vec.push(self.infer_expr(*arg, &Expectation::none())); |
1017 | } | 1040 | } |
1018 | 1041 | ||
1019 | Ty::Tuple(Arc::from(ty_vec)) | 1042 | Ty::apply(TypeCtor::Tuple, Substs(ty_vec.into())) |
1020 | } | 1043 | } |
1021 | Expr::Array { exprs } => { | 1044 | Expr::Array { exprs } => { |
1022 | let elem_ty = match &expected.ty { | 1045 | let elem_ty = match &expected.ty { |
1023 | Ty::Slice(inner) | Ty::Array(inner) => Ty::clone(&inner), | 1046 | Ty::Apply(a_ty) => match a_ty.ctor { |
1047 | TypeCtor::Slice | TypeCtor::Array => { | ||
1048 | Ty::clone(&a_ty.parameters.as_single()) | ||
1049 | } | ||
1050 | _ => self.new_type_var(), | ||
1051 | }, | ||
1024 | _ => self.new_type_var(), | 1052 | _ => self.new_type_var(), |
1025 | }; | 1053 | }; |
1026 | 1054 | ||
@@ -1028,21 +1056,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1028 | self.infer_expr(*expr, &Expectation::has_type(elem_ty.clone())); | 1056 | self.infer_expr(*expr, &Expectation::has_type(elem_ty.clone())); |
1029 | } | 1057 | } |
1030 | 1058 | ||
1031 | Ty::Array(Arc::new(elem_ty)) | 1059 | Ty::apply_one(TypeCtor::Array, elem_ty) |
1032 | } | 1060 | } |
1033 | Expr::Literal(lit) => match lit { | 1061 | Expr::Literal(lit) => match lit { |
1034 | Literal::Bool(..) => Ty::Bool, | 1062 | Literal::Bool(..) => Ty::simple(TypeCtor::Bool), |
1035 | Literal::String(..) => Ty::Ref(Arc::new(Ty::Str), Mutability::Shared), | 1063 | Literal::String(..) => { |
1064 | Ty::apply_one(TypeCtor::Ref(Mutability::Shared), Ty::simple(TypeCtor::Str)) | ||
1065 | } | ||
1036 | Literal::ByteString(..) => { | 1066 | Literal::ByteString(..) => { |
1037 | let byte_type = Arc::new(Ty::Int(primitive::UncertainIntTy::Unsigned( | 1067 | let byte_type = Ty::simple(TypeCtor::Int(primitive::UncertainIntTy::Unsigned( |
1038 | primitive::UintTy::U8, | 1068 | primitive::UintTy::U8, |
1039 | ))); | 1069 | ))); |
1040 | let slice_type = Arc::new(Ty::Slice(byte_type)); | 1070 | let slice_type = Ty::apply_one(TypeCtor::Slice, byte_type); |
1041 | Ty::Ref(slice_type, Mutability::Shared) | 1071 | Ty::apply_one(TypeCtor::Ref(Mutability::Shared), slice_type) |
1042 | } | 1072 | } |
1043 | Literal::Char(..) => Ty::Char, | 1073 | Literal::Char(..) => Ty::simple(TypeCtor::Char), |
1044 | Literal::Int(_v, ty) => Ty::Int(*ty), | 1074 | Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int(*ty)), |
1045 | Literal::Float(_v, ty) => Ty::Float(*ty), | 1075 | Literal::Float(_v, ty) => Ty::simple(TypeCtor::Float(*ty)), |
1046 | }, | 1076 | }, |
1047 | }; | 1077 | }; |
1048 | // use a new type variable if we got Ty::Unknown here | 1078 | // use a new type variable if we got Ty::Unknown here |
@@ -1178,11 +1208,11 @@ impl InferTy { | |||
1178 | match self { | 1208 | match self { |
1179 | InferTy::TypeVar(..) => Ty::Unknown, | 1209 | InferTy::TypeVar(..) => Ty::Unknown, |
1180 | InferTy::IntVar(..) => { | 1210 | InferTy::IntVar(..) => { |
1181 | Ty::Int(primitive::UncertainIntTy::Signed(primitive::IntTy::I32)) | 1211 | Ty::simple(TypeCtor::Int(primitive::UncertainIntTy::Signed(primitive::IntTy::I32))) |
1182 | } | ||
1183 | InferTy::FloatVar(..) => { | ||
1184 | Ty::Float(primitive::UncertainFloatTy::Known(primitive::FloatTy::F64)) | ||
1185 | } | 1212 | } |
1213 | InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float( | ||
1214 | primitive::UncertainFloatTy::Known(primitive::FloatTy::F64), | ||
1215 | )), | ||
1186 | } | 1216 | } |
1187 | } | 1217 | } |
1188 | } | 1218 | } |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 389a2fc68..72b1234bf 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -6,8 +6,6 @@ | |||
6 | //! | 6 | //! |
7 | //! This usually involves resolving names, collecting generic arguments etc. | 7 | //! This usually involves resolving names, collecting generic arguments etc. |
8 | 8 | ||
9 | use std::sync::Arc; | ||
10 | |||
11 | use crate::{ | 9 | use crate::{ |
12 | Function, Struct, StructField, Enum, EnumVariant, Path, | 10 | Function, Struct, StructField, Enum, EnumVariant, Path, |
13 | ModuleDef, TypeAlias, | 11 | ModuleDef, TypeAlias, |
@@ -21,40 +19,40 @@ use crate::{ | |||
21 | generics::GenericParams, | 19 | generics::GenericParams, |
22 | adt::VariantDef, | 20 | adt::VariantDef, |
23 | }; | 21 | }; |
24 | use super::{Ty, primitive, FnSig, Substs}; | 22 | use super::{Ty, primitive, FnSig, Substs, TypeCtor}; |
25 | 23 | ||
26 | impl Ty { | 24 | impl Ty { |
27 | pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { | 25 | pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { |
28 | match type_ref { | 26 | match type_ref { |
29 | TypeRef::Never => Ty::Never, | 27 | TypeRef::Never => Ty::simple(TypeCtor::Never), |
30 | TypeRef::Tuple(inner) => { | 28 | TypeRef::Tuple(inner) => { |
31 | let inner_tys = | 29 | let inner_tys = |
32 | inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); | 30 | inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); |
33 | Ty::Tuple(inner_tys.into()) | 31 | Ty::apply(TypeCtor::Tuple, Substs(inner_tys.into())) |
34 | } | 32 | } |
35 | TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), | 33 | TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), |
36 | TypeRef::RawPtr(inner, mutability) => { | 34 | TypeRef::RawPtr(inner, mutability) => { |
37 | let inner_ty = Ty::from_hir(db, resolver, inner); | 35 | let inner_ty = Ty::from_hir(db, resolver, inner); |
38 | Ty::RawPtr(Arc::new(inner_ty), *mutability) | 36 | Ty::apply_one(TypeCtor::RawPtr(*mutability), inner_ty) |
39 | } | 37 | } |
40 | TypeRef::Array(inner) => { | 38 | TypeRef::Array(inner) => { |
41 | let inner_ty = Ty::from_hir(db, resolver, inner); | 39 | let inner_ty = Ty::from_hir(db, resolver, inner); |
42 | Ty::Array(Arc::new(inner_ty)) | 40 | Ty::apply_one(TypeCtor::Array, inner_ty) |
43 | } | 41 | } |
44 | TypeRef::Slice(inner) => { | 42 | TypeRef::Slice(inner) => { |
45 | let inner_ty = Ty::from_hir(db, resolver, inner); | 43 | let inner_ty = Ty::from_hir(db, resolver, inner); |
46 | Ty::Slice(Arc::new(inner_ty)) | 44 | Ty::apply_one(TypeCtor::Slice, inner_ty) |
47 | } | 45 | } |
48 | TypeRef::Reference(inner, mutability) => { | 46 | TypeRef::Reference(inner, mutability) => { |
49 | let inner_ty = Ty::from_hir(db, resolver, inner); | 47 | let inner_ty = Ty::from_hir(db, resolver, inner); |
50 | Ty::Ref(Arc::new(inner_ty), *mutability) | 48 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) |
51 | } | 49 | } |
52 | TypeRef::Placeholder => Ty::Unknown, | 50 | TypeRef::Placeholder => Ty::Unknown, |
53 | TypeRef::Fn(params) => { | 51 | TypeRef::Fn(params) => { |
54 | let inner_tys = | 52 | let inner_tys = |
55 | params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); | 53 | params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); |
56 | let sig = FnSig { params_and_return: inner_tys.into() }; | 54 | let sig = Substs(inner_tys.into()); |
57 | Ty::FnPtr(sig) | 55 | Ty::apply(TypeCtor::FnPtr, sig) |
58 | } | 56 | } |
59 | TypeRef::Error => Ty::Unknown, | 57 | TypeRef::Error => Ty::Unknown, |
60 | } | 58 | } |
@@ -64,14 +62,14 @@ impl Ty { | |||
64 | if let Some(name) = path.as_ident() { | 62 | if let Some(name) = path.as_ident() { |
65 | // TODO handle primitive type names in resolver as well? | 63 | // TODO handle primitive type names in resolver as well? |
66 | if let Some(int_ty) = primitive::UncertainIntTy::from_type_name(name) { | 64 | if let Some(int_ty) = primitive::UncertainIntTy::from_type_name(name) { |
67 | return Ty::Int(int_ty); | 65 | return Ty::simple(TypeCtor::Int(int_ty)); |
68 | } else if let Some(float_ty) = primitive::UncertainFloatTy::from_type_name(name) { | 66 | } else if let Some(float_ty) = primitive::UncertainFloatTy::from_type_name(name) { |
69 | return Ty::Float(float_ty); | 67 | return Ty::simple(TypeCtor::Float(float_ty)); |
70 | } else if let Some(known) = name.as_known_name() { | 68 | } else if let Some(known) = name.as_known_name() { |
71 | match known { | 69 | match known { |
72 | KnownName::Bool => return Ty::Bool, | 70 | KnownName::Bool => return Ty::simple(TypeCtor::Bool), |
73 | KnownName::Char => return Ty::Char, | 71 | KnownName::Char => return Ty::simple(TypeCtor::Char), |
74 | KnownName::Str => return Ty::Str, | 72 | KnownName::Str => return Ty::simple(TypeCtor::Str), |
75 | _ => {} | 73 | _ => {} |
76 | } | 74 | } |
77 | } | 75 | } |
@@ -247,7 +245,7 @@ fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { | |||
247 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { | 245 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { |
248 | let generics = def.generic_params(db); | 246 | let generics = def.generic_params(db); |
249 | let substs = make_substs(&generics); | 247 | let substs = make_substs(&generics); |
250 | Ty::FnDef { def: def.into(), substs } | 248 | Ty::apply(TypeCtor::FnDef(def.into()), substs) |
251 | } | 249 | } |
252 | 250 | ||
253 | /// Build the declared type of a const. | 251 | /// Build the declared type of a const. |
@@ -289,7 +287,7 @@ fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | |||
289 | } | 287 | } |
290 | let generics = def.generic_params(db); | 288 | let generics = def.generic_params(db); |
291 | let substs = make_substs(&generics); | 289 | let substs = make_substs(&generics); |
292 | Ty::FnDef { def: def.into(), substs } | 290 | Ty::apply(TypeCtor::FnDef(def.into()), substs) |
293 | } | 291 | } |
294 | 292 | ||
295 | fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig { | 293 | fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig { |
@@ -317,7 +315,7 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> | |||
317 | } | 315 | } |
318 | let generics = def.parent_enum(db).generic_params(db); | 316 | let generics = def.parent_enum(db).generic_params(db); |
319 | let substs = make_substs(&generics); | 317 | let substs = make_substs(&generics); |
320 | Ty::FnDef { def: def.into(), substs } | 318 | Ty::apply(TypeCtor::FnDef(def.into()), substs) |
321 | } | 319 | } |
322 | 320 | ||
323 | fn make_substs(generics: &GenericParams) -> Substs { | 321 | fn make_substs(generics: &GenericParams) -> Substs { |
@@ -333,12 +331,12 @@ fn make_substs(generics: &GenericParams) -> Substs { | |||
333 | 331 | ||
334 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { | 332 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { |
335 | let generics = s.generic_params(db); | 333 | let generics = s.generic_params(db); |
336 | Ty::Adt { def_id: s.into(), substs: make_substs(&generics) } | 334 | Ty::apply(TypeCtor::Adt(s.into()), make_substs(&generics)) |
337 | } | 335 | } |
338 | 336 | ||
339 | fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { | 337 | fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { |
340 | let generics = s.generic_params(db); | 338 | let generics = s.generic_params(db); |
341 | Ty::Adt { def_id: s.into(), substs: make_substs(&generics) } | 339 | Ty::apply(TypeCtor::Adt(s.into()), make_substs(&generics)) |
342 | } | 340 | } |
343 | 341 | ||
344 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { | 342 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 804824868..ed75bfaee 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -10,7 +10,7 @@ use crate::{ | |||
10 | HirDatabase, Module, Crate, Name, Function, Trait, | 10 | HirDatabase, Module, Crate, Name, Function, Trait, |
11 | ids::TraitId, | 11 | ids::TraitId, |
12 | impl_block::{ImplId, ImplBlock, ImplItem}, | 12 | impl_block::{ImplId, ImplBlock, ImplItem}, |
13 | ty::{AdtDef, Ty}, | 13 | ty::{Ty, TypeCtor}, |
14 | nameres::CrateModuleId, | 14 | nameres::CrateModuleId, |
15 | 15 | ||
16 | }; | 16 | }; |
@@ -18,7 +18,7 @@ use crate::{ | |||
18 | /// This is used as a key for indexing impls. | 18 | /// This is used as a key for indexing impls. |
19 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 19 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
20 | pub enum TyFingerprint { | 20 | pub enum TyFingerprint { |
21 | Adt(AdtDef), // we'll also want to index impls for primitive types etc. | 21 | Apply(TypeCtor), |
22 | } | 22 | } |
23 | 23 | ||
24 | impl TyFingerprint { | 24 | impl TyFingerprint { |
@@ -27,7 +27,7 @@ impl TyFingerprint { | |||
27 | /// `impl &S`. Hence, this will return `None` for reference types and such. | 27 | /// `impl &S`. Hence, this will return `None` for reference types and such. |
28 | fn for_impl(ty: &Ty) -> Option<TyFingerprint> { | 28 | fn for_impl(ty: &Ty) -> Option<TyFingerprint> { |
29 | match ty { | 29 | match ty { |
30 | Ty::Adt { def_id, .. } => Some(TyFingerprint::Adt(*def_id)), | 30 | Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)), |
31 | _ => None, | 31 | _ => None, |
32 | } | 32 | } |
33 | } | 33 | } |
@@ -111,7 +111,10 @@ impl CrateImplBlocks { | |||
111 | 111 | ||
112 | fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> { | 112 | fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> { |
113 | match ty { | 113 | match ty { |
114 | Ty::Adt { def_id, .. } => def_id.krate(db), | 114 | Ty::Apply(a_ty) => match a_ty.ctor { |
115 | TypeCtor::Adt(def_id) => def_id.krate(db), | ||
116 | _ => None, | ||
117 | }, | ||
115 | _ => None, | 118 | _ => None, |
116 | } | 119 | } |
117 | } | 120 | } |
diff --git a/crates/ra_hir/src/ty/op.rs b/crates/ra_hir/src/ty/op.rs index 8703cf236..235661a5d 100644 --- a/crates/ra_hir/src/ty/op.rs +++ b/crates/ra_hir/src/ty/op.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use crate::expr::BinaryOp; | 1 | use crate::{ ty::ApplicationTy, expr::BinaryOp}; |
2 | use super::{Ty, InferTy}; | 2 | use super::{Ty, TypeCtor, InferTy}; |
3 | 3 | ||
4 | pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { | 4 | pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { |
5 | match op { | 5 | match op { |
@@ -10,7 +10,7 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { | |||
10 | | BinaryOp::LesserEqualTest | 10 | | BinaryOp::LesserEqualTest |
11 | | BinaryOp::GreaterEqualTest | 11 | | BinaryOp::GreaterEqualTest |
12 | | BinaryOp::LesserTest | 12 | | BinaryOp::LesserTest |
13 | | BinaryOp::GreaterTest => Ty::Bool, | 13 | | BinaryOp::GreaterTest => Ty::simple(TypeCtor::Bool), |
14 | BinaryOp::Assignment | 14 | BinaryOp::Assignment |
15 | | BinaryOp::AddAssign | 15 | | BinaryOp::AddAssign |
16 | | BinaryOp::SubAssign | 16 | | BinaryOp::SubAssign |
@@ -32,10 +32,11 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { | |||
32 | | BinaryOp::BitwiseAnd | 32 | | BinaryOp::BitwiseAnd |
33 | | BinaryOp::BitwiseOr | 33 | | BinaryOp::BitwiseOr |
34 | | BinaryOp::BitwiseXor => match rhs_ty { | 34 | | BinaryOp::BitwiseXor => match rhs_ty { |
35 | Ty::Int(..) | 35 | Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { |
36 | | Ty::Float(..) | 36 | TypeCtor::Int(..) | TypeCtor::Float(..) => rhs_ty, |
37 | | Ty::Infer(InferTy::IntVar(..)) | 37 | _ => Ty::Unknown, |
38 | | Ty::Infer(InferTy::FloatVar(..)) => rhs_ty, | 38 | }, |
39 | Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => rhs_ty, | ||
39 | _ => Ty::Unknown, | 40 | _ => Ty::Unknown, |
40 | }, | 41 | }, |
41 | BinaryOp::RangeRightOpen | BinaryOp::RangeRightClosed => Ty::Unknown, | 42 | BinaryOp::RangeRightOpen | BinaryOp::RangeRightClosed => Ty::Unknown, |
@@ -44,9 +45,17 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { | |||
44 | 45 | ||
45 | pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { | 46 | pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { |
46 | match op { | 47 | match op { |
47 | BinaryOp::BooleanAnd | BinaryOp::BooleanOr => Ty::Bool, | 48 | BinaryOp::BooleanAnd | BinaryOp::BooleanOr => Ty::simple(TypeCtor::Bool), |
48 | BinaryOp::Assignment | BinaryOp::EqualityTest => match lhs_ty { | 49 | BinaryOp::Assignment | BinaryOp::EqualityTest => match lhs_ty { |
49 | Ty::Int(..) | Ty::Float(..) | Ty::Str | Ty::Char | Ty::Bool => lhs_ty, | 50 | Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { |
51 | TypeCtor::Int(..) | ||
52 | | TypeCtor::Float(..) | ||
53 | | TypeCtor::Str | ||
54 | | TypeCtor::Char | ||
55 | | TypeCtor::Bool => lhs_ty, | ||
56 | _ => Ty::Unknown, | ||
57 | }, | ||
58 | Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => lhs_ty, | ||
50 | _ => Ty::Unknown, | 59 | _ => Ty::Unknown, |
51 | }, | 60 | }, |
52 | BinaryOp::LesserEqualTest | 61 | BinaryOp::LesserEqualTest |
@@ -73,7 +82,11 @@ pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { | |||
73 | | BinaryOp::BitwiseAnd | 82 | | BinaryOp::BitwiseAnd |
74 | | BinaryOp::BitwiseOr | 83 | | BinaryOp::BitwiseOr |
75 | | BinaryOp::BitwiseXor => match lhs_ty { | 84 | | BinaryOp::BitwiseXor => match lhs_ty { |
76 | Ty::Int(..) | Ty::Float(..) => lhs_ty, | 85 | Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { |
86 | TypeCtor::Int(..) | TypeCtor::Float(..) => lhs_ty, | ||
87 | _ => Ty::Unknown, | ||
88 | }, | ||
89 | Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => lhs_ty, | ||
77 | _ => Ty::Unknown, | 90 | _ => Ty::Unknown, |
78 | }, | 91 | }, |
79 | _ => Ty::Unknown, | 92 | _ => Ty::Unknown, |
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 94c66be31..31d5374ba 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 @@ | |||
1 | use hir::{Ty, AdtDef}; | 1 | use hir::{Ty, AdtDef, TypeCtor}; |
2 | 2 | ||
3 | use crate::completion::{CompletionContext, Completions}; | 3 | use crate::completion::{CompletionContext, Completions}; |
4 | 4 | ||
@@ -24,23 +24,20 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { | |||
24 | fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { | 24 | fn 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, ref substs, .. } => { | 27 | Ty::Apply(a_ty) => match a_ty.ctor { |
28 | match def_id { | 28 | TypeCtor::Adt(AdtDef::Struct(s)) => { |
29 | AdtDef::Struct(s) => { | 29 | for field in s.fields(ctx.db) { |
30 | for field in s.fields(ctx.db) { | 30 | acc.add_field(ctx, field, &a_ty.parameters); |
31 | acc.add_field(ctx, field, substs); | ||
32 | } | ||
33 | } | 31 | } |
34 | |||
35 | // TODO unions | ||
36 | AdtDef::Enum(_) => (), | ||
37 | } | 32 | } |
38 | } | 33 | // TODO unions |
39 | Ty::Tuple(fields) => { | 34 | TypeCtor::Tuple => { |
40 | for (i, ty) in fields.iter().enumerate() { | 35 | for (i, ty) in a_ty.parameters.iter().enumerate() { |
41 | acc.add_pos_field(ctx, i, ty); | 36 | acc.add_pos_field(ctx, i, ty); |
37 | } | ||
42 | } | 38 | } |
43 | } | 39 | _ => {} |
40 | }, | ||
44 | _ => {} | 41 | _ => {} |
45 | }; | 42 | }; |
46 | } | 43 | } |
diff --git a/crates/ra_ide_api/src/completion/complete_struct_literal.rs b/crates/ra_ide_api/src/completion/complete_struct_literal.rs index 6bef9624e..b75526282 100644 --- a/crates/ra_ide_api/src/completion/complete_struct_literal.rs +++ b/crates/ra_ide_api/src/completion/complete_struct_literal.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use hir::{Ty, AdtDef}; | 1 | use hir::AdtDef; |
2 | 2 | ||
3 | use crate::completion::{CompletionContext, Completions}; | 3 | use crate::completion::{CompletionContext, Completions}; |
4 | 4 | ||
@@ -15,8 +15,8 @@ pub(super) fn complete_struct_literal(acc: &mut Completions, ctx: &CompletionCon | |||
15 | None => return, | 15 | None => return, |
16 | }; | 16 | }; |
17 | let ty = infer_result[expr].clone(); | 17 | let ty = infer_result[expr].clone(); |
18 | let (adt, substs) = match ty { | 18 | let (adt, substs) = match ty.as_adt() { |
19 | Ty::Adt { def_id, ref substs, .. } => (def_id, substs), | 19 | Some(res) => res, |
20 | _ => return, | 20 | _ => return, |
21 | }; | 21 | }; |
22 | match adt { | 22 | match adt { |
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index d4e10b69c..f94487d94 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -87,14 +87,12 @@ pub(crate) fn reference_definition( | |||
87 | 87 | ||
88 | if let Some(expr) = struct_lit.and_then(|lit| source_map.node_expr(lit.into())) { | 88 | if let Some(expr) = struct_lit.and_then(|lit| source_map.node_expr(lit.into())) { |
89 | let ty = infer_result[expr].clone(); | 89 | let ty = infer_result[expr].clone(); |
90 | if let hir::Ty::Adt { def_id, .. } = ty { | 90 | if let Some((hir::AdtDef::Struct(s), _)) = ty.as_adt() { |
91 | if let hir::AdtDef::Struct(s) = def_id { | 91 | let hir_path = hir::Path::from_name_ref(name_ref); |
92 | let hir_path = hir::Path::from_name_ref(name_ref); | 92 | let hir_name = hir_path.as_ident().unwrap(); |
93 | let hir_name = hir_path.as_ident().unwrap(); | ||
94 | 93 | ||
95 | if let Some(field) = s.field(db, hir_name) { | 94 | if let Some(field) = s.field(db, hir_name) { |
96 | return Exact(NavigationTarget::from_field(db, field)); | 95 | return Exact(NavigationTarget::from_field(db, field)); |
97 | } | ||
98 | } | 96 | } |
99 | } | 97 | } |
100 | } | 98 | } |
@@ -124,7 +122,7 @@ pub(crate) fn reference_definition( | |||
124 | Some(Resolution::SelfType(impl_block)) => { | 122 | Some(Resolution::SelfType(impl_block)) => { |
125 | let ty = impl_block.target_ty(db); | 123 | let ty = impl_block.target_ty(db); |
126 | 124 | ||
127 | if let hir::Ty::Adt { def_id, .. } = ty { | 125 | if let Some((def_id, _)) = ty.as_adt() { |
128 | return Exact(NavigationTarget::from_adt_def(db, def_id)); | 126 | return Exact(NavigationTarget::from_adt_def(db, def_id)); |
129 | } | 127 | } |
130 | } | 128 | } |
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index f6a83dd93..f6443580d 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs | |||
@@ -517,23 +517,8 @@ The Some variant | |||
517 | assert_eq!("u32", &type_name); | 517 | assert_eq!("u32", &type_name); |
518 | } | 518 | } |
519 | 519 | ||
520 | // FIXME: improve type_of to make this work | ||
521 | #[test] | 520 | #[test] |
522 | fn test_type_of_for_expr_1() { | 521 | fn test_type_of_for_expr() { |
523 | let (analysis, range) = single_file_with_range( | ||
524 | " | ||
525 | fn main() { | ||
526 | let foo = <|>1 + foo_test<|>; | ||
527 | } | ||
528 | ", | ||
529 | ); | ||
530 | |||
531 | let type_name = analysis.type_of(range).unwrap().unwrap(); | ||
532 | assert_eq!("{unknown}", &type_name); | ||
533 | } | ||
534 | |||
535 | #[test] | ||
536 | fn test_type_of_for_expr_2() { | ||
537 | let (analysis, range) = single_file_with_range( | 522 | let (analysis, range) = single_file_with_range( |
538 | " | 523 | " |
539 | fn main() { | 524 | fn main() { |