mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 06:41:48 +00:00
Merge #10353
10353: Remove `GenericParams::new` r=SkiFire13 a=SkiFire13 Helps with #10305 I made the implementations of `HasChildSource<_>` and `ChildBySource` for `GenericDefId` use their own logic instead of relying on `GenericParams::new`. This in turn means that `GenericParams::new` is unused and can be removed. `SourceMap` becomes also unused because all the rest of the code does is insert into it, so it can be removed too. This also helps avoid creating a completly new `GenericParams` when `GenericDefId::child_source` and `GenericDefId::child_by_source_to` are called, and also creating a `SourceMap` in `item_tree::lower::Ctx::lower_generic_params`. Co-authored-by: Giacomo Stevanato <giaco.stevanato@gmail.com>
This commit is contained in:
commit
5347c3ab59
2 changed files with 122 additions and 131 deletions
|
@ -6,7 +6,7 @@
|
||||||
use base_db::FileId;
|
use base_db::FileId;
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
name::{name, AsName, Name},
|
name::{AsName, Name},
|
||||||
HirFileId, InFile,
|
HirFileId, InFile,
|
||||||
};
|
};
|
||||||
use la_arena::{Arena, ArenaMap};
|
use la_arena::{Arena, ArenaMap};
|
||||||
|
@ -90,13 +90,6 @@ pub enum WherePredicateTypeTarget {
|
||||||
TypeParam(LocalTypeParamId),
|
TypeParam(LocalTypeParamId),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub(crate) struct SourceMap {
|
|
||||||
pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::TypeParam, ast::Trait>>,
|
|
||||||
lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>,
|
|
||||||
const_params: ArenaMap<LocalConstParamId, ast::ConstParam>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GenericParams {
|
impl GenericParams {
|
||||||
pub(crate) fn generic_params_query(
|
pub(crate) fn generic_params_query(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
|
@ -153,93 +146,9 @@ impl GenericParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) {
|
pub(crate) fn fill(&mut self, lower_ctx: &LowerCtx, node: &dyn HasGenericParams) {
|
||||||
let mut generics = GenericParams::default();
|
|
||||||
let mut sm = SourceMap::default();
|
|
||||||
|
|
||||||
// FIXME: add `: Sized` bound for everything except for `Self` in traits
|
|
||||||
let file_id = match def {
|
|
||||||
GenericDefId::FunctionId(it) => {
|
|
||||||
let src = it.lookup(db).source(db);
|
|
||||||
let lower_ctx = LowerCtx::new(db, src.file_id);
|
|
||||||
generics.fill(&lower_ctx, &mut sm, &src.value);
|
|
||||||
// lower `impl Trait` in arguments
|
|
||||||
let data = db.function_data(it);
|
|
||||||
for param in &data.params {
|
|
||||||
generics.fill_implicit_impl_trait_args(param);
|
|
||||||
}
|
|
||||||
src.file_id
|
|
||||||
}
|
|
||||||
GenericDefId::AdtId(AdtId::StructId(it)) => {
|
|
||||||
let src = it.lookup(db).source(db);
|
|
||||||
let lower_ctx = LowerCtx::new(db, src.file_id);
|
|
||||||
generics.fill(&lower_ctx, &mut sm, &src.value);
|
|
||||||
src.file_id
|
|
||||||
}
|
|
||||||
GenericDefId::AdtId(AdtId::UnionId(it)) => {
|
|
||||||
let src = it.lookup(db).source(db);
|
|
||||||
let lower_ctx = LowerCtx::new(db, src.file_id);
|
|
||||||
generics.fill(&lower_ctx, &mut sm, &src.value);
|
|
||||||
src.file_id
|
|
||||||
}
|
|
||||||
GenericDefId::AdtId(AdtId::EnumId(it)) => {
|
|
||||||
let src = it.lookup(db).source(db);
|
|
||||||
let lower_ctx = LowerCtx::new(db, src.file_id);
|
|
||||||
generics.fill(&lower_ctx, &mut sm, &src.value);
|
|
||||||
src.file_id
|
|
||||||
}
|
|
||||||
GenericDefId::TraitId(it) => {
|
|
||||||
let src = it.lookup(db).source(db);
|
|
||||||
let lower_ctx = LowerCtx::new(db, src.file_id);
|
|
||||||
|
|
||||||
// traits get the Self type as an implicit first type parameter
|
|
||||||
let self_param_id = generics.types.alloc(TypeParamData {
|
|
||||||
name: Some(name![Self]),
|
|
||||||
default: None,
|
|
||||||
provenance: TypeParamProvenance::TraitSelf,
|
|
||||||
});
|
|
||||||
sm.type_params.insert(self_param_id, Either::Right(src.value.clone()));
|
|
||||||
// add super traits as bounds on Self
|
|
||||||
// i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
|
|
||||||
let self_param = TypeRef::Path(name![Self].into());
|
|
||||||
generics.fill_bounds(&lower_ctx, &src.value, Either::Left(self_param));
|
|
||||||
|
|
||||||
generics.fill(&lower_ctx, &mut sm, &src.value);
|
|
||||||
src.file_id
|
|
||||||
}
|
|
||||||
GenericDefId::TypeAliasId(it) => {
|
|
||||||
let src = it.lookup(db).source(db);
|
|
||||||
let lower_ctx = LowerCtx::new(db, src.file_id);
|
|
||||||
|
|
||||||
generics.fill(&lower_ctx, &mut sm, &src.value);
|
|
||||||
src.file_id
|
|
||||||
}
|
|
||||||
// Note that we don't add `Self` here: in `impl`s, `Self` is not a
|
|
||||||
// type-parameter, but rather is a type-alias for impl's target
|
|
||||||
// type, so this is handled by the resolver.
|
|
||||||
GenericDefId::ImplId(it) => {
|
|
||||||
let src = it.lookup(db).source(db);
|
|
||||||
let lower_ctx = LowerCtx::new(db, src.file_id);
|
|
||||||
|
|
||||||
generics.fill(&lower_ctx, &mut sm, &src.value);
|
|
||||||
src.file_id
|
|
||||||
}
|
|
||||||
// We won't be using this ID anyway
|
|
||||||
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => FileId(!0).into(),
|
|
||||||
};
|
|
||||||
|
|
||||||
generics.shrink_to_fit();
|
|
||||||
(generics, InFile::new(file_id, sm))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn fill(
|
|
||||||
&mut self,
|
|
||||||
lower_ctx: &LowerCtx,
|
|
||||||
sm: &mut SourceMap,
|
|
||||||
node: &dyn HasGenericParams,
|
|
||||||
) {
|
|
||||||
if let Some(params) = node.generic_param_list() {
|
if let Some(params) = node.generic_param_list() {
|
||||||
self.fill_params(lower_ctx, sm, params)
|
self.fill_params(lower_ctx, params)
|
||||||
}
|
}
|
||||||
if let Some(where_clause) = node.where_clause() {
|
if let Some(where_clause) = node.where_clause() {
|
||||||
self.fill_where_predicates(lower_ctx, where_clause);
|
self.fill_where_predicates(lower_ctx, where_clause);
|
||||||
|
@ -259,12 +168,7 @@ impl GenericParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_params(
|
fn fill_params(&mut self, lower_ctx: &LowerCtx, params: ast::GenericParamList) {
|
||||||
&mut self,
|
|
||||||
lower_ctx: &LowerCtx,
|
|
||||||
sm: &mut SourceMap,
|
|
||||||
params: ast::GenericParamList,
|
|
||||||
) {
|
|
||||||
for type_param in params.type_params() {
|
for type_param in params.type_params() {
|
||||||
let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
|
let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
|
||||||
// FIXME: Use `Path::from_src`
|
// FIXME: Use `Path::from_src`
|
||||||
|
@ -275,9 +179,7 @@ impl GenericParams {
|
||||||
default,
|
default,
|
||||||
provenance: TypeParamProvenance::TypeParamList,
|
provenance: TypeParamProvenance::TypeParamList,
|
||||||
};
|
};
|
||||||
let param_id = self.types.alloc(param);
|
self.types.alloc(param);
|
||||||
sm.type_params.insert(param_id, Either::Left(type_param.clone()));
|
|
||||||
|
|
||||||
let type_ref = TypeRef::Path(name.into());
|
let type_ref = TypeRef::Path(name.into());
|
||||||
self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref));
|
self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref));
|
||||||
}
|
}
|
||||||
|
@ -285,8 +187,7 @@ impl GenericParams {
|
||||||
let name =
|
let name =
|
||||||
lifetime_param.lifetime().map_or_else(Name::missing, |lt| Name::new_lifetime(<));
|
lifetime_param.lifetime().map_or_else(Name::missing, |lt| Name::new_lifetime(<));
|
||||||
let param = LifetimeParamData { name: name.clone() };
|
let param = LifetimeParamData { name: name.clone() };
|
||||||
let param_id = self.lifetimes.alloc(param);
|
self.lifetimes.alloc(param);
|
||||||
sm.lifetime_params.insert(param_id, lifetime_param.clone());
|
|
||||||
let lifetime_ref = LifetimeRef::new_name(name);
|
let lifetime_ref = LifetimeRef::new_name(name);
|
||||||
self.fill_bounds(lower_ctx, &lifetime_param, Either::Right(lifetime_ref));
|
self.fill_bounds(lower_ctx, &lifetime_param, Either::Right(lifetime_ref));
|
||||||
}
|
}
|
||||||
|
@ -294,8 +195,7 @@ impl GenericParams {
|
||||||
let name = const_param.name().map_or_else(Name::missing, |it| it.as_name());
|
let name = const_param.name().map_or_else(Name::missing, |it| it.as_name());
|
||||||
let ty = const_param.ty().map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it));
|
let ty = const_param.ty().map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it));
|
||||||
let param = ConstParamData { name, ty: Interned::new(ty) };
|
let param = ConstParamData { name, ty: Interned::new(ty) };
|
||||||
let param_id = self.consts.alloc(param);
|
self.consts.alloc(param);
|
||||||
sm.const_params.insert(param_id, const_param.clone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,13 +307,71 @@ impl GenericParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn file_id_and_params_of(
|
||||||
|
def: GenericDefId,
|
||||||
|
db: &dyn DefDatabase,
|
||||||
|
) -> (HirFileId, Option<ast::GenericParamList>) {
|
||||||
|
match def {
|
||||||
|
GenericDefId::FunctionId(it) => {
|
||||||
|
let src = it.lookup(db).source(db);
|
||||||
|
(src.file_id, src.value.generic_param_list())
|
||||||
|
}
|
||||||
|
GenericDefId::AdtId(AdtId::StructId(it)) => {
|
||||||
|
let src = it.lookup(db).source(db);
|
||||||
|
(src.file_id, src.value.generic_param_list())
|
||||||
|
}
|
||||||
|
GenericDefId::AdtId(AdtId::UnionId(it)) => {
|
||||||
|
let src = it.lookup(db).source(db);
|
||||||
|
(src.file_id, src.value.generic_param_list())
|
||||||
|
}
|
||||||
|
GenericDefId::AdtId(AdtId::EnumId(it)) => {
|
||||||
|
let src = it.lookup(db).source(db);
|
||||||
|
(src.file_id, src.value.generic_param_list())
|
||||||
|
}
|
||||||
|
GenericDefId::TraitId(it) => {
|
||||||
|
let src = it.lookup(db).source(db);
|
||||||
|
(src.file_id, src.value.generic_param_list())
|
||||||
|
}
|
||||||
|
GenericDefId::TypeAliasId(it) => {
|
||||||
|
let src = it.lookup(db).source(db);
|
||||||
|
(src.file_id, src.value.generic_param_list())
|
||||||
|
}
|
||||||
|
GenericDefId::ImplId(it) => {
|
||||||
|
let src = it.lookup(db).source(db);
|
||||||
|
(src.file_id, src.value.generic_param_list())
|
||||||
|
}
|
||||||
|
// We won't be using this ID anyway
|
||||||
|
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => (FileId(!0).into(), None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HasChildSource<LocalTypeParamId> for GenericDefId {
|
impl HasChildSource<LocalTypeParamId> for GenericDefId {
|
||||||
type Value = Either<ast::TypeParam, ast::Trait>;
|
type Value = Either<ast::TypeParam, ast::Trait>;
|
||||||
fn child_source(
|
fn child_source(
|
||||||
&self,
|
&self,
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
) -> InFile<ArenaMap<LocalTypeParamId, Self::Value>> {
|
) -> InFile<ArenaMap<LocalTypeParamId, Self::Value>> {
|
||||||
GenericParams::new(db, *self).1.map(|source_maps| source_maps.type_params)
|
let generic_params = db.generic_params(*self);
|
||||||
|
let mut idx_iter = generic_params.types.iter().map(|(idx, _)| idx);
|
||||||
|
|
||||||
|
let (file_id, generic_params_list) = file_id_and_params_of(*self, db);
|
||||||
|
|
||||||
|
let mut params = ArenaMap::default();
|
||||||
|
|
||||||
|
// For traits the first type index is `Self`, we need to add it before the other params.
|
||||||
|
if let GenericDefId::TraitId(id) = *self {
|
||||||
|
let trait_ref = id.lookup(db).source(db).value.clone();
|
||||||
|
let idx = idx_iter.next().unwrap();
|
||||||
|
params.insert(idx, Either::Right(trait_ref))
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(generic_params_list) = generic_params_list {
|
||||||
|
for (idx, ast_param) in idx_iter.zip(generic_params_list.type_params()) {
|
||||||
|
params.insert(idx, Either::Left(ast_param));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InFile::new(file_id, params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,7 +381,20 @@ impl HasChildSource<LocalLifetimeParamId> for GenericDefId {
|
||||||
&self,
|
&self,
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
) -> InFile<ArenaMap<LocalLifetimeParamId, Self::Value>> {
|
) -> InFile<ArenaMap<LocalLifetimeParamId, Self::Value>> {
|
||||||
GenericParams::new(db, *self).1.map(|source_maps| source_maps.lifetime_params)
|
let generic_params = db.generic_params(*self);
|
||||||
|
let idx_iter = generic_params.lifetimes.iter().map(|(idx, _)| idx);
|
||||||
|
|
||||||
|
let (file_id, generic_params_list) = file_id_and_params_of(*self, db);
|
||||||
|
|
||||||
|
let mut params = ArenaMap::default();
|
||||||
|
|
||||||
|
if let Some(generic_params_list) = generic_params_list {
|
||||||
|
for (idx, ast_param) in idx_iter.zip(generic_params_list.lifetime_params()) {
|
||||||
|
params.insert(idx, ast_param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InFile::new(file_id, params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,28 +404,50 @@ impl HasChildSource<LocalConstParamId> for GenericDefId {
|
||||||
&self,
|
&self,
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
) -> InFile<ArenaMap<LocalConstParamId, Self::Value>> {
|
) -> InFile<ArenaMap<LocalConstParamId, Self::Value>> {
|
||||||
GenericParams::new(db, *self).1.map(|source_maps| source_maps.const_params)
|
let generic_params = db.generic_params(*self);
|
||||||
|
let idx_iter = generic_params.consts.iter().map(|(idx, _)| idx);
|
||||||
|
|
||||||
|
let (file_id, generic_params_list) = file_id_and_params_of(*self, db);
|
||||||
|
|
||||||
|
let mut params = ArenaMap::default();
|
||||||
|
|
||||||
|
if let Some(generic_params_list) = generic_params_list {
|
||||||
|
for (idx, ast_param) in idx_iter.zip(generic_params_list.const_params()) {
|
||||||
|
params.insert(idx, ast_param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InFile::new(file_id, params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChildBySource for GenericDefId {
|
impl ChildBySource for GenericDefId {
|
||||||
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, _: HirFileId) {
|
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, _: HirFileId) {
|
||||||
let (_, sm) = GenericParams::new(db, *self);
|
let generic_params = db.generic_params(*self);
|
||||||
|
let mut types_idx_iter = generic_params.types.iter().map(|(idx, _)| idx);
|
||||||
|
let lts_idx_iter = generic_params.lifetimes.iter().map(|(idx, _)| idx);
|
||||||
|
let consts_idx_iter = generic_params.consts.iter().map(|(idx, _)| idx);
|
||||||
|
|
||||||
let sm = sm.as_ref();
|
let (file_id, generic_params_list) = file_id_and_params_of(*self, db);
|
||||||
for (local_id, src) in sm.value.type_params.iter() {
|
|
||||||
let id = TypeParamId { parent: *self, local_id };
|
// For traits the first type index is `Self`, skip it.
|
||||||
if let Either::Left(type_param) = src {
|
if let GenericDefId::TraitId(_) = *self {
|
||||||
res[keys::TYPE_PARAM].insert(sm.with_value(type_param.clone()), id)
|
types_idx_iter.next().unwrap(); // advance_by(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(generic_params_list) = generic_params_list {
|
||||||
|
for (local_id, ast_param) in types_idx_iter.zip(generic_params_list.type_params()) {
|
||||||
|
let id = TypeParamId { parent: *self, local_id };
|
||||||
|
res[keys::TYPE_PARAM].insert(InFile::new(file_id, ast_param), id);
|
||||||
|
}
|
||||||
|
for (local_id, ast_param) in lts_idx_iter.zip(generic_params_list.lifetime_params()) {
|
||||||
|
let id = LifetimeParamId { parent: *self, local_id };
|
||||||
|
res[keys::LIFETIME_PARAM].insert(InFile::new(file_id, ast_param), id);
|
||||||
|
}
|
||||||
|
for (local_id, ast_param) in consts_idx_iter.zip(generic_params_list.const_params()) {
|
||||||
|
let id = ConstParamId { parent: *self, local_id };
|
||||||
|
res[keys::CONST_PARAM].insert(InFile::new(file_id, ast_param), id);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
for (local_id, src) in sm.value.lifetime_params.iter() {
|
|
||||||
let id = LifetimeParamId { parent: *self, local_id };
|
|
||||||
res[keys::LIFETIME_PARAM].insert(sm.with_value(src.clone()), id);
|
|
||||||
}
|
|
||||||
for (local_id, src) in sm.value.const_params.iter() {
|
|
||||||
let id = ConstParamId { parent: *self, local_id };
|
|
||||||
res[keys::CONST_PARAM].insert(sm.with_value(src.clone()), id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -662,11 +662,10 @@ impl<'a> Ctx<'a> {
|
||||||
owner: GenericsOwner<'_>,
|
owner: GenericsOwner<'_>,
|
||||||
node: &impl ast::HasGenericParams,
|
node: &impl ast::HasGenericParams,
|
||||||
) -> Interned<GenericParams> {
|
) -> Interned<GenericParams> {
|
||||||
let mut sm = &mut Default::default();
|
|
||||||
let mut generics = GenericParams::default();
|
let mut generics = GenericParams::default();
|
||||||
match owner {
|
match owner {
|
||||||
GenericsOwner::Function(func) => {
|
GenericsOwner::Function(func) => {
|
||||||
generics.fill(&self.body_ctx, sm, node);
|
generics.fill(&self.body_ctx, node);
|
||||||
// lower `impl Trait` in arguments
|
// lower `impl Trait` in arguments
|
||||||
for id in func.params.clone() {
|
for id in func.params.clone() {
|
||||||
if let Param::Normal(ty) = &self.data().params[id] {
|
if let Param::Normal(ty) = &self.data().params[id] {
|
||||||
|
@ -678,27 +677,26 @@ impl<'a> Ctx<'a> {
|
||||||
| GenericsOwner::Enum
|
| GenericsOwner::Enum
|
||||||
| GenericsOwner::Union
|
| GenericsOwner::Union
|
||||||
| GenericsOwner::TypeAlias => {
|
| GenericsOwner::TypeAlias => {
|
||||||
generics.fill(&self.body_ctx, sm, node);
|
generics.fill(&self.body_ctx, node);
|
||||||
}
|
}
|
||||||
GenericsOwner::Trait(trait_def) => {
|
GenericsOwner::Trait(trait_def) => {
|
||||||
// traits get the Self type as an implicit first type parameter
|
// traits get the Self type as an implicit first type parameter
|
||||||
let self_param_id = generics.types.alloc(TypeParamData {
|
generics.types.alloc(TypeParamData {
|
||||||
name: Some(name![Self]),
|
name: Some(name![Self]),
|
||||||
default: None,
|
default: None,
|
||||||
provenance: TypeParamProvenance::TraitSelf,
|
provenance: TypeParamProvenance::TraitSelf,
|
||||||
});
|
});
|
||||||
sm.type_params.insert(self_param_id, Either::Right(trait_def.clone()));
|
|
||||||
// add super traits as bounds on Self
|
// add super traits as bounds on Self
|
||||||
// i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
|
// i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
|
||||||
let self_param = TypeRef::Path(name![Self].into());
|
let self_param = TypeRef::Path(name![Self].into());
|
||||||
generics.fill_bounds(&self.body_ctx, trait_def, Either::Left(self_param));
|
generics.fill_bounds(&self.body_ctx, trait_def, Either::Left(self_param));
|
||||||
generics.fill(&self.body_ctx, &mut sm, node);
|
generics.fill(&self.body_ctx, node);
|
||||||
}
|
}
|
||||||
GenericsOwner::Impl => {
|
GenericsOwner::Impl => {
|
||||||
// Note that we don't add `Self` here: in `impl`s, `Self` is not a
|
// Note that we don't add `Self` here: in `impl`s, `Self` is not a
|
||||||
// type-parameter, but rather is a type-alias for impl's target
|
// type-parameter, but rather is a type-alias for impl's target
|
||||||
// type, so this is handled by the resolver.
|
// type, so this is handled by the resolver.
|
||||||
generics.fill(&self.body_ctx, &mut sm, node);
|
generics.fill(&self.body_ctx, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue