Auto merge of #16709 - ShoyuVanilla:fix-goto-index-mut, r=Veykril

fix: Goto definition for `index_mut`

Mostly same with #16696.
0ac05c0527/crates/hir-ty/src/infer/mutability.rs (L103-L133)
Thankfully, we are doing similar method resolutions so we can use them like the mentioned PR.
As there are only three `LangItem`s having `Mut` in there names; `FnMut`, `DerefMut` and `IndexMut`, I think that this is the last one 😄
This commit is contained in:
bors 2024-02-29 13:55:23 +00:00
commit 0ec6015b6e
2 changed files with 44 additions and 1 deletions

View file

@ -420,7 +420,22 @@ impl SourceAnalyzer {
let base_ty = self.ty_of_expr(db, &index_expr.base()?)?; let base_ty = self.ty_of_expr(db, &index_expr.base()?)?;
let index_ty = self.ty_of_expr(db, &index_expr.index()?)?; let index_ty = self.ty_of_expr(db, &index_expr.index()?)?;
let (op_trait, op_fn) = self.lang_trait_fn(db, LangItem::Index, &name![index])?; let (index_trait, index_fn) = self.lang_trait_fn(db, LangItem::Index, &name![index])?;
let (op_trait, op_fn) = self
.infer
.as_ref()
.and_then(|infer| {
let expr = self.expr_id(db, &index_expr.clone().into())?;
let (func, _) = infer.method_resolution(expr)?;
let (index_mut_trait, index_mut_fn) =
self.lang_trait_fn(db, LangItem::IndexMut, &name![index_mut])?;
if func == index_mut_fn {
Some((index_mut_trait, index_mut_fn))
} else {
None
}
})
.unwrap_or((index_trait, index_fn));
// HACK: subst for all methods coincides with that for their trait because the methods // 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. // 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) let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None)

View file

@ -1955,6 +1955,34 @@ fn f() {
); );
} }
#[test]
fn goto_index_mut_op() {
check(
r#"
//- minicore: index
struct Foo;
struct Bar;
impl core::ops::Index<usize> for Foo {
type Output = Bar;
fn index(&self, index: usize) -> &Self::Output {}
}
impl core::ops::IndexMut<usize> for Foo {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {}
//^^^^^^^^^
}
fn f() {
let mut foo = Foo;
foo[0]$0 = Bar;
}
"#,
);
}
#[test] #[test]
fn goto_prefix_op() { fn goto_prefix_op() {
check( check(