mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-28 04:45:05 +00:00
Use ImplItems instead of just Function
This commit is contained in:
parent
49da9a3e81
commit
3d8d880c59
3 changed files with 65 additions and 40 deletions
|
@ -29,6 +29,7 @@ use crate::{
|
||||||
Function, StructField, Path, Name,
|
Function, StructField, Path, Name,
|
||||||
FnSignature, AdtDef,
|
FnSignature, AdtDef,
|
||||||
HirDatabase,
|
HirDatabase,
|
||||||
|
ImplItem,
|
||||||
type_ref::{TypeRef, Mutability},
|
type_ref::{TypeRef, Mutability},
|
||||||
expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self},
|
expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self},
|
||||||
generics::GenericParams,
|
generics::GenericParams,
|
||||||
|
@ -54,8 +55,8 @@ pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> {
|
||||||
Arc::new(ctx.resolve_all())
|
Arc::new(ctx.resolve_all())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
enum ExprOrPatId {
|
pub enum ExprOrPatId {
|
||||||
Expr(ExprId),
|
Expr(ExprId),
|
||||||
Pat(PatId),
|
Pat(PatId),
|
||||||
}
|
}
|
||||||
|
@ -79,8 +80,8 @@ pub struct InferenceResult {
|
||||||
method_resolutions: FxHashMap<ExprId, Function>,
|
method_resolutions: FxHashMap<ExprId, Function>,
|
||||||
/// For each field access expr, records the field it resolves to.
|
/// For each field access expr, records the field it resolves to.
|
||||||
field_resolutions: FxHashMap<ExprId, StructField>,
|
field_resolutions: FxHashMap<ExprId, StructField>,
|
||||||
/// For each associated function call expr, records the function it resolves to
|
/// For each associated item record what it resolves to
|
||||||
assoc_fn_resolutions: FxHashMap<ExprId, Function>,
|
assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>,
|
||||||
pub(super) type_of_expr: ArenaMap<ExprId, Ty>,
|
pub(super) type_of_expr: ArenaMap<ExprId, Ty>,
|
||||||
pub(super) type_of_pat: ArenaMap<PatId, Ty>,
|
pub(super) type_of_pat: ArenaMap<PatId, Ty>,
|
||||||
}
|
}
|
||||||
|
@ -92,8 +93,8 @@ impl InferenceResult {
|
||||||
pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> {
|
pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> {
|
||||||
self.field_resolutions.get(&expr).map(|it| *it)
|
self.field_resolutions.get(&expr).map(|it| *it)
|
||||||
}
|
}
|
||||||
pub fn assoc_fn_resolutions(&self, expr: ExprId) -> Option<Function> {
|
pub fn assoc_resolutions(&self, id: ExprOrPatId) -> Option<ImplItem> {
|
||||||
self.assoc_fn_resolutions.get(&expr).map(|it| *it)
|
self.assoc_resolutions.get(&id).map(|it| *it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +123,7 @@ struct InferenceContext<'a, D: HirDatabase> {
|
||||||
var_unification_table: InPlaceUnificationTable<TypeVarId>,
|
var_unification_table: InPlaceUnificationTable<TypeVarId>,
|
||||||
method_resolutions: FxHashMap<ExprId, Function>,
|
method_resolutions: FxHashMap<ExprId, Function>,
|
||||||
field_resolutions: FxHashMap<ExprId, StructField>,
|
field_resolutions: FxHashMap<ExprId, StructField>,
|
||||||
assoc_fn_resolutions: FxHashMap<ExprId, Function>,
|
assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>,
|
||||||
type_of_expr: ArenaMap<ExprId, Ty>,
|
type_of_expr: ArenaMap<ExprId, Ty>,
|
||||||
type_of_pat: ArenaMap<PatId, Ty>,
|
type_of_pat: ArenaMap<PatId, Ty>,
|
||||||
/// The return type of the function being inferred.
|
/// The return type of the function being inferred.
|
||||||
|
@ -134,7 +135,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
InferenceContext {
|
InferenceContext {
|
||||||
method_resolutions: FxHashMap::default(),
|
method_resolutions: FxHashMap::default(),
|
||||||
field_resolutions: FxHashMap::default(),
|
field_resolutions: FxHashMap::default(),
|
||||||
assoc_fn_resolutions: FxHashMap::default(),
|
assoc_resolutions: FxHashMap::default(),
|
||||||
type_of_expr: ArenaMap::default(),
|
type_of_expr: ArenaMap::default(),
|
||||||
type_of_pat: ArenaMap::default(),
|
type_of_pat: ArenaMap::default(),
|
||||||
var_unification_table: InPlaceUnificationTable::new(),
|
var_unification_table: InPlaceUnificationTable::new(),
|
||||||
|
@ -160,7 +161,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
InferenceResult {
|
InferenceResult {
|
||||||
method_resolutions: self.method_resolutions,
|
method_resolutions: self.method_resolutions,
|
||||||
field_resolutions: self.field_resolutions,
|
field_resolutions: self.field_resolutions,
|
||||||
assoc_fn_resolutions: self.assoc_fn_resolutions,
|
assoc_resolutions: self.assoc_resolutions,
|
||||||
type_of_expr: expr_types,
|
type_of_expr: expr_types,
|
||||||
type_of_pat: pat_types,
|
type_of_pat: pat_types,
|
||||||
}
|
}
|
||||||
|
@ -178,8 +179,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
self.field_resolutions.insert(expr, field);
|
self.field_resolutions.insert(expr, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_assoc_fn_resolution(&mut self, expr: ExprId, func: Function) {
|
fn write_assoc_resolution(&mut self, id: ExprOrPatId, item: ImplItem) {
|
||||||
self.assoc_fn_resolutions.insert(expr, func);
|
self.assoc_resolutions.insert(id, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_pat_ty(&mut self, pat: PatId, ty: Ty) {
|
fn write_pat_ty(&mut self, pat: PatId, ty: Ty) {
|
||||||
|
@ -423,26 +424,47 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
// Attempt to find an impl_item for the type which has a name matching
|
// Attempt to find an impl_item for the type which has a name matching
|
||||||
// the current segment
|
// the current segment
|
||||||
log::debug!("looking for path segment: {:?}", segment);
|
log::debug!("looking for path segment: {:?}", segment);
|
||||||
let item: crate::ModuleDef = ty.iterate_impl_items(self.db, |item| match item {
|
let item: crate::ModuleDef = ty.iterate_impl_items(self.db, |item| {
|
||||||
crate::ImplItem::Method(func) => {
|
let matching_def: Option<crate::ModuleDef> = match item {
|
||||||
let sig = func.signature(self.db);
|
crate::ImplItem::Method(func) => {
|
||||||
if segment.name == *sig.name() {
|
let sig = func.signature(self.db);
|
||||||
return Some(func.into());
|
if segment.name == *sig.name() {
|
||||||
|
Some(func.into())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
crate::ImplItem::Const(konst) => {
|
crate::ImplItem::Const(konst) => {
|
||||||
let sig = konst.signature(self.db);
|
let sig = konst.signature(self.db);
|
||||||
if segment.name == *sig.name() {
|
if segment.name == *sig.name() {
|
||||||
return Some(konst.into());
|
Some(konst.into())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Resolve associated types
|
// TODO: Resolve associated types
|
||||||
crate::ImplItem::TypeAlias(_) => None,
|
crate::ImplItem::TypeAlias(_) => None,
|
||||||
|
};
|
||||||
|
match matching_def {
|
||||||
|
Some(_) => {
|
||||||
|
self.write_assoc_resolution(id, item);
|
||||||
|
return matching_def;
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if let ExprOrPatId::Expr(expr) = id {
|
||||||
|
match typable {
|
||||||
|
TypableDef::Function(func) => self.write_assoc_fn_resolution(expr, func),
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
resolved = Resolution::Def(item.into());
|
resolved = Resolution::Def(item.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,14 +472,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
Resolution::Def(def) => {
|
Resolution::Def(def) => {
|
||||||
let typable: Option<TypableDef> = def.into();
|
let typable: Option<TypableDef> = def.into();
|
||||||
let typable = typable?;
|
let typable = typable?;
|
||||||
|
|
||||||
if let ExprOrPatId::Expr(expr) = id {
|
|
||||||
match typable {
|
|
||||||
TypableDef::Function(func) => self.write_assoc_fn_resolution(expr, func),
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
|
let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
|
||||||
let ty = self.db.type_for_def(typable, Namespace::Values).apply_substs(substs);
|
let ty = self.db.type_for_def(typable, Namespace::Values).apply_substs(substs);
|
||||||
let ty = self.insert_type_vars(ty);
|
let ty = self.insert_type_vars(ty);
|
||||||
|
|
|
@ -5,7 +5,7 @@ use ra_syntax::{
|
||||||
SyntaxNode,
|
SyntaxNode,
|
||||||
};
|
};
|
||||||
use test_utils::tested_by;
|
use test_utils::tested_by;
|
||||||
use hir::Resolution;
|
use hir::{ImplItem, Resolution};
|
||||||
|
|
||||||
use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo};
|
use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo};
|
||||||
|
|
||||||
|
@ -131,14 +131,25 @@ pub(crate) fn reference_definition(
|
||||||
name_ref.syntax().ancestors().find_map(ast::PathExpr::cast)
|
name_ref.syntax().ancestors().find_map(ast::PathExpr::cast)
|
||||||
{
|
{
|
||||||
let infer_result = function.infer(db);
|
let infer_result = function.infer(db);
|
||||||
let syntax_mapping = function.body_syntax_mapping(db);
|
let source_map = function.body_source_map(db);
|
||||||
let expr = ast::Expr::cast(path_expr.syntax()).unwrap();
|
let expr = ast::Expr::cast(path_expr.syntax()).unwrap();
|
||||||
|
|
||||||
if let Some(func) = syntax_mapping
|
if let Some(res) = source_map
|
||||||
.node_expr(expr)
|
.node_expr(expr)
|
||||||
.and_then(|it| infer_result.assoc_fn_resolutions(it))
|
.and_then(|it| infer_result.assoc_resolutions(it.into()))
|
||||||
{
|
{
|
||||||
return Exact(NavigationTarget::from_function(db, func));
|
match res {
|
||||||
|
ImplItem::Method(f) => {
|
||||||
|
return Exact(NavigationTarget::from_function(db, f));
|
||||||
|
}
|
||||||
|
ImplItem::Const(c) => {
|
||||||
|
let (file, node) = c.source(db);
|
||||||
|
let file = file.original_file(db);
|
||||||
|
let node = &*node;
|
||||||
|
return Exact(NavigationTarget::from_named(file, node));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -531,7 +531,7 @@ mod tests {
|
||||||
",
|
",
|
||||||
);
|
);
|
||||||
let hover = analysis.hover(position).unwrap().unwrap();
|
let hover = analysis.hover(position).unwrap().unwrap();
|
||||||
assert_eq!(hover.info.first(), Some("```rust\nfn new() -> Thing\n```"));
|
assert_eq!(trim_markup_opt(hover.info.first()), Some("fn new() -> Thing"));
|
||||||
assert_eq!(hover.info.is_exact(), true);
|
assert_eq!(hover.info.is_exact(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue