about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2024-01-16 20:15:31 +0100
committerLukas Wirth <lukastw97@gmail.com>2024-01-16 20:15:31 +0100
commit0a75a8c0614efbd6dfcf23870a789fd64e16618b (patch)
tree2c484f8f2d1cf85e06ef70c6e2b8dbefa5c35bd6
parentffeaee84afbb24176b9f7375dcb02c5542a8cb64 (diff)
downloadrust-0a75a8c0614efbd6dfcf23870a789fd64e16618b.tar.gz
rust-0a75a8c0614efbd6dfcf23870a789fd64e16618b.zip
Notable traits for type info hovers
-rw-r--r--crates/ide/src/hover.rs55
-rw-r--r--crates/ide/src/hover/render.rs86
-rw-r--r--crates/ide/src/hover/tests.rs559
3 files changed, 378 insertions, 322 deletions
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 5ed3b2dbbcf..77a06a97e22 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -393,30 +393,7 @@ pub(crate) fn hover_for_definition(
         Definition::BuiltinType(it) => Some(it.ty(db)),
         _ => None,
     };
-    let notable_traits = def_ty
-        .map(|ty| {
-            db.notable_traits_in_deps(ty.krate(db).into())
-                .iter()
-                .flat_map(|it| &**it)
-                .filter_map(move |&trait_| {
-                    let trait_ = trait_.into();
-                    ty.impls_trait(db, trait_, &[]).then(|| {
-                        (
-                            trait_,
-                            trait_
-                                .items(db)
-                                .into_iter()
-                                .filter_map(hir::AssocItem::as_type_alias)
-                                .map(|alias| {
-                                    (ty.normalize_trait_assoc_type(db, &[], alias), alias.name(db))
-                                })
-                                .collect::<Vec<_>>(),
-                        )
-                    })
-                })
-                .collect::<Vec<_>>()
-        })
-        .unwrap_or_default();
+    let notable_traits = def_ty.map(|ty| notable_traits(db, &ty)).unwrap_or_default();
 
     render::definition(sema.db, def, famous_defs.as_ref(), &notable_traits, config).map(|markup| {
         HoverResult {
@@ -434,6 +411,32 @@ pub(crate) fn hover_for_definition(
     })
 }
 
+fn notable_traits(
+    db: &RootDatabase,
+    ty: &hir::Type,
+) -> Vec<(hir::Trait, Vec<(Option<hir::Type>, hir::Name)>)> {
+    db.notable_traits_in_deps(ty.krate(db).into())
+        .iter()
+        .flat_map(|it| &**it)
+        .filter_map(move |&trait_| {
+            let trait_ = trait_.into();
+            ty.impls_trait(db, trait_, &[]).then(|| {
+                (
+                    trait_,
+                    trait_
+                        .items(db)
+                        .into_iter()
+                        .filter_map(hir::AssocItem::as_type_alias)
+                        .map(|alias| {
+                            (ty.normalize_trait_assoc_type(db, &[], alias), alias.name(db))
+                        })
+                        .collect::<Vec<_>>(),
+                )
+            })
+        })
+        .collect::<Vec<_>>()
+}
+
 fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
     fn to_action(nav_target: NavigationTarget) -> HoverAction {
         HoverAction::Implementation(FilePosition {
@@ -583,7 +586,9 @@ fn dedupe_or_merge_hover_actions(actions: Vec<HoverAction>) -> Vec<HoverAction>
     }
 
     if !go_to_type_targets.is_empty() {
-        deduped_actions.push(HoverAction::GoToType(go_to_type_targets.into_iter().collect()));
+        deduped_actions.push(HoverAction::GoToType(
+            go_to_type_targets.into_iter().sorted_by(|a, b| a.mod_path.cmp(&b.mod_path)).collect(),
+        ));
     }
 
     deduped_actions
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index 511137f67c8..787b74fc62c 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -3,8 +3,8 @@ use std::{mem, ops::Not};
 
 use either::Either;
 use hir::{
-    Adt, AsAssocItem, CaptureKind, HasSource, HirDisplay, Layout, LayoutError, Name, Semantics,
-    Trait, Type, TypeInfo,
+    Adt, AsAssocItem, CaptureKind, HasCrate, HasSource, HirDisplay, Layout, LayoutError, Name,
+    Semantics, Trait, Type, TypeInfo,
 };
 use ide_db::{
     base_db::SourceDatabase,
@@ -25,7 +25,7 @@ use syntax::{
 
 use crate::{
     doc_links::{remove_links, rewrite_links},
-    hover::walk_and_push_ty,
+    hover::{notable_traits, walk_and_push_ty},
     HoverAction, HoverConfig, HoverResult, Markup, MemoryLayoutHoverConfig,
     MemoryLayoutHoverRenderKind,
 };
@@ -471,38 +471,8 @@ pub(super) fn definition(
         _ => None,
     };
 
-    let notable_traits = {
-        let mut desc = String::new();
-        let mut needs_impl_header = true;
-        for (trait_, assoc_types) in notable_traits {
-            desc.push_str(if mem::take(&mut needs_impl_header) {
-                " // notable traits implemented: "
-            } else {
-                ", "
-            });
-            format_to!(desc, "{}", trait_.name(db).display(db),);
-            if !assoc_types.is_empty() {
-                desc.push('<');
-                format_to!(
-                    desc,
-                    "{}",
-                    assoc_types.into_iter().format_with(", ", |(ty, name), f| {
-                        f(&name.display(db))?;
-                        f(&" = ")?;
-                        match ty {
-                            Some(ty) => f(&ty.display(db)),
-                            None => f(&"?"),
-                        }
-                    })
-                );
-                desc.push('>');
-            }
-        }
-        desc.is_empty().not().then(|| desc)
-    };
-
     let mut desc = String::new();
-    if let Some(notable_traits) = notable_traits {
+    if let Some(notable_traits) = render_notable_trait_comment(db, notable_traits) {
         desc.push_str(&notable_traits);
         desc.push('\n');
     }
@@ -519,6 +489,39 @@ pub(super) fn definition(
     markup(docs.map(Into::into), desc, mod_path)
 }
 
+fn render_notable_trait_comment(
+    db: &RootDatabase,
+    notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)],
+) -> Option<String> {
+    let mut desc = String::new();
+    let mut needs_impl_header = true;
+    for (trait_, assoc_types) in notable_traits {
+        desc.push_str(if mem::take(&mut needs_impl_header) {
+            " // notable traits implemented: "
+        } else {
+            ", "
+        });
+        format_to!(desc, "{}", trait_.name(db).display(db),);
+        if !assoc_types.is_empty() {
+            desc.push('<');
+            format_to!(
+                desc,
+                "{}",
+                assoc_types.into_iter().format_with(", ", |(ty, name), f| {
+                    f(&name.display(db))?;
+                    f(&" = ")?;
+                    match ty {
+                        Some(ty) => f(&ty.display(db)),
+                        None => f(&"?"),
+                    }
+                })
+            );
+            desc.push('>');
+        }
+    }
+    desc.is_empty().not().then(|| desc)
+}
+
 fn type_info(
     sema: &Semantics<'_, RootDatabase>,
     config: &HoverConfig,
@@ -536,8 +539,12 @@ fn type_info(
         }
     };
     walk_and_push_ty(sema.db, &original, &mut push_new_def);
-
-    res.markup = if let Some(adjusted_ty) = adjusted {
+    let mut desc = match render_notable_trait_comment(sema.db, &notable_traits(sema.db, &original))
+    {
+        Some(desc) => desc + "\n",
+        None => String::new(),
+    };
+    desc += &if let Some(adjusted_ty) = adjusted {
         walk_and_push_ty(sema.db, &adjusted_ty, &mut push_new_def);
         let original = original.display(sema.db).to_string();
         let adjusted = adjusted_ty.display(sema.db).to_string();
@@ -549,10 +556,10 @@ fn type_info(
             apad = static_text_diff_len + adjusted.len().max(original.len()),
             opad = original.len(),
         )
-        .into()
     } else {
-        Markup::fenced_block(&original.display(sema.db))
+        Markup::fenced_block(&original.display(sema.db)).into()
     };
+    res.markup = desc.into();
     if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets) {
         res.actions.push(actions);
     }
@@ -607,6 +614,9 @@ fn closure_ty(
     {
         format_to!(markup, "{layout}");
     }
+    if let Some(trait_) = c.fn_trait(sema.db).get_id(sema.db, original.krate(sema.db).into()) {
+        push_new_def(hir::Trait::from(trait_).into())
+    }
     format_to!(
         markup,
         "\n{}\n```{adjusted}\n\n## Captures\n{}",
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 09548745f6e..d8d439c0d2b 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -400,6 +400,20 @@ fn main() {
                                 description: "struct S",
                             },
                         },
+                        HoverGotoTypeData {
+                            mod_path: "core::ops::function::FnOnce",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 631..866,
+                                focus_range: 692..698,
+                                name: "FnOnce",
+                                kind: Trait,
+                                container_name: "function",
+                                description: "pub trait FnOnce<Args>\nwhere\n    Args: Tuple,",
+                            },
+                        },
                     ],
                 ),
             ]
@@ -2387,39 +2401,39 @@ struct S<T>{ f1: T }
 fn main() { let s$0t = S{ f1:Arg(0) }; }
 "#,
         expect![[r#"
-                [
-                    GoToType(
-                        [
-                            HoverGotoTypeData {
-                                mod_path: "test::S",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 17..37,
-                                    focus_range: 24..25,
-                                    name: "S",
-                                    kind: Struct,
-                                    description: "struct S<T> {\n    f1: T,\n}",
-                                },
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "test::Arg",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 0..16,
+                                focus_range: 7..10,
+                                name: "Arg",
+                                kind: Struct,
+                                description: "struct Arg(u32);",
                             },
-                            HoverGotoTypeData {
-                                mod_path: "test::Arg",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 0..16,
-                                    focus_range: 7..10,
-                                    name: "Arg",
-                                    kind: Struct,
-                                    description: "struct Arg(u32);",
-                                },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "test::S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 17..37,
+                                focus_range: 24..25,
+                                name: "S",
+                                kind: Struct,
+                                description: "struct S<T> {\n    f1: T,\n}",
                             },
-                        ],
-                    ),
-                ]
-            "#]],
+                        },
+                    ],
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -2446,39 +2460,39 @@ struct S<T>{ f1: T }
 fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; }
 "#,
         expect![[r#"
-                [
-                    GoToType(
-                        [
-                            HoverGotoTypeData {
-                                mod_path: "test::S",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 17..37,
-                                    focus_range: 24..25,
-                                    name: "S",
-                                    kind: Struct,
-                                    description: "struct S<T> {\n    f1: T,\n}",
-                                },
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "test::Arg",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 0..16,
+                                focus_range: 7..10,
+                                name: "Arg",
+                                kind: Struct,
+                                description: "struct Arg(u32);",
                             },
-                            HoverGotoTypeData {
-                                mod_path: "test::Arg",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 0..16,
-                                    focus_range: 7..10,
-                                    name: "Arg",
-                                    kind: Struct,
-                                    description: "struct Arg(u32);",
-                                },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "test::S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 17..37,
+                                focus_range: 24..25,
+                                name: "S",
+                                kind: Struct,
+                                description: "struct S<T> {\n    f1: T,\n}",
                             },
-                        ],
-                    ),
-                ]
-            "#]],
+                        },
+                    ],
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -2636,39 +2650,39 @@ fn foo() -> impl Foo + Bar {}
 fn main() { let s$0t = foo(); }
 "#,
         expect![[r#"
-                [
-                    GoToType(
-                        [
-                            HoverGotoTypeData {
-                                mod_path: "test::Foo",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 0..12,
-                                    focus_range: 6..9,
-                                    name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
-                                },
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "test::Bar",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 13..25,
+                                focus_range: 19..22,
+                                name: "Bar",
+                                kind: Trait,
+                                description: "trait Bar",
                             },
-                            HoverGotoTypeData {
-                                mod_path: "test::Bar",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 13..25,
-                                    focus_range: 19..22,
-                                    name: "Bar",
-                                    kind: Trait,
-                                    description: "trait Bar",
-                                },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "test::Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 0..12,
+                                focus_range: 6..9,
+                                name: "Foo",
+                                kind: Trait,
+                                description: "trait Foo",
                             },
-                        ],
-                    ),
-                ]
-            "#]],
+                        },
+                    ],
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -2686,65 +2700,65 @@ fn foo() -> impl Foo<S1> + Bar<S2> {}
 fn main() { let s$0t = foo(); }
 "#,
         expect![[r#"
-                [
-                    GoToType(
-                        [
-                            HoverGotoTypeData {
-                                mod_path: "test::Foo",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 0..15,
-                                    focus_range: 6..9,
-                                    name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo<T>",
-                                },
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "test::Bar",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 16..31,
+                                focus_range: 22..25,
+                                name: "Bar",
+                                kind: Trait,
+                                description: "trait Bar<T>",
                             },
-                            HoverGotoTypeData {
-                                mod_path: "test::Bar",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 16..31,
-                                    focus_range: 22..25,
-                                    name: "Bar",
-                                    kind: Trait,
-                                    description: "trait Bar<T>",
-                                },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "test::Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 0..15,
+                                focus_range: 6..9,
+                                name: "Foo",
+                                kind: Trait,
+                                description: "trait Foo<T>",
                             },
-                            HoverGotoTypeData {
-                                mod_path: "test::S1",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 32..44,
-                                    focus_range: 39..41,
-                                    name: "S1",
-                                    kind: Struct,
-                                    description: "struct S1 {}",
-                                },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "test::S1",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 32..44,
+                                focus_range: 39..41,
+                                name: "S1",
+                                kind: Struct,
+                                description: "struct S1 {}",
                             },
-                            HoverGotoTypeData {
-                                mod_path: "test::S2",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 45..57,
-                                    focus_range: 52..54,
-                                    name: "S2",
-                                    kind: Struct,
-                                    description: "struct S2 {}",
-                                },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "test::S2",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 45..57,
+                                focus_range: 52..54,
+                                name: "S2",
+                                kind: Struct,
+                                description: "struct S2 {}",
                             },
-                        ],
-                    ),
-                ]
-            "#]],
+                        },
+                    ],
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -2790,52 +2804,52 @@ struct S{}
 fn foo(ar$0g: &impl Foo + Bar<S>) {}
 "#,
         expect![[r#"
-                [
-                    GoToType(
-                        [
-                            HoverGotoTypeData {
-                                mod_path: "test::Foo",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 0..12,
-                                    focus_range: 6..9,
-                                    name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
-                                },
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "test::Bar",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 13..28,
+                                focus_range: 19..22,
+                                name: "Bar",
+                                kind: Trait,
+                                description: "trait Bar<T>",
                             },
-                            HoverGotoTypeData {
-                                mod_path: "test::Bar",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 13..28,
-                                    focus_range: 19..22,
-                                    name: "Bar",
-                                    kind: Trait,
-                                    description: "trait Bar<T>",
-                                },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "test::Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 0..12,
+                                focus_range: 6..9,
+                                name: "Foo",
+                                kind: Trait,
+                                description: "trait Foo",
                             },
-                            HoverGotoTypeData {
-                                mod_path: "test::S",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 29..39,
-                                    focus_range: 36..37,
-                                    name: "S",
-                                    kind: Struct,
-                                    description: "struct S {}",
-                                },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "test::S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 29..39,
+                                focus_range: 36..37,
+                                name: "S",
+                                kind: Struct,
+                                description: "struct S {}",
                             },
-                        ],
-                    ),
-                ]
-            "#]],
+                        },
+                    ],
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -3077,65 +3091,65 @@ struct S {}
 fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
 "#,
         expect![[r#"
-                [
-                    GoToType(
-                        [
-                            HoverGotoTypeData {
-                                mod_path: "test::ImplTrait",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 0..21,
-                                    focus_range: 6..15,
-                                    name: "ImplTrait",
-                                    kind: Trait,
-                                    description: "trait ImplTrait<T>",
-                                },
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "test::B",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 43..57,
+                                focus_range: 50..51,
+                                name: "B",
+                                kind: Struct,
+                                description: "struct B<T> {}",
                             },
-                            HoverGotoTypeData {
-                                mod_path: "test::B",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 43..57,
-                                    focus_range: 50..51,
-                                    name: "B",
-                                    kind: Struct,
-                                    description: "struct B<T> {}",
-                                },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "test::DynTrait",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 22..42,
+                                focus_range: 28..36,
+                                name: "DynTrait",
+                                kind: Trait,
+                                description: "trait DynTrait<T>",
                             },
-                            HoverGotoTypeData {
-                                mod_path: "test::DynTrait",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 22..42,
-                                    focus_range: 28..36,
-                                    name: "DynTrait",
-                                    kind: Trait,
-                                    description: "trait DynTrait<T>",
-                                },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "test::ImplTrait",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 0..21,
+                                focus_range: 6..15,
+                                name: "ImplTrait",
+                                kind: Trait,
+                                description: "trait ImplTrait<T>",
                             },
-                            HoverGotoTypeData {
-                                mod_path: "test::S",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 58..69,
-                                    focus_range: 65..66,
-                                    name: "S",
-                                    kind: Struct,
-                                    description: "struct S {}",
-                                },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "test::S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 58..69,
+                                focus_range: 65..66,
+                                name: "S",
+                                kind: Struct,
+                                description: "struct S {}",
                             },
-                        ],
-                    ),
-                ]
-            "#]],
+                        },
+                    ],
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -7121,6 +7135,33 @@ impl Iterator for S {
 }
 
 #[test]
