aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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