Skip to content

Commit 0ec6015

Browse files
committed
Auto merge of rust-lang#16709 - ShoyuVanilla:fix-goto-index-mut, r=Veykril
fix: Goto definition for `index_mut` Mostly same with rust-lang#16696. https://github.com/rust-lang/rust-analyzer/blob/0ac05c05271f31c43d31017cbd288e8737a0edb0/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 😄
2 parents 0ac05c0 + bf23dee commit 0ec6015

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

crates/hir/src/source_analyzer.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,22 @@ impl SourceAnalyzer {
420420
let base_ty = self.ty_of_expr(db, &index_expr.base()?)?;
421421
let index_ty = self.ty_of_expr(db, &index_expr.index()?)?;
422422

423-
let (op_trait, op_fn) = self.lang_trait_fn(db, LangItem::Index, &name![index])?;
423+
let (index_trait, index_fn) = self.lang_trait_fn(db, LangItem::Index, &name![index])?;
424+
let (op_trait, op_fn) = self
425+
.infer
426+
.as_ref()
427+
.and_then(|infer| {
428+
let expr = self.expr_id(db, &index_expr.clone().into())?;
429+
let (func, _) = infer.method_resolution(expr)?;
430+
let (index_mut_trait, index_mut_fn) =
431+
self.lang_trait_fn(db, LangItem::IndexMut, &name![index_mut])?;
432+
if func == index_mut_fn {
433+
Some((index_mut_trait, index_mut_fn))
434+
} else {
435+
None
436+
}
437+
})
438+
.unwrap_or((index_trait, index_fn));
424439
// HACK: subst for all methods coincides with that for their trait because the methods
425440
// don't have any generic parameters, so we skip building another subst for the methods.
426441
let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None)

crates/ide/src/goto_definition.rs

+28
Original file line numberDiff line numberDiff line change
@@ -1955,6 +1955,34 @@ fn f() {
19551955
);
19561956
}
19571957

1958+
#[test]
1959+
fn goto_index_mut_op() {
1960+
check(
1961+
r#"
1962+
//- minicore: index
1963+
1964+
struct Foo;
1965+
struct Bar;
1966+
1967+
impl core::ops::Index<usize> for Foo {
1968+
type Output = Bar;
1969+
1970+
fn index(&self, index: usize) -> &Self::Output {}
1971+
}
1972+
1973+
impl core::ops::IndexMut<usize> for Foo {
1974+
fn index_mut(&mut self, index: usize) -> &mut Self::Output {}
1975+
//^^^^^^^^^
1976+
}
1977+
1978+
fn f() {
1979+
let mut foo = Foo;
1980+
foo[0]$0 = Bar;
1981+
}
1982+
"#,
1983+
);
1984+
}
1985+
19581986
#[test]
19591987
fn goto_prefix_op() {
19601988
check(

0 commit comments

Comments
 (0)