Repository: rust-lang/rust-mode (language: rust)

Issue:
imenu ignores impls with lifetimes
Specifically, it ignores `impl`s with rust 2015 style lifetimes, but finds `impl`s with rust 2018 lifetime elision.

```
impl<'a> WithLifetime2015<'a> {
    fn foo() {}
}

impl WithLifetime2018<'a> {
    fn bar() {}
}

```

produces the following `imenu--index-alist`:

```
(("Impl"
  ("WithLifetime2018" . #<marker at 52 in tmp.rs>))
 ("Fn"
  ("foo" . #<marker at 33 in tmp.rs>)
  ("bar" . #<marker at 80 in tmp.rs>)))
```

Using rust-mode 20180626.1512.


Discussion / hints:

Fix patch:
diff --git a/rust-mode.el b/rust-mode.el
index 8af6610b..a8af671e 100644
--- a/rust-mode.el
+++ b/rust-mode.el
@@ -39,6 +39,8 @@
 (defconst rust-re-vis "pub")
 (defconst rust-re-unsafe "unsafe")
 (defconst rust-re-extern "extern")
+(defconst rust-re-generic
+  (concat "<[[:space:]]*'" rust-re-ident "[[:space:]]*>"))
 (defconst rust-re-union
   (rx-to-string
    `(seq
@@ -561,7 +563,9 @@ buffer."
 (defun rust-re-grab (inner) (concat "\\(" inner "\\)"))
 (defun rust-re-shy (inner) (concat "\\(?:" inner "\\)"))
 (defun rust-re-item-def (itype)
-  (concat (rust-re-word itype) "[[:space:]]+" (rust-re-grab rust-re-ident)))
+  (concat (rust-re-word itype)
+	  (rust-re-shy rust-re-generic) "?"
+	  "[[:space:]]+" (rust-re-grab rust-re-ident)))
 (defun rust-re-item-def-imenu (itype)
   (concat "^[[:space:]]*"
           (rust-re-shy (concat (rust-re-word rust-re-vis) "[[:space:]]+")) "?"


Test patch:
diff --git a/rust-mode-tests.el b/rust-mode-tests.el
index 64d65c42..9d879602 100644
--- a/rust-mode-tests.el
+++ b/rust-mode-tests.el
@@ -3061,6 +3061,20 @@ extern \"rust-intrinsic\" fn five() {
       "four"
       "five"))))
 
+(ert-deftest rust-test-imenu-impl-with-lifetime ()
+  (test-imenu
+   "
+impl<'a> One<'a> {
+    fn one() {}
+}
+
+impl Two<'a> {
+    fn two() {}
+}
+"
+   '(("Impl" "One" "Two")
+     ("Fn" "one" "two"))))
+
 (when (executable-find rust-cargo-bin)
   (ert-deftest rust-test-project-located ()
     (lexical-let* ((test-dir (expand-file-name "test-project" default-directory))