From d1bdebf2b969eee013de2c8f3a2512f799e00263 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Tue, 27 Feb 2024 23:53:43 +0900 Subject: [PATCH 1/3] Add a new failing test for goto deref_mut --- crates/ide/src/goto_definition.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index 88255d222ed8..35efe144e1b9 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -1977,6 +1977,33 @@ fn f() { ); } + #[test] + fn goto_deref_mut() { + check( + r#" +//- minicore: deref, deref_mut + +struct Foo; +struct Bar; + +impl core::ops::Deref for Foo { + type Target = Bar; + fn deref(&self) -> &Self::Target {} +} + +impl core::ops::DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Self::Target {} + //^^^^^^^^^ +} + +fn f() { + let a = Foo; + $0*a = Bar; +} +"#, + ); + } + #[test] fn goto_bin_op() { check( From 0f4e313028df78bb637f67ec1f936a3fc7f18f34 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Tue, 27 Feb 2024 23:55:19 +0900 Subject: [PATCH 2/3] Fix goto `deref_mut` --- crates/hir/src/source_analyzer.rs | 32 +++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index fd0a11784215..a3dea4f8030d 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -42,7 +42,7 @@ use hir_ty::{ use itertools::Itertools; use smallvec::SmallVec; use syntax::{ - ast::{self, AstNode}, + ast::{self, AstNode, BinExpr, Expr, IdentPat, PathExpr}, SyntaxKind, SyntaxNode, TextRange, TextSize, }; use triomphe::Arc; @@ -377,14 +377,34 @@ impl SourceAnalyzer { db: &dyn HirDatabase, prefix_expr: &ast::PrefixExpr, ) -> Option { - let (lang_item, fn_name) = match prefix_expr.op_kind()? { - ast::UnaryOp::Deref => (LangItem::Deref, name![deref]), - ast::UnaryOp::Not => (LangItem::Not, name![not]), - ast::UnaryOp::Neg => (LangItem::Neg, name![neg]), + let (op_trait, op_fn) = match prefix_expr.op_kind()? { + ast::UnaryOp::Deref => { + // This can be either `Deref::deref` or `DerefMut::deref_mut`. + // Since deref kind is inferenced and stored in `InferenceResult.method_resolution`, + // use that result to find out which one it is. + let (deref_trait, deref) = + self.lang_trait_fn(db, LangItem::Deref, &name![deref])?; + self.infer + .as_ref() + .and_then(|infer| { + let expr = self.expr_id(db, &prefix_expr.clone().into())?; + let (func, _) = infer.method_resolution(expr)?; + let (deref_mut_trait, deref_mut) = + self.lang_trait_fn(db, LangItem::DerefMut, &name![deref_mut])?; + if func == deref_mut { + Some((deref_mut_trait, deref_mut)) + } else { + None + } + }) + .unwrap_or((deref_trait, deref)) + } + ast::UnaryOp::Not => self.lang_trait_fn(db, LangItem::Not, &name![not])?, + ast::UnaryOp::Neg => self.lang_trait_fn(db, LangItem::Neg, &name![neg])?, }; + let ty = self.ty_of_expr(db, &prefix_expr.expr()?)?; - let (op_trait, op_fn) = self.lang_trait_fn(db, lang_item, &fn_name)?; // HACK: subst for all methods coincides with that for their trait because the methods // don't have any generic parameters, so we skip building another subst for the methods. let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None).push(ty.clone()).build(); From 612443111b207044d4a7b204d2eab9a1d2ee914c Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 28 Feb 2024 00:10:08 +0900 Subject: [PATCH 3/3] Remove unused imports --- crates/hir/src/source_analyzer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index a3dea4f8030d..bcc9111f2ba1 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -42,7 +42,7 @@ use hir_ty::{ use itertools::Itertools; use smallvec::SmallVec; use syntax::{ - ast::{self, AstNode, BinExpr, Expr, IdentPat, PathExpr}, + ast::{self, AstNode}, SyntaxKind, SyntaxNode, TextRange, TextSize, }; use triomphe::Arc;