From 49da9a3e814a42a2f4dea0cd79dbdae86bea5ce4 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Fri, 1 Mar 2019 18:26:49 -0500 Subject: Make goto definition/hover resolve constructors --- crates/ra_hir/src/ty/infer.rs | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 5e4d49ffb..f7a35f05b 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -54,6 +54,24 @@ pub fn infer(db: &impl HirDatabase, func: Function) -> Arc { Arc::new(ctx.resolve_all()) } +#[derive(Debug, Copy, Clone)] +enum ExprOrPatId { + Expr(ExprId), + Pat(PatId), +} + +impl From for ExprOrPatId { + fn from(id: ExprId) -> Self { + ExprOrPatId::Expr(id) + } +} + +impl From for ExprOrPatId { + fn from(id: PatId) -> Self { + ExprOrPatId::Pat(id) + } +} + /// The result of type inference: A mapping from expressions and patterns to types. #[derive(Clone, PartialEq, Eq, Debug)] pub struct InferenceResult { @@ -61,6 +79,8 @@ pub struct InferenceResult { method_resolutions: FxHashMap, /// For each field access expr, records the field it resolves to. field_resolutions: FxHashMap, + /// For each associated function call expr, records the function it resolves to + assoc_fn_resolutions: FxHashMap, pub(super) type_of_expr: ArenaMap, pub(super) type_of_pat: ArenaMap, } @@ -72,6 +92,9 @@ impl InferenceResult { pub fn field_resolution(&self, expr: ExprId) -> Option { self.field_resolutions.get(&expr).map(|it| *it) } + pub fn assoc_fn_resolutions(&self, expr: ExprId) -> Option { + self.assoc_fn_resolutions.get(&expr).map(|it| *it) + } } impl Index for InferenceResult { @@ -99,6 +122,7 @@ struct InferenceContext<'a, D: HirDatabase> { var_unification_table: InPlaceUnificationTable, method_resolutions: FxHashMap, field_resolutions: FxHashMap, + assoc_fn_resolutions: FxHashMap, type_of_expr: ArenaMap, type_of_pat: ArenaMap, /// The return type of the function being inferred. @@ -110,6 +134,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { InferenceContext { method_resolutions: FxHashMap::default(), field_resolutions: FxHashMap::default(), + assoc_fn_resolutions: FxHashMap::default(), type_of_expr: ArenaMap::default(), type_of_pat: ArenaMap::default(), var_unification_table: InPlaceUnificationTable::new(), @@ -135,6 +160,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { InferenceResult { method_resolutions: self.method_resolutions, field_resolutions: self.field_resolutions, + assoc_fn_resolutions: self.assoc_fn_resolutions, type_of_expr: expr_types, type_of_pat: pat_types, } @@ -152,6 +178,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.field_resolutions.insert(expr, field); } + fn write_assoc_fn_resolution(&mut self, expr: ExprId, func: Function) { + self.assoc_fn_resolutions.insert(expr, func); + } + fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { self.type_of_pat.insert(pat, ty); } @@ -341,7 +371,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }) } - fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path) -> Option { + fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path, id: ExprOrPatId) -> Option { let resolved = resolver.resolve_path_segments(self.db, &path); let (def, remaining_index) = resolved.into_inner(); @@ -421,6 +451,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let typable: Option = def.into(); 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 ty = self.db.type_for_def(typable, Namespace::Values).apply_substs(substs); let ty = self.insert_type_vars(ty); @@ -572,7 +609,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Pat::Path(path) => { // TODO use correct resolver for the surrounding expression let resolver = self.resolver.clone(); - self.infer_path_expr(&resolver, &path).unwrap_or(Ty::Unknown) + self.infer_path_expr(&resolver, &path, pat.into()).unwrap_or(Ty::Unknown) } Pat::Bind { mode, name: _name, subpat } => { let inner_ty = if let Some(subpat) = subpat { @@ -782,7 +819,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Expr::Path(p) => { // TODO this could be more efficient... let resolver = expr::resolver_for_expr(self.body.clone(), self.db, tgt_expr); - self.infer_path_expr(&resolver, p).unwrap_or(Ty::Unknown) + self.infer_path_expr(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) } Expr::Continue => Ty::Never, Expr::Break { expr } => { -- cgit v1.2.3