From 12ec946216a3637685f30ae359bc955313595a22 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Wed, 20 Nov 2019 20:50:34 +0300
Subject: [PATCH] Simplify generic params

---
 crates/ra_hir/src/code_model.rs   | 23 +++++-------------
 crates/ra_hir/src/impl_block.rs   |  8 +++----
 crates/ra_hir/src/resolve.rs      | 39 +++++++++++++++++++------------
 crates/ra_hir_def/src/generics.rs |  3 +--
 4 files changed, 34 insertions(+), 39 deletions(-)

diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 920899dceb4..e2638cf92f9 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -322,9 +322,7 @@ impl Struct {
         // take the outer scope...
         let r = self.module(db).resolver(db);
         // ...and add generic params, if present
-        let p = self.generic_params(db);
-        let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
-        r
+        r.push_generic_params_scope(db, self.into())
     }
 }
 
@@ -352,9 +350,7 @@ impl Union {
         // take the outer scope...
         let r = self.module(db).resolver(db);
         // ...and add generic params, if present
-        let p = self.generic_params(db);
-        let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
-        r
+        r.push_generic_params_scope(db, self.into())
     }
 }
 
@@ -402,8 +398,7 @@ impl Enum {
         // take the outer scope...
         let r = self.module(db).resolver(db);
         // ...and add generic params, if present
-        let p = self.generic_params(db);
-        let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
+        let r = r.push_generic_params_scope(db, self.into());
         r.push_scope(Scope::AdtScope(self.into()))
     }
 }
@@ -709,9 +704,7 @@ impl Function {
         // take the outer scope...
         let r = self.container(db).map_or_else(|| self.module(db).resolver(db), |c| c.resolver(db));
         // ...and add generic params, if present
-        let p = self.generic_params(db);
-        let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
-        r
+        r.push_generic_params_scope(db, self.into())
     }
 
     pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) {
@@ -946,9 +939,7 @@ impl Trait {
     pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver {
         let r = self.module(db).resolver(db);
         // add generic params, if present
-        let p = self.generic_params(db);
-        let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
-        r
+        r.push_generic_params_scope(db, self.into())
     }
 }
 
@@ -1010,9 +1001,7 @@ impl TypeAlias {
             .map(|ib| ib.resolver(db))
             .unwrap_or_else(|| self.module(db).resolver(db));
         // ...and add generic params, if present
-        let p = self.generic_params(db);
-        let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
-        r
+        r.push_generic_params_scope(db, self.into())
     }
 }
 
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 0513f28a961..492d964a43c 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -5,7 +5,6 @@ use ra_syntax::ast::{self};
 
 use crate::{
     db::{AstDatabase, DefDatabase, HirDatabase},
-    generics::HasGenericParams,
     resolve::Resolver,
     ty::Ty,
     AssocItem, Crate, HasSource, ImplBlock, Module, Source, TraitRef,
@@ -52,12 +51,11 @@ impl ImplBlock {
         Crate { crate_id: self.module(db).id.krate }
     }
 
-    pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
+    pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver {
         let r = self.module(db).resolver(db);
         // add generic params, if present
-        let p = self.generic_params(db);
-        let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
-        let r = r.push_impl_block_scope(self.clone());
+        let r = r.push_generic_params_scope(db, self.into());
+        let r = r.push_impl_block_scope(self);
         r
     }
 }
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index a2fa0bb79e1..e5e768be90e 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -14,9 +14,9 @@ use crate::{
     code_model::Crate,
     db::{DefDatabase, HirDatabase},
     expr::{ExprScopes, PatId, ScopeId},
-    generics::GenericParams,
-    Adt, Const, DefWithBody, Enum, EnumVariant, Function, ImplBlock, Local, MacroDef, ModuleDef,
-    PerNs, Static, Struct, Trait, TypeAlias,
+    generics::{GenericParams, HasGenericParams},
+    Adt, Const, DefWithBody, Enum, EnumVariant, Function, GenericDef, ImplBlock, Local, MacroDef,
+    ModuleDef, PerNs, Static, Struct, Trait, TypeAlias,
 };
 
 #[derive(Debug, Clone, Default)]
