diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 00ae3595360..3c9c02d03ed 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -587,7 +587,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                 self.write_method_resolution(tgt_expr, func);
                 (ty, self.db.value_ty(func.into()), Some(generics(self.db, func.into())))
             }
-            // TODO fix this
             None => (receiver_ty, Binders::new(0, Ty::Unknown), None),
         };
         let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty);
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 68c2f0b061a..c5fe18c8550 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -287,17 +287,20 @@ pub enum Ty {
     /// trait and all its parameters are fully known.
     Projection(ProjectionTy),
 
-    /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
-    // TODO fix documentation
+    /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T)
+    /// {}` when we're type-checking the body of that function. In this
+    /// situation, we know this stands for *some* type, but don't know the exact
+    /// type.
     Param(TypeParamId),
 
-    /// A bound type variable. Used during trait resolution to represent Chalk
-    /// variables, and in `Dyn` and `Opaque` bounds to represent the `Self` type.
-    // TODO fix documentation
+    /// A bound type variable. This is used in various places: when representing
+    /// some polymorphic type like the type of function `fn f<T>`, the type
+    /// parameters get turned into variables; during trait resolution, inference
+    /// variables get turned into bound variables and back; and in `Dyn` the
+    /// `Self` type is represented with a bound variable as well.
     Bound(u32),
 
-    /// A type variable used during type checking. Not to be confused with a
-    /// type parameter.
+    /// A type variable used during type checking.
     Infer(InferTy),
 
     /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust).
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index d2df3fe2b54..c68c5852be7 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -890,9 +890,13 @@ pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Binders<Ty> {
     }
 }
 
-pub(crate) fn ty_recover(_db: &impl HirDatabase, _cycle: &[String], _def: &TyDefId) -> Binders<Ty> {
-    // TODO still need correct number of binders here
-    Binders::new(0, Ty::Unknown)
+pub(crate) fn ty_recover(db: &impl HirDatabase, _cycle: &[String], def: &TyDefId) -> Binders<Ty> {
+    let num_binders = match *def {
+        TyDefId::BuiltinType(_) => 0,
+        TyDefId::AdtId(it) => generics(db, it.into()).len(),
+        TyDefId::TypeAliasId(it) => generics(db, it.into()).len(),
+    };
+    Binders::new(num_binders, Ty::Unknown)
 }
 
 pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Binders<Ty> {