functions resolve to impl
This commit is contained in:
parent
36fadc4224
commit
6ecabe352a
@ -348,9 +348,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
|||||||
self.imp.resolve_method_call(call).map(Function::from)
|
self.imp.resolve_method_call(call).map(Function::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_impl_method(&self, call: &ast::Expr) -> Option<Function> {
|
|
||||||
self.imp.resolve_impl_method(call).map(Function::from)
|
|
||||||
}
|
|
||||||
pub fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
|
pub fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
|
||||||
self.imp.resolve_method_call_as_callable(call)
|
self.imp.resolve_method_call_as_callable(call)
|
||||||
}
|
}
|
||||||
@ -981,10 +978,6 @@ impl<'db> SemanticsImpl<'db> {
|
|||||||
self.analyze(call.syntax())?.resolve_method_call(self.db, call).map(|(id, _)| id)
|
self.analyze(call.syntax())?.resolve_method_call(self.db, call).map(|(id, _)| id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_impl_method(&self, call: &ast::Expr) -> Option<FunctionId> {
|
|
||||||
self.analyze(call.syntax())?.resolve_impl_method(self.db, call)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
|
fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
|
||||||
let source_analyzer = self.analyze(call.syntax())?;
|
let source_analyzer = self.analyze(call.syntax())?;
|
||||||
let (func, subst) = source_analyzer.resolve_method_call(self.db, call)?;
|
let (func, subst) = source_analyzer.resolve_method_call(self.db, call)?;
|
||||||
|
@ -21,8 +21,8 @@ use hir_def::{
|
|||||||
path::{ModPath, Path, PathKind},
|
path::{ModPath, Path, PathKind},
|
||||||
resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
|
resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
|
||||||
type_ref::Mutability,
|
type_ref::Mutability,
|
||||||
AsMacroCall, DefWithBodyId, FieldId, FunctionId, ItemContainerId, LocalFieldId, Lookup,
|
AsMacroCall, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, LocalFieldId,
|
||||||
ModuleDefId, VariantId,
|
Lookup, ModuleDefId, VariantId,
|
||||||
};
|
};
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
builtin_fn_macro::BuiltinFnLikeExpander, hygiene::Hygiene, name::AsName, HirFileId, InFile,
|
builtin_fn_macro::BuiltinFnLikeExpander, hygiene::Hygiene, name::AsName, HirFileId, InFile,
|
||||||
@ -245,55 +245,9 @@ impl SourceAnalyzer {
|
|||||||
call: &ast::MethodCallExpr,
|
call: &ast::MethodCallExpr,
|
||||||
) -> Option<(FunctionId, Substitution)> {
|
) -> Option<(FunctionId, Substitution)> {
|
||||||
let expr_id = self.expr_id(db, &call.clone().into())?;
|
let expr_id = self.expr_id(db, &call.clone().into())?;
|
||||||
self.infer.as_ref()?.method_resolution(expr_id)
|
let (f_in_trait, substs) = self.infer.as_ref()?.method_resolution(expr_id)?;
|
||||||
}
|
let f_in_impl = self.resolve_impl_method(db, f_in_trait, &substs);
|
||||||
|
Some((f_in_impl.unwrap_or(f_in_trait), substs))
|
||||||
pub(crate) fn resolve_impl_method(
|
|
||||||
&self,
|
|
||||||
db: &dyn HirDatabase,
|
|
||||||
call: &ast::Expr,
|
|
||||||
) -> Option<FunctionId> {
|
|
||||||
let infered = self.infer.as_ref()?;
|
|
||||||
let expr_id = self.expr_id(db, call)?;
|
|
||||||
|
|
||||||
let mut fun_info = None;
|
|
||||||
match call {
|
|
||||||
&ast::Expr::MethodCallExpr(..) => {
|
|
||||||
let (func, subs) = infered.method_resolution(expr_id)?;
|
|
||||||
if subs.is_empty(Interner) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
fun_info.replace((func, subs.at(Interner, 0).ty(Interner)?.clone()));
|
|
||||||
}
|
|
||||||
&ast::Expr::PathExpr(..) => {
|
|
||||||
let func_ty = infered.type_of_expr.get(expr_id)?;
|
|
||||||
if let TyKind::FnDef(fn_def, subs) = func_ty.kind(Interner) {
|
|
||||||
if subs.is_empty(Interner) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
if let hir_ty::CallableDefId::FunctionId(f_id) =
|
|
||||||
db.lookup_intern_callable_def(fn_def.clone().into())
|
|
||||||
{
|
|
||||||
fun_info.replace((f_id, subs.at(Interner, 0).ty(Interner)?.clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
};
|
|
||||||
let (func, self_ty) = fun_info?;
|
|
||||||
let impled_trait = match func.lookup(db.upcast()).container {
|
|
||||||
ItemContainerId::TraitId(trait_id) => trait_id,
|
|
||||||
_ => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let krate = self.resolver.krate();
|
|
||||||
let trait_env = self.resolver.body_owner()?.as_generic_def_id().map_or_else(
|
|
||||||
|| Arc::new(hir_ty::TraitEnvironment::empty(krate)),
|
|
||||||
|d| db.trait_environment(d),
|
|
||||||
);
|
|
||||||
|
|
||||||
let fun_data = db.function_data(func);
|
|
||||||
method_resolution::lookup_impl_method(&self_ty, db, trait_env, impled_trait, &fun_data.name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn resolve_field(
|
pub(crate) fn resolve_field(
|
||||||
@ -391,6 +345,25 @@ impl SourceAnalyzer {
|
|||||||
let expr_id = self.expr_id(db, &path_expr.into())?;
|
let expr_id = self.expr_id(db, &path_expr.into())?;
|
||||||
let infer = self.infer.as_ref()?;
|
let infer = self.infer.as_ref()?;
|
||||||
if let Some(assoc) = infer.assoc_resolutions_for_expr(expr_id) {
|
if let Some(assoc) = infer.assoc_resolutions_for_expr(expr_id) {
|
||||||
|
let assoc = match assoc {
|
||||||
|
AssocItemId::FunctionId(f_in_trait) => {
|
||||||
|
match infer.type_of_expr.get(expr_id) {
|
||||||
|
None => assoc,
|
||||||
|
Some(func_ty) => {
|
||||||
|
if let TyKind::FnDef(_fn_def, subs) = func_ty.kind(Interner) {
|
||||||
|
self.resolve_impl_method(db, f_in_trait, subs)
|
||||||
|
.map(AssocItemId::FunctionId)
|
||||||
|
.unwrap_or(assoc)
|
||||||
|
} else {
|
||||||
|
assoc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => assoc,
|
||||||
|
};
|
||||||
|
|
||||||
return Some(PathResolution::Def(AssocItem::from(assoc).into()));
|
return Some(PathResolution::Def(AssocItem::from(assoc).into()));
|
||||||
}
|
}
|
||||||
if let Some(VariantId::EnumVariantId(variant)) =
|
if let Some(VariantId::EnumVariantId(variant)) =
|
||||||
@ -616,6 +589,30 @@ impl SourceAnalyzer {
|
|||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_impl_method(
|
||||||
|
&self,
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
func: FunctionId,
|
||||||
|
substs: &Substitution,
|
||||||
|
) -> Option<FunctionId> {
|
||||||
|
let impled_trait = match func.lookup(db.upcast()).container {
|
||||||
|
ItemContainerId::TraitId(trait_id) => trait_id,
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
if substs.is_empty(Interner) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let self_ty = substs.at(Interner, 0).ty(Interner)?;
|
||||||
|
let krate = self.resolver.krate();
|
||||||
|
let trait_env = self.resolver.body_owner()?.as_generic_def_id().map_or_else(
|
||||||
|
|| Arc::new(hir_ty::TraitEnvironment::empty(krate)),
|
||||||
|
|d| db.trait_environment(d),
|
||||||
|
);
|
||||||
|
|
||||||
|
let fun_data = db.function_data(func);
|
||||||
|
method_resolution::lookup_impl_method(self_ty, db, trait_env, impled_trait, &fun_data.name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scope_for(
|
fn scope_for(
|
||||||
|
@ -162,22 +162,6 @@ impl IdentClass {
|
|||||||
.or_else(|| NameClass::classify_lifetime(sema, lifetime).map(IdentClass::NameClass))
|
.or_else(|| NameClass::classify_lifetime(sema, lifetime).map(IdentClass::NameClass))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn classify_token_to_impl(
|
|
||||||
sema: &Semantics<RootDatabase>,
|
|
||||||
token: &SyntaxToken,
|
|
||||||
) -> Option<Definition> {
|
|
||||||
let p = token.parent()?;
|
|
||||||
match_ast! {
|
|
||||||
match p {
|
|
||||||
ast::NameRef(name_ref) => match NameRefClass::classify_to_impl(sema, name_ref)? {
|
|
||||||
NameRefClass::Definition(d) => Some(d),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn definitions(self) -> ArrayVec<Definition, 2> {
|
pub fn definitions(self) -> ArrayVec<Definition, 2> {
|
||||||
let mut res = ArrayVec::new();
|
let mut res = ArrayVec::new();
|
||||||
match self {
|
match self {
|
||||||
@ -433,29 +417,6 @@ impl NameRefClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn classify_to_impl(
|
|
||||||
sema: &Semantics<RootDatabase>,
|
|
||||||
name_ref: ast::NameRef,
|
|
||||||
) -> Option<NameRefClass> {
|
|
||||||
let parent = name_ref.syntax().parent()?;
|
|
||||||
let expr = match_ast! {
|
|
||||||
match parent {
|
|
||||||
ast::MethodCallExpr(method_call) => {
|
|
||||||
Some(ast::Expr::MethodCallExpr(method_call))
|
|
||||||
},
|
|
||||||
ast::PathSegment(..) => {
|
|
||||||
parent.ancestors()
|
|
||||||
.find_map(ast::PathExpr::cast)
|
|
||||||
.map(ast::Expr::PathExpr)
|
|
||||||
},
|
|
||||||
_=> None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
expr.as_ref()
|
|
||||||
.and_then(|e| sema.resolve_impl_method(e))
|
|
||||||
.map(Definition::Function)
|
|
||||||
.map(NameRefClass::Definition)
|
|
||||||
}
|
|
||||||
pub fn classify_lifetime(
|
pub fn classify_lifetime(
|
||||||
sema: &Semantics<RootDatabase>,
|
sema: &Semantics<RootDatabase>,
|
||||||
lifetime: &ast::Lifetime,
|
lifetime: &ast::Lifetime,
|
||||||
|
@ -65,7 +65,7 @@ pub(crate) fn goto_definition(
|
|||||||
.definitions()
|
.definitions()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|def| {
|
.flat_map(|def| {
|
||||||
try_filter_trait_item_definition(sema, &def, &token)
|
try_filter_trait_item_definition(sema, &def)
|
||||||
.unwrap_or_else(|| def_to_nav(sema.db, def))
|
.unwrap_or_else(|| def_to_nav(sema.db, def))
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
@ -114,14 +114,11 @@ fn try_lookup_include_path(
|
|||||||
fn try_filter_trait_item_definition(
|
fn try_filter_trait_item_definition(
|
||||||
sema: &Semantics<RootDatabase>,
|
sema: &Semantics<RootDatabase>,
|
||||||
def: &Definition,
|
def: &Definition,
|
||||||
token: &SyntaxToken,
|
|
||||||
) -> Option<Vec<NavigationTarget>> {
|
) -> Option<Vec<NavigationTarget>> {
|
||||||
let db = sema.db;
|
let db = sema.db;
|
||||||
let assoc = def.as_assoc_item(db)?;
|
let assoc = def.as_assoc_item(db)?;
|
||||||
match assoc {
|
match assoc {
|
||||||
AssocItem::Function(..) => {
|
AssocItem::Function(..) => None,
|
||||||
IdentClass::classify_token_to_impl(sema, &token).map(|def| def_to_nav(db, def))
|
|
||||||
}
|
|
||||||
AssocItem::Const(..) | AssocItem::TypeAlias(..) => {
|
AssocItem::Const(..) | AssocItem::TypeAlias(..) => {
|
||||||
let imp = match assoc.container(db) {
|
let imp = match assoc.container(db) {
|
||||||
hir::AssocItemContainer::Impl(imp) => imp,
|
hir::AssocItemContainer::Impl(imp) => imp,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user