@@ -43,7 +43,7 @@ pub(crate) enum Scope {
     /// All the items and imported names of a module
     ModuleScope(ModuleItemMap),
     /// Brings the generic parameters of an item into scope
-    GenericParams(Arc<GenericParams>),
+    GenericParams { def: GenericDef, params: Arc<GenericParams> },
     /// Brings `Self` in `impl` block into scope
     ImplBlockScope(ImplBlock),
     /// Brings `Self` in enum, struct and union definitions into scope
@@ -141,9 +141,9 @@ impl Resolver {
         for scope in self.scopes.iter().rev() {
             match scope {
                 Scope::ExprScope(_) => continue,
-                Scope::GenericParams(_) | Scope::ImplBlockScope(_) if skip_to_mod => continue,
+                Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue,
 
-                Scope::GenericParams(params) => {
+                Scope::GenericParams { params, .. } => {
                     if let Some(param) = params.find_by_name(first_name) {
                         let idx = if path.segments.len() == 1 { None } else { Some(1) };
                         return Some((TypeNs::GenericParam(param.idx), idx));
@@ -212,7 +212,7 @@ impl Resolver {
             match scope {
                 Scope::AdtScope(_)
                 | Scope::ExprScope(_)
-                | Scope::GenericParams(_)
+                | Scope::GenericParams { .. }
                 | Scope::ImplBlockScope(_)
                     if skip_to_mod =>
                 {
@@ -232,13 +232,13 @@ impl Resolver {
                 }
                 Scope::ExprScope(_) => continue,
 
-                Scope::GenericParams(params) if n_segments > 1 => {
+                Scope::GenericParams { params, .. } if n_segments > 1 => {
                     if let Some(param) = params.find_by_name(first_name) {
                         let ty = TypeNs::GenericParam(param.idx);
                         return Some(ResolveValueResult::Partial(ty, 1));
                     }
                 }
-                Scope::GenericParams(_) => continue,
+                Scope::GenericParams { .. } => continue,
 
                 Scope::ImplBlockScope(impl_) if n_segments > 1 => {
                     if first_name == &name::SELF_TYPE {
@@ -361,7 +361,7 @@ impl Resolver {
         self.scopes
             .iter()
             .filter_map(|scope| match scope {
-                Scope::GenericParams(params) => Some(params),
+                Scope::GenericParams { params, .. } => Some(params),
                 _ => None,
             })
             .flat_map(|params| params.where_predicates.iter())
@@ -369,7 +369,7 @@ impl Resolver {
 
     pub(crate) fn generic_def(&self) -> Option<crate::generics::GenericDef> {
         self.scopes.iter().find_map(|scope| match scope {
-            Scope::GenericParams(params) => Some(params.def.into()),
+            Scope::GenericParams { def, .. } => Some(*def),
             _ => None,
         })
     }
@@ -381,8 +381,17 @@ impl Resolver {
         self
     }
 
-    pub(crate) fn push_generic_params_scope(self, params: Arc<GenericParams>) -> Resolver {
-        self.push_scope(Scope::GenericParams(params))
+    pub(crate) fn push_generic_params_scope(
+        self,
+        db: &impl DefDatabase,
+        def: GenericDef,
+    ) -> Resolver {
+        let params = def.generic_params(db);
+        if params.params.is_empty() {
+            self
+        } else {
+            self.push_scope(Scope::GenericParams { def, params })
+        }
     }
 
     pub(crate) fn push_impl_block_scope(self, impl_block: ImplBlock) -> Resolver {
@@ -457,8 +466,8 @@ impl Scope {
                     });
                 }
             }
-            Scope::GenericParams(gp) => {
-                for param in &gp.params {
+            Scope::GenericParams { params, .. } => {
+                for param in params.params.iter() {
                     f(param.name.clone(), ScopeDef::GenericParam(param.idx))
                 }
             }
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index f794eefbcdc..9e2e4c3cc31 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -25,7 +25,6 @@ pub struct GenericParam {
 /// Data about the generic parameters of a function, struct, impl, etc.
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct GenericParams {
-    pub def: GenericDefId,
     pub parent_params: Option<Arc<GenericParams>>,
     pub params: Vec<GenericParam>,
     pub where_predicates: Vec<WherePredicate>,
@@ -56,7 +55,7 @@ impl GenericParams {
         parent_params: Option<Arc<GenericParams>>,
     ) -> GenericParams {
         let mut generics =
-            GenericParams { def, params: Vec::new(), parent_params, where_predicates: Vec::new() };
+            GenericParams { params: Vec::new(), parent_params, where_predicates: Vec::new() };
         let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
         // FIXME: add `: Sized` bound for everything except for `Self` in traits
         match def {