10305: Move `GenericParams`'s handling of `impl Trait` into `fn_data_query` r=flodiebold a=SkiFire13

Fixes #10286

Co-authored-by: Giacomo Stevanato <giaco.stevanato@gmail.com>
This commit is contained in:
bors[bot] 2021-09-28 16:30:07 +00:00 committed by GitHub
commit c6d95657ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 73 additions and 28 deletions

View file

@ -7,13 +7,15 @@ use base_db::FileId;
use either::Either; use either::Either;
use hir_expand::{ use hir_expand::{
name::{AsName, Name}, name::{AsName, Name},
HirFileId, InFile, ExpandResult, HirFileId, InFile,
}; };
use la_arena::{Arena, ArenaMap}; use la_arena::{Arena, ArenaMap};
use once_cell::unsync::Lazy;
use std::ops::DerefMut;
use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds}; use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds};
use crate::{ use crate::{
body::LowerCtx, body::{Expander, LowerCtx},
child_by_source::ChildBySource, child_by_source::ChildBySource,
db::DefDatabase, db::DefDatabase,
dyn_map::DynMap, dyn_map::DynMap,
@ -21,8 +23,8 @@ use crate::{
keys, keys,
src::{HasChildSource, HasSource}, src::{HasChildSource, HasSource},
type_ref::{LifetimeRef, TypeBound, TypeRef}, type_ref::{LifetimeRef, TypeBound, TypeRef},
AdtId, ConstParamId, GenericDefId, LifetimeParamId, LocalConstParamId, LocalLifetimeParamId, AdtId, ConstParamId, GenericDefId, HasModule, LifetimeParamId, LocalConstParamId,
LocalTypeParamId, Lookup, TypeParamId, LocalLifetimeParamId, LocalTypeParamId, Lookup, TypeParamId,
}; };
/// Data about a generic type parameter (to a function, struct, impl, ...). /// Data about a generic type parameter (to a function, struct, impl, ...).
@ -99,10 +101,23 @@ impl GenericParams {
match def { match def {
GenericDefId::FunctionId(id) => { GenericDefId::FunctionId(id) => {
let id = id.lookup(db).id; let loc = id.lookup(db);
let tree = id.item_tree(db); let tree = loc.id.item_tree(db);
let item = &tree[id.value]; let item = &tree[loc.id.value];
item.generic_params.clone()
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)) => { GenericDefId::AdtId(AdtId::StructId(id)) => {
let id = id.lookup(db).id; let id = id.lookup(db).id;
@ -259,7 +274,12 @@ impl GenericParams {
self.where_predicates.push(predicate); 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| { type_ref.walk(&mut |type_ref| {
if let TypeRef::ImplTrait(bounds) = type_ref { if let TypeRef::ImplTrait(bounds) = type_ref {
let param = TypeParamData { 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);
}
_ => {}
}
}
}); });
} }

View file

@ -605,7 +605,7 @@ pub struct ExternBlock {
pub struct Function { pub struct Function {
pub name: Name, pub name: Name,
pub visibility: RawVisibilityId, pub visibility: RawVisibilityId,
pub generic_params: Interned<GenericParams>, pub explicit_generic_params: Interned<GenericParams>,
pub abi: Option<Interned<str>>, pub abi: Option<Interned<str>>,
pub params: IdRange<Param>, pub params: IdRange<Param>,
pub ret_type: Interned<TypeRef>, pub ret_type: Interned<TypeRef>,

View file

@ -401,7 +401,7 @@ impl<'a> Ctx<'a> {
let mut res = Function { let mut res = Function {
name, name,
visibility, visibility,
generic_params: Interned::new(GenericParams::default()), explicit_generic_params: Interned::new(GenericParams::default()),
abi, abi,
params, params,
ret_type: Interned::new(ret_type), ret_type: Interned::new(ret_type),
@ -409,7 +409,8 @@ impl<'a> Ctx<'a> {
ast_id, ast_id,
flags, 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))) Some(id(self.data().functions.alloc(res)))
} }
@ -664,16 +665,8 @@ impl<'a> Ctx<'a> {
) -> Interned<GenericParams> { ) -> Interned<GenericParams> {
let mut generics = GenericParams::default(); let mut generics = GenericParams::default();
match owner { match owner {
GenericsOwner::Function(func) => { GenericsOwner::Function(_)
generics.fill(&self.body_ctx, node); | GenericsOwner::Struct
// 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::Enum | GenericsOwner::Enum
| GenericsOwner::Union | GenericsOwner::Union
| GenericsOwner::TypeAlias => { | GenericsOwner::TypeAlias => {

View file

@ -234,7 +234,7 @@ impl<'a> Printer<'a> {
let Function { let Function {
name, name,
visibility, visibility,
generic_params, explicit_generic_params,
abi, abi,
params, params,
ret_type, ret_type,
@ -250,7 +250,7 @@ impl<'a> Printer<'a> {
w!(self, "extern \"{}\" ", abi); w!(self, "extern \"{}\" ", abi);
} }
w!(self, "fn {}", name); w!(self, "fn {}", name);
self.print_generic_params(generic_params); self.print_generic_params(explicit_generic_params);
w!(self, "("); w!(self, "(");
if !params.is_empty() { if !params.is_empty() {
self.indented(|this| { self.indented(|this| {
@ -271,7 +271,7 @@ impl<'a> Printer<'a> {
} }
w!(self, ") -> "); w!(self, ") -> ");
self.print_type_ref(ret_type); self.print_type_ref(ret_type);
self.print_where_clause(generic_params); self.print_where_clause(explicit_generic_params);
wln!(self, ";"); wln!(self, ";");
} }
ModItem::Struct(it) => { ModItem::Struct(it) => {

View file

@ -340,12 +340,11 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
T: 'b T: 'b
{ {
// flags = 0x2 // flags = 0x2
pub(self) fn f<G, _anon_1>( pub(self) fn f<G>(
_: impl Copy, _: impl Copy,
) -> impl Copy ) -> impl Copy
where where
G: 'a, G: 'a;
_anon_1: Copy;
} }
pub(self) enum Enum<'a, T, const U: u8> { pub(self) enum Enum<'a, T, const U: u8> {

View file

@ -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(());
}
"#,
)
}