From bed6869865ccfc6e72be26cb2041d83ab5cdbe3c Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Tue, 26 Nov 2019 22:56:07 +0300
Subject: [PATCH] Cleanup

---
 crates/ra_hir/src/code_model.rs               |  49 +++++++--
 crates/ra_hir/src/source_binder.rs            |   4 +-
 crates/ra_hir/src/ty/lower.rs                 |   2 +-
 crates/ra_hir/src/ty/method_resolution.rs     | 101 +++++++-----------
 crates/ra_hir_def/src/resolver.rs             |   4 +-
 .../src/completion/complete_path.rs           |   2 +-
 6 files changed, 85 insertions(+), 77 deletions(-)

diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index b4b47057de8..54da937eaae 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -28,7 +28,8 @@ use crate::{
     expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId},
     ty::display::HirFormatter,
     ty::{
-        self, InEnvironment, InferenceResult, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
+        self, InEnvironment, InferenceResult, TraitEnvironment, TraitRef, Ty, TyDefId, TypeCtor,
+        TypeWalk,
     },
     CallableDef, Either, HirDisplay, Name, Source,
 };
@@ -498,12 +499,9 @@ impl Adt {
         let subst = db.generic_defaults(self.into());
         subst.iter().any(|ty| ty == &Ty::Unknown)
     }
