Merge #2838
2838: Move Type API to type r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
e5cb836448
@ -21,8 +21,8 @@ use hir_expand::{
|
||||
MacroDefId,
|
||||
};
|
||||
use hir_ty::{
|
||||
autoderef, display::HirFormatter, expr::ExprValidator, method_resolution::implements_trait,
|
||||
ApplicationTy, Canonical, InEnvironment, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk,
|
||||
autoderef, display::HirFormatter, expr::ExprValidator, method_resolution, ApplicationTy,
|
||||
Canonical, InEnvironment, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk,
|
||||
};
|
||||
use ra_db::{CrateId, Edition, FileId};
|
||||
use ra_prof::profile;
|
||||
@ -120,7 +120,8 @@ impl_froms!(
|
||||
BuiltinType
|
||||
);
|
||||
|
||||
pub use hir_def::{attr::Attrs, visibility::Visibility};
|
||||
pub use hir_def::{attr::Attrs, visibility::Visibility, AssocItemId};
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
impl Module {
|
||||
pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module {
|
||||
@ -891,7 +892,13 @@ impl Type {
|
||||
};
|
||||
|
||||
let canonical_ty = Canonical { value: self.ty.value.clone(), num_vars: 0 };
|
||||
implements_trait(&canonical_ty, db, self.ty.environment.clone(), krate, std_future_trait)
|
||||
method_resolution::implements_trait(
|
||||
&canonical_ty,
|
||||
db,
|
||||
self.ty.environment.clone(),
|
||||
krate,
|
||||
std_future_trait,
|
||||
)
|
||||
}
|
||||
|
||||
// FIXME: this method is broken, as it doesn't take closures into account.
|
||||
@ -1002,6 +1009,65 @@ impl Type {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn iterate_method_candidates<T>(
|
||||
&self,
|
||||
db: &impl HirDatabase,
|
||||
krate: Crate,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
name: Option<&Name>,
|
||||
mut callback: impl FnMut(&Ty, Function) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
// There should be no inference vars in types passed here
|
||||
// FIXME check that?
|
||||
// FIXME replace Unknown by bound vars here
|
||||
let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 };
|
||||
|
||||
let env = self.ty.environment.clone();
|
||||
let krate = krate.id;
|
||||
|
||||
method_resolution::iterate_method_candidates(
|
||||
&canonical,
|
||||
db,
|
||||
env,
|
||||
krate,
|
||||
traits_in_scope,
|
||||
name,
|
||||
method_resolution::LookupMode::MethodCall,
|
||||
|ty, it| match it {
|
||||
AssocItemId::FunctionId(f) => callback(ty, f.into()),
|
||||
_ => None,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn iterate_path_candidates<T>(
|
||||
&self,
|
||||
db: &impl HirDatabase,
|
||||
krate: Crate,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
name: Option<&Name>,
|
||||
mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
// There should be no inference vars in types passed here
|
||||
// FIXME check that?
|
||||
// FIXME replace Unknown by bound vars here
|
||||
let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 };
|
||||
|
||||
let env = self.ty.environment.clone();
|
||||
let krate = krate.id;
|
||||
|
||||
method_resolution::iterate_method_candidates(
|
||||
&canonical,
|
||||
db,
|
||||
env,
|
||||
krate,
|
||||
traits_in_scope,
|
||||
name,
|
||||
method_resolution::LookupMode::Path,
|
||||
|ty, it| callback(ty, it.into()),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn as_adt(&self) -> Option<Adt> {
|
||||
let (adt, _subst) = self.ty.value.as_adt()?;
|
||||
Some(adt.into())
|
||||
|
@ -16,12 +16,12 @@ use hir_def::{
|
||||
expr::{ExprId, PatId},
|
||||
nameres::ModuleSource,
|
||||
resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs},
|
||||
AssocItemId, DefWithBodyId,
|
||||
DefWithBodyId, TraitId,
|
||||
};
|
||||
use hir_expand::{
|
||||
hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind,
|
||||
};
|
||||
use hir_ty::{method_resolution, Canonical, InEnvironment, InferenceResult, TraitEnvironment, Ty};
|
||||
use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment};
|
||||
use ra_prof::profile;
|
||||
use ra_syntax::{
|
||||
ast::{self, AstNode},
|
||||
@ -29,11 +29,11 @@ use ra_syntax::{
|
||||
SyntaxKind::*,
|
||||
SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextUnit,
|
||||
};
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
use crate::{
|
||||
db::HirDatabase, Adt, AssocItem, Const, DefWithBody, Enum, EnumVariant, FromSource, Function,
|
||||
ImplBlock, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias,
|
||||
TypeParam,
|
||||
db::HirDatabase, Adt, Const, DefWithBody, Enum, EnumVariant, FromSource, Function, ImplBlock,
|
||||
Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam,
|
||||
};
|
||||
|
||||
/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
|
||||
@ -347,49 +347,9 @@ impl SourceAnalyzer {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn iterate_method_candidates<T>(
|
||||
&self,
|
||||
db: &impl HirDatabase,
|
||||
ty: &Type,
|
||||
name: Option<&Name>,
|
||||
mut callback: impl FnMut(&Ty, Function) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
// There should be no inference vars in types passed here
|
||||
// FIXME check that?
|
||||
// FIXME replace Unknown by bound vars here
|
||||
let canonical = Canonical { value: ty.ty.value.clone(), num_vars: 0 };
|
||||
method_resolution::iterate_method_candidates(
|
||||
&canonical,
|
||||
db,
|
||||
&self.resolver,
|
||||
name,
|
||||
method_resolution::LookupMode::MethodCall,
|
||||
|ty, it| match it {
|
||||
AssocItemId::FunctionId(f) => callback(ty, f.into()),
|
||||
_ => None,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn iterate_path_candidates<T>(
|
||||
&self,
|
||||
db: &impl HirDatabase,
|
||||
ty: &Type,
|
||||
name: Option<&Name>,
|
||||
mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
// There should be no inference vars in types passed here
|
||||
// FIXME check that?
|
||||
// FIXME replace Unknown by bound vars here
|
||||
let canonical = Canonical { value: ty.ty.value.clone(), num_vars: 0 };
|
||||
method_resolution::iterate_method_candidates(
|
||||
&canonical,
|
||||
db,
|
||||
&self.resolver,
|
||||
name,
|
||||
method_resolution::LookupMode::Path,
|
||||
|ty, it| callback(ty, it.into()),
|
||||
)
|
||||
/// Note: `FxHashSet<TraitId>` should be treated as an opaque type, passed into `Type
|
||||
pub fn traits_in_scope(&self, db: &impl HirDatabase) -> FxHashSet<TraitId> {
|
||||
self.resolver.traits_in_scope(db)
|
||||
}
|
||||
|
||||
pub fn expand(
|
||||
|
@ -569,12 +569,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
) -> Ty {
|
||||
let receiver_ty = self.infer_expr(receiver, &Expectation::none());
|
||||
let canonicalized_receiver = self.canonicalizer().canonicalize_ty(receiver_ty.clone());
|
||||
let resolved = method_resolution::lookup_method(
|
||||
&canonicalized_receiver.value,
|
||||
self.db,
|
||||
method_name,
|
||||
&self.resolver,
|
||||
);
|
||||
|
||||
let traits_in_scope = self.resolver.traits_in_scope(self.db);
|
||||
|
||||
let resolved = self.resolver.krate().and_then(|krate| {
|
||||
method_resolution::lookup_method(
|
||||
&canonicalized_receiver.value,
|
||||
self.db,
|
||||
self.trait_env.clone(),
|
||||
krate,
|
||||
&traits_in_scope,
|
||||
method_name,
|
||||
)
|
||||
});
|
||||
let (derefed_receiver_ty, method_ty, def_generics) = match resolved {
|
||||
Some((ty, func)) => {
|
||||
let ty = canonicalized_receiver.decanonicalize_ty(ty);
|
||||
|
@ -11,7 +11,7 @@ use hir_expand::name::Name;
|
||||
|
||||
use crate::{db::HirDatabase, method_resolution, Substs, Ty, TypeWalk, ValueTyDefId};
|
||||
|
||||
use super::{ExprOrPatId, InferenceContext, TraitRef};
|
||||
use super::{ExprOrPatId, InferenceContext, TraitEnvironment, TraitRef};
|
||||
|
||||
impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
pub(super) fn infer_path(
|
||||
@ -193,11 +193,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
}
|
||||
|
||||
let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone());
|
||||
let env = TraitEnvironment::lower(self.db, &self.resolver);
|
||||
let krate = self.resolver.krate()?;
|
||||
let traits_in_scope = self.resolver.traits_in_scope(self.db);
|
||||
|
||||
method_resolution::iterate_method_candidates(
|
||||
&canonical_ty.value,
|
||||
self.db,
|
||||
&self.resolver.clone(),
|
||||
env,
|
||||
krate,
|
||||
&traits_in_scope,
|
||||
Some(name),
|
||||
method_resolution::LookupMode::Path,
|
||||
move |_ty, item| {
|
||||
|
@ -6,13 +6,13 @@ use std::sync::Arc;
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use hir_def::{
|
||||
lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocContainerId,
|
||||
AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId,
|
||||
lang_item::LangItemTarget, type_ref::Mutability, AssocContainerId, AssocItemId, FunctionId,
|
||||
HasModule, ImplId, Lookup, TraitId,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use ra_db::CrateId;
|
||||
use ra_prof::profile;
|
||||
use rustc_hash::FxHashMap;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
use super::Substs;
|
||||
use crate::{
|
||||
@ -144,14 +144,24 @@ impl Ty {
|
||||
pub(crate) fn lookup_method(
|
||||
ty: &Canonical<Ty>,
|
||||
db: &impl HirDatabase,
|
||||
env: Arc<TraitEnvironment>,
|
||||
krate: CrateId,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
name: &Name,
|
||||
resolver: &Resolver,
|
||||
) -> Option<(Ty, FunctionId)> {
|
||||
iterate_method_candidates(ty, db, resolver, Some(name), LookupMode::MethodCall, |ty, f| match f
|
||||
{
|
||||
AssocItemId::FunctionId(f) => Some((ty.clone(), f)),
|
||||
_ => None,
|
||||
})
|
||||
iterate_method_candidates(
|
||||
ty,
|
||||
db,
|
||||
env,
|
||||
krate,
|
||||
&traits_in_scope,
|
||||
Some(name),
|
||||
LookupMode::MethodCall,
|
||||
|ty, f| match f {
|
||||
AssocItemId::FunctionId(f) => Some((ty.clone(), f)),
|
||||
_ => None,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Whether we're looking up a dotted method call (like `v.len()`) or a path
|
||||
@ -172,7 +182,9 @@ pub enum LookupMode {
|
||||
pub fn iterate_method_candidates<T>(
|
||||
ty: &Canonical<Ty>,
|
||||
db: &impl HirDatabase,
|
||||
resolver: &Resolver,
|
||||
env: Arc<TraitEnvironment>,
|
||||
krate: CrateId,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
name: Option<&Name>,
|
||||
mode: LookupMode,
|
||||
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
|
||||
@ -187,9 +199,7 @@ pub fn iterate_method_candidates<T>(
|
||||
// Also note that when we've got a receiver like &S, even if the method we
|
||||
// find in the end takes &self, we still do the autoderef step (just as
|
||||
// rustc does an autoderef and then autoref again).
|
||||
let environment = TraitEnvironment::lower(db, resolver);
|
||||
let ty = InEnvironment { value: ty.clone(), environment };
|
||||
let krate = resolver.krate()?;
|
||||
let ty = InEnvironment { value: ty.clone(), environment: env.clone() };
|
||||
|
||||
// We have to be careful about the order we're looking at candidates
|
||||
// in here. Consider the case where we're resolving `x.clone()`
|
||||
@ -209,7 +219,9 @@ pub fn iterate_method_candidates<T>(
|
||||
if let Some(result) = iterate_method_candidates_with_autoref(
|
||||
&deref_chain[i..],
|
||||
db,
|
||||
resolver,
|
||||
env.clone(),
|
||||
krate,
|
||||
traits_in_scope,
|
||||
name,
|
||||
&mut callback,
|
||||
) {
|
||||
@ -220,7 +232,15 @@ pub fn iterate_method_candidates<T>(
|
||||
}
|
||||
LookupMode::Path => {
|
||||
// No autoderef for path lookups
|
||||
iterate_method_candidates_for_self_ty(&ty, db, resolver, name, &mut callback)
|
||||
iterate_method_candidates_for_self_ty(
|
||||
&ty,
|
||||
db,
|
||||
env,
|
||||
krate,
|
||||
traits_in_scope,
|
||||
name,
|
||||
&mut callback,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -228,7 +248,9 @@ pub fn iterate_method_candidates<T>(
|
||||
fn iterate_method_candidates_with_autoref<T>(
|
||||
deref_chain: &[Canonical<Ty>],
|
||||
db: &impl HirDatabase,
|
||||
resolver: &Resolver,
|
||||
env: Arc<TraitEnvironment>,
|
||||
krate: CrateId,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
name: Option<&Name>,
|
||||
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
@ -236,7 +258,9 @@ fn iterate_method_candidates_with_autoref<T>(
|
||||
&deref_chain[0],
|
||||
&deref_chain[1..],
|
||||
db,
|
||||
resolver,
|
||||
env.clone(),
|
||||
krate,
|
||||
&traits_in_scope,
|
||||
name,
|
||||
&mut callback,
|
||||
) {
|
||||
@ -250,7 +274,9 @@ fn iterate_method_candidates_with_autoref<T>(
|
||||
&refed,
|
||||
deref_chain,
|
||||
db,
|
||||
resolver,
|
||||
env.clone(),
|
||||
krate,
|
||||
&traits_in_scope,
|
||||
name,
|
||||
&mut callback,
|
||||
) {
|
||||
@ -264,7 +290,9 @@ fn iterate_method_candidates_with_autoref<T>(
|
||||
&ref_muted,
|
||||
deref_chain,
|
||||
db,
|
||||
resolver,
|
||||
env.clone(),
|
||||
krate,
|
||||
&traits_in_scope,
|
||||
name,
|
||||
&mut callback,
|
||||
) {
|
||||
@ -277,14 +305,15 @@ fn iterate_method_candidates_by_receiver<T>(
|
||||
receiver_ty: &Canonical<Ty>,
|
||||
rest_of_deref_chain: &[Canonical<Ty>],
|
||||
db: &impl HirDatabase,
|
||||
resolver: &Resolver,
|
||||
env: Arc<TraitEnvironment>,
|
||||
krate: CrateId,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
name: Option<&Name>,
|
||||
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
// We're looking for methods with *receiver* type receiver_ty. These could
|
||||
// be found in any of the derefs of receiver_ty, so we have to go through
|
||||
// that.
|
||||
let krate = resolver.krate()?;
|
||||
for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) {
|
||||
if let Some(result) =
|
||||
iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback)
|
||||
@ -296,7 +325,9 @@ fn iterate_method_candidates_by_receiver<T>(
|
||||
if let Some(result) = iterate_trait_method_candidates(
|
||||
self_ty,
|
||||
db,
|
||||
resolver,
|
||||
env.clone(),
|
||||
krate,
|
||||
&traits_in_scope,
|
||||
name,
|
||||
Some(receiver_ty),
|
||||
&mut callback,
|
||||
@ -310,17 +341,25 @@ fn iterate_method_candidates_by_receiver<T>(
|
||||
fn iterate_method_candidates_for_self_ty<T>(
|
||||
self_ty: &Canonical<Ty>,
|
||||
db: &impl HirDatabase,
|
||||
resolver: &Resolver,
|
||||
env: Arc<TraitEnvironment>,
|
||||
krate: CrateId,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
name: Option<&Name>,
|
||||
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
let krate = resolver.krate()?;
|
||||
if let Some(result) = iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) {
|
||||
return Some(result);
|
||||
}
|
||||
if let Some(result) =
|
||||
iterate_trait_method_candidates(self_ty, db, resolver, name, None, &mut callback)
|
||||
{
|
||||
if let Some(result) = iterate_trait_method_candidates(
|
||||
self_ty,
|
||||
db,
|
||||
env,
|
||||
krate,
|
||||
traits_in_scope,
|
||||
name,
|
||||
None,
|
||||
&mut callback,
|
||||
) {
|
||||
return Some(result);
|
||||
}
|
||||
None
|
||||
@ -329,14 +368,13 @@ fn iterate_method_candidates_for_self_ty<T>(
|
||||
fn iterate_trait_method_candidates<T>(
|
||||
self_ty: &Canonical<Ty>,
|
||||
db: &impl HirDatabase,
|
||||
resolver: &Resolver,
|
||||
env: Arc<TraitEnvironment>,
|
||||
krate: CrateId,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
name: Option<&Name>,
|
||||
receiver_ty: Option<&Canonical<Ty>>,
|
||||
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
let krate = resolver.krate()?;
|
||||
// FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
|
||||
let env = TraitEnvironment::lower(db, resolver);
|
||||
// if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope
|
||||
let inherent_trait = self_ty.value.inherent_trait().into_iter();
|
||||
// if we have `T: Trait` in the param env, the trait doesn't need to be in scope
|
||||
@ -344,8 +382,7 @@ fn iterate_trait_method_candidates<T>(
|
||||
.trait_predicates_for_self_ty(&self_ty.value)
|
||||
.map(|tr| tr.trait_)
|
||||
.flat_map(|t| all_super_traits(db, t));
|
||||
let traits =
|
||||
inherent_trait.chain(traits_from_env).chain(resolver.traits_in_scope(db).into_iter());
|
||||
let traits = inherent_trait.chain(traits_from_env).chain(traits_in_scope.iter().copied());
|
||||
'traits: for t in traits {
|
||||
let data = db.trait_data(t);
|
||||
|
||||
|
@ -53,13 +53,16 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Ty
|
||||
}
|
||||
|
||||
fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
|
||||
let mut seen_methods = FxHashSet::default();
|
||||
ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| {
|
||||
if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) {
|
||||
acc.add_function(ctx, func);
|
||||
}
|
||||
None::<()>
|
||||
});
|
||||
if let Some(krate) = ctx.module.map(|it| it.krate()) {
|
||||
let mut seen_methods = FxHashSet::default();
|
||||
let traits_in_scope = ctx.analyzer.traits_in_scope(ctx.db);
|
||||
receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| {
|
||||
if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) {
|
||||
acc.add_function(ctx, func);
|
||||
}
|
||||
None::<()>
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -49,22 +49,24 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
ctx.analyzer.iterate_path_candidates(ctx.db, &ty, None, |_ty, item| {
|
||||
match item {
|
||||
hir::AssocItem::Function(func) => {
|
||||
if !func.has_self_param(ctx.db) {
|
||||
acc.add_function(ctx, func);
|
||||
}
|
||||
}
|
||||
hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
|
||||
hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
|
||||
}
|
||||
None::<()>
|
||||
});
|
||||
// Iterate assoc types separately
|
||||
// FIXME: complete T::AssocType
|
||||
let krate = ctx.module.map(|m| m.krate());
|
||||
if let Some(krate) = krate {
|
||||
let traits_in_scope = ctx.analyzer.traits_in_scope(ctx.db);
|
||||
ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
|
||||
match item {
|
||||
hir::AssocItem::Function(func) => {
|
||||
if !func.has_self_param(ctx.db) {
|
||||
acc.add_function(ctx, func);
|
||||
}
|
||||
}
|
||||
hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
|
||||
hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
|
||||
}
|
||||
None::<()>
|
||||
});
|
||||
|
||||
ty.iterate_impl_items(ctx.db, krate, |item| {
|
||||
match item {
|
||||
hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user