mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
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 <giaco.stevanato@gmail.com>
This commit is contained in:
commit
c6d95657ee
6 changed files with 73 additions and 28 deletions
|
@ -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);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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(());
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue