mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 21:05:02 +00:00
Move Type API to type
This commit is contained in:
parent
21c5fd8b1b
commit
a38540771f
4 changed files with 102 additions and 85 deletions
|
@ -21,8 +21,8 @@ use hir_expand::{
|
||||||
MacroDefId,
|
MacroDefId,
|
||||||
};
|
};
|
||||||
use hir_ty::{
|
use hir_ty::{
|
||||||
autoderef, display::HirFormatter, expr::ExprValidator, method_resolution::implements_trait,
|
autoderef, display::HirFormatter, expr::ExprValidator, method_resolution, ApplicationTy,
|
||||||
ApplicationTy, Canonical, InEnvironment, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk,
|
Canonical, InEnvironment, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk,
|
||||||
};
|
};
|
||||||
use ra_db::{CrateId, Edition, FileId};
|
use ra_db::{CrateId, Edition, FileId};
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
|
@ -120,7 +120,8 @@ impl_froms!(
|
||||||
BuiltinType
|
BuiltinType
|
||||||
);
|
);
|
||||||
|
|
||||||
pub use hir_def::{attr::Attrs, visibility::Visibility};
|
pub use hir_def::{attr::Attrs, visibility::Visibility, AssocItemId};
|
||||||
|
use rustc_hash::FxHashSet;
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> 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 };
|
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.
|
// FIXME: this method is broken, as it doesn't take closures into account.
|
||||||
|
@ -1002,6 +1009,65 @@ impl Type {
|
||||||
None
|
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> {
|
pub fn as_adt(&self) -> Option<Adt> {
|
||||||
let (adt, _subst) = self.ty.value.as_adt()?;
|
let (adt, _subst) = self.ty.value.as_adt()?;
|
||||||
Some(adt.into())
|
Some(adt.into())
|
||||||
|
|
|
@ -16,12 +16,12 @@ use hir_def::{
|
||||||
expr::{ExprId, PatId},
|
expr::{ExprId, PatId},
|
||||||
nameres::ModuleSource,
|
nameres::ModuleSource,
|
||||||
resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs},
|
resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs},
|
||||||
AssocItemId, DefWithBodyId,
|
DefWithBodyId, TraitId,
|
||||||
};
|
};
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind,
|
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_prof::profile;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode},
|
||||||
|
@ -29,11 +29,11 @@ use ra_syntax::{
|
||||||
SyntaxKind::*,
|
SyntaxKind::*,
|
||||||
SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextUnit,
|
SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextUnit,
|
||||||
};
|
};
|
||||||
|
use rustc_hash::FxHashSet;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase, Adt, AssocItem, Const, DefWithBody, Enum, EnumVariant, FromSource, Function,
|
db::HirDatabase, Adt, Const, DefWithBody, Enum, EnumVariant, FromSource, Function, ImplBlock,
|
||||||
ImplBlock, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias,
|
Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam,
|
||||||
TypeParam,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
|
/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
|
||||||
|
@ -347,63 +347,9 @@ impl SourceAnalyzer {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iterate_method_candidates<T>(
|
/// Note: `FxHashSet<TraitId>` should be treated as an opaque type, passed into `Type
|
||||||
&self,
|
pub fn traits_in_scope(&self, db: &impl HirDatabase) -> FxHashSet<TraitId> {
|
||||||
db: &impl HirDatabase,
|
self.resolver.traits_in_scope(db)
|
||||||
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 };
|
|
||||||
|
|
||||||
let env = TraitEnvironment::lower(db, &self.resolver);
|
|
||||||
let krate = self.resolver.krate()?;
|
|
||||||
let traits_in_scope = self.resolver.traits_in_scope(db);
|
|
||||||
|
|
||||||
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,
|
|
||||||
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 };
|
|
||||||
|
|
||||||
let env = TraitEnvironment::lower(db, &self.resolver);
|
|
||||||
let krate = self.resolver.krate()?;
|
|
||||||
let traits_in_scope = self.resolver.traits_in_scope(db);
|
|
||||||
|
|
||||||
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 expand(
|
pub fn expand(
|
||||||
|
|
|
@ -53,13 +53,16 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Ty
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
|
fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
|
||||||
let mut seen_methods = FxHashSet::default();
|
if let Some(krate) = ctx.module.map(|it| it.krate()) {
|
||||||
ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| {
|
let mut seen_methods = FxHashSet::default();
|
||||||
if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) {
|
let traits_in_scope = ctx.analyzer.traits_in_scope(ctx.db);
|
||||||
acc.add_function(ctx, func);
|
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)) {
|
||||||
None::<()>
|
acc.add_function(ctx, func);
|
||||||
});
|
}
|
||||||
|
None::<()>
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -49,22 +49,24 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
|
hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
|
||||||
_ => unreachable!(),
|
_ => 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
|
// Iterate assoc types separately
|
||||||
// FIXME: complete T::AssocType
|
// FIXME: complete T::AssocType
|
||||||
let krate = ctx.module.map(|m| m.krate());
|
let krate = ctx.module.map(|m| m.krate());
|
||||||
if let Some(krate) = 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| {
|
ty.iterate_impl_items(ctx.db, krate, |item| {
|
||||||
match item {
|
match item {
|
||||||
hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}
|
hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue