Repository: intellij-rust/intellij-rust
Issue:  Mutable reference in 'for in' loop erases types.

```rust
let mut xx: Vec<X> = Vec::new();
for x in &mut xx { x.0 = 42 }
```

`x` is `<unknown>` here and is highlighted as an immutable.
An assignment is also marked as "assignment to field of immutable binding [E0594]".

This looks similar to https://github.com/intellij-rust/intellij-rust/issues/1430 but for mutable references.


Changed files:
src/test/kotlin/org/rust/lang/core/resolve/RsTypeAwareGenericResolveTest.kt, src/test/kotlin/org/rust/lang/core/type/RsStdlibExpressionTypeInferenceTest.kt, src/main/kotlin/org/rust/lang/core/resolve/ImplLookup.kt, src/test/kotlin/org/rust/ide/hints/RsInlayParameterHintsProviderTest.kt

diff --git a/src/main/kotlin/org/rust/lang/core/resolve/ImplLookup.kt b/src/main/kotlin/org/rust/lang/core/resolve/ImplLookup.kt
index 40000a44d..fb9259bac 100644
--- a/src/main/kotlin/org/rust/lang/core/resolve/ImplLookup.kt
+++ b/src/main/kotlin/org/rust/lang/core/resolve/ImplLookup.kt
@@ -155,10 +155,6 @@ class ImplLookup(
         val trait = RsLangItemIndex.findLangItem(project, "index") ?: return@lazy null
         trait.findAssociatedType("Output")?.let { trait to it }
     }
-    private val iteratorTraitAndOutput: Pair<RsTraitItem, RsTypeAlias>? by lazy(NONE) {
-        val trait = items.findIteratorTrait() ?: return@lazy null
-        trait.findAssociatedType("Item")?.let { trait to it }
-    }
     private val intoIteratorTraitAndOutput: Pair<RsTraitItem, RsTypeAlias>? by lazy(NONE) {
         val trait = items.findCoreItem("iter::IntoIterator") as? RsTraitItem ?: return@lazy null
         trait.findAssociatedType("Item")?.let { trait to it }
@@ -530,8 +526,7 @@ class ImplLookup(
     }
 
     fun findIteratorItemType(ty: Ty): TyWithObligations<Ty>? {
-        return selectProjection(iteratorTraitAndOutput ?: return null, ty).ok()
-            ?: selectProjection(intoIteratorTraitAndOutput ?: return null, ty).ok()
+        return selectProjection(intoIteratorTraitAndOutput ?: return null, ty).ok()
     }
 
     fun findIndexOutputType(containerType: Ty, indexType: Ty): TyWithObligations<Ty>? {
diff --git a/src/test/kotlin/org/rust/ide/hints/RsInlayParameterHintsProviderTest.kt b/src/test/kotlin/org/rust/ide/hints/RsInlayParameterHintsProviderTest.kt
index 1f0721ba4..a04a69028 100644
--- a/src/test/kotlin/org/rust/ide/hints/RsInlayParameterHintsProviderTest.kt
+++ b/src/test/kotlin/org/rust/ide/hints/RsInlayParameterHintsProviderTest.kt
@@ -8,7 +8,9 @@ package org.rust.ide.hints
 import com.intellij.openapi.vfs.VirtualFileFilter
 import com.intellij.psi.PsiElement
 import org.intellij.lang.annotations.Language
+import org.rust.ProjectDescriptor
 import org.rust.RsTestBase
+import org.rust.WithStdlibRustProjectDescriptor
 import org.rust.fileTreeFromText
 import org.rust.lang.core.psi.*
 import org.rust.lang.core.psi.ext.ancestorOrSelf
@@ -239,9 +241,8 @@ class RsInlayParameterHintsProviderTest : RsTestBase() {
         }
     """, ": S<fn(i32) -> i32, S<fn(i32) -> i32, S<_, _>>>", 0)
 
+    @ProjectDescriptor(WithStdlibRustProjectDescriptor::class)
     fun `test inlay hint for loops`() = checkByText<RsForExpr>("""
-        #[lang = "std::iter::Iterator"]
-        trait Iterator { type Item; fn next(&mut self) -> Option<Self::Item>; }
         struct S;
         struct I;
         impl Iterator for I {
diff --git a/src/test/kotlin/org/rust/lang/core/resolve/RsTypeAwareGenericResolveTest.kt b/src/test/kotlin/org/rust/lang/core/resolve/RsTypeAwareGenericResolveTest.kt
index adcc5a4a8..f640a8ca6 100644
--- a/src/test/kotlin/org/rust/lang/core/resolve/RsTypeAwareGenericResolveTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/resolve/RsTypeAwareGenericResolveTest.kt
@@ -217,6 +217,17 @@ class RsTypeAwareGenericResolveTest : RsResolveTestBase() {
     fun `test iterator for loop resolve`() = checkByCode("""
         #[lang = "std::iter::Iterator"]
         trait Iterator { type Item; fn next(&mut self) -> Option<Self::Item>; }
+        #[lang = "std::iter::IntoIterator"]
+        trait IntoIterator {
+            type Item;
+            type IntoIter: Iterator<Item=Self::Item>;
+            fn into_iter(self) -> Self::IntoIter;
+        }
+        impl<I: Iterator> IntoIterator for I {
+            type Item = I::Item;
+            type IntoIter = I;
+            fn into_iter(self) -> I { self }
+        }
 
         struct S;
         impl S { fn foo(&self) {} }
diff --git a/src/test/kotlin/org/rust/lang/core/type/RsStdlibExpressionTypeInferenceTest.kt b/src/test/kotlin/org/rust/lang/core/type/RsStdlibExpressionTypeInferenceTest.kt
index e925c93ff..b00e34c8d 100644
--- a/src/test/kotlin/org/rust/lang/core/type/RsStdlibExpressionTypeInferenceTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/type/RsStdlibExpressionTypeInferenceTest.kt
@@ -494,7 +494,7 @@ class RsStdlibExpressionTypeInferenceTest : RsTypificationTestBase() {
         }
     """)
 
-    // https://github.com/intellij-rust/intellij-rust/issues/2514
+    /** Issue [#2514](https://github.com/intellij-rust/intellij-rust/issues/2514) */
     fun `test issue 2514`() = stubOnlyTypeInfer("""
     //- main.rs
         struct Foo {
@@ -508,4 +508,13 @@ class RsStdlibExpressionTypeInferenceTest : RsTypificationTestBase() {
             } //^ i32
         }
     """)
+
+    /** Issue [#2791](https://github.com/intellij-rust/intellij-rust/issues/2791)*/
+    fun `test issue 2791`() = stubOnlyTypeInfer("""
+    //- main.rs
+        fn main() {
+            let mut vec: Vec<i32> = Vec::new();
+            for x in &mut vec { x; }
+        }                     //^ &mut i32
+    """)
 }