//! Completion tests for type position. use expect_test::expect; use crate::tests::{check, check_with_base_items}; #[test] fn record_field_ty() { check_with_base_items( r#" struct Foo<'lt, T, const C: usize> { f: $0 } "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module sp Self Foo<'_, {unknown}, _> st Foo<…> Foo<'_, {unknown}, _> st Record Record st Tuple Tuple st Unit Unit tt Trait tp T un Union Union bt u32 u32 kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ) } #[test] fn tuple_struct_field() { check_with_base_items( r#" struct Foo<'lt, T, const C: usize>(f$0); "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module sp Self Foo<'_, {unknown}, _> st Foo<…> Foo<'_, {unknown}, _> st Record Record st Tuple Tuple st Unit Unit tt Trait tp T un Union Union bt u32 u32 kw crate:: kw dyn kw fn kw for kw impl kw pub kw pub(crate) kw pub(super) kw self:: "#]], ) } #[test] fn fn_return_type() { check_with_base_items( r#" fn x<'lt, T, const C: usize>() -> $0 "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Record Record st Tuple Tuple st Unit Unit tt Trait tp T un Union Union bt u32 u32 kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); } #[test] fn fn_return_type_after_reference() { check_with_base_items( r#" fn x<'lt, T, const C: usize>(_: &()) -> &$0 "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Record Record st Tuple Tuple st Unit Unit tt Trait tp T un Union Union bt u32 u32 kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); } #[test] fn fn_return_type_no_local_items() { check_with_base_items( r#" fn foo() -> B$0 { struct Bar; enum Baz {} union Bax { i: i32, f: f32 } } "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Record Record st Tuple Tuple st Unit Unit tt Trait un Union Union bt u32 u32 it () kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ) } #[test] fn inferred_type_const() { check_with_base_items( r#" struct Foo(T); const FOO: $0 = Foo(2); "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Foo<…> Foo<{unknown}> st Record Record st Tuple Tuple st Unit Unit tt Trait un Union Union bt u32 u32 it Foo kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); } #[test] fn inferred_type_static() { check_with_base_items( r#" struct Foo(T); static FOO: $0 = Foo(2); "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Foo<…> Foo<{unknown}> st Record Record st Tuple Tuple st Unit Unit tt Trait un Union Union bt u32 u32 it Foo kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); } #[test] fn inferred_type_closure_param() { check_with_base_items( r#" fn f1(f: fn(i32) -> i32) {} fn f2() { f1(|x: $0); } "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Record Record st Tuple Tuple st Unit Unit tt Trait un Union Union bt u32 u32 it i32 kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); } #[test] fn inferred_type_closure_return() { check_with_base_items( r#" fn f1(f: fn(u64) -> u64) {} fn f2() { f1(|x| -> $0 { x + 5 }); } "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Record Record st Tuple Tuple st Unit Unit tt Trait un Union Union bt u32 u32 it u64 kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); } #[test] fn inferred_type_fn_return() { check_with_base_items( r#" fn f2(x: u64) -> $0 { x + 5 } "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Record Record st Tuple Tuple st Unit Unit tt Trait un Union Union bt u32 u32 it u64 kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); } #[test] fn inferred_type_fn_param() { check_with_base_items( r#" fn f1(x: i32) {} fn f2(x: $0) { f1(x); } "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Record Record st Tuple Tuple st Unit Unit tt Trait un Union Union bt u32 u32 it i32 kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); } #[test] fn inferred_type_not_in_the_scope() { check_with_base_items( r#" mod a { pub struct Foo(T); pub fn x() -> Foo> { Foo(Foo(2)) } } fn foo<'lt, T, const C: usize>() { let local = (); let foo: $0 = a::x(); } "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md a md module st Record Record st Tuple Tuple st Unit Unit tt Trait tp T un Union Union bt u32 u32 it a::Foo> kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); } #[test] fn inferred_type_let() { check_with_base_items( r#" struct Foo(T); fn foo<'lt, T, const C: usize>() { let local = (); let foo: $0 = Foo(2); } "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Foo<…> Foo<{unknown}> st Record Record st Tuple Tuple st Unit Unit tt Trait tp T un Union Union bt u32 u32 it Foo kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); } #[test] fn body_type_pos() { check_with_base_items( r#" fn foo<'lt, T, const C: usize>() { let local = (); let _: $0; } "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Record Record st Tuple Tuple st Unit Unit tt Trait tp T un Union Union bt u32 u32 kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); check_with_base_items( r#" fn foo<'lt, T, const C: usize>() { let local = (); let _: self::$0; } "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Record Record st Tuple Tuple st Unit Unit tt Trait un Union Union "#]], ); } #[test] fn completes_types_and_const_in_arg_list() { cov_mark::check!(complete_assoc_type_in_generics_list); check_with_base_items( r#" trait Trait1 { type Super; } trait Trait2: Trait1 { type Foo; } fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {} "#, expect![[r#" ta Foo = (as Trait2) type Foo ta Super = (as Trait1) type Super "#]], ); check_with_base_items( r#" trait Trait1 { type Super; } trait Trait2: Trait1 { type Foo; } fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {} "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Record Record st Tuple Tuple st Unit Unit tt Trait tt Trait1 tt Trait2 tp T un Union Union bt u32 u32 kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); check_with_base_items( r#" trait Trait2 { type Foo; } fn foo<'lt, T: Trait2, const CONST_PARAM: usize>(_: T) {} "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Record Record st Tuple Tuple st Unit Unit tt Trait tt Trait2 un Union Union "#]], ); } #[test] fn no_assoc_completion_outside_type_bounds() { check_with_base_items( r#" struct S; trait Tr { type Ty; } impl Tr<$0 "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module sp Self dyn Tr<{unknown}> + 'static st Record Record st S S st Tuple Tuple st Unit Unit tt Tr tt Trait un Union Union bt u32 u32 kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); } #[test] fn enum_qualified() { check_with_base_items( r#" impl Enum { type AssocType = (); const ASSOC_CONST: () = (); fn assoc_fn() {} } fn func(_: Enum::$0) {} "#, expect![[r#" ta AssocType type AssocType = () "#]], ); } #[test] fn completes_type_parameter_or_associated_type() { check_with_base_items( r#" trait MyTrait { type Item1; type Item2; }; fn f(t: impl MyTrait { type Item1; type Item2; }; fn f(t: impl MyTrait { type Item1; type Item2; }; fn f(t: impl MyTrait { type Item1; type Item2; }; fn f(t: impl MyTrait { type Item1; type Item2; }; fn f(t: impl MyTrait { type Item1; type Item2; }; fn f(t: impl MyTrait() {} fn main() { foo::(); } "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Foo Foo st Record Record st Tuple Tuple st Unit Unit tt Trait un Union Union bt u32 u32 kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); // FIXME: This should probably also suggest completions for types, at least those that have // associated constants usable in this position. For example, a user could be typing // `foo::<_, { usize::MAX }>()`, but we currently don't suggest `usize` in constant position. check_with_base_items( r#" struct Foo; const X: usize = 0; fn foo() {} fn main() { foo::<_, $0>(); } "#, expect![[r#" ct CONST Unit ct X usize ma makro!(…) macro_rules! makro kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); // Method generic params check_with_base_items( r#" const X: usize = 0; struct Foo; impl Foo { fn bar(self) {} } fn main() { Foo.bar::<_, $0>(); } "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Foo Foo st Record Record st Tuple Tuple st Unit Unit tt Trait un Union Union bt u32 u32 kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); check_with_base_items( r#" const X: usize = 0; struct Foo; impl Foo { fn bar(self) {} } fn main() { Foo.bar::(); } "#, expect![[r#" ct CONST Unit ct X usize ma makro!(…) macro_rules! makro kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); // Associated type generic params check_with_base_items( r#" const X: usize = 0; struct Foo; trait Bar { type Baz; } fn foo(_: impl Bar = ()>) {} "#, expect![[r#" en Enum Enum ma makro!(…) macro_rules! makro md module st Foo Foo st Record Record st Tuple Tuple st Unit Unit tt Bar tt Trait un Union Union bt u32 u32 kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); check_with_base_items( r#" const X: usize = 0; struct Foo; trait Bar { type Baz; } fn foo = ()>>() {} "#, expect![[r#" ct CONST Unit ct X usize ma makro!(…) macro_rules! makro kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); // Type generic params check_with_base_items( r#" const X: usize = 0; struct Foo(T); fn main() { let _: Foo::<_, $0> = Foo(()); } "#, expect![[r#" ct CONST Unit ct X usize ma makro!(…) macro_rules! makro kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); // Type alias generic params check_with_base_items( r#" const X: usize = 0; struct Foo(T); type Bar = Foo; fn main() { let _: Bar:: = Bar(()); } "#, expect![[r#" ct CONST Unit ct X usize ma makro!(…) macro_rules! makro kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); // Enum variant params check_with_base_items( r#" const X: usize = 0; enum Foo { A(T), B } fn main() { Foo::B::<(), $0>; } "#, expect![[r#" ct CONST Unit ct X usize ma makro!(…) macro_rules! makro kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); // Trait params check_with_base_items( r#" const X: usize = 0; trait Foo {} impl Foo<(), $0> for () {} "#, expect![[r#" ct CONST Unit ct X usize ma makro!(…) macro_rules! makro kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); // Trait alias params check_with_base_items( r#" #![feature(trait_alias)] const X: usize = 0; trait Foo {} trait Bar = Foo; fn foo>() {} "#, expect![[r#" ct CONST Unit ct X usize ma makro!(…) macro_rules! makro kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); // Omitted lifetime params check_with_base_items( r#" struct S<'a, 'b, const C: usize, T>(core::marker::PhantomData<&'a &'b T>); fn foo<'a>() { S::; } "#, expect![[r#" ct CONST Unit ma makro!(…) macro_rules! makro kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); // Explicit lifetime params check_with_base_items( r#" struct S<'a, 'b, const C: usize, T>(core::marker::PhantomData<&'a &'b T>); fn foo<'a>() { S::<'static, 'static, F$0, _>; } "#, expect![[r#" ct CONST Unit ma makro!(…) macro_rules! makro kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); check_with_base_items( r#" struct S<'a, 'b, const C: usize, T>(core::marker::PhantomData<&'a &'b T>); fn foo<'a>() { S::<'static, F$0, _, _>; } "#, expect![[r#" lt 'a ma makro!(…) macro_rules! makro kw crate:: kw dyn kw fn kw for kw impl kw self:: "#]], ); } #[test] fn complete_traits_on_impl_trait_block() { check_with_base_items( r#" trait Foo {} struct Bar; impl $0 for Bar { } "#, expect![[r#" md module tt Foo tt Trait kw crate:: kw self:: "#]], ); } #[test] fn complete_traits_with_path_on_impl_trait_block() { check_with_base_items( r#" mod outer { pub trait Foo {} pub struct Bar; pub mod inner { } } impl outer::$0 for Bar { } "#, expect![[r#" md inner tt Foo "#]], ); }