]> git.lizzy.rs Git - rust.git/commitdiff
Move `GenericParams`'s handling of `impl Trait` into `GenericParams::generic_params_q...
authorGiacomo Stevanato <giaco.stevanato@gmail.com>
Tue, 21 Sep 2021 13:36:52 +0000 (15:36 +0200)
committerGiacomo Stevanato <giaco.stevanato@gmail.com>
Mon, 27 Sep 2021 14:59:25 +0000 (16:59 +0200)
crates/hir_def/src/generics.rs
crates/hir_def/src/item_tree.rs
crates/hir_def/src/item_tree/lower.rs
crates/hir_def/src/item_tree/pretty.rs

index 0921ecea6fcad288a441f5fb3439f38560aede78..8c5313fa458c9c478b16150e9b60378b9b45a128 100644 (file)
@@ -7,13 +7,15 @@
 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 @@
     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 @@ pub(crate) fn generic_params_query(
 
         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 @@ fn add_where_predicate_from_bound(
         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 @@ pub(crate) fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) {
                     });
                 }
             }
+            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);
+                    }
+                    _ => {}
+                }
+            }
         });
     }
 
index df46ceeaeedebbea4cefdfee01a9f14bea4ed817..3900e7e97cc8d45cfd864b859ebd5f76f700239d 100644 (file)
@@ -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>,
index 6d34556b3eafaa0f559575e897aa7c5e5d9db20c..9c278f5ac6b9203e4761bdf9fe263a036c639380 100644 (file)
@@ -401,7 +401,7 @@ fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>>
         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 @@ fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>>
             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 @@ fn lower_generic_params(
     ) -> 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 => {
index 3e33b0c46c2963126e3340322e15d6fd20cf9204..49dc1eef18b6ced74d990f6aa2aa71dd9e3ac096 100644 (file)
@@ -234,7 +234,7 @@ fn print_mod_item(&mut self, item: ModItem) {
                 let Function {
                     name,
                     visibility,
-                    generic_params,
+                    explicit_generic_params,
                     abi,
                     params,
                     ret_type,
@@ -250,7 +250,7 @@ fn print_mod_item(&mut self, item: ModItem) {
                     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 @@ fn print_mod_item(&mut self, item: ModItem) {
                 }
                 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) => {