Repository: intellij-rust/intellij-rust
Issue: Erroneous Red Underline In `Ord` Implementation

<!--
Hello and thank you for the issue!
If you would like to report a bug, we have added some points below that you can fill out.
Feel free to remove all the irrelevant text to request a new feature.
-->

## Environment

* **IntelliJ Rust plugin version:** 0.3.126.3220-202
* **Rust toolchain version:** 1.45.0 (5c1f21c3b 2020-07-13) x86_64-apple-darwin
* **IDE name and version:** CLion 2020.2 Beta (CL-202.6397.12)
* **Operating system:** macOS 10.15.6

## Problem description
An implementation of `Ord` and `PartialOrd`. for a struct which compiles correctly shows a red underline on the `Ord` impl, with the mouse over error: "the trait bound `Example<A, B>: PartialOrd<Example<A, B>>` is not satisf [E277]"

## Steps to reproduce

```rust
use std::cmp::{Ord, Ordering};
use std::time::Instant;

#[derive(Eq, PartialEq)]
struct Example<A, B>
    where A: Ord,
          B: Eq + PartialEq,
{
    a: A,
    b: B,
    c: u8,
    d: Instant,  // We can presume `Instant`s will never be == here
}

impl <A, B> PartialOrd for Example<A, B>
    where A: Ord,
          B: Eq + PartialEq,
{
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

// The `Ord` here has the red underline and the mouse over error described
impl <A, B> Ord for Example<A, B>
    where A: Ord,
          B: Eq + PartialEq,
{
    fn cmp(&self, other: &Self) -> Ordering {
        self.c.cmp(&other.c).then_with(||other.d.cmp(&self.d))
    }
}

```
<!--
Please include as much of your codebase as needed to reproduce the error.
If the relevant files are large, please provide a link to a public repository or a [Gist](https://gist.github.com/).
-->            


Changed files:
src/main/kotlin/org/rust/lang/core/resolve/ref/RsPathReferenceImpl.kt, src/main/kotlin/org/rust/ide/annotator/RsErrorAnnotator.kt, src/test/kotlin/org/rust/ide/annotator/RsErrorAnnotatorTest.kt

diff --git a/src/main/kotlin/org/rust/ide/annotator/RsErrorAnnotator.kt b/src/main/kotlin/org/rust/ide/annotator/RsErrorAnnotator.kt
index 9eb54edde..c93ae146e 100644
--- a/src/main/kotlin/org/rust/ide/annotator/RsErrorAnnotator.kt
+++ b/src/main/kotlin/org/rust/ide/annotator/RsErrorAnnotator.kt
@@ -11,6 +11,7 @@ import com.intellij.ide.annotator.AnnotatorBase
 import com.intellij.lang.annotation.AnnotationHolder
 import com.intellij.lang.annotation.AnnotationSession
 import com.intellij.openapi.util.Key
+import com.intellij.openapiext.isUnitTestMode
 import com.intellij.psi.PsiElement
 import com.intellij.psi.PsiFile
 import com.intellij.psi.util.PsiTreeUtil
@@ -577,7 +578,7 @@ class RsErrorAnnotator : AnnotatorBase(), HighlightRangeExtension {
     }
 
     private fun checkSuperTraitImplemented(holder: RsAnnotationHolder, impl: RsImplItem, trait: RsTraitItem) {
-        if (impl.project.macroExpansionManager.macroExpansionMode !is MacroExpansionMode.New) return
+        if (!isUnitTestMode && impl.project.macroExpansionManager.macroExpansionMode !is MacroExpansionMode.New) return
 
         val traitRef = impl.traitRef ?: return
         val typeRef = impl.typeReference ?: return
diff --git a/src/main/kotlin/org/rust/lang/core/resolve/ref/RsPathReferenceImpl.kt b/src/main/kotlin/org/rust/lang/core/resolve/ref/RsPathReferenceImpl.kt
index 32a6896ae..d8e7a0a31 100644
--- a/src/main/kotlin/org/rust/lang/core/resolve/ref/RsPathReferenceImpl.kt
+++ b/src/main/kotlin/org/rust/lang/core/resolve/ref/RsPathReferenceImpl.kt
@@ -10,17 +10,14 @@ import com.intellij.psi.ResolveResult
 import org.rust.lang.core.psi.*
 import org.rust.lang.core.psi.ext.*
 import org.rust.lang.core.resolve.*
-import org.rust.lang.core.types.BoundElement
-import org.rust.lang.core.types.Substitution
+import org.rust.lang.core.types.*
 import org.rust.lang.core.types.consts.CtConstParameter
 import org.rust.lang.core.types.consts.CtUnknown
 import org.rust.lang.core.types.infer.foldTyInferWith
 import org.rust.lang.core.types.infer.resolve
 import org.rust.lang.core.types.infer.substitute
-import org.rust.lang.core.types.inference
 import org.rust.lang.core.types.regions.ReEarlyBound
 import org.rust.lang.core.types.ty.*
-import org.rust.lang.core.types.type
 import org.rust.lang.utils.evaluation.PathExprResolver
 import org.rust.lang.utils.evaluation.evaluate
 import org.rust.stdext.buildMap
@@ -217,7 +214,20 @@ fun <T : RsElement> instantiatePathGenerics(
         } else {
             // Args aren't optional, and some args/turbofish aren't present OR not optional and turbofis is present.
             // Use either default argument from a definition `struct S<T=u8>(T);` or falling back to `TyUnknown`
-            param.typeReference?.type ?: TyUnknown
+            val defaultTy = param.typeReference?.type ?: TyUnknown
+
+            if (parent is RsTraitRef && parent.parent is RsBound) {
+                val pred = parent.ancestorStrict<RsWherePred>()
+                val selfTy = if (pred != null) {
+                    pred.typeReference?.type
+                } else {
+                    parent.ancestorStrict<RsTypeParameter>()?.declaredType
+                } ?: TyUnknown
+
+                defaultTy.substitute(mapOf(TyTypeParameter.self() to selfTy).toTypeSubst())
+            } else {
+                defaultTy
+            }
         }
         paramTy to value
     }
diff --git a/src/test/kotlin/org/rust/ide/annotator/RsErrorAnnotatorTest.kt b/src/test/kotlin/org/rust/ide/annotator/RsErrorAnnotatorTest.kt
index 2a9ebb4a2..efe7bf66c 100644
--- a/src/test/kotlin/org/rust/ide/annotator/RsErrorAnnotatorTest.kt
+++ b/src/test/kotlin/org/rust/ide/annotator/RsErrorAnnotatorTest.kt
@@ -1426,7 +1426,6 @@ class RsErrorAnnotatorTest : RsAnnotatorTestBase(RsErrorAnnotator::class) {
 //        }
     """)
 
-    @ExpandMacros
     fun `test supertrait is not implemented E0277 simple trait`() = checkErrors("""
         trait A {}
         trait B: A {}
@@ -1436,7 +1435,6 @@ class RsErrorAnnotatorTest : RsAnnotatorTestBase(RsErrorAnnotator::class) {
         impl <error descr="the trait bound `S: A` is not satisfied [E0277]">B</error> for S {}
     """)
 
-    @ExpandMacros
     fun `test supertrait is not implemented E0277 multiple traits`() = checkErrors("""
         trait A {}
         trait B {}
@@ -1448,7 +1446,6 @@ class RsErrorAnnotatorTest : RsAnnotatorTestBase(RsErrorAnnotator::class) {
         impl <error descr="the trait bound `S: B` is not satisfied [E0277]"><error descr="the trait bound `S: A` is not satisfied [E0277]">C</error></error> for S {}
     """)
 
-    @ExpandMacros
     fun `test supertrait is not implemented E0277 generic supertrait`() = checkErrors("""
         trait A<T> {}
         trait B: A<u32> {}
@@ -1490,7 +1487,6 @@ class RsErrorAnnotatorTest : RsAnnotatorTestBase(RsErrorAnnotator::class) {
         impl C<u32> for S9 {}
     """)
 
-    @ExpandMacros
     fun `test supertrait is not implemented E0277 ignore unknown type`() = checkErrors("""
         trait A<T> {}
         trait B<T>: A<T> {}
@@ -1499,7 +1495,6 @@ class RsErrorAnnotatorTest : RsAnnotatorTestBase(RsErrorAnnotator::class) {
         impl B<Foo> for S {}
     """)
 
-    @ExpandMacros
     fun `test supertrait is not implemented E0277 self substitution`() = checkErrors("""
         trait Tr1<A=Self> {}
         trait Tr2<A=Self> : Tr1<A> {}
@@ -1509,6 +1504,26 @@ class RsErrorAnnotatorTest : RsAnnotatorTestBase(RsErrorAnnotator::class) {
         impl Tr2 for S {}
     """)
 
+    fun `test supertrait is not implemented E0277 self substitution 2`() = checkErrors("""
+        trait Trait<Rhs: ?Sized = Self> {}
+        trait Trait2: Trait<Self> {}
+
+        struct X<T>(T);
+
+        impl <T> Trait for X<T> where T: Trait {}
+        impl <T> Trait2 for X<T> where T: Trait<T> {}
+    """)
+
+    fun `test supertrait is not implemented E0277 self substitution 3`() = checkErrors("""
+        trait Trait<Rhs: ?Sized = Self> {}
+        trait Trait2: Trait<Self> {}
+
+        struct X<T>(T);
+
+        impl <T: Trait> Trait for X<T> {}
+        impl <T> Trait2 for X<T> where T: Trait<T> {}
+    """)
+
     @MockRustcVersion("1.27.1")
     fun `test crate visibility feature E0658`() = checkErrors("""
         <error descr="`crate` visibility modifier is experimental [E0658]">crate</error> struct Foo;