+fn notable_ranged() {
+    check_hover_range(
+        r#"
+//- minicore: future, iterator
+struct S;
+#[doc(notable_trait)]
+trait Notable {}
+impl Notable for S {}
+impl core::future::Future for S {
+    type Output = u32;
+}
+impl Iterator for S {
+    type Item = S;
+}
+fn main() {
+    $0S$0;
+}
+"#,
+        expect![[r#"
+             // notable traits implemented: Notable, Future<Output = u32>, Iterator<Item = S>
+            ```rust
+            S
+            ```"#]],
+    );
+}
+
+#[test]
 fn notable_actions() {
     check_actions(
         r#"
@@ -7150,19 +7191,6 @@ impl Iterator for S {
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Notable",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    0,
-                                ),
-                                full_range: 21..59,
-                                focus_range: 49..56,
-                                name: "Notable",
-                                kind: Trait,
-                                description: "trait Notable",
-                            },
-                        },
-                        HoverGotoTypeData {
                             mod_path: "core::future::Future",
                             nav: NavigationTarget {
                                 file_id: FileId(
@@ -7191,6 +7219,19 @@ impl Iterator for S {
                             },
                         },
                         HoverGotoTypeData {
+                            mod_path: "test::Notable",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 21..59,
+                                focus_range: 49..56,
+                                name: "Notable",
+                                kind: Trait,
+                                description: "trait Notable",
+                            },
+                        },
+                        HoverGotoTypeData {
                             mod_path: "test::S2",
                             nav: NavigationTarget {
                                 file_id: FileId(