Unnamed repository; edit this file 'description' to name the repository.
Merge #10305
10305: Move `GenericParams`'s handling of `impl Trait` into `fn_data_query` r=flodiebold a=SkiFire13 Fixes #10286 Co-authored-by: Giacomo Stevanato <[email protected]>
bors[bot] 2021-09-28
parent dd21ad6 · parent 49ba313 · commit c6d9565
-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
-rw-r--r--crates/hir_def/src/item_tree/tests.rs5
-rw-r--r--crates/hir_ty/src/tests/regression.rs21
6 files changed, 73 insertions, 28 deletions
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index 0921ecea6f..8c5313fa45 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 df46ceeaee..3900e7e97c 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 6d34556b3e..9c278f5ac6 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 3e33b0c46c..49dc1eef18 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) => {
diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs
index a153e17b17..7671ccefd1 100644
--- a/crates/hir_def/src/item_tree/tests.rs
+++ b/crates/hir_def/src/item_tree/tests.rs
@@ -340,12 +340,11 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
T: 'b
{
// flags = 0x2
- pub(self) fn f<G, _anon_1>(
+ pub(self) fn f<G>(
_: impl Copy,
) -> impl Copy
where
- G: 'a,
- _anon_1: Copy;
+ G: 'a;
}
pub(self) enum Enum<'a, T, const U: u8> {
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index 618499fdc1..2f38d584a1 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -1177,3 +1177,24 @@ fn multiexp_inner() {
"#,
);
}
+
+#[test]
+fn macro_expands_to_impl_trait() {
+ check_no_mismatches(
+ r#"
+trait Foo {}
+
+macro_rules! ty {
+ () => {
+ impl Foo
+ }
+}
+
+fn foo(_: ty!()) {}
+
+fn bar() {
+ foo(());
+}
+ "#,
+ )
+}