Repository: intellij-rust/intellij-rust
Issue: No support for in_band_lifetimes

<!--
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.137.3503-203-nightly
* **Rust toolchain version:** rustc 1.50.0-nightly (a0d664bae 2020-11-22)
* **IDE name and version:** CLion 2020.3 Beta
* **Operating system:** Windows 10

## Problem description

An error is emitted on the following, despite `in_band_lifetime` being enabled:
```rust
impl Foo<'a> {
}
```

## Steps to reproduce

Create a crate, and add `#![feature(in_band_lifetimes)]` to it. Add the code shown above.

<!--
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/NameResolution.kt, src/main/kotlin/org/rust/ide/annotator/RsErrorAnnotator.kt, src/test/kotlin/org/rust/ide/annotator/RsErrorAnnotatorTest.kt, src/test/kotlin/org/rust/lang/core/resolve/RsResolveTest.kt

diff --git a/src/main/kotlin/org/rust/ide/annotator/RsErrorAnnotator.kt b/src/main/kotlin/org/rust/ide/annotator/RsErrorAnnotator.kt
index d33ccde4f..7a68ed6b0 100644
--- a/src/main/kotlin/org/rust/ide/annotator/RsErrorAnnotator.kt
+++ b/src/main/kotlin/org/rust/ide/annotator/RsErrorAnnotator.kt
@@ -629,9 +629,13 @@ class RsErrorAnnotator : AnnotatorBase(), HighlightRangeExtension {
 
         val owner = lifetime.ancestorStrict<RsGenericDeclaration>() ?: return
         val declarationParts = listOfNotNull(
-            owner.typeParameterList,
+            (owner as? RsImplItem)?.traitRef,
+            (owner as? RsImplItem)?.typeReference,
+            (owner as? RsImplItem)?.whereClause,
+
+            (owner as? RsFunction)?.typeParameterList,
             (owner as? RsFunction)?.valueParameterList,
-            owner.whereClause
+            (owner as? RsFunction)?.whereClause
         )
         val inDeclaration = lifetime.ancestors.takeWhile { it != owner }.any { it in declarationParts }
 
diff --git a/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt b/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt
index 82a9aba35..997904c79 100644
--- a/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt
+++ b/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt
@@ -726,9 +726,13 @@ fun processLifetimeResolveVariants(lifetime: RsLifetime, processor: RsResolvePro
             override fun visitElement(element: RsElement) =
                 element.stubChildrenOfType<RsElement>().forEach { it.accept(this) }
         }
-        owner.typeParameterList?.accept(visitor)
+
+        (owner as? RsImplItem)?.traitRef?.accept(visitor)
+        (owner as? RsImplItem)?.typeReference?.accept(visitor)
+        (owner as? RsFunction)?.typeParameterList?.accept(visitor)
         (owner as? RsFunction)?.valueParameterList?.accept(visitor)
-        owner.whereClause?.accept(visitor)
+        (owner as? RsFunction)?.whereClause?.accept(visitor)
+
         return processAll(lifetimes, processor)
     }
 
