From 0d49da5e1845a3f1c3aff5d65239b08d8315f529 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Tue, 21 Sep 2021 15:36:52 +0200 Subject: [PATCH] Move `GenericParams`'s handling of `impl Trait` into `GenericParams::generic_params_query` --- crates/hir_def/src/generics.rs | 50 +++++++++++++++++++++----- crates/hir_def/src/item_tree.rs | 2 +- crates/hir_def/src/item_tree/lower.rs | 17 +++------ crates/hir_def/src/item_tree/pretty.rs | 6 ++-- 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 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, + 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::(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, + pub explicit_generic_params: Interned, pub abi: Option>, pub params: IdRange, pub ret_type: Interned, 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 @@ fn lower_function(&mut self, func: &ast::Fn) -> Option> 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> 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 { 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 @@ 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) => {