about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGiacomo Stevanato <giaco.stevanato@gmail.com>2021-09-21 15:36:52 +0200
committerGiacomo Stevanato <giaco.stevanato@gmail.com>2021-09-27 16:59:25 +0200
commit0d49da5e1845a3f1c3aff5d65239b08d8315f529 (patch)
tree41b8c21bc31c398b5dbe91758f1b9bb179cb1253
parent5347c3ab5989a968b8e942104bdb3b55fb7e7d6f (diff)
downloadrust-0d49da5e1845a3f1c3aff5d65239b08d8315f529.tar.gz
rust-0d49da5e1845a3f1c3aff5d65239b08d8315f529.zip
Move `GenericParams`'s handling of `impl Trait` into `GenericParams::generic_params_query`
-rw-r--r--crates/hir_def/src/generics.rs50
-rw-r--r--crates/hir_def/src/item_tree.rs2
-rw-r--r--crates/hir_def/src/item_tree/lower.rs17
-rw-r--r--crates/hir_def/src/item_tree/pretty.rs6
4 files changed, 50 insertions, 25 deletions
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index 0921ecea6fc..8c5313fa458 100644
--- a/crates/hir_def/src/generics.rs
+++ b/crates/hir_def/src/generics.rs
@@ -7,13 +7,15 @@ use base_db::FileId;
 use either::Either;
 use hir_expand::{
     name::{AsName, Name},
-    HirFileId, InFile,
+    ExpandResult, HirFileId, InFile,
 };
 use la_arena::{Arena, ArenaMap};