-    pub fn ty(self, db: &impl HirDatabase) -> Ty {
-        match self {
-            Adt::Struct(it) => it.ty(db),
-            Adt::Union(it) => it.ty(db),
-            Adt::Enum(it) => it.ty(db),
-        }
+    pub fn ty(self, db: &impl HirDatabase) -> Type {
+        let id = AdtId::from(self);
+        Type::from_def(db, id.module(db).krate, id)
     }
 
     pub fn module(self, db: &impl DefDatabase) -> Module {
@@ -795,8 +793,8 @@ impl TypeAlias {
         db.type_alias_data(self.id).type_ref.clone()
     }
 
-    pub fn ty(self, db: &impl HirDatabase) -> Ty {
-        db.ty(self.id.into())
+    pub fn ty(self, db: &impl HirDatabase) -> Type {
+        Type::from_def(db, self.id.lookup(db).module(db).krate, self.id)
     }
 
     pub fn name(self, db: &impl DefDatabase) -> Name {
@@ -989,6 +987,17 @@ pub struct Type {
 }
 
 impl Type {
+    fn from_def(
+        db: &impl HirDatabase,
+        krate: CrateId,
+        def: impl HasResolver + Into<TyDefId>,
+    ) -> Type {
+        let resolver = def.resolver(db);
+        let environment = TraitEnvironment::lower(db, &resolver);
+        let ty = db.ty(def.into());
+        Type { krate, ty: InEnvironment { value: ty, environment } }
+    }
+
     pub fn is_bool(&self) -> bool {
         match &self.ty.value {
             Ty::Apply(a_ty) => match a_ty.ctor {
@@ -1097,6 +1106,28 @@ impl Type {
             .map(move |ty| self.derived(ty))
     }
 
+    // This would be nicer if it just returned an iterator, but that runs into
+    // lifetime problems, because we need to borrow temp `CrateImplBlocks`.
+    pub fn iterate_impl_items<T>(
+        self,
+        db: &impl HirDatabase,
+        krate: Crate,
+        mut callback: impl FnMut(AssocItem) -> Option<T>,
+    ) -> Option<T> {
+        for krate in self.ty.value.def_crates(db, krate.crate_id)? {
+            let impls = db.impls_in_crate(krate);
+
+            for impl_block in impls.lookup_impl_blocks(&self.ty.value) {
+                for &item in db.impl_data(impl_block).items.iter() {
+                    if let Some(result) = callback(item.into()) {
+                        return Some(result);
+                    }
+                }
+            }
+        }
+        None
+    }
+
     // FIXME: remove
     pub fn into_ty(self) -> Ty {
         self.ty.value
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 7c4ebd4b4f9..9f3e6c43f21 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -389,14 +389,14 @@ impl SourceAnalyzer {
     pub fn iterate_path_candidates<T>(
         &self,
         db: &impl HirDatabase,
-        ty: Ty,
+        ty: &Type,
         name: Option<&Name>,
         callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
     ) -> Option<T> {
         // There should be no inference vars in types passed here
         // FIXME check that?
         // FIXME replace Unknown by bound vars here
-        let canonical = crate::ty::Canonical { value: ty, num_vars: 0 };
+        let canonical = crate::ty::Canonical { value: ty.ty.value.clone(), num_vars: 0 };
         method_resolution::iterate_method_candidates(
             &canonical,
             db,
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 709492d2176..1c0f71adc2c 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -189,7 +189,7 @@ impl Ty {
                 Ty::Param { idx, name }
             }
             TypeNs::SelfType(impl_block) => ImplBlock::from(impl_block).target_ty(db),
-            TypeNs::AdtSelfType(adt) => Adt::from(adt).ty(db),
+            TypeNs::AdtSelfType(adt) => db.ty(adt.into()),
 
             TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()),
             TypeNs::BuiltinType(it) => {
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index fdc87a28d08..92645e2a523 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -97,14 +97,15 @@ impl CrateImplBlocks {
     }
 }
 
-fn def_crates(
-    db: &impl HirDatabase,
-    cur_crate: CrateId,
-    ty: &Ty,
-) -> Option<ArrayVec<[CrateId; 2]>> {
-    // Types like slice can have inherent impls in several crates, (core and alloc).
-    // The corresponding impls are marked with lang items, so we can use them to find the required crates.
-    macro_rules! lang_item_crate {
+impl Ty {
+    pub(crate) fn def_crates(
+        &self,
+        db: &impl HirDatabase,
+        cur_crate: CrateId,
+    ) -> Option<ArrayVec<[CrateId; 2]>> {
+        // Types like slice can have inherent impls in several crates, (core and alloc).
+        // The corresponding impls are marked with lang items, so we can use them to find the required crates.
+        macro_rules! lang_item_crate {
         ($($name:expr),+ $(,)?) => {{
             let mut v = ArrayVec::<[LangItemTarget; 2]>::new();
             $(
@@ -114,38 +115,38 @@ fn def_crates(
         }};
     }
 
-    let lang_item_targets = match ty {
-        Ty::Apply(a_ty) => match a_ty.ctor {
-            TypeCtor::Adt(def_id) => {
-                return Some(std::iter::once(def_id.module(db).krate).collect())
-            }
-            TypeCtor::Bool => lang_item_crate!("bool"),
-            TypeCtor::Char => lang_item_crate!("char"),
-            TypeCtor::Float(Uncertain::Known(f)) => match f.bitness {
-                // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
-                FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"),
-                FloatBitness::X64 => lang_item_crate!("f64", "f64_runtime"),
+        let lang_item_targets = match self {
+            Ty::Apply(a_ty) => match a_ty.ctor {
+                TypeCtor::Adt(def_id) => {
+                    return Some(std::iter::once(def_id.module(db).krate).collect())
+                }
+                TypeCtor::Bool => lang_item_crate!("bool"),
+                TypeCtor::Char => lang_item_crate!("char"),
+                TypeCtor::Float(Uncertain::Known(f)) => match f.bitness {
+                    // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
+                    FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"),
+                    FloatBitness::X64 => lang_item_crate!("f64", "f64_runtime"),
+                },
+                TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(i.ty_to_string()),
+                TypeCtor::Str => lang_item_crate!("str_alloc", "str"),
+                TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"),
+                TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"),
+                TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"),
+                _ => return None,
             },
-            TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(i.ty_to_string()),
-            TypeCtor::Str => lang_item_crate!("str_alloc", "str"),
-            TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"),
-            TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"),
-            TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"),
             _ => return None,
-        },
-        _ => return None,
-    };
-    let res = lang_item_targets
-        .into_iter()
-        .filter_map(|it| match it {
-            LangItemTarget::ImplBlockId(it) => Some(it),
-            _ => None,
-        })
-        .map(|it| it.module(db).krate)
-        .collect();
-    Some(res)
+        };
+        let res = lang_item_targets
+            .into_iter()
+            .filter_map(|it| match it {
+                LangItemTarget::ImplBlockId(it) => Some(it),
+                _ => None,
+            })
+            .map(|it| it.module(db).krate)
+            .collect();
+        Some(res)
+    }
 }
-
 /// Look up the method with the given name, returning the actual autoderefed
 /// receiver type (but without autoref applied yet).
 pub(crate) fn lookup_method(
@@ -286,7 +287,7 @@ fn iterate_inherent_methods<T>(
     krate: CrateId,
     mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
 ) -> Option<T> {
-    for krate in def_crates(db, krate, &ty.value)? {
+    for krate in ty.value.def_crates(db, krate)? {
         let impls = db.impls_in_crate(krate);
 
         for impl_block in impls.lookup_impl_blocks(&ty.value) {
@@ -342,30 +343,6 @@ pub(crate) fn implements_trait(
     solution.is_some()
 }
 
-impl Ty {
-    // This would be nicer if it just returned an iterator, but that runs into
-    // lifetime problems, because we need to borrow temp `CrateImplBlocks`.
-    pub fn iterate_impl_items<T>(
-        self,
-        db: &impl HirDatabase,
-        krate: CrateId,
-        mut callback: impl FnMut(AssocItem) -> Option<T>,
-    ) -> Option<T> {
-        for krate in def_crates(db, krate, &self)? {
-            let impls = db.impls_in_crate(krate);
-
-            for impl_block in impls.lookup_impl_blocks(&self) {
-                for &item in db.impl_data(impl_block).items.iter() {
-                    if let Some(result) = callback(item.into()) {
-                        return Some(result);
-                    }
-                }
-            }
-        }
-        None
-    }
-}
-
 /// This creates Substs for a trait with the given Self type and type variables
 /// for all other parameters, to query Chalk with it.
 fn generic_implements_goal(
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index c40f41717b0..5155365ccbb 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -484,7 +484,7 @@ impl Resolver {
     }
 }
 
-pub trait HasResolver {
+pub trait HasResolver: Copy {
     /// Builds a resolver for type references inside this def.
     fn resolver(self, db: &impl DefDatabase) -> Resolver;
 }
@@ -502,7 +502,7 @@ impl HasResolver for TraitId {
     }
 }
 
-impl<T: Into<AdtId>> HasResolver for T {
+impl<T: Into<AdtId> + Copy> HasResolver for T {
     fn resolver(self, db: &impl DefDatabase) -> Resolver {
         let def = self.into();
         def.module(db)
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index 63e25e0bf10..89e0009a17a 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -50,7 +50,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
                 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
                 _ => unreachable!(),
             };
-            ctx.analyzer.iterate_path_candidates(ctx.db, ty.clone(), None, |_ty, item| {
+            ctx.analyzer.iterate_path_candidates(ctx.db, &ty, None, |_ty, item| {
                 match item {
                     hir::AssocItem::Function(func) => {
                         if !func.has_self_param(ctx.db) {