aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-03-22 05:32:48 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-03-22 05:32:48 +0000
commit9c6c6a7cb51b701585827c1a39d36450ddb5cd51 (patch)
treec5e4c46da389accd0b03b3b285f5057265f65f65 /crates
parent51323a852a8979a71c21725b3b2771224132b85f (diff)
parent1ee779d1f74f48d9f3098001c63108b794dbc0b5 (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]>
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/fill_match_arms.rs14
-rw-r--r--crates/ra_assists/src/fill_struct_fields.rs6
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/ty.rs261
-rw-r--r--crates/ra_hir/src/ty/infer.rs264
-rw-r--r--crates/ra_hir/src/ty/lower.rs40
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs11
-rw-r--r--crates/ra_hir/src/ty/op.rs33
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs27
-rw-r--r--crates/ra_ide_api/src/completion/complete_struct_literal.rs6
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs14
-rw-r--r--crates/ra_ide_api/src/hover.rs17
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 @@
1use std::fmt::Write; 1use std::fmt::Write;
2 2
3use hir::{ 3use hir::{
4 AdtDef, Ty, FieldSource, source_binder, 4 AdtDef, FieldSource, source_binder,
5 db::HirDatabase, 5 db::HirDatabase,
6}; 6};
7use ra_syntax::ast::{self, AstNode}; 7use 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 @@
1use std::fmt::Write; 1use std::fmt::Write;
2 2
3use hir::{AdtDef, Ty, db::HirDatabase, source_binder::function_from_child_node}; 3use hir::{AdtDef, db::HirDatabase, source_binder::function_from_child_node};
4 4
5use ra_syntax::ast::{self, AstNode}; 5use 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
20pub(crate) use infer::{infer, InferenceResult, InferTy}; 20pub(crate) use infer::{infer, InferenceResult, InferTy};
21use display::{HirDisplay, HirFormatter}; 21use 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)]
27pub enum Ty { 27pub 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)]
95pub 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)]
107pub 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)]
142pub struct FnSig { 175pub 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
169impl Ty { 207impl 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
308impl HirDisplay for Ty { 333impl 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
408impl 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};
41use super::{Ty, TypableDef, Substs, primitive, op}; 41use 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.
44pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { 44pub 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
9use std::sync::Arc;
10
11use crate::{ 9use 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};
24use super::{Ty, primitive, FnSig, Substs}; 22use super::{Ty, primitive, FnSig, Substs, TypeCtor};
25 23
26impl Ty { 24impl 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 {
247fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { 245fn 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
295fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig { 293fn 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
323fn make_substs(generics: &GenericParams) -> Substs { 321fn make_substs(generics: &GenericParams) -> Substs {
@@ -333,12 +331,12 @@ fn make_substs(generics: &GenericParams) -> Substs {
333 331
334fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { 332fn 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
339fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { 337fn 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
344fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { 342fn 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)]
20pub enum TyFingerprint { 20pub enum TyFingerprint {
21 Adt(AdtDef), // we'll also want to index impls for primitive types etc. 21 Apply(TypeCtor),
22} 22}
23 23
24impl TyFingerprint { 24impl 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
112fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> { 112fn 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 @@
1use crate::expr::BinaryOp; 1use crate::{ ty::ApplicationTy, expr::BinaryOp};
2use super::{Ty, InferTy}; 2use super::{Ty, TypeCtor, InferTy};
3 3
4pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { 4pub(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
45pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { 46pub(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 @@
1use hir::{Ty, AdtDef}; 1use hir::{Ty, AdtDef, TypeCtor};
2 2
3use crate::completion::{CompletionContext, Completions}; 3use crate::completion::{CompletionContext, Completions};
4 4
@@ -24,23 +24,20 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
24fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { 24fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
25 for receiver in receiver.autoderef(ctx.db) { 25 for receiver in receiver.autoderef(ctx.db) {
26 match receiver { 26 match receiver {
27 Ty::Adt { def_id, 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 @@
1use hir::{Ty, AdtDef}; 1use hir::AdtDef;
2 2
3use crate::completion::{CompletionContext, Completions}; 3use 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() {