+use once_cell::unsync::Lazy;
+use std::ops::DerefMut;
 use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds};
 
 use crate::{
-    body::LowerCtx,
+    body::{Expander, LowerCtx},
     child_by_source::ChildBySource,
     db::DefDatabase,
     dyn_map::DynMap,
@@ -21,8 +23,8 @@ use crate::{
     keys,
     src::{HasChildSource, HasSource},
     type_ref::{LifetimeRef, TypeBound, TypeRef},
-    AdtId, ConstParamId, GenericDefId, LifetimeParamId, LocalConstParamId, LocalLifetimeParamId,
-    LocalTypeParamId, Lookup, TypeParamId,
+    AdtId, ConstParamId, GenericDefId, HasModule, LifetimeParamId, LocalConstParamId,
+    LocalLifetimeParamId, LocalTypeParamId, Lookup, TypeParamId,
 };
 
 /// Data about a generic type parameter (to a function, struct, impl, ...).
@@ -99,10 +101,23 @@ impl GenericParams {
 
         match def {
             GenericDefId::FunctionId(id) => {
-                let id = id.lookup(db).id;
-                let tree = id.item_tree(db);
-                let item = &tree[id.value];
-                item.generic_params.clone()
+                let loc = id.lookup(db);
+                let tree = loc.id.item_tree(db);
+                let item = &tree[loc.id.value];
+
+                let mut generic_params = GenericParams::clone(&item.explicit_generic_params);
+
+                let module = loc.container.module(db);
+                let func_data = db.function_data(id);
+
+                // Don't create an `Expander` nor call `loc.source(db)` if not needed since this
+                // causes a reparse after the `ItemTree` has been created.
+                let mut expander = Lazy::new(|| Expander::new(db, loc.source(db).file_id, module));
+                for param in &func_data.params {
+                    generic_params.fill_implicit_impl_trait_args(db, &mut expander, param);
+                }
+
+                Interned::new(generic_params)
             }
             GenericDefId::AdtId(AdtId::StructId(id)) => {
                 let id = id.lookup(db).id;
@@ -259,7 +274,12 @@ impl GenericParams {
         self.where_predicates.push(predicate);
     }
 
-    pub(crate) fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) {
+    pub(crate) fn fill_implicit_impl_trait_args(
+        &mut self,
+        db: &dyn DefDatabase,
+        expander: &mut impl DerefMut<Target = Expander>,
+        type_ref: &TypeRef,
+    ) {
         type_ref.walk(&mut |type_ref| {
             if let TypeRef::ImplTrait(bounds) = type_ref {
                 let param = TypeParamData {
@@ -275,6 +295,18 @@ impl GenericParams {
                     });
                 }
             }
+            if let TypeRef::Macro(mc) = type_ref {
+                let macro_call = mc.to_node(db.upcast());
+                match expander.enter_expand::<ast::Type>(db, macro_call) {
+                    Ok(ExpandResult { value: Some((mark, expanded)), .. }) => {
+                        let ctx = LowerCtx::new(db, mc.file_id);
+                        let type_ref = TypeRef::from_ast(&ctx, expanded);
+                        self.fill_implicit_impl_trait_args(db, expander, &type_ref);
+                        expander.exit(db, mark);
+                    }
+                    _ => {}
+                }
+            }
         });
     }
 
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index df46ceeaeed..3900e7e97cc 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -605,7 +605,7 @@ pub struct ExternBlock {
 pub struct Function {
     pub name: Name,
     pub visibility: RawVisibilityId,
-    pub generic_params: Interned<GenericParams>,
+    pub explicit_generic_params: Interned<GenericParams>,
     pub abi: Option<Interned<str>>,
     pub params: IdRange<Param>,
     pub ret_type: Interned<TypeRef>,
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 6d34556b3ea..9c278f5ac6b 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -401,7 +401,7 @@ impl<'a> Ctx<'a> {
         let mut res = Function {
             name,
             visibility,
-            generic_params: Interned::new(GenericParams::default()),
+            explicit_generic_params: Interned::new(GenericParams::default()),
             abi,
             params,
             ret_type: Interned::new(ret_type),
@@ -409,7 +409,8 @@ impl<'a> Ctx<'a> {
             ast_id,
             flags,
         };
-        res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func);
+        res.explicit_generic_params =
+            self.lower_generic_params(GenericsOwner::Function(&res), func);
 
         Some(id(self.data().functions.alloc(res)))
     }
@@ -664,16 +665,8 @@ impl<'a> Ctx<'a> {
     ) -> Interned<GenericParams> {
         let mut generics = GenericParams::default();
         match owner {
-            GenericsOwner::Function(func) => {
-                generics.fill(&self.body_ctx, node);
-                // lower `impl Trait` in arguments
-                for id in func.params.clone() {
-                    if let Param::Normal(ty) = &self.data().params[id] {
-                        generics.fill_implicit_impl_trait_args(ty);
-                    }
-                }
-            }
-            GenericsOwner::Struct
+            GenericsOwner::Function(_)
+            | GenericsOwner::Struct
             | GenericsOwner::Enum
             | GenericsOwner::Union
             | GenericsOwner::TypeAlias => {
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs
index 3e33b0c46c2..49dc1eef18b 100644
--- a/crates/hir_def/src/item_tree/pretty.rs
+++ b/crates/hir_def/src/item_tree/pretty.rs
@@ -234,7 +234,7 @@ impl<'a> Printer<'a> {
                 let Function {
                     name,
                     visibility,
-                    generic_params,
+                    explicit_generic_params,
                     abi,
                     params,
                     ret_type,
@@ -250,7 +250,7 @@ impl<'a> Printer<'a> {
                     w!(self, "extern \"{}\" ", abi);
                 }
                 w!(self, "fn {}", name);
-                self.print_generic_params(generic_params);
+                self.print_generic_params(explicit_generic_params);
                 w!(self, "(");
                 if !params.is_empty() {
                     self.indented(|this| {
@@ -271,7 +271,7 @@ impl<'a> Printer<'a> {
                 }
                 w!(self, ") -> ");
                 self.print_type_ref(ret_type);
-                self.print_where_clause(generic_params);
+                self.print_where_clause(explicit_generic_params);
                 wln!(self, ";");
             }
             ModItem::Struct(it) => {