9356: internal: Move out and regroup more completion tests r=Veykril a=Veykril

bors r+

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot] 2021-06-21 13:15:12 +00:00 committed by GitHub
commit c69f762f26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 557 additions and 677 deletions

View File

@ -92,7 +92,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
}
if !ctx.has_visibility_prev_sibling()
&& (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_record_field())
&& (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_field())
{
add_keyword("pub(crate)", "pub(crate) ");
add_keyword("pub", "pub ");
@ -122,6 +122,10 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
add_keyword("union", "union $1 {\n $0\n}");
}
if ctx.expects_type() {
return;
}
if ctx.expects_expression() {
if !has_block_expr_parent {
add_keyword("unsafe", "unsafe {\n $0\n}");
@ -372,28 +376,6 @@ fn quux() -> i32 {
);
}
#[test]
fn test_mut_in_ref_and_in_fn_parameters_list() {
check(
r"fn my_fn(&$0) {}",
expect![[r#"
kw mut
"#]],
);
check(
r"fn my_fn($0) {}",
expect![[r#"
kw mut
"#]],
);
check(
r"fn my_fn() { let &$0 }",
expect![[r#"
kw mut
"#]],
);
}
#[test]
fn no_keyword_completion_in_comments() {
cov_mark::check!(no_keyword_completion_in_comments);

View File

@ -55,398 +55,3 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
}
});
}
#[cfg(test)]
mod tests {
use expect_test::{expect, Expect};
use crate::{
tests::{check_edit, filtered_completion_list},
CompletionKind,
};
fn check(ra_fixture: &str, expect: Expect) {
let actual = filtered_completion_list(ra_fixture, CompletionKind::Reference);
expect.assert_eq(&actual)
}
fn check_snippet(ra_fixture: &str, expect: Expect) {
let actual = filtered_completion_list(ra_fixture, CompletionKind::Snippet);
expect.assert_eq(&actual)
}
#[test]
fn completes_enum_variants_and_modules() {
check(
r#"
enum E { X }
use self::E::X;
const Z: E = E::X;
mod m {}
static FOO: E = E::X;
struct Bar { f: u32 }
fn foo() {
match E::X { a$0 }
}
"#,
expect![[r#"
en E
ct Z
st Bar
ev X
md m
"#]],
);
}
#[test]
fn does_not_complete_non_fn_macros() {
check(
r#"
macro_rules! m { ($e:expr) => { $e } }
enum E { X }
#[rustc_builtin_macro]
macro Clone {}
fn foo() {
match E::X { $0 }
}
"#,
expect![[r#"
ev E::X ()
en E
ma m!() macro_rules! m
"#]],
);
}
#[test]
fn completes_in_simple_macro_call() {
check(
r#"
macro_rules! m { ($e:expr) => { $e } }
enum E { X }
fn foo() {
m!(match E::X { a$0 })
}
"#,
expect![[r#"
ev E::X ()
en E
ma m!() macro_rules! m
"#]],
);
}
#[test]
fn completes_in_irrefutable_let() {
check(
r#"
enum E { X }
use self::E::X;
const Z: E = E::X;
mod m {}
static FOO: E = E::X;
struct Bar { f: u32 }
fn foo() {
let a$0
}
"#,
expect![[r#"
st Bar
"#]],
);
}
#[test]
fn completes_in_param() {
check(
r#"
enum E { X }
static FOO: E = E::X;
struct Bar { f: u32 }
fn foo(a$0) {
}
"#,
expect![[r#"
st Bar
"#]],
);
}
#[test]
fn completes_pat_in_let() {
check_snippet(
r#"
struct Bar { f: u32 }
fn foo() {
let a$0
}
"#,
expect![[r#"
bn Bar Bar { f$1 }$0
"#]],
);
}
#[test]
fn completes_param_pattern() {
check_snippet(
r#"
struct Foo { bar: String, baz: String }
struct Bar(String, String);
struct Baz;
fn outer(a$0) {}
"#,
expect![[r#"
bn Foo Foo { bar$1, baz$2 }: Foo$0
bn Bar Bar($1, $2): Bar$0
"#]],
)
}
#[test]
fn completes_let_pattern() {
check_snippet(
r#"
struct Foo { bar: String, baz: String }
struct Bar(String, String);
struct Baz;
fn outer() {
let a$0
}
"#,
expect![[r#"
bn Foo Foo { bar$1, baz$2 }$0
bn Bar Bar($1, $2)$0
"#]],
)
}
#[test]
fn completes_refutable_pattern() {
check_snippet(
r#"
struct Foo { bar: i32, baz: i32 }
struct Bar(String, String);
struct Baz;
fn outer() {
match () {
a$0
}
}
"#,
expect![[r#"
bn Foo Foo { bar$1, baz$2 }$0
bn Bar Bar($1, $2)$0
"#]],
)
}
#[test]
fn omits_private_fields_pat() {
check_snippet(
r#"
mod foo {
pub struct Foo { pub bar: i32, baz: i32 }
pub struct Bar(pub String, String);
pub struct Invisible(String, String);
}
use foo::*;
fn outer() {
match () {
a$0
}
}
"#,
expect![[r#"
bn Foo Foo { bar$1, .. }$0
bn Bar Bar($1, ..)$0
"#]],
)
}
#[test]
fn only_shows_ident_completion() {
check_edit(
"Foo",
r#"
struct Foo(i32);
fn main() {
match Foo(92) {
a$0(92) => (),
}
}
"#,
r#"
struct Foo(i32);
fn main() {
match Foo(92) {
Foo(92) => (),
}
}
"#,
);
}
#[test]
fn completes_self_pats() {
check_snippet(
r#"
struct Foo(i32);
impl Foo {
fn foo() {
match () {
a$0
}
}
}
"#,
expect![[r#"
bn Self Self($1)$0
bn Foo Foo($1)$0
"#]],
)
}
#[test]
fn completes_qualified_variant() {
check_snippet(
r#"
enum Foo {
Bar { baz: i32 }
}
impl Foo {
fn foo() {
match {Foo::Bar { baz: 0 }} {
B$0
}
}
}
"#,
expect![[r#"
bn Self::Bar Self::Bar { baz$1 }$0
bn Foo::Bar Foo::Bar { baz$1 }$0
"#]],
)
}
#[test]
fn completes_enum_variant_matcharm() {
check(
r#"
enum Foo { Bar, Baz, Quux }
fn main() {
let foo = Foo::Quux;
match foo { Qu$0 }
}
"#,
expect![[r#"
ev Foo::Bar ()
ev Foo::Baz ()
ev Foo::Quux ()
en Foo
"#]],
)
}
#[test]
fn completes_enum_variant_matcharm_ref() {
check(
r#"
enum Foo { Bar, Baz, Quux }
fn main() {
let foo = Foo::Quux;
match &foo { Qu$0 }
}
"#,
expect![[r#"
ev Foo::Bar ()
ev Foo::Baz ()
ev Foo::Quux ()
en Foo
"#]],
)
}
#[test]
fn completes_enum_variant_iflet() {
check(
r#"
enum Foo { Bar, Baz, Quux }
fn main() {
let foo = Foo::Quux;
if let Qu$0 = foo { }
}
"#,
expect![[r#"
ev Foo::Bar ()
ev Foo::Baz ()
ev Foo::Quux ()
en Foo
"#]],
)
}
#[test]
fn completes_enum_variant_impl() {
check(
r#"
enum Foo { Bar, Baz, Quux }
impl Foo {
fn foo() { match Foo::Bar { Q$0 } }
}
"#,
expect![[r#"
ev Self::Bar ()
ev Self::Baz ()
ev Self::Quux ()
ev Foo::Bar ()
ev Foo::Baz ()
ev Foo::Quux ()
sp Self
en Foo
"#]],
)
}
#[test]
fn completes_in_record_field_pat() {
check_snippet(
r#"
struct Foo { bar: Bar }
struct Bar(u32);
fn outer(Foo { bar: $0 }: Foo) {}
"#,
expect![[r#"
bn Foo Foo { bar$1 }$0
bn Bar Bar($1)$0
"#]],
)
}
#[test]
fn skips_in_record_field_pat_name() {
check_snippet(
r#"
struct Foo { bar: Bar }
struct Bar(u32);
fn outer(Foo { bar$0 }: Foo) {}
"#,
expect![[r#""#]],
)
}
}

View File

@ -218,36 +218,6 @@ mod tests {
expect.assert_eq(&actual);
}
#[test]
fn dont_complete_values_in_type_pos() {
check(
r#"
const FOO: () = ();
static BAR: () = ();
struct Baz;
fn foo() {
let _: self::$0;
}
"#,
expect![[r#"
st Baz
"#]],
);
}
#[test]
fn dont_complete_enum_variants_in_type_pos() {
check(
r#"
enum Foo { Bar }
fn foo() {
let _: Foo::$0;
}
"#,
expect![[r#""#]],
);
}
#[test]
fn dont_complete_primitive_in_use() {
check_builtin(r#"use self::$0;"#, expect![[""]]);
@ -258,32 +228,6 @@ fn foo() {
check_builtin(r#"fn foo() { self::$0 }"#, expect![[""]]);
}
#[test]
fn completes_primitives() {
check_builtin(
r#"fn main() { let _: $0 = 92; }"#,
expect![[r#"
bt u32
bt bool
bt u8
bt isize
bt u16
bt u64
bt u128
bt f32
bt i128
bt i16
bt str
bt i64
bt char
bt f64
bt i32
bt i8
bt usize
"#]],
);
}
#[test]
fn completes_enum_variant() {
check(
@ -749,24 +693,4 @@ fn main() {
"#]],
);
}
#[test]
fn completes_types_and_const_in_arg_list() {
check(
r#"
mod foo {
pub const CONST: () = ();
pub type Type = ();
}
struct Foo<T>(t);
fn foo(_: Foo<foo::$0>) {}
"#,
expect![[r#"
ta Type
ct CONST
"#]],
);
}
}

View File

@ -112,78 +112,6 @@ mod tests {
expect.assert_eq(&actual)
}
#[test]
fn dont_complete_values_in_type_pos() {
check(
r#"
const FOO: () = ();
static BAR: () = ();
enum Foo {
Bar
}
struct Baz;
fn foo() {
let local = ();
let _: $0;
}
"#,
expect![[r#"
en Foo
st Baz
"#]],
);
}
#[test]
fn bind_pat_and_path_ignore_at() {
check(
r#"
enum Enum { A, B }
fn quux(x: Option<Enum>) {
match x {
None => (),
Some(en$0 @ Enum::A) => (),
}
}
"#,
expect![[r#""#]],
);
}
#[test]
fn bind_pat_and_path_ignore_ref() {
check(
r#"
enum Enum { A, B }
fn quux(x: Option<Enum>) {
match x {
None => (),
Some(ref en$0) => (),
}
}
"#,
expect![[r#""#]],
);
}
#[test]
fn bind_pat_and_path() {
check(
r#"
enum Enum { A, B }
fn quux(x: Option<Enum>) {
match x {
None => (),
Some(En$0) => (),
}
}
"#,
expect![[r#"
en Enum
"#]],
);
}
#[test]
fn completes_bindings_from_let() {
check(
@ -288,29 +216,6 @@ fn main() {
);
}
#[test]
fn completes_generic_params_in_struct() {
check(
r#"struct S<T> { x: $0}"#,
expect![[r#"
sp Self
tp T
st S<>
"#]],
);
}
#[test]
fn completes_self_in_enum() {
check(
r#"enum X { Y($0) }"#,
expect![[r#"
sp Self
en X
"#]],
);
}
#[test]
fn completes_module_items() {
check(
@ -364,19 +269,6 @@ mod m {
);
}
#[test]
fn completes_return_type() {
check(
r#"
struct Foo;
fn x() -> $0
"#,
expect![[r#"
st Foo
"#]],
);
}
#[test]
fn dont_show_both_completions_for_shadowing() {
check(
@ -558,19 +450,6 @@ fn foo() { $0 }
);
}
#[test]
fn completes_macros_as_type() {
check(
r#"
macro_rules! foo { () => {} }
fn main() { let x: $0 }
"#,
expect![[r#"
ma foo!() macro_rules! foo
"#]],
);
}
#[test]
fn completes_macros_as_stmt() {
check(
@ -716,30 +595,4 @@ fn f() {}
expect![[""]],
)
}
#[test]
fn completes_types_and_const_in_arg_list() {
check(
r#"
enum Bar {
Baz
}
trait Foo {
type Bar;
}
const CONST: () = ();
fn foo<T: Foo<$0>, const CONST_PARAM: usize>(_: T) {}
"#,
expect![[r#"
ta Bar = type Bar;
tp T
cp CONST_PARAM
tt Foo
en Bar
ct CONST
"#]],
);
}
}

View File

@ -286,8 +286,11 @@ impl<'a> CompletionContext<'a> {
)
}
pub(crate) fn expect_record_field(&self) -> bool {
matches!(self.completion_location, Some(ImmediateLocation::RecordField))
pub(crate) fn expect_field(&self) -> bool {
matches!(
self.completion_location,
Some(ImmediateLocation::RecordField | ImmediateLocation::TupleField)
)
}
pub(crate) fn in_use_tree(&self) -> bool {

View File

@ -31,6 +31,7 @@ pub(crate) enum ImmediateLocation {
Impl,
Trait,
RecordField,
TupleField,
RefExpr,
IdentPat,
BlockExpr,
@ -187,7 +188,13 @@ pub(crate) fn determine_location(
ast::SourceFile(_it) => ImmediateLocation::ItemList,
ast::ItemList(_it) => ImmediateLocation::ItemList,
ast::RefExpr(_it) => ImmediateLocation::RefExpr,
ast::RecordField(_it) => ImmediateLocation::RecordField,
ast::RecordField(it) => if it.ty().map_or(false, |it| it.syntax().text_range().contains(offset)) {
return None;
} else {
ImmediateLocation::RecordField
},
ast::TupleField(_it) => ImmediateLocation::TupleField,
ast::TupleFieldList(_it) => ImmediateLocation::TupleField,
ast::AssocItemList(it) => match it.syntax().parent().map(|it| it.kind()) {
Some(IMPL) => ImmediateLocation::Impl,
Some(TRAIT) => ImmediateLocation::Trait,

View File

@ -7,6 +7,10 @@
mod item_list;
mod use_tree;
mod items;
mod pattern;
mod type_pos;
use std::mem;
use hir::{PrefixKind, Semantics};
use ide_db::{
@ -45,7 +49,16 @@ pub(crate) fn completion_list(code: &str) -> String {
}
fn completion_list_with_config(config: CompletionConfig, code: &str) -> String {
render_completion_list(get_all_items(config, code))
// filter out all but one builtintype completion for smaller test outputs
let items = get_all_items(config, code);
let mut bt_seen = false;
let items = items
.into_iter()
.filter(|it| {
it.completion_kind != CompletionKind::BuiltinType || !mem::replace(&mut bt_seen, true)
})
.collect();
render_completion_list(items)
}
/// Creates analysis from a multi-file fixture, returns positions marked with $0.

View File

@ -35,22 +35,6 @@ impl Tra$0
ma foo!() #[macro_export] macro_rules! foo
ma foo!() #[macro_export] macro_rules! foo
bt u32
bt bool
bt u8
bt isize
bt u16
bt u64
bt u128
bt f32
bt i128
bt i16
bt str
bt i64
bt char
bt f64
bt i32
bt i8
bt usize
"##]],
)
}
@ -69,22 +53,6 @@ impl Trait for Str$0
ma foo!() #[macro_export] macro_rules! foo
ma foo!() #[macro_export] macro_rules! foo
bt u32
bt bool
bt u8
bt isize
bt u16
bt u64
bt u128
bt f32
bt i128
bt i16
bt str
bt i64
bt char
bt f64
bt i32
bt i8
bt usize
"##]],
)
}

View File

@ -0,0 +1,348 @@
//! Completions tests for pattern position.
use expect_test::{expect, Expect};
use crate::tests::completion_list;
fn check(ra_fixture: &str, expect: Expect) {
let actual = completion_list(ra_fixture);
expect.assert_eq(&actual)
}
fn check_with(ra_fixture: &str, expect: Expect) {
let base = r#"
enum Enum { TupleV(u32), RecordV { field: u32 }, UnitV }
use self::Enum::TupleV;
mod module {}
static STATIC: Unit = Unit;
const CONST: Unit = Unit;
struct Record { field: u32 }
struct Tuple(u32);
struct Unit
macro_rules! makro {}
"#;
let actual = completion_list(&format!("{}\n{}", base, ra_fixture));
expect.assert_eq(&actual)
}
#[test]
fn ident_rebind_pat() {
check(
r#"
fn quux() {
let en$0 @ x
}
"#,
expect![[r#"
kw mut
"#]],
);
}
#[test]
fn ident_ref_pat() {
check(
r#"
fn quux() {
let ref en$0
}
"#,
expect![[r#"
kw mut
"#]],
);
check(
r#"
fn quux() {
let ref en$0 @ x
}
"#,
expect![[r#"
kw mut
"#]],
);
}
#[test]
fn ident_ref_mut_pat() {
// FIXME mut is already here, don't complete it again
check(
r#"
fn quux() {
let ref mut en$0
}
"#,
expect![[r#"
kw mut
"#]],
);
check(
r#"
fn quux() {
let ref mut en$0 @ x
}
"#,
expect![[r#"
kw mut
"#]],
);
}
#[test]
fn ref_pat() {
check(
r#"
fn quux() {
let &en$0
}
"#,
expect![[r#"
kw mut
"#]],
);
// FIXME mut is already here, don't complete it again
check(
r#"
fn quux() {
let &mut en$0
}
"#,
expect![[r#"
kw mut
"#]],
);
}
#[test]
fn refutable() {
check_with(
r#"
fn foo() {
if let a$0
}
"#,
expect![[r#"
kw mut
bn Record Record { field$1 }$0
st Record
en Enum
bn Tuple Tuple($1)$0
st Tuple
md module
bn TupleV TupleV($1)$0
ev TupleV
st Unit
ct CONST
ma makro!() macro_rules! makro
"#]],
);
}
#[test]
fn irrefutable() {
check_with(
r#"
fn foo() {
let a$0
}
"#,
expect![[r#"
kw mut
bn Record Record { field$1 }$0
st Record
bn Tuple Tuple($1)$0
st Tuple
st Unit
ma makro!() macro_rules! makro
"#]],
);
}
#[test]
fn in_param() {
check_with(
r#"
fn foo(a$0) {
}
"#,
expect![[r#"
kw mut
bn Record Record { field$1 }: Record$0
st Record
bn Tuple Tuple($1): Tuple$0
st Tuple
st Unit
ma makro!() macro_rules! makro
"#]],
);
}
#[test]
fn only_fn_like_macros() {
check(
r#"
macro_rules! m { ($e:expr) => { $e } }
#[rustc_builtin_macro]
macro Clone {}
fn foo() {
let x$0
}
"#,
expect![[r#"
kw mut
ma m!() macro_rules! m
"#]],
);
}
#[test]
fn in_simple_macro_call() {
check(
r#"
macro_rules! m { ($e:expr) => { $e } }
enum E { X }
fn foo() {
m!(match E::X { a$0 })
}
"#,
expect![[r#"
kw mut
ev E::X ()
en E
ma m!() macro_rules! m
"#]],
);
}
#[test]
fn omits_private_fields_pat() {
check(
r#"
mod foo {
pub struct Record { pub field: i32, _field: i32 }
pub struct Tuple(pub u32, u32);
pub struct Invisible(u32, u32);
}
use foo::*;
fn outer() {
if let a$0
}
"#,
expect![[r#"
kw mut
bn Record Record { field$1, .. }$0
st Record
bn Tuple Tuple($1, ..)$0
st Tuple
st Invisible
md foo
"#]],
)
}
// #[test]
// fn only_shows_ident_completion() {
// check_edit(
// "Foo",
// r#"
// struct Foo(i32);
// fn main() {
// match Foo(92) {
// a$0(92) => (),
// }
// }
// "#,
// r#"
// struct Foo(i32);
// fn main() {
// match Foo(92) {
// Foo(92) => (),
// }
// }
// "#,
// );
// }
#[test]
fn completes_self_pats() {
check(
r#"
struct Foo(i32);
impl Foo {
fn foo() {
match Foo(0) {
a$0
}
}
}
"#,
expect![[r#"
kw mut
bn Self Self($1)$0
sp Self
bn Foo Foo($1)$0
st Foo
"#]],
)
}
#[test]
fn completes_qualified_variant() {
check(
r#"
enum Foo {
Bar { baz: i32 }
}
impl Foo {
fn foo() {
match {Foo::Bar { baz: 0 }} {
B$0
}
}
}
"#,
expect![[r#"
kw mut
bn Self::Bar Self::Bar { baz$1 }$0
ev Self::Bar { baz: i32 }
bn Foo::Bar Foo::Bar { baz$1 }$0
ev Foo::Bar { baz: i32 }
sp Self
en Foo
"#]],
)
}
#[test]
fn completes_in_record_field_pat() {
check(
r#"
struct Foo { bar: Bar }
struct Bar(u32);
fn outer(Foo { bar: $0 }: Foo) {}
"#,
expect![[r#"
kw mut
bn Foo Foo { bar$1 }$0
st Foo
bn Bar Bar($1)$0
st Bar
"#]],
)
}
#[test]
fn skips_in_record_field_pat_name() {
check(
r#"
struct Foo { bar: Bar }
struct Bar(u32);
fn outer(Foo { bar$0 }: Foo) {}
"#,
expect![[r#""#]],
)
}

View File

@ -0,0 +1,177 @@
//! Completions tests for type position.
use expect_test::{expect, Expect};
use crate::tests::completion_list;
fn check_with(ra_fixture: &str, expect: Expect) {
let base = r#"
enum Enum { TupleV(u32), RecordV { field: u32 }, UnitV }
use self::Enum::TupleV;
mod module {}
trait Trait {}
static STATIC: Unit = Unit;
const CONST: Unit = Unit;
struct Record { field: u32 }
struct Tuple(u32);
struct Unit
macro_rules! makro {}
"#;
let actual = completion_list(&format!("{}\n{}", base, ra_fixture));
expect.assert_eq(&actual)
}
#[test]
fn record_field_ty() {
check_with(
r#"
struct Foo<'lt, T, const C: usize> {
f: $0
}
"#,
expect![[r#"
sp Self
tp T
tt Trait
en Enum
st Record
st Tuple
md module
st Foo<>
st Unit
ma makro!() macro_rules! makro
bt u32
"#]],
)
}
#[test]
fn tuple_struct_field() {
check_with(
r#"
struct Foo<'lt, T, const C: usize>(f$0);
"#,
expect![[r#"
kw pub(crate)
kw pub
sp Self
tp T
tt Trait
en Enum
st Record
st Tuple
md module
st Foo<>
st Unit
ma makro!() macro_rules! makro
bt u32
"#]],
)
}
#[test]
fn fn_return_type() {
check_with(
r#"
fn x<'lt, T, const C: usize>() -> $0
"#,
expect![[r#"
tp T
tt Trait
en Enum
st Record
st Tuple
md module
st Unit
ma makro!() macro_rules! makro
bt u32
"#]],
);
}
#[test]
fn body_type_pos() {
check_with(
r#"
fn foo<'lt, T, const C: usize>() {
let local = ();
let _: $0;
}
"#,
expect![[r#"
tp T
tt Trait
en Enum
st Record
st Tuple
md module
st Unit
ma makro!() macro_rules! makro
bt u32
"#]],
);
check_with(
r#"
fn foo<'lt, T, const C: usize>() {
let local = ();
let _: self::$0;
}
"#,
expect![[r#"
tt Trait
en Enum
st Record
st Tuple
md module
st Unit
"#]],
);
}
#[test]
fn completes_types_and_const_in_arg_list() {
// FIXME: we should complete the lifetime here for now
check_with(
r#"
trait Trait2 {
type Foo;
}
fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {}
"#,
expect![[r#"
ta Foo = type Foo;
tp T
cp CONST_PARAM
tt Trait
en Enum
st Record
st Tuple
tt Trait2
md module
st Unit
ct CONST
ma makro!() macro_rules! makro
bt u32
"#]],
);
check_with(
r#"
trait Trait2 {
type Foo;
}
fn foo<'lt, T: Trait2<self::$0>, const CONST_PARAM: usize>(_: T) {}
"#,
expect![[r#"
tt Trait
en Enum
st Record
st Tuple
tt Trait2
md module
st Unit
ct CONST
"#]],
);
}