Repository: intellij-rust/intellij-rust
Issue: False positive cannot move when str == str

## Environment

* **Intellij-Rust plugin version:** `0.2.91.2115-183`
* **Rust toolchain version:** `rustc 1.32.0 (stable-x86_64-pc-windows-gnu)`
* **IDE name and version:** `CLion 2018.3.3`
* **Operating system:** `Windows 10 (x64)`

## Problem description

IJ reports a "Cannot move" error when comparing two `str`, but it is legal upon compilation.

## Steps to reproduce

```rust
fn main() {
    let a = "abc";
    let b = "abc";

    // Cannot move less... (Ctrl+F1)
    // Inspection info: Implements simple cases of borrow checking. 
    if *a == *b {
        println!("Same str");
    }
}
```


Changed files:
src/main/kotlin/org/rust/lang/core/types/infer/TypeInference.kt, src/test/kotlin/org/rust/ide/inspections/borrowck/RsBorrowCheckerMovesTest.kt

diff --git a/src/main/kotlin/org/rust/lang/core/types/infer/TypeInference.kt b/src/main/kotlin/org/rust/lang/core/types/infer/TypeInference.kt
index e9c4b86a4..e993f5972 100644
--- a/src/main/kotlin/org/rust/lang/core/types/infer/TypeInference.kt
+++ b/src/main/kotlin/org/rust/lang/core/types/infer/TypeInference.kt
@@ -1434,13 +1434,11 @@ class RsFnInferenceContext(
                     val rhsType = resolveTypeVarsWithObligations(expr.right?.inferType() ?: TyUnknown)
                     enforceOverloadedBinopTypes(lhsType, rhsType, op)
 
-                    if (!isPrimitiveOrInferPrimitive(lhsType)) {
-                        val lhsAdjustment = BorrowReference(TyReference(lhsType, IMMUTABLE))
-                        ctx.addAdjustment(expr.left, lhsAdjustment)
+                    val lhsAdjustment = BorrowReference(TyReference(lhsType, IMMUTABLE))
+                    ctx.addAdjustment(expr.left, lhsAdjustment)
 
-                        val rhsAdjustment = BorrowReference(TyReference(rhsType, IMMUTABLE))
-                        expr.right?.let { ctx.addAdjustment(it, rhsAdjustment) }
-                    }
+                    val rhsAdjustment = BorrowReference(TyReference(rhsType, IMMUTABLE))
+                    expr.right?.let { ctx.addAdjustment(it, rhsAdjustment) }
                 } else {
                     expr.right?.inferTypeCoercableTo(lhsType)
                 }
@@ -1455,10 +1453,8 @@ class RsFnInferenceContext(
                     val rhsType = resolveTypeVarsWithObligations(expr.right?.inferType() ?: TyUnknown)
                     enforceOverloadedBinopTypes(lhsType, rhsType, op)
 
-                    if (!isPrimitiveOrInferPrimitive(lhsType)) {
-                        val lhsAdjustment = BorrowReference(TyReference(lhsType, MUTABLE))
-                        ctx.addAdjustment(expr.left, lhsAdjustment)
-                    }
+                    val lhsAdjustment = BorrowReference(TyReference(lhsType, MUTABLE))
+                    ctx.addAdjustment(expr.left, lhsAdjustment)
                 } else {
                     expr.right?.inferTypeCoercableTo(lhsType)
                 }
@@ -1472,9 +1468,6 @@ class RsFnInferenceContext(
         selection?.nestedObligations?.forEach(fulfill::registerPredicateObligation)
     }
 
-    private fun isPrimitiveOrInferPrimitive(lhsType: Ty) =
-        lhsType is TyPrimitive || lhsType is TyInfer.IntVar || lhsType is TyInfer.FloatVar
-
     private fun inferTryExprType(expr: RsTryExpr): Ty {
         val base = expr.expr.inferType() as? TyAdt ?: return TyUnknown
         // TODO: make it work with generic `std::ops::Try` trait
diff --git a/src/test/kotlin/org/rust/ide/inspections/borrowck/RsBorrowCheckerMovesTest.kt b/src/test/kotlin/org/rust/ide/inspections/borrowck/RsBorrowCheckerMovesTest.kt
index d5fbf6b0e..6b0d207e4 100644
--- a/src/test/kotlin/org/rust/ide/inspections/borrowck/RsBorrowCheckerMovesTest.kt
+++ b/src/test/kotlin/org/rust/ide/inspections/borrowck/RsBorrowCheckerMovesTest.kt
@@ -21,7 +21,7 @@ class RsBorrowCheckerMovesTest : RsInspectionsTestBase(RsBorrowCheckerInspection
             let x = S { data: 42 };
             let mut i = 0;
             while i < 10 {
-                if <error descr="Use of moved value">x.data</error> == 10 { f(<error descr="Use of moved value">x</error>); } else {}
+                if x.data == 10 { f(<error descr="Use of moved value">x</error>); } else {}
                 i += 1;
             }
             <error descr="Use of moved value">x<caret></error>;
@@ -338,4 +338,14 @@ class RsBorrowCheckerMovesTest : RsInspectionsTestBase(RsBorrowCheckerInspection
             };
         }
     """, checkWarn = false)
+
+    /** Issue [#3314](https://github.com/intellij-rust/intellij-rust/issues/3314) */
+    @ProjectDescriptor(WithStdlibRustProjectDescriptor::class)
+    fun `test no move error deref str inside binary expr`() = checkByText("""
+        fn main() {
+            let a = "abc";
+            let b = "abc";
+            if *a == *b {}
+        }
+    """, checkWarn = false)
 }