diff --git a/crates/ide-completion/src/completions/dot.rs b/crates/ide-completion/src/completions/dot.rs index a00c6ecb91..c5bbb7f8d7 100644 --- a/crates/ide-completion/src/completions/dot.rs +++ b/crates/ide-completion/src/completions/dot.rs @@ -113,8 +113,12 @@ fn complete_fields( } } for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() { - // Tuple fields are always public (tuple struct fields are handled above). - tuple_index(acc, i, ty); + // Tuples are always the last type in a deref chain, so just check if the name is + // already seen without inserting into the hashset. + if !seen_names.contains(&hir::Name::new_tuple_field(i)) { + // Tuple fields are always public (tuple struct fields are handled above). + tuple_index(acc, i, ty); + } } } } @@ -720,6 +724,28 @@ fn test(a: A) { ); } + #[test] + fn test_tuple_struct_deref_to_tuple_no_same_index() { + check( + r#" +//- minicore: deref +struct A(u8); +impl core::ops::Deref for A { + type Target = (u16, u32); + fn deref(&self) -> &Self::Target { loop {} } +} +fn test(a: A) { + a.$0 +} +"#, + expect![[r#" + fd 0 u8 + fd 1 u32 + me deref() (use core::ops::Deref) fn(&self) -> &::Target + "#]], + ); + } + #[test] fn test_completion_works_in_consts() { check(