aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2018-12-29 12:24:40 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2018-12-29 12:24:40 +0000
commit9220641ba4d3c7a95db7355d9999da54d455607c (patch)
tree7c240880b47d94ecb9c9d39766579e8ec563b018
parenta9528c540b1e71d03d643244dd915f6420b38191 (diff)
parentb1590bdf6a88c03e2aeeedbe04f4dbc4203073db (diff)
Merge #355
355: Type variables / unification r=matklad a=flodiebold This will really become necessary when we implement generics, but even now, it allows us to reason 'backwards' to infer types of expressions that we didn't understand for some reason. This uses [ena](https://crates.io/crates/ena) to keep track of type variables. Also turn `Ty::Tuple` from a `Vec` into an `Arc<[Ty]>` to keep `Ty` easily cloneable. Though to be honest I'm not sure how often we actually share data here, with all the make_muts and modifying... Co-authored-by: Florian Diebold <[email protected]>
-rw-r--r--Cargo.lock10
-rw-r--r--crates/ra_hir/Cargo.toml1
-rw-r--r--crates/ra_hir/src/ty.rs453
-rw-r--r--crates/ra_hir/src/ty/tests.rs21
-rw-r--r--crates/ra_hir/src/ty/tests/data/0002_let.txt2
-rw-r--r--crates/ra_hir/src/ty/tests/data/0003_paths.txt8
-rw-r--r--crates/ra_hir/src/ty/tests/data/0004_struct.txt4
-rw-r--r--crates/ra_hir/src/ty/tests/data/0006_backwards.txt20
8 files changed, 400 insertions, 119 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d64c0bce0..fa3363bd2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -272,6 +272,14 @@ version = "1.5.0"
272source = "registry+https://github.com/rust-lang/crates.io-index" 272source = "registry+https://github.com/rust-lang/crates.io-index"
273 273
274[[package]] 274[[package]]
275name = "ena"
276version = "0.11.0"
277source = "registry+https://github.com/rust-lang/crates.io-index"
278dependencies = [
279 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
280]
281
282[[package]]
275name = "error-chain" 283name = "error-chain"
276version = "0.12.0" 284version = "0.12.0"
277source = "registry+https://github.com/rust-lang/crates.io-index" 285source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -737,6 +745,7 @@ name = "ra_hir"
737version = "0.1.0" 745version = "0.1.0"
738dependencies = [ 746dependencies = [
739 "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", 747 "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
748 "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
740 "flexi_logger 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", 749 "flexi_logger 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
741 "id-arena 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 750 "id-arena 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
742 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 751 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1546,6 +1555,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1546"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" 1555"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
1547"checksum drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f" 1556"checksum drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f"
1548"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" 1557"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
1558"checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00"
1549"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" 1559"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
1550"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" 1560"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7"
1551"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" 1561"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596"
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml
index 4ec890c73..c3fbd327d 100644
--- a/crates/ra_hir/Cargo.toml
+++ b/crates/ra_hir/Cargo.toml
@@ -12,6 +12,7 @@ salsa = "0.9.0"
12rustc-hash = "1.0" 12rustc-hash = "1.0"
13parking_lot = "0.7.0" 13parking_lot = "0.7.0"
14id-arena = "2.0" 14id-arena = "2.0"
15ena = "0.11"
15ra_syntax = { path = "../ra_syntax" } 16ra_syntax = { path = "../ra_syntax" }
16ra_editor = { path = "../ra_editor" } 17ra_editor = { path = "../ra_editor" }
17ra_db = { path = "../ra_db" } 18ra_db = { path = "../ra_db" }
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 38720b7b5..4ebd44d27 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -3,10 +3,11 @@ mod primitive;
3mod tests; 3mod tests;
4 4
5use std::sync::Arc; 5use std::sync::Arc;
6use std::fmt; 6use std::{fmt, mem};
7 7
8use log; 8use log;
9use rustc_hash::{FxHashMap}; 9use rustc_hash::FxHashMap;
10use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError};
10 11
11use ra_db::{LocalSyntaxPtr, Cancelable}; 12use ra_db::{LocalSyntaxPtr, Cancelable};
12use ra_syntax::{ 13use ra_syntax::{
@@ -17,10 +18,89 @@ use ra_syntax::{
17use crate::{ 18use crate::{
18 Def, DefId, FnScopes, Module, Function, Struct, Enum, Path, Name, AsName, 19 Def, DefId, FnScopes, Module, Function, Struct, Enum, Path, Name, AsName,
19 db::HirDatabase, 20 db::HirDatabase,
20 adt::VariantData,
21 type_ref::{TypeRef, Mutability}, 21 type_ref::{TypeRef, Mutability},
22}; 22};
23 23
24#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
25pub struct TypeVarId(u32);
26
27impl UnifyKey for TypeVarId {
28 type Value = TypeVarValue;
29
30 fn index(&self) -> u32 {
31 self.0
32 }
33
34 fn from_index(i: u32) -> Self {
35 TypeVarId(i)
36 }
37
38 fn tag() -> &'static str {
39 "TypeVarId"
40 }
41}
42
43#[derive(Clone, PartialEq, Eq, Debug)]
44pub enum TypeVarValue {
45 Known(Ty),
46 Unknown,
47}
48
49impl TypeVarValue {
50 pub fn known(&self) -> Option<&Ty> {
51 match self {
52 TypeVarValue::Known(ty) => Some(ty),
53 TypeVarValue::Unknown => None,
54 }
55 }
56}
57
58impl UnifyValue for TypeVarValue {
59 type Error = NoError;
60
61 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
62 match (value1, value2) {
63 // We should never equate two type variables, both of which have
64 // known types. Instead, we recursively equate those types.
65 (TypeVarValue::Known(..), TypeVarValue::Known(..)) => {
66 panic!("equating two type variables, both of which have known types")
67 }
68
69 // If one side is known, prefer that one.
70 (TypeVarValue::Known(..), TypeVarValue::Unknown) => Ok(value1.clone()),
71 (TypeVarValue::Unknown, TypeVarValue::Known(..)) => Ok(value2.clone()),
72
73 (TypeVarValue::Unknown, TypeVarValue::Unknown) => Ok(TypeVarValue::Unknown),
74 }
75 }
76}
77
78#[derive(Clone, PartialEq, Eq, Hash, Debug)]
79pub enum InferTy {
80 TypeVar(TypeVarId),
81 // later we'll have IntVar and FloatVar as well
82}
83
84/// When inferring an expression, we propagate downward whatever type hint we
85/// are able in the form of an `Expectation`.
86#[derive(Clone, PartialEq, Eq, Debug)]
87struct Expectation {
88 ty: Ty,
89 // TODO: In some cases, we need to be aware whether the expectation is that
90 // the type match exactly what we passed, or whether it just needs to be
91 // coercible to the expected type. See Expectation::rvalue_hint in rustc.
92}
93
94impl Expectation {
95 fn has_type(ty: Ty) -> Self {
96 Expectation { ty }
97 }
98
99 fn none() -> Self {
100 Expectation { ty: Ty::Unknown }
101 }
102}
103
24#[derive(Clone, PartialEq, Eq, Hash, Debug)] 104#[derive(Clone, PartialEq, Eq, Hash, Debug)]
25pub enum Ty { 105pub enum Ty {
26 /// The primitive boolean type. Written as `bool`. 106 /// The primitive boolean type. Written as `bool`.
@@ -75,23 +155,22 @@ pub enum Ty {
75 155
76 // A trait, defined with `dyn trait`. 156 // A trait, defined with `dyn trait`.
77 // Dynamic(), 157 // Dynamic(),
78 /// The anonymous type of a closure. Used to represent the type of 158 // The anonymous type of a closure. Used to represent the type of
79 /// `|a| a`. 159 // `|a| a`.
80 // Closure(DefId, ClosureSubsts<'tcx>), 160 // Closure(DefId, ClosureSubsts<'tcx>),
81 161
82 /// The anonymous type of a generator. Used to represent the type of 162 // The anonymous type of a generator. Used to represent the type of
83 /// `|a| yield a`. 163 // `|a| yield a`.
84 // Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability), 164 // Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
85 165
86 /// A type representin the types stored inside a generator. 166 // A type representin the types stored inside a generator.
87 /// This should only appear in GeneratorInteriors. 167 // This should only appear in GeneratorInteriors.
88 // GeneratorWitness(Binder<&'tcx List<Ty<'tcx>>>), 168 // GeneratorWitness(Binder<&'tcx List<Ty<'tcx>>>),
89
90 /// The never type `!` 169 /// The never type `!`
91 Never, 170 Never,
92 171
93 /// A tuple type. For example, `(i32, bool)`. 172 /// A tuple type. For example, `(i32, bool)`.
94 Tuple(Vec<Ty>), 173 Tuple(Arc<[Ty]>),
95 174
96 // The projection of an associated type. For example, 175 // The projection of an associated type. For example,
97 // `<T as Trait<..>>::N`.pub 176 // `<T as Trait<..>>::N`.pub
@@ -106,14 +185,14 @@ pub enum Ty {
106 185
107 // A type parameter; for example, `T` in `fn f<T>(x: T) {} 186 // A type parameter; for example, `T` in `fn f<T>(x: T) {}
108 // Param(ParamTy), 187 // Param(ParamTy),
109 188 /// A type variable used during type checking. Not to be confused with a
110 // A placeholder type - universally quantified higher-ranked type. 189 /// type parameter.
111 // Placeholder(ty::PlaceholderType), 190 Infer(InferTy),
112 191
113 // A type variable used during type checking. 192 /// A placeholder for a type which could not be computed; this is propagated
114 // Infer(InferTy), 193 /// to avoid useless error messages. Doubles as a placeholder where type
115 /// A placeholder for a type which could not be computed; this is 194 /// variables are inserted before type checking, since we want to try to
116 /// propagated to avoid useless error messages. 195 /// infer a better type here anyway.
117 Unknown, 196 Unknown,
118} 197}
119 198
@@ -137,8 +216,8 @@ impl Ty {
137 let inner_tys = inner 216 let inner_tys = inner
138 .iter() 217 .iter()
139 .map(|tr| Ty::from_hir(db, module, tr)) 218 .map(|tr| Ty::from_hir(db, module, tr))
140 .collect::<Cancelable<_>>()?; 219 .collect::<Cancelable<Vec<_>>>()?;
141 Ty::Tuple(inner_tys) 220 Ty::Tuple(inner_tys.into())
142 } 221 }
143 TypeRef::Path(path) => Ty::from_hir_path(db, module, path)?, 222 TypeRef::Path(path) => Ty::from_hir_path(db, module, path)?,
144 TypeRef::RawPtr(inner, mutability) => { 223 TypeRef::RawPtr(inner, mutability) => {
@@ -154,7 +233,7 @@ impl Ty {
154 let inner_ty = Ty::from_hir(db, module, inner)?; 233 let inner_ty = Ty::from_hir(db, module, inner)?;
155 Ty::Ref(Arc::new(inner_ty), *mutability) 234 Ty::Ref(Arc::new(inner_ty), *mutability)
156 } 235 }
157 TypeRef::Placeholder => Ty::Unknown, // TODO 236 TypeRef::Placeholder => Ty::Unknown,
158 TypeRef::Fn(params) => { 237 TypeRef::Fn(params) => {
159 let mut inner_tys = params 238 let mut inner_tys = params
160 .iter() 239 .iter()
@@ -217,7 +296,41 @@ impl Ty {
217 } 296 }
218 297
219 pub fn unit() -> Self { 298 pub fn unit() -> Self {
220 Ty::Tuple(Vec::new()) 299 Ty::Tuple(Arc::new([]))
300 }
301
302 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
303 f(self);
304 match self {
305 Ty::Slice(t) => Arc::make_mut(t).walk_mut(f),
306 Ty::RawPtr(t, _) => Arc::make_mut(t).walk_mut(f),
307 Ty::Ref(t, _) => Arc::make_mut(t).walk_mut(f),
308 Ty::Tuple(ts) => {
309 // Without an Arc::make_mut_slice, we can't avoid the clone here:
310 let mut v: Vec<_> = ts.iter().cloned().collect();
311 for t in &mut v {
312 t.walk_mut(f);
313 }
314 *ts = v.into();
315 }
316 Ty::FnPtr(sig) => {
317 let sig_mut = Arc::make_mut(sig);
318 for input in &mut sig_mut.input {
319 input.walk_mut(f);
320 }
321 sig_mut.output.walk_mut(f);
322 }
323 Ty::Adt { .. } => {} // need to walk type parameters later
324 _ => {}
325 }
326 }
327
328 fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Ty {
329 self.walk_mut(&mut |ty_mut| {
330 let ty = mem::replace(ty_mut, Ty::Unknown);
331 *ty_mut = f(ty);
332 });
333 self
221 } 334 }
222} 335}
223 336
@@ -236,7 +349,7 @@ impl fmt::Display for Ty {
236 Ty::Never => write!(f, "!"), 349 Ty::Never => write!(f, "!"),
237 Ty::Tuple(ts) => { 350 Ty::Tuple(ts) => {
238 write!(f, "(")?; 351 write!(f, "(")?;
239 for t in ts { 352 for t in ts.iter() {
240 write!(f, "{},", t)?; 353 write!(f, "{},", t)?;
241 } 354 }
242 write!(f, ")") 355 write!(f, ")")
@@ -250,6 +363,7 @@ impl fmt::Display for Ty {
250 } 363 }
251 Ty::Adt { name, .. } => write!(f, "{}", name), 364 Ty::Adt { name, .. } => write!(f, "{}", name),
252 Ty::Unknown => write!(f, "[unknown]"), 365 Ty::Unknown => write!(f, "[unknown]"),
366 Ty::Infer(..) => write!(f, "_"),
253 } 367 }
254 } 368 }
255} 369}
@@ -267,7 +381,11 @@ pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> {
267 .collect() 381 .collect()
268 }) 382 })
269 .unwrap_or_else(|| Ok(Vec::new()))?; 383 .unwrap_or_else(|| Ok(Vec::new()))?;
270 let output = Ty::from_ast_opt(db, &module, node.ret_type().and_then(|rt| rt.type_ref()))?; 384 let output = if let Some(type_ref) = node.ret_type().and_then(|rt| rt.type_ref()) {
385 Ty::from_ast(db, &module, type_ref)?
386 } else {
387 Ty::unit()
388 };
271 let sig = FnSig { input, output }; 389 let sig = FnSig { input, output };
272 Ok(Ty::FnPtr(Arc::new(sig))) 390 Ok(Ty::FnPtr(Arc::new(sig)))
273} 391}
@@ -342,7 +460,7 @@ pub struct InferenceContext<'a, D: HirDatabase> {
342 db: &'a D, 460 db: &'a D,
343 scopes: Arc<FnScopes>, 461 scopes: Arc<FnScopes>,
344 module: Module, 462 module: Module,
345 // TODO unification tables... 463 var_unification_table: InPlaceUnificationTable<TypeVarId>,
346 type_of: FxHashMap<LocalSyntaxPtr, Ty>, 464 type_of: FxHashMap<LocalSyntaxPtr, Ty>,
347} 465}
348 466
@@ -350,33 +468,116 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
350 fn new(db: &'a D, scopes: Arc<FnScopes>, module: Module) -> Self { 468 fn new(db: &'a D, scopes: Arc<FnScopes>, module: Module) -> Self {
351 InferenceContext { 469 InferenceContext {
352 type_of: FxHashMap::default(), 470 type_of: FxHashMap::default(),
471 var_unification_table: InPlaceUnificationTable::new(),
353 db, 472 db,
354 scopes, 473 scopes,
355 module, 474 module,
356 } 475 }
357 } 476 }
358 477
478 fn resolve_all(mut self) -> InferenceResult {
479 let mut types = mem::replace(&mut self.type_of, FxHashMap::default());
480 for ty in types.values_mut() {
481 let resolved = self.resolve_ty_completely(mem::replace(ty, Ty::Unknown));
482 *ty = resolved;
483 }
484 InferenceResult { type_of: types }
485 }
486
359 fn write_ty(&mut self, node: SyntaxNodeRef, ty: Ty) { 487 fn write_ty(&mut self, node: SyntaxNodeRef, ty: Ty) {
360 self.type_of.insert(LocalSyntaxPtr::new(node), ty); 488 self.type_of.insert(LocalSyntaxPtr::new(node), ty);
361 } 489 }
362 490
363 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> Option<Ty> { 491 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
364 if *ty1 == Ty::Unknown { 492 match (ty1, ty2) {
365 return Some(ty2.clone()); 493 (Ty::Unknown, ..) => true,
366 } 494 (.., Ty::Unknown) => true,
367 if *ty2 == Ty::Unknown { 495 (Ty::Bool, _)
368 return Some(ty1.clone()); 496 | (Ty::Str, _)
497 | (Ty::Never, _)
498 | (Ty::Char, _)
499 | (Ty::Int(..), Ty::Int(..))
500 | (Ty::Uint(..), Ty::Uint(..))
501 | (Ty::Float(..), Ty::Float(..)) => ty1 == ty2,
502 (
503 Ty::Adt {
504 def_id: def_id1, ..
505 },
506 Ty::Adt {
507 def_id: def_id2, ..
508 },
509 ) if def_id1 == def_id2 => true,
510 (Ty::Slice(t1), Ty::Slice(t2)) => self.unify(t1, t2),
511 (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => self.unify(t1, t2),
512 (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify(t1, t2),
513 (Ty::FnPtr(sig1), Ty::FnPtr(sig2)) if sig1 == sig2 => true,
514 (Ty::Tuple(ts1), Ty::Tuple(ts2)) if ts1.len() == ts2.len() => ts1
515 .iter()
516 .zip(ts2.iter())
517 .all(|(t1, t2)| self.unify(t1, t2)),
518 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) => {
519 self.var_unification_table.union(*tv1, *tv2);
520 true
521 }
522 (Ty::Infer(InferTy::TypeVar(tv)), other) | (other, Ty::Infer(InferTy::TypeVar(tv))) => {
523 self.var_unification_table
524 .union_value(*tv, TypeVarValue::Known(other.clone()));
525 true
526 }
527 _ => false,
369 } 528 }
370 if ty1 == ty2 { 529 }
371 return Some(ty1.clone()); 530
531 fn new_type_var(&mut self) -> Ty {
532 Ty::Infer(InferTy::TypeVar(
533 self.var_unification_table.new_key(TypeVarValue::Unknown),
534 ))
535 }
536
537 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it.
538 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
539 match ty {
540 Ty::Unknown => self.new_type_var(),
541 _ => ty,
372 } 542 }
373 // TODO implement actual unification
374 return None;
375 } 543 }
376 544
377 fn unify_with_coercion(&mut self, ty1: &Ty, ty2: &Ty) -> Option<Ty> { 545 fn insert_type_vars(&mut self, ty: Ty) -> Ty {
378 // TODO implement coercion 546 ty.fold(&mut |ty| self.insert_type_vars_shallow(ty))
379 self.unify(ty1, ty2) 547 }
548
549 /// Resolves the type as far as currently possible, replacing type variables
550 /// by their known types. All types returned by the infer_* functions should
551 /// be resolved as far as possible, i.e. contain no type variables with
552 /// known type.
553 fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty {
554 ty.fold(&mut |ty| match ty {
555 Ty::Infer(InferTy::TypeVar(tv)) => {
556 if let Some(known_ty) = self.var_unification_table.probe_value(tv).known() {
557 // known_ty may contain other variables that are known by now
558 self.resolve_ty_as_possible(known_ty.clone())
559 } else {
560 Ty::Infer(InferTy::TypeVar(tv))
561 }
562 }
563 _ => ty,
564 })
565 }
566
567 /// Resolves the type completely; type variables without known type are
568 /// replaced by Ty::Unknown.
569 fn resolve_ty_completely(&mut self, ty: Ty) -> Ty {
570 ty.fold(&mut |ty| match ty {
571 Ty::Infer(InferTy::TypeVar(tv)) => {
572 if let Some(known_ty) = self.var_unification_table.probe_value(tv).known() {
573 // known_ty may contain other variables that are known by now
574 self.resolve_ty_completely(known_ty.clone())
575 } else {
576 Ty::Unknown
577 }
578 }
579 _ => ty,
580 })
380 } 581 }
381 582
382 fn infer_path_expr(&mut self, expr: ast::PathExpr) -> Cancelable<Option<Ty>> { 583 fn infer_path_expr(&mut self, expr: ast::PathExpr) -> Cancelable<Option<Ty>> {
@@ -387,21 +588,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
387 let name = ctry!(ast_path.segment().and_then(|s| s.name_ref())); 588 let name = ctry!(ast_path.segment().and_then(|s| s.name_ref()));
388 if let Some(scope_entry) = self.scopes.resolve_local_name(name) { 589 if let Some(scope_entry) = self.scopes.resolve_local_name(name) {
389 let ty = ctry!(self.type_of.get(&scope_entry.ptr())); 590 let ty = ctry!(self.type_of.get(&scope_entry.ptr()));
390 return Ok(Some(ty.clone())); 591 let ty = self.resolve_ty_as_possible(ty.clone());
592 return Ok(Some(ty));
391 }; 593 };
392 }; 594 };
393 595
394 // resolve in module 596 // resolve in module
395 let resolved = ctry!(self.module.resolve_path(self.db, &path)?.take_values()); 597 let resolved = ctry!(self.module.resolve_path(self.db, &path)?.take_values());
396 let ty = self.db.type_for_def(resolved)?; 598 let ty = self.db.type_for_def(resolved)?;
397 // TODO we will need to add type variables for type parameters etc. here 599 let ty = self.insert_type_vars(ty);
398 Ok(Some(ty)) 600 Ok(Some(ty))
399 } 601 }
400 602
401 fn resolve_variant( 603 fn resolve_variant(&self, path: Option<ast::Path>) -> Cancelable<(Ty, Option<DefId>)> {
402 &self,
403 path: Option<ast::Path>,
404 ) -> Cancelable<(Ty, Option<Arc<VariantData>>)> {
405 let path = if let Some(path) = path.and_then(Path::from_ast) { 604 let path = if let Some(path) = path.and_then(Path::from_ast) {
406 path 605 path
407 } else { 606 } else {
@@ -414,102 +613,116 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
414 }; 613 };
415 Ok(match def_id.resolve(self.db)? { 614 Ok(match def_id.resolve(self.db)? {
416 Def::Struct(s) => { 615 Def::Struct(s) => {
417 let struct_data = self.db.struct_data(def_id)?;
418 let ty = type_for_struct(self.db, s)?; 616 let ty = type_for_struct(self.db, s)?;
419 (ty, Some(struct_data.variant_data().clone())) 617 (ty, Some(def_id))
420 } 618 }
421 _ => (Ty::Unknown, None), 619 _ => (Ty::Unknown, None),
422 }) 620 })
423 } 621 }
424 622
425 fn infer_expr_opt(&mut self, expr: Option<ast::Expr>) -> Cancelable<Ty> { 623 fn infer_expr_opt(
624 &mut self,
625 expr: Option<ast::Expr>,
626 expected: &Expectation,
627 ) -> Cancelable<Ty> {
426 if let Some(e) = expr { 628 if let Some(e) = expr {
427 self.infer_expr(e) 629 self.infer_expr(e, expected)
428 } else { 630 } else {
429 Ok(Ty::Unknown) 631 Ok(Ty::Unknown)
430 } 632 }
431 } 633 }
432 634
433 fn infer_expr(&mut self, expr: ast::Expr) -> Cancelable<Ty> { 635 fn infer_expr(&mut self, expr: ast::Expr, expected: &Expectation) -> Cancelable<Ty> {
434 let ty = match expr { 636 let ty = match expr {
435 ast::Expr::IfExpr(e) => { 637 ast::Expr::IfExpr(e) => {
436 if let Some(condition) = e.condition() { 638 if let Some(condition) = e.condition() {
437 // TODO if no pat, this should be bool 639 let expected = if condition.pat().is_none() {
438 self.infer_expr_opt(condition.expr())?; 640 Expectation::has_type(Ty::Bool)
641 } else {
642 Expectation::none()
643 };
644 self.infer_expr_opt(condition.expr(), &expected)?;
439 // TODO write type for pat 645 // TODO write type for pat
440 }; 646 };
441 let if_ty = self.infer_block_opt(e.then_branch())?; 647 let if_ty = self.infer_block_opt(e.then_branch(), expected)?;
442 let else_ty = self.infer_block_opt(e.else_branch())?; 648 if let Some(else_branch) = e.else_branch() {
443 if let Some(ty) = self.unify(&if_ty, &else_ty) { 649 self.infer_block(else_branch, expected)?;
444 ty
445 } else { 650 } else {
446 // TODO report diagnostic 651 // no else branch -> unit
447 Ty::Unknown 652 self.unify(&expected.ty, &Ty::unit()); // actually coerce
448 } 653 }
654 if_ty
449 } 655 }
450 ast::Expr::BlockExpr(e) => self.infer_block_opt(e.block())?, 656 ast::Expr::BlockExpr(e) => self.infer_block_opt(e.block(), expected)?,
451 ast::Expr::LoopExpr(e) => { 657 ast::Expr::LoopExpr(e) => {
452 self.infer_block_opt(e.loop_body())?; 658 self.infer_block_opt(e.loop_body(), &Expectation::has_type(Ty::unit()))?;
453 // TODO never, or the type of the break param 659 // TODO never, or the type of the break param
454 Ty::Unknown 660 Ty::Unknown
455 } 661 }
456 ast::Expr::WhileExpr(e) => { 662 ast::Expr::WhileExpr(e) => {
457 if let Some(condition) = e.condition() { 663 if let Some(condition) = e.condition() {
458 // TODO if no pat, this should be bool 664 let expected = if condition.pat().is_none() {
459 self.infer_expr_opt(condition.expr())?; 665 Expectation::has_type(Ty::Bool)
666 } else {
667 Expectation::none()
668 };
669 self.infer_expr_opt(condition.expr(), &expected)?;
460 // TODO write type for pat 670 // TODO write type for pat
461 }; 671 };
462 self.infer_block_opt(e.loop_body())?; 672 self.infer_block_opt(e.loop_body(), &Expectation::has_type(Ty::unit()))?;
463 // TODO always unit? 673 // TODO always unit?
464 Ty::Unknown 674 Ty::unit()
465 } 675 }
466 ast::Expr::ForExpr(e) => { 676 ast::Expr::ForExpr(e) => {
467 let _iterable_ty = self.infer_expr_opt(e.iterable()); 677 let _iterable_ty = self.infer_expr_opt(e.iterable(), &Expectation::none());
468 if let Some(_pat) = e.pat() { 678 if let Some(_pat) = e.pat() {
469 // TODO write type for pat 679 // TODO write type for pat
470 } 680 }
471 self.infer_block_opt(e.loop_body())?; 681 self.infer_block_opt(e.loop_body(), &Expectation::has_type(Ty::unit()))?;
472 // TODO always unit? 682 // TODO always unit?
473 Ty::Unknown 683 Ty::unit()
474 } 684 }
475 ast::Expr::LambdaExpr(e) => { 685 ast::Expr::LambdaExpr(e) => {
476 let _body_ty = self.infer_expr_opt(e.body())?; 686 let _body_ty = self.infer_expr_opt(e.body(), &Expectation::none())?;
477 Ty::Unknown 687 Ty::Unknown
478 } 688 }
479 ast::Expr::CallExpr(e) => { 689 ast::Expr::CallExpr(e) => {
480 let callee_ty = self.infer_expr_opt(e.expr())?; 690 let callee_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?;
481 if let Some(arg_list) = e.arg_list() { 691 let (arg_tys, ret_ty) = match &callee_ty {
482 for arg in arg_list.args() { 692 Ty::FnPtr(sig) => (&sig.input[..], sig.output.clone()),
483 // TODO unify / expect argument type
484 self.infer_expr(arg)?;
485 }
486 }
487 match callee_ty {
488 Ty::FnPtr(sig) => sig.output.clone(),
489 _ => { 693 _ => {
490 // not callable 694 // not callable
491 // TODO report an error? 695 // TODO report an error?
492 Ty::Unknown 696 (&[][..], Ty::Unknown)
697 }
698 };
699 if let Some(arg_list) = e.arg_list() {
700 for (i, arg) in arg_list.args().enumerate() {
701 self.infer_expr(
702 arg,
703 &Expectation::has_type(arg_tys.get(i).cloned().unwrap_or(Ty::Unknown)),
704 )?;
493 } 705 }
494 } 706 }
707 ret_ty
495 } 708 }
496 ast::Expr::MethodCallExpr(e) => { 709 ast::Expr::MethodCallExpr(e) => {
497 let _receiver_ty = self.infer_expr_opt(e.expr())?; 710 let _receiver_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?;
498 if let Some(arg_list) = e.arg_list() { 711 if let Some(arg_list) = e.arg_list() {
499 for arg in arg_list.args() { 712 for arg in arg_list.args() {
500 // TODO unify / expect argument type 713 // TODO unify / expect argument type
501 self.infer_expr(arg)?; 714 self.infer_expr(arg, &Expectation::none())?;
502 } 715 }
503 } 716 }
504 Ty::Unknown 717 Ty::Unknown
505 } 718 }
506 ast::Expr::MatchExpr(e) => { 719 ast::Expr::MatchExpr(e) => {
507 let _ty = self.infer_expr_opt(e.expr())?; 720 let _ty = self.infer_expr_opt(e.expr(), &Expectation::none())?;
508 if let Some(match_arm_list) = e.match_arm_list() { 721 if let Some(match_arm_list) = e.match_arm_list() {
509 for arm in match_arm_list.arms() { 722 for arm in match_arm_list.arms() {
510 // TODO type the bindings in pat 723 // TODO type the bindings in pat
511 // TODO type the guard 724 // TODO type the guard
512 let _ty = self.infer_expr_opt(arm.expr())?; 725 let _ty = self.infer_expr_opt(arm.expr(), &Expectation::none())?;
513 } 726 }
514 // TODO unify all the match arm types 727 // TODO unify all the match arm types
515 Ty::Unknown 728 Ty::Unknown
@@ -522,10 +735,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
522 ast::Expr::PathExpr(e) => self.infer_path_expr(e)?.unwrap_or(Ty::Unknown), 735 ast::Expr::PathExpr(e) => self.infer_path_expr(e)?.unwrap_or(Ty::Unknown),
523 ast::Expr::ContinueExpr(_e) => Ty::Never, 736 ast::Expr::ContinueExpr(_e) => Ty::Never,
524 ast::Expr::BreakExpr(_e) => Ty::Never, 737 ast::Expr::BreakExpr(_e) => Ty::Never,
525 ast::Expr::ParenExpr(e) => self.infer_expr_opt(e.expr())?, 738 ast::Expr::ParenExpr(e) => self.infer_expr_opt(e.expr(), expected)?,
526 ast::Expr::Label(_e) => Ty::Unknown, 739 ast::Expr::Label(_e) => Ty::Unknown,
527 ast::Expr::ReturnExpr(e) => { 740 ast::Expr::ReturnExpr(e) => {
528 self.infer_expr_opt(e.expr())?; 741 self.infer_expr_opt(e.expr(), &Expectation::none())?;
529 Ty::Never 742 Ty::Never
530 } 743 }
531 ast::Expr::MatchArmList(_) | ast::Expr::MatchArm(_) | ast::Expr::MatchGuard(_) => { 744 ast::Expr::MatchArmList(_) | ast::Expr::MatchArm(_) | ast::Expr::MatchGuard(_) => {
@@ -533,11 +746,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
533 Ty::Unknown 746 Ty::Unknown
534 } 747 }
535 ast::Expr::StructLit(e) => { 748 ast::Expr::StructLit(e) => {
536 let (ty, _variant_data) = self.resolve_variant(e.path())?; 749 let (ty, def_id) = self.resolve_variant(e.path())?;
537 if let Some(nfl) = e.named_field_list() { 750 if let Some(nfl) = e.named_field_list() {
538 for field in nfl.fields() { 751 for field in nfl.fields() {
539 // TODO unify with / expect field type 752 let field_ty = if let (Some(def_id), Some(nr)) = (def_id, field.name_ref())
540 self.infer_expr_opt(field.expr())?; 753 {
754 self.db.type_for_field(def_id, nr.as_name())?
755 } else {
756 Ty::Unknown
757 };
758 self.infer_expr_opt(field.expr(), &Expectation::has_type(field_ty))?;
541 } 759 }
542 } 760 }
543 ty 761 ty
@@ -548,9 +766,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
548 } 766 }
549 ast::Expr::IndexExpr(_e) => Ty::Unknown, 767 ast::Expr::IndexExpr(_e) => Ty::Unknown,
550 ast::Expr::FieldExpr(e) => { 768 ast::Expr::FieldExpr(e) => {
551 let receiver_ty = self.infer_expr_opt(e.expr())?; 769 let receiver_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?;
552 if let Some(nr) = e.name_ref() { 770 if let Some(nr) = e.name_ref() {
553 match receiver_ty { 771 let ty = match receiver_ty {
554 Ty::Tuple(fields) => { 772 Ty::Tuple(fields) => {
555 let i = nr.text().parse::<usize>().ok(); 773 let i = nr.text().parse::<usize>().ok();
556 i.and_then(|i| fields.get(i).cloned()) 774 i.and_then(|i| fields.get(i).cloned())
@@ -558,29 +776,32 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
558 } 776 }
559 Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, nr.as_name())?, 777 Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, nr.as_name())?,
560 _ => Ty::Unknown, 778 _ => Ty::Unknown,
561 } 779 };
780 self.insert_type_vars(ty)
562 } else { 781 } else {
563 Ty::Unknown 782 Ty::Unknown
564 } 783 }
565 } 784 }
566 ast::Expr::TryExpr(e) => { 785 ast::Expr::TryExpr(e) => {
567 let _inner_ty = self.infer_expr_opt(e.expr())?; 786 let _inner_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?;
568 Ty::Unknown 787 Ty::Unknown
569 } 788 }
570 ast::Expr::CastExpr(e) => { 789 ast::Expr::CastExpr(e) => {
571 let _inner_ty = self.infer_expr_opt(e.expr())?; 790 let _inner_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?;
572 let cast_ty = Ty::from_ast_opt(self.db, &self.module, e.type_ref())?; 791 let cast_ty = Ty::from_ast_opt(self.db, &self.module, e.type_ref())?;
792 let cast_ty = self.insert_type_vars(cast_ty);
573 // TODO do the coercion... 793 // TODO do the coercion...
574 cast_ty 794 cast_ty
575 } 795 }
576 ast::Expr::RefExpr(e) => { 796 ast::Expr::RefExpr(e) => {
577 let inner_ty = self.infer_expr_opt(e.expr())?; 797 // TODO pass the expectation down
798 let inner_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?;
578 let m = Mutability::from_mutable(e.is_mut()); 799 let m = Mutability::from_mutable(e.is_mut());
579 // TODO reference coercions etc. 800 // TODO reference coercions etc.
580 Ty::Ref(Arc::new(inner_ty), m) 801 Ty::Ref(Arc::new(inner_ty), m)
581 } 802 }
582 ast::Expr::PrefixExpr(e) => { 803 ast::Expr::PrefixExpr(e) => {
583 let inner_ty = self.infer_expr_opt(e.expr())?; 804 let inner_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?;
584 match e.op() { 805 match e.op() {
585 Some(PrefixOp::Deref) => { 806 Some(PrefixOp::Deref) => {
586 match inner_ty { 807 match inner_ty {
@@ -598,28 +819,34 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
598 ast::Expr::BinExpr(_e) => Ty::Unknown, 819 ast::Expr::BinExpr(_e) => Ty::Unknown,
599 ast::Expr::Literal(_e) => Ty::Unknown, 820 ast::Expr::Literal(_e) => Ty::Unknown,
600 }; 821 };
822 // use a new type variable if we got Ty::Unknown here
823 let ty = self.insert_type_vars_shallow(ty);
824 self.unify(&ty, &expected.ty);
601 self.write_ty(expr.syntax(), ty.clone()); 825 self.write_ty(expr.syntax(), ty.clone());
602 Ok(ty) 826 Ok(ty)
603 } 827 }
604 828
605 fn infer_block_opt(&mut self, node: Option<ast::Block>) -> Cancelable<Ty> { 829 fn infer_block_opt(
830 &mut self,
831 node: Option<ast::Block>,
832 expected: &Expectation,
833 ) -> Cancelable<Ty> {
606 if let Some(b) = node { 834 if let Some(b) = node {
607 self.infer_block(b) 835 self.infer_block(b, expected)
608 } else { 836 } else {
609 Ok(Ty::Unknown) 837 Ok(Ty::Unknown)
610 } 838 }
611 } 839 }
612 840
613 fn infer_block(&mut self, node: ast::Block) -> Cancelable<Ty> { 841 fn infer_block(&mut self, node: ast::Block, expected: &Expectation) -> Cancelable<Ty> {
614 for stmt in node.statements() { 842 for stmt in node.statements() {
615 match stmt { 843 match stmt {
616 ast::Stmt::LetStmt(stmt) => { 844 ast::Stmt::LetStmt(stmt) => {
617 let decl_ty = Ty::from_ast_opt(self.db, &self.module, stmt.type_ref())?; 845 let decl_ty = Ty::from_ast_opt(self.db, &self.module, stmt.type_ref())?;
846 let decl_ty = self.insert_type_vars(decl_ty);
618 let ty = if let Some(expr) = stmt.initializer() { 847 let ty = if let Some(expr) = stmt.initializer() {
619 // TODO pass expectation 848 let expr_ty = self.infer_expr(expr, &Expectation::has_type(decl_ty))?;
620 let expr_ty = self.infer_expr(expr)?; 849 expr_ty
621 self.unify_with_coercion(&expr_ty, &decl_ty)
622 .unwrap_or(decl_ty)
623 } else { 850 } else {
624 decl_ty 851 decl_ty
625 }; 852 };
@@ -629,12 +856,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
629 }; 856 };
630 } 857 }
631 ast::Stmt::ExprStmt(expr_stmt) => { 858 ast::Stmt::ExprStmt(expr_stmt) => {
632 self.infer_expr_opt(expr_stmt.expr())?; 859 self.infer_expr_opt(expr_stmt.expr(), &Expectation::none())?;
633 } 860 }
634 } 861 }
635 } 862 }
636 let ty = if let Some(expr) = node.expr() { 863 let ty = if let Some(expr) = node.expr() {
637 self.infer_expr(expr)? 864 self.infer_expr(expr, expected)?
638 } else { 865 } else {
639 Ty::unit() 866 Ty::unit()
640 }; 867 };
@@ -660,25 +887,27 @@ pub fn infer(db: &impl HirDatabase, function: Function) -> Cancelable<InferenceR
660 }; 887 };
661 if let Some(type_ref) = param.type_ref() { 888 if let Some(type_ref) = param.type_ref() {
662 let ty = Ty::from_ast(db, &ctx.module, type_ref)?; 889 let ty = Ty::from_ast(db, &ctx.module, type_ref)?;
890 let ty = ctx.insert_type_vars(ty);
663 ctx.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty); 891 ctx.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty);
664 } else { 892 } else {
665 // TODO self param 893 // TODO self param
894 let type_var = ctx.new_type_var();
666 ctx.type_of 895 ctx.type_of
667 .insert(LocalSyntaxPtr::new(pat.syntax()), Ty::Unknown); 896 .insert(LocalSyntaxPtr::new(pat.syntax()), type_var);
668 }; 897 };
669 } 898 }
670 } 899 }
671 900
672 // TODO get Ty for node.ret_type() and pass that to infer_block as expectation 901 let ret_ty = if let Some(type_ref) = node.ret_type().and_then(|n| n.type_ref()) {
673 // (see Expectation in rustc_typeck) 902 let ty = Ty::from_ast(db, &ctx.module, type_ref)?;
903 ctx.insert_type_vars(ty)
904 } else {
905 Ty::unit()
906 };
674 907
675 if let Some(block) = node.body() { 908 if let Some(block) = node.body() {
676 ctx.infer_block(block)?; 909 ctx.infer_block(block, &Expectation::has_type(ret_ty))?;
677 } 910 }
678 911
679 // TODO 'resolve' the types: replace inference variables by their inferred results 912 Ok(ctx.resolve_all())
680
681 Ok(InferenceResult {
682 type_of: ctx.type_of,
683 })
684} 913}
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index a76925b58..93bf431c4 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -113,6 +113,27 @@ fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) {
113 ); 113 );
114} 114}
115 115
116#[test]
117fn infer_backwards() {
118 check_inference(
119 r#"
120fn takes_u32(x: u32) {}
121
122struct S { i32_field: i32 }
123
124fn test() -> &mut &f64 {
125 let a = unknown_function();
126 takes_u32(a);
127 let b = unknown_function();
128 S { i32_field: b };
129 let c = unknown_function();
130 &mut &c
131}
132"#,
133 "0006_backwards.txt",
134 );
135}
136
116fn infer(content: &str) -> String { 137fn infer(content: &str) -> String {
117 let (db, _, file_id) = MockDatabase::with_single_file(content); 138 let (db, _, file_id) = MockDatabase::with_single_file(content);
118 let source_file = db.source_file(file_id); 139 let source_file = db.source_file(file_id);
diff --git a/crates/ra_hir/src/ty/tests/data/0002_let.txt b/crates/ra_hir/src/ty/tests/data/0002_let.txt
index 2d0d1f57b..916ca25a1 100644
--- a/crates/ra_hir/src/ty/tests/data/0002_let.txt
+++ b/crates/ra_hir/src/ty/tests/data/0002_let.txt
@@ -1,5 +1,5 @@
1[21; 22) 'a': [unknown] 1[21; 22) 'a': [unknown]
2[52; 53) '1': [unknown] 2[52; 53) '1': usize
3[11; 71) '{ ...= b; }': () 3[11; 71) '{ ...= b; }': ()
4[63; 64) 'c': usize 4[63; 64) 'c': usize
5[25; 31) '1isize': [unknown] 5[25; 31) '1isize': [unknown]
diff --git a/crates/ra_hir/src/ty/tests/data/0003_paths.txt b/crates/ra_hir/src/ty/tests/data/0003_paths.txt
index dcb5456ae..2a12d264f 100644
--- a/crates/ra_hir/src/ty/tests/data/0003_paths.txt
+++ b/crates/ra_hir/src/ty/tests/data/0003_paths.txt
@@ -1,7 +1,7 @@
1[15; 20) '{ 1 }': [unknown] 1[15; 20) '{ 1 }': u32
2[17; 18) '1': [unknown] 2[17; 18) '1': u32
3[50; 51) '1': [unknown] 3[50; 51) '1': u32
4[48; 53) '{ 1 }': [unknown] 4[48; 53) '{ 1 }': u32
5[82; 88) 'b::c()': u32 5[82; 88) 'b::c()': u32
6[67; 91) '{ ...c(); }': () 6[67; 91) '{ ...c(); }': ()
7[73; 74) 'a': fn() -> u32 7[73; 74) 'a': fn() -> u32
diff --git a/crates/ra_hir/src/ty/tests/data/0004_struct.txt b/crates/ra_hir/src/ty/tests/data/0004_struct.txt
index cc8f3665b..b4af18b87 100644
--- a/crates/ra_hir/src/ty/tests/data/0004_struct.txt
+++ b/crates/ra_hir/src/ty/tests/data/0004_struct.txt
@@ -1,5 +1,5 @@
1[86; 90) 'C(1)': [unknown] 1[86; 90) 'C(1)': [unknown]
2[121; 122) 'B': [unknown] 2[121; 122) 'B': B
3[86; 87) 'C': [unknown] 3[86; 87) 'C': [unknown]
4[129; 130) '1': [unknown] 4[129; 130) '1': [unknown]
5[107; 108) 'a': A 5[107; 108) 'a': A
@@ -13,4 +13,4 @@
13[96; 97) 'B': [unknown] 13[96; 97) 'B': [unknown]
14[88; 89) '1': [unknown] 14[88; 89) '1': [unknown]
15[82; 83) 'c': [unknown] 15[82; 83) 'c': [unknown]
16[127; 131) 'C(1)': [unknown] 16[127; 131) 'C(1)': C
diff --git a/crates/ra_hir/src/ty/tests/data/0006_backwards.txt b/crates/ra_hir/src/ty/tests/data/0006_backwards.txt
new file mode 100644
index 000000000..120069401
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/data/0006_backwards.txt
@@ -0,0 +1,20 @@
1[22; 24) '{}': ()
2[14; 15) 'x': u32
3[142; 158) 'unknow...nction': [unknown]
4[126; 127) 'a': u32
5[198; 216) 'unknow...tion()': f64
6[228; 229) 'c': f64
7[198; 214) 'unknow...nction': [unknown]
8[166; 184) 'S { i3...d: b }': S
9[222; 229) '&mut &c': &mut &f64
10[194; 195) 'c': f64
11[92; 110) 'unknow...tion()': u32
12[142; 160) 'unknow...tion()': i32
13[92; 108) 'unknow...nction': [unknown]
14[116; 128) 'takes_u32(a)': ()
15[78; 231) '{ ...t &c }': &mut &f64
16[227; 229) '&c': &f64
17[88; 89) 'a': u32
18[181; 182) 'b': i32
19[116; 125) 'takes_u32': fn(u32,) -> ()
20[138; 139) 'b': i32