Repository: intellij-rust/intellij-rust
Issue: Invalid suggestion to remove explicit lifetime

## Environment

* **Intellij-Rust plugin version: 0.2.0.2103-182**
* **Rust toolchain version: 1.28.0**
* **IDE name and version: CLion 2018.2**
* **Operating system: Ubuntu 18.04**

## Problem description

Plugin suggests to remove explicit lifetime for method:

```rust
fn cls_ids_and_refs<'a>(&'a self) -> Box<dyn Iterator<Item = (Sym, ObjId)> + 'a> {
    Box::new(self.cls_id_by_ref.iter().map(|(_ref, id)| (*_ref, *id)))
}
```

When I remove it I get a compilation error:

```
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
   --> src/ecore.rs:507:37
    |
507 |         Box::new(self.cls_id_by_ref.iter().map(|(_ref, id)| (*_ref, *id)))
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 506:5...
   --> src/ecore.rs:506:5
    |
506 | /     fn cls_ids_and_refs(&self) -> Box<dyn Iterator<Item = (Sym, ObjId)>> {
507 | |         Box::new(self.cls_id_by_ref.iter().map(|(_ref, id)| (*_ref, *id)))
508 | |     }
    | |_____^
note: ...so that reference does not outlive borrowed content
   --> src/ecore.rs:507:18
    |
507 |         Box::new(self.cls_id_by_ref.iter().map(|(_ref, id)| (*_ref, *id)))
    |                  ^^^^^^^^^^^^^^^^^^
    = note: but, the lifetime must be valid for the static lifetime...
    = note: ...so that the expression is assignable:
            expected std::boxed::Box<(dyn std::iter::Iterator<Item=(Sym, obj_id::ObjId)> + 'static)>
               found std::boxed::Box<dyn std::iter::Iterator<Item=(Sym, obj_id::ObjId)>>

```

## Steps to reproduce

self.cls_id_by_ref is a HashMap<Sym, ObjId>. Sym and ObjId could be replaced with an integer.


Changed files:
src/test/kotlin/org/rust/ide/inspections/RsNeedlessLifetimesInspectionTest.kt, src/main/kotlin/org/rust/ide/inspections/RsNeedlessLifetimesInspection.kt

diff --git a/src/main/kotlin/org/rust/ide/inspections/RsNeedlessLifetimesInspection.kt b/src/main/kotlin/org/rust/ide/inspections/RsNeedlessLifetimesInspection.kt
index 67aea5795..123c4500a 100644
--- a/src/main/kotlin/org/rust/ide/inspections/RsNeedlessLifetimesInspection.kt
+++ b/src/main/kotlin/org/rust/ide/inspections/RsNeedlessLifetimesInspection.kt
@@ -39,7 +39,7 @@ private fun couldUseElision(fn: RsFunction): Boolean {
     val typeParametersBounds = fn.typeParameters.flatMap { it.bounds }.map { it.bound }
     if (typeParametersBounds.any { hasNamedReferenceLifetime(it) }) return false
 
-    val (inputLifetimes, outputLifetimes) = collectLifetimesFromFnSignature(fn)
+    val (inputLifetimes, outputLifetimes) = collectLifetimesFromFnSignature(fn) ?: return false
 
     // no input lifetimes? easy case!
     if (inputLifetimes.isEmpty()) return false
@@ -77,6 +77,7 @@ private fun couldUseElision(fn: RsFunction): Boolean {
 }
 
 private class LifetimesCollector : RsVisitor() {
+    var abort: Boolean = false
     val lifetimes = mutableListOf<ReferenceLifetime>()
 
     override fun visitSelfParameter(selfParameter: RsSelfParameter) {
@@ -90,6 +91,12 @@ private class LifetimesCollector : RsVisitor() {
         super.visitRefLikeType(refLike)
     }
 
+    override fun visitTraitType(trait: RsTraitType) {
+        val lifetimeBounds = trait.polyboundList.mapNotNull { it.bound.lifetime }
+        if (lifetimeBounds.isNotEmpty()) abort = true
+        super.visitTraitType(trait)
+    }
+
     override fun visitPath(path: RsPath) {
         collectAnonymousLifetimes(path)
         super.visitPath(path)
@@ -98,7 +105,7 @@ private class LifetimesCollector : RsVisitor() {
     override fun visitLifetime(lifetime: RsLifetime) = record(lifetime)
 
     override fun visitElement(element: RsElement) {
-        if (element is RsItemElement /* ignore nested items */) return
+        if (abort || element is RsItemElement /* ignore nested items */) return
         element.forEachChild { it.accept(this) }
     }
 
@@ -135,7 +142,7 @@ private class BodyLifetimeChecker : RsVisitor() {
     }
 }
 
-private fun collectLifetimesFromFnSignature(fn: RsFunction): Pair<List<ReferenceLifetime>, List<ReferenceLifetime>> {
+private fun collectLifetimesFromFnSignature(fn: RsFunction): Pair<List<ReferenceLifetime>, List<ReferenceLifetime>>? {
     // these will collect all the lifetimes for references in arg/return types
     val inputCollector = LifetimesCollector()
     val outputCollector = LifetimesCollector()
@@ -145,9 +152,11 @@ private fun collectLifetimesFromFnSignature(fn: RsFunction): Pair<List<Reference
         it.selfParameter?.accept(inputCollector)
         it.valueParameterList.forEach { it.typeReference?.accept(inputCollector) }
     }
+    if (inputCollector.abort) return null
 
     // extract lifetimes in output type
     fn.retType?.typeReference?.accept(outputCollector)
+    if (outputCollector.abort) return null
 
     return Pair(inputCollector.lifetimes, outputCollector.lifetimes)
 }
diff --git a/src/test/kotlin/org/rust/ide/inspections/RsNeedlessLifetimesInspectionTest.kt b/src/test/kotlin/org/rust/ide/inspections/RsNeedlessLifetimesInspectionTest.kt
index 6d4930611..4fc6befb6 100644
--- a/src/test/kotlin/org/rust/ide/inspections/RsNeedlessLifetimesInspectionTest.kt
+++ b/src/test/kotlin/org/rust/ide/inspections/RsNeedlessLifetimesInspectionTest.kt
@@ -261,6 +261,10 @@ class RsNeedlessLifetimesInspectionTest : RsInspectionsTestBase(RsNeedlessLifeti
         fn foo<'a, 'b: 'a>(a: &'a str, b: &'b str) { unimplemented!() }
     """)
 
+    fun `test no elision if there are lifetime bounds in trait type`() = doTest("""
+        fn foo<'a>(a: &'a [i32]) -> Box<Iterator<Item=i32> + 'a> { unimplemented!() }
+    """)
+
     fun `test ignore 'static in body`() = doTest("""
         <weak_warning>fn <caret>foo<'a>(s: &'a str)</weak_warning> { let x: &'static str = unimplemented!(); }
     """, """