diff --git a/src/test/kotlin/org/rust/ide/annotator/RsErrorAnnotatorTest.kt b/src/test/kotlin/org/rust/ide/annotator/RsErrorAnnotatorTest.kt
index e8293dbfd..d003f75e8 100644
--- a/src/test/kotlin/org/rust/ide/annotator/RsErrorAnnotatorTest.kt
+++ b/src/test/kotlin/org/rust/ide/annotator/RsErrorAnnotatorTest.kt
@@ -554,30 +554,71 @@ class RsErrorAnnotatorTest : RsAnnotatorTestBase(RsErrorAnnotator::class) {
     """)
 
     @MockRustcVersion("1.23.0")
-    fun `test in-band lifetimes feature E0658 1`() = checkErrors("""
+    fun `test in-band lifetimes feature E0658 in fn 1`() = checkErrors("""
         fn foo(x: &<error descr="in-band lifetimes is experimental [E0658]">'a</error> str) {}
     """)
 
     @MockRustcVersion("1.23.0-nightly")
-    fun `test in-band lifetimes feature E0658 2`() = checkErrors("""
+    fun `test in-band lifetimes feature E0658 in fn 2`() = checkErrors("""
         #![feature(in_band_lifetimes)]
         fn foo<T: 'a>(x: &'b str) where 'c: 'd {}
     """)
 
     @MockRustcVersion("1.23.0-nightly")
-    fun `test in-band lifetimes feature E0658 3`() = checkErrors("""
+    fun `test in-band lifetimes feature E0658 in fn 3`() = checkErrors("""
         #![feature(in_band_lifetimes)]
         fn foo<'b>(x: &<error descr="Cannot mix in-band and explicit lifetime definitions [E0688]">'a</error> str) {}
     """)
 
     @MockRustcVersion("1.23.0-nightly")
-    fun `test in-band lifetimes feature E0658 4`() = checkErrors("""
+    fun `test in-band lifetimes feature E0658 in let`() = checkErrors("""
         #![feature(in_band_lifetimes)]
         fn foo() {
             let x: &<error descr="Use of undeclared lifetime name `'a` [E0261]">'a</error> str = unimplemented!();
         }
     """)
 
+    @MockRustcVersion("1.23.0")
+    fun `test in-band lifetimes feature E0658 in impl 1`() = checkErrors("""
+        trait T<'a> {}
+        struct S<'a>(&'a str);
+        impl T<<error descr="in-band lifetimes is experimental [E0658]">'a</error>> for S<<error descr="in-band lifetimes is experimental [E0658]">'a</error>> {}
+    """)
+
+    @MockRustcVersion("1.23.0-nightly")
+    fun `test in-band lifetimes feature E0658 in impl 2`() = checkErrors("""
+        #![feature(in_band_lifetimes)]
+        trait T<'a> {}
+        struct S<'a>(&'a str);
+        impl T<'a> for S<'b> where 'c: 'd {}
+    """)
+
+    @MockRustcVersion("1.23.0-nightly")
+    fun `test in-band lifetimes feature E0658 in impl 3`() = checkErrors("""
+        #![feature(in_band_lifetimes)]
+        trait T<'a> {}
+        struct S<'a>(&'a str);
+        impl <'b> T<<error descr="Cannot mix in-band and explicit lifetime definitions [E0688]">'a</error>> for S<<error descr="Cannot mix in-band and explicit lifetime definitions [E0688]">'a</error>> {}
+    """)
+
+    @MockRustcVersion("1.23.0-nightly")
+    fun `test in-band lifetimes feature E0658 in struct`() = checkErrors("""
+        #![feature(in_band_lifetimes)]
+        struct S(&<error descr="Use of undeclared lifetime name `'a` [E0261]">'a</error> str);
+    """)
+
+    @MockRustcVersion("1.23.0-nightly")
+    fun `test in-band lifetimes feature E0658 in trait`() = checkErrors("""
+        #![feature(in_band_lifetimes)]
+        trait S<T: <error descr="Use of undeclared lifetime name `'a` [E0261]">'a</error>> {}
+    """)
+
+    @MockRustcVersion("1.23.0-nightly")
+    fun `test in-band lifetimes feature E0658 in enum`() = checkErrors("""
+        #![feature(in_band_lifetimes)]
+        enum E<T: <error descr="Use of undeclared lifetime name `'a` [E0261]">'a</error>> {}
+    """)
+
     fun `test lifetime name duplication in generic params E0263`() = checkErrors("""
         fn foo<'a, 'b>(x: &'a str, y: &'b str) { }
         struct Str<'a, 'b> { a: &'a u32, b: &'b f64 }
diff --git a/src/test/kotlin/org/rust/lang/core/resolve/RsResolveTest.kt b/src/test/kotlin/org/rust/lang/core/resolve/RsResolveTest.kt
index 5e9969730..ac00d6aab 100644
--- a/src/test/kotlin/org/rust/lang/core/resolve/RsResolveTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/resolve/RsResolveTest.kt
@@ -1142,6 +1142,38 @@ class RsResolveTest : RsResolveTestBase() {
         ) {}
     """)
 
+    @MockRustcVersion("1.23.0-nightly")
+    fun `test in-band lifetime resolve in impl`() = checkByCode("""
+        #![feature(in_band_lifetimes)]
+        trait T<'a> {}
+        struct S<'a>(&'a str);
+        impl T<'a>
+              //X
+        for S<'a> {}
+             //^
+    """)
+
+    @MockRustcVersion("1.23.0-nightly")
+    fun `test in-band lifetime resolve in impl (where)`() = checkByCode("""
+        #![feature(in_band_lifetimes)]
+        trait T<'a> {}
+        struct S<'a>(&'a str);
+        impl T<'a>
+              //X
+        for S<'a>
+        where 'a: 'static {}
+             //^
+    """)
+
+    @MockRustcVersion("1.23.0-nightly")
+    fun `test in-band lifetime resolve in impl and explicit lifetimes`() = checkByCode("""
+        #![feature(in_band_lifetimes)]
+        trait T<'a> {}
+        struct S<'a>(&'a str);
+        impl <'b> T<'a> for S<'a> {}
+                             //^ unresolved
+    """)
+
     fun `test loop label`() = checkByCode("""
         fn foo() {
             'a: loop {