Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/signature_help.rs')
| -rw-r--r-- | crates/ide/src/signature_help.rs | 215 |
1 files changed, 174 insertions, 41 deletions
diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs index f45d096ac1..78dc3f7e86 100644 --- a/crates/ide/src/signature_help.rs +++ b/crates/ide/src/signature_help.rs @@ -11,7 +11,6 @@ use hir::{ use ide_db::{ FilePosition, FxIndexMap, active_parameter::{callable_for_arg_list, generic_def_for_node}, - base_db::salsa, documentation::{Documentation, HasDocs}, }; use itertools::Itertools; @@ -32,7 +31,7 @@ use crate::RootDatabase; /// edited. #[derive(Debug)] pub struct SignatureHelp { - pub doc: Option<Documentation>, + pub doc: Option<Documentation<'static>>, pub signature: String, pub active_parameter: Option<usize>, parameters: Vec<TextRange>, @@ -85,8 +84,7 @@ pub(crate) fn signature_help( // this prevents us from leaving the CallExpression .and_then(|tok| algo::skip_trivia_token(tok, Direction::Prev))?; let token = sema.descend_into_macros_single_exact(token); - let edition = - sema.attach_first_edition(file_id).map(|it| it.edition(db)).unwrap_or(Edition::CURRENT); + let edition = sema.attach_first_edition(file_id).edition(db); let display_target = sema.first_crate(file_id)?.to_display_target(db); for node in token.parent_ancestors() { @@ -175,7 +173,10 @@ fn signature_help_for_call( let mut fn_params = None; match callable.kind() { hir::CallableKind::Function(func) => { - res.doc = func.docs(db); + res.doc = func.docs(db).map(Documentation::into_owned); + if func.is_async(db) { + format_to!(res.signature, "async "); + } format_to!(res.signature, "fn {}", func.name(db).display(db, edition)); let generic_params = GenericDef::Function(func) @@ -197,7 +198,7 @@ fn signature_help_for_call( }); } hir::CallableKind::TupleStruct(strukt) => { - res.doc = strukt.docs(db); + res.doc = strukt.docs(db).map(Documentation::into_owned); format_to!(res.signature, "struct {}", strukt.name(db).display(db, edition)); let generic_params = GenericDef::Adt(strukt.into()) @@ -210,7 +211,7 @@ fn signature_help_for_call( } } hir::CallableKind::TupleEnumVariant(variant) => { - res.doc = variant.docs(db); + res.doc = variant.docs(db).map(Documentation::into_owned); format_to!( res.signature, "enum {}", @@ -267,7 +268,7 @@ fn signature_help_for_call( // In that case, fall back to render definitions of the respective parameters. // This is overly conservative: we do not substitute known type vars // (see FIXME in tests::impl_trait) and falling back on any unknowns. - salsa::attach(db, || match (p.ty().contains_unknown(), fn_params.as_deref()) { + hir::attach_db(db, || match (p.ty().contains_unknown(), fn_params.as_deref()) { (true, Some(fn_params)) => { format_to!(buf, "{}", fn_params[idx].ty().display(db, display_target)) } @@ -284,13 +285,16 @@ fn signature_help_for_call( } }; match callable.kind() { - hir::CallableKind::Function(func) if callable.return_type().contains_unknown() => { - render(func.ret_type(db)) + hir::CallableKind::Function(func) => render(func.async_ret_type(db).unwrap_or_else(|| { + if callable.return_type().contains_unknown() { + func.ret_type(db) + } else { + callable.return_type() + } + })), + hir::CallableKind::Closure(_) | hir::CallableKind::FnPtr | hir::CallableKind::FnImpl(_) => { + render(callable.return_type()) } - hir::CallableKind::Function(_) - | hir::CallableKind::Closure(_) - | hir::CallableKind::FnPtr - | hir::CallableKind::FnImpl(_) => render(callable.return_type()), hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {} } Some(res) @@ -315,33 +319,33 @@ fn signature_help_for_generics( let db = sema.db; match generics_def { hir::GenericDef::Function(it) => { - res.doc = it.docs(db); + res.doc = it.docs(db).map(Documentation::into_owned); format_to!(res.signature, "fn {}", it.name(db).display(db, edition)); } hir::GenericDef::Adt(hir::Adt::Enum(it)) => { - res.doc = it.docs(db); + res.doc = it.docs(db).map(Documentation::into_owned); format_to!(res.signature, "enum {}", it.name(db).display(db, edition)); if let Some(variant) = variant { // In paths, generics of an enum can be specified *after* one of its variants. // eg. `None::<u8>` // We'll use the signature of the enum, but include the docs of the variant. - res.doc = variant.docs(db); + res.doc = variant.docs(db).map(Documentation::into_owned); } } hir::GenericDef::Adt(hir::Adt::Struct(it)) => { - res.doc = it.docs(db); + res.doc = it.docs(db).map(Documentation::into_owned); format_to!(res.signature, "struct {}", it.name(db).display(db, edition)); } hir::GenericDef::Adt(hir::Adt::Union(it)) => { - res.doc = it.docs(db); + res.doc = it.docs(db).map(Documentation::into_owned); format_to!(res.signature, "union {}", it.name(db).display(db, edition)); } hir::GenericDef::Trait(it) => { - res.doc = it.docs(db); + res.doc = it.docs(db).map(Documentation::into_owned); format_to!(res.signature, "trait {}", it.name(db).display(db, edition)); } hir::GenericDef::TypeAlias(it) => { - res.doc = it.docs(db); + res.doc = it.docs(db).map(Documentation::into_owned); format_to!(res.signature, "type {}", it.name(db).display(db, edition)); } // These don't have generic args that can be specified @@ -496,7 +500,7 @@ fn signature_help_for_tuple_struct_pat( let fields: Vec<_> = if let PathResolution::Def(ModuleDef::Variant(variant)) = path_res { let en = variant.parent_enum(db); - res.doc = en.docs(db); + res.doc = en.docs(db).map(Documentation::into_owned); format_to!( res.signature, "enum {}::{} (", @@ -513,7 +517,7 @@ fn signature_help_for_tuple_struct_pat( match adt { hir::Adt::Struct(it) => { - res.doc = it.docs(db); + res.doc = it.docs(db).map(Documentation::into_owned); format_to!(res.signature, "struct {} (", it.name(db).display(db, edition)); it.fields(db) } @@ -526,7 +530,7 @@ fn signature_help_for_tuple_struct_pat( pat.syntax(), token, pat.fields(), - fields.into_iter().map(|it| it.ty(db)), + fields.into_iter().map(|it| it.ty(db).to_type(db)), display_target, )) } @@ -623,7 +627,7 @@ fn signature_help_for_record_<'db>( fields = variant.fields(db); let en = variant.parent_enum(db); - res.doc = en.docs(db); + res.doc = en.docs(db).map(Documentation::into_owned); format_to!( res.signature, "enum {}::{} {{ ", @@ -640,12 +644,12 @@ fn signature_help_for_record_<'db>( match adt { hir::Adt::Struct(it) => { fields = it.fields(db); - res.doc = it.docs(db); + res.doc = it.docs(db).map(Documentation::into_owned); format_to!(res.signature, "struct {} {{ ", it.name(db).display(db, edition)); } hir::Adt::Union(it) => { fields = it.fields(db); - res.doc = it.docs(db); + res.doc = it.docs(db).map(Documentation::into_owned); format_to!(res.signature, "union {} {{ ", it.name(db).display(db, edition)); } _ => return None, @@ -730,7 +734,7 @@ fn signature_help_for_tuple_pat_ish<'db>( mod tests { use expect_test::{Expect, expect}; - use ide_db::{FilePosition, base_db::salsa}; + use ide_db::FilePosition; use stdx::format_to; use test_fixture::ChangeFixture; @@ -741,25 +745,19 @@ mod tests { #[rust_analyzer::rust_fixture] ra_fixture: &str, ) -> (RootDatabase, FilePosition) { let mut database = RootDatabase::default(); - let change_fixture = ChangeFixture::parse(&database, ra_fixture); + let change_fixture = ChangeFixture::parse(ra_fixture); database.apply_change(change_fixture.change); let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker ($0)"); let offset = range_or_offset.expect_offset(); - let position = FilePosition { file_id: file_id.file_id(&database), offset }; + let position = FilePosition { file_id: file_id.file_id(), offset }; (database, position) } #[track_caller] fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { - let fixture = format!( - r#" -//- minicore: sized, fn -{ra_fixture} - "# - ); - let (db, position) = position(&fixture); - let sig_help = salsa::attach(&db, || crate::signature_help::signature_help(&db, position)); + let (db, position) = position(ra_fixture); + let sig_help = hir::attach_db(&db, || crate::signature_help::signature_help(&db, position)); let actual = match sig_help { Some(sig_help) => { let mut rendered = String::new(); @@ -796,6 +794,7 @@ mod tests { fn test_fn_signature_two_args() { check( r#" +//- minicore: sized, fn fn foo(x: u32, y: u32) -> u32 {x + y} fn bar() { foo($03, ); } "#, @@ -806,6 +805,7 @@ fn bar() { foo($03, ); } ); check( r#" +//- minicore: sized, fn fn foo(x: u32, y: u32) -> u32 {x + y} fn bar() { foo(3$0, ); } "#, @@ -816,6 +816,7 @@ fn bar() { foo(3$0, ); } ); check( r#" +//- minicore: sized, fn fn foo(x: u32, y: u32) -> u32 {x + y} fn bar() { foo(3,$0 ); } "#, @@ -826,6 +827,7 @@ fn bar() { foo(3,$0 ); } ); check( r#" +//- minicore: sized, fn fn foo(x: u32, y: u32) -> u32 {x + y} fn bar() { foo(3, $0); } "#, @@ -840,6 +842,7 @@ fn bar() { foo(3, $0); } fn test_fn_signature_two_args_empty() { check( r#" +//- minicore: sized, fn fn foo(x: u32, y: u32) -> u32 {x + y} fn bar() { foo($0); } "#, @@ -854,6 +857,7 @@ fn bar() { foo($0); } fn test_fn_signature_two_args_first_generics() { check( r#" +//- minicore: sized, fn fn foo<T, U: Copy + Display>(x: T, y: U) -> u32 where T: Copy + Display, U: Debug { x + y } @@ -871,6 +875,7 @@ fn bar() { foo($03, ); } fn test_fn_signature_no_params() { check( r#" +//- minicore: sized, fn fn foo<T>() -> T where T: Copy + Display {} fn bar() { foo($0); } "#, @@ -884,6 +889,7 @@ fn bar() { foo($0); } fn test_fn_signature_for_impl() { check( r#" +//- minicore: sized, fn struct F; impl F { pub fn new() { } } fn bar() { @@ -900,6 +906,7 @@ fn bar() { fn test_fn_signature_for_method_self() { check( r#" +//- minicore: sized, fn struct S; impl S { pub fn do_it(&self) {} } @@ -918,6 +925,7 @@ fn bar() { fn test_fn_signature_for_method_with_arg() { check( r#" +//- minicore: sized, fn struct S; impl S { fn foo(&self, x: i32) {} @@ -936,6 +944,7 @@ fn main() { S.foo($0); } fn test_fn_signature_for_generic_method() { check( r#" +//- minicore: sized, fn struct S<T>(T); impl<T> S<T> { fn foo(&self, x: T) {} @@ -954,6 +963,7 @@ fn main() { S(1u32).foo($0); } fn test_fn_signature_for_method_with_arg_as_assoc_fn() { check( r#" +//- minicore: sized, fn struct S; impl S { fn foo(&self, x: i32) {} @@ -972,6 +982,7 @@ fn main() { S::foo($0); } fn test_fn_signature_with_docs_simple() { check( r#" +//- minicore: sized, fn /// test // non-doc-comment fn foo(j: u32) -> u32 { @@ -995,6 +1006,7 @@ fn bar() { fn test_fn_signature_with_docs() { check( r#" +//- minicore: sized, fn /// Adds one to the number given. /// /// # Examples @@ -1032,6 +1044,7 @@ pub fn r#do() { fn test_fn_signature_with_docs_impl() { check( r#" +//- minicore: sized, fn struct addr; impl addr { /// Adds one to the number given. @@ -1074,6 +1087,7 @@ pub fn do_it() { fn test_fn_signature_with_docs_from_actix() { check( r#" +//- minicore: sized, fn trait Actor { /// Actor execution context type type Context; @@ -1107,6 +1121,7 @@ fn foo(mut r: impl WriteHandler<()>) { fn call_info_bad_offset() { check( r#" +//- minicore: sized, fn fn foo(x: u32, y: u32) -> u32 {x + y} fn bar() { foo $0 (3, ); } "#, @@ -1118,6 +1133,7 @@ fn bar() { foo $0 (3, ); } fn outside_of_arg_list() { check( r#" +//- minicore: sized, fn fn foo(a: u8) {} fn f() { foo(123)$0 @@ -1127,6 +1143,7 @@ fn f() { ); check( r#" +//- minicore: sized, fn fn foo<T>(a: u8) {} fn f() { foo::<u32>$0() @@ -1136,6 +1153,7 @@ fn f() { ); check( r#" +//- minicore: sized, fn fn foo(a: u8) -> u8 {a} fn bar(a: u8) -> u8 {a} fn f() { @@ -1149,6 +1167,7 @@ fn f() { ); check( r#" +//- minicore: sized, fn struct Vec<T>(T); struct Vec2<T>(T); fn f() { @@ -1166,6 +1185,7 @@ fn f() { fn test_nested_method_in_lambda() { check( r#" +//- minicore: sized, fn struct Foo; impl Foo { fn bar(&self, _: u32) { } } @@ -1187,6 +1207,7 @@ fn main() { fn works_for_tuple_structs() { check( r#" +//- minicore: sized, fn /// A cool tuple struct struct S(u32, i32); fn main() { @@ -1206,6 +1227,7 @@ fn main() { fn tuple_struct_pat() { check( r#" +//- minicore: sized, fn /// A cool tuple struct struct S(u32, i32); fn main() { @@ -1225,6 +1247,7 @@ fn main() { fn tuple_struct_pat_rest() { check( r#" +//- minicore: sized, fn /// A cool tuple struct struct S(u32, i32, f32, u16); fn main() { @@ -1240,6 +1263,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn /// A cool tuple struct struct S(u32, i32, f32, u16, u8); fn main() { @@ -1255,6 +1279,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn /// A cool tuple struct struct S(u32, i32, f32, u16); fn main() { @@ -1270,6 +1295,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn /// A cool tuple struct struct S(u32, i32, f32, u16, u8); fn main() { @@ -1285,6 +1311,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn /// A cool tuple struct struct S(u32, i32, f32, u16); fn main() { @@ -1300,6 +1327,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn /// A cool tuple struct struct S(u32, i32, f32, u16); fn main() { @@ -1319,6 +1347,7 @@ fn main() { fn generic_struct() { check( r#" +//- minicore: sized, fn struct S<T>(T); fn main() { let s = S($0); @@ -1335,6 +1364,7 @@ fn main() { fn works_for_enum_variants() { check( r#" +//- minicore: sized, fn enum E { /// A Variant A(i32), @@ -1361,6 +1391,7 @@ fn main() { fn cant_call_struct_record() { check( r#" +//- minicore: sized, fn struct S { x: u32, y: i32 } fn main() { let s = S($0); @@ -1374,6 +1405,7 @@ fn main() { fn cant_call_enum_record() { check( r#" +//- minicore: sized, fn enum E { /// A Variant A(i32), @@ -1395,6 +1427,7 @@ fn main() { fn fn_signature_for_call_in_macro() { check( r#" +//- minicore: sized, fn macro_rules! id { ($($tt:tt)*) => { $($tt)* } } fn foo() { } id! { @@ -1411,6 +1444,7 @@ id! { fn fn_signature_for_method_call_defined_in_macro() { check( r#" +//- minicore: sized, fn macro_rules! id { ($($tt:tt)*) => { $($tt)* } } struct S; id! { @@ -1430,6 +1464,7 @@ fn test() { S.foo($0); } fn call_info_for_lambdas() { check( r#" +//- minicore: sized, fn struct S; fn foo(s: S) -> i32 { 92 } fn main() { @@ -1444,6 +1479,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn struct S; fn foo(s: S) -> i32 { 92 } fn main() { @@ -1457,6 +1493,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn struct S; fn foo(s: S) -> i32 { 92 } fn main() { @@ -1475,6 +1512,7 @@ fn main() { fn call_info_for_fn_def_over_reference() { check( r#" +//- minicore: sized, fn struct S; fn foo(s: S) -> i32 { 92 } fn main() { @@ -1493,6 +1531,7 @@ fn main() { fn call_info_for_fn_ptr() { check( r#" +//- minicore: sized, fn fn main(f: fn(i32, f64) -> char) { f(0, $0) } @@ -1508,6 +1547,7 @@ fn main(f: fn(i32, f64) -> char) { fn call_info_for_fn_impl() { check( r#" +//- minicore: sized, fn struct S; impl core::ops::FnOnce<(i32, f64)> for S { type Output = char; @@ -1525,6 +1565,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn struct S; impl core::ops::FnOnce<(i32, f64)> for S { type Output = char; @@ -1542,6 +1583,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn struct S; impl core::ops::FnOnce<(i32, f64)> for S { type Output = char; @@ -1557,6 +1599,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn struct S; impl core::ops::FnOnce<(i32, f64)> for S { type Output = char; @@ -1577,6 +1620,7 @@ fn main() { fn call_info_for_unclosed_call() { check( r#" +//- minicore: sized, fn fn foo(foo: u32, bar: u32) {} fn main() { foo($0 @@ -1589,6 +1633,7 @@ fn main() { // check with surrounding space check( r#" +//- minicore: sized, fn fn foo(foo: u32, bar: u32) {} fn main() { foo( $0 @@ -1604,6 +1649,7 @@ fn main() { fn test_multiline_argument() { check( r#" +//- minicore: sized, fn fn callee(a: u8, b: u8) {} fn main() { callee(match 0 { @@ -1614,6 +1660,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn callee(a: u8, b: u8) {} fn main() { callee(match 0 { @@ -1627,6 +1674,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn callee(a: u8, b: u8) {} fn main() { callee($0match 0 { @@ -1644,6 +1692,7 @@ fn main() { fn test_generics_simple() { check( r#" +//- minicore: sized, fn /// Option docs. enum Option<T> { Some(T), @@ -1667,6 +1716,7 @@ fn f() { fn test_generics_on_variant() { check( r#" +//- minicore: sized, fn /// Option docs. enum Option<T> { /// Some docs. @@ -1694,6 +1744,7 @@ fn f() { fn test_lots_of_generics() { check( r#" +//- minicore: sized, fn trait Tr<T> {} struct S<T>(T); @@ -1717,6 +1768,7 @@ fn f() { fn test_generics_in_trait_ufcs() { check( r#" +//- minicore: sized, fn trait Tr { fn f<T: Tr, U>() {} } @@ -1740,6 +1792,7 @@ fn f() { fn test_generics_in_method_call() { check( r#" +//- minicore: sized, fn struct S; impl S { @@ -1761,6 +1814,7 @@ fn f() { fn test_generic_param_in_method_call() { check( r#" +//- minicore: sized, fn struct Foo; impl Foo { fn test<V>(&mut self, val: V) {} @@ -1780,6 +1834,7 @@ fn sup() { fn test_generic_kinds() { check( r#" +//- minicore: sized, fn fn callee<'a, const A: u8, T, const C: u8>() {} fn f() { @@ -1793,6 +1848,7 @@ fn f() { ); check( r#" +//- minicore: sized, fn fn callee<'a, const A: u8, T, const C: u8>() {} fn f() { @@ -1810,6 +1866,7 @@ fn f() { fn test_trait_assoc_types() { check( r#" +//- minicore: sized, fn trait Trait<'a, T> { type Assoc; } @@ -1822,6 +1879,7 @@ fn f() -> impl Trait<(), $0 ); check( r#" +//- minicore: sized, fn trait Iterator { type Item; } @@ -1834,6 +1892,7 @@ fn f() -> impl Iterator<$0 ); check( r#" +//- minicore: sized, fn trait Iterator { type Item; } @@ -1846,6 +1905,7 @@ fn f() -> impl Iterator<Item = $0 ); check( r#" +//- minicore: sized, fn trait Tr { type A; type B; @@ -1859,6 +1919,7 @@ fn f() -> impl Tr<$0 ); check( r#" +//- minicore: sized, fn trait Tr { type A; type B; @@ -1872,6 +1933,7 @@ fn f() -> impl Tr<B$0 ); check( r#" +//- minicore: sized, fn trait Tr { type A; type B; @@ -1885,6 +1947,7 @@ fn f() -> impl Tr<B = $0 ); check( r#" +//- minicore: sized, fn trait Tr { type A; type B; @@ -1902,6 +1965,7 @@ fn f() -> impl Tr<B = (), $0 fn test_supertrait_assoc() { check( r#" +//- minicore: sized, fn trait Super { type SuperTy; } @@ -1921,6 +1985,7 @@ fn f() -> impl Sub<$0 fn no_assoc_types_outside_type_bounds() { check( r#" +//- minicore: sized, fn trait Tr<T> { type Assoc; } @@ -1939,6 +2004,7 @@ impl Tr<$0 // FIXME: Substitute type vars in impl trait (`U` -> `i8`) check( r#" +//- minicore: sized, fn trait Trait<T> {} struct Wrap<T>(T); fn foo<U>(x: Wrap<impl Trait<U>>) {} @@ -1957,6 +2023,7 @@ fn f() { fn fully_qualified_syntax() { check( r#" +//- minicore: sized, fn fn f() { trait A { fn foo(&self, other: Self); } A::foo(&self$0, other); @@ -1973,6 +2040,7 @@ fn f() { fn help_for_generic_call() { check( r#" +//- minicore: sized, fn fn f<F: FnOnce(u8, u16) -> i32>(f: F) { f($0) } @@ -1984,6 +2052,7 @@ fn f<F: FnOnce(u8, u16) -> i32>(f: F) { ); check( r#" +//- minicore: sized, fn fn f<T, F: FnMut(&T, u16) -> &T>(f: F) { f($0) } @@ -1997,8 +2066,15 @@ fn f<T, F: FnMut(&T, u16) -> &T>(f: F) { #[test] fn regression_13579() { + // FIXME(next-solver): There should be signature help available here. + // The reason it is not is because of a trait solver bug. Since `Error` is not provided + // nor it can be inferred, it becomes an error type. The bug is that the solver ignores + // predicates on error types, and they do not guide infer vars, not allowing us to infer + // that `take`'s return type is callable. + // https://github.com/rust-lang/rust/pull/146602 should fix the solver bug. check( r#" +//- minicore: sized, fn fn f() { take(2)($0); } @@ -2009,9 +2085,7 @@ fn take<C, Error>( move || count } "#, - expect![[r#" - impl Fn() -> i32 - "#]], + expect![""], ); } @@ -2019,6 +2093,7 @@ fn take<C, Error>( fn record_literal() { check( r#" +//- minicore: sized, fn struct Strukt<T, U = ()> { t: T, u: U, @@ -2042,6 +2117,7 @@ fn f() { fn record_literal_nonexistent_field() { check( r#" +//- minicore: sized, fn struct Strukt { a: u8, } @@ -2063,6 +2139,7 @@ fn f() { fn tuple_variant_record_literal() { check( r#" +//- minicore: sized, fn enum Opt { Some(u8), } @@ -2077,6 +2154,7 @@ fn f() { ); check( r#" +//- minicore: sized, fn enum Opt { Some(u8), } @@ -2095,6 +2173,7 @@ fn f() { fn record_literal_self() { check( r#" +//- minicore: sized, fn struct S { t: u8 } impl S { fn new() -> Self { @@ -2113,6 +2192,7 @@ impl S { fn record_pat() { check( r#" +//- minicore: sized, fn struct Strukt<T, U = ()> { t: T, u: U, @@ -2136,6 +2216,7 @@ fn f() { fn test_enum_in_nested_method_in_lambda() { check( r#" +//- minicore: sized, fn enum A { A, B @@ -2159,6 +2240,7 @@ fn main() { fn test_tuple_expr_free() { check( r#" +//- minicore: sized, fn fn main() { (0$0, 1, 3); } @@ -2170,6 +2252,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { ($0 1, 3); } @@ -2181,6 +2264,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { (1, 3 $0); } @@ -2192,6 +2276,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { (1, 3 $0,); } @@ -2207,6 +2292,7 @@ fn main() { fn test_tuple_expr_expected() { check( r#" +//- minicore: sized, fn fn main() { let _: (&str, u32, u32)= ($0, 1, 3); } @@ -2219,6 +2305,7 @@ fn main() { // FIXME: Should typeck report a 4-ary tuple for the expression here? check( r#" +//- minicore: sized, fn fn main() { let _: (&str, u32, u32, u32) = ($0, 1, 3); } @@ -2230,6 +2317,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { let _: (&str, u32, u32)= ($0, 1, 3, 5); } @@ -2245,6 +2333,7 @@ fn main() { fn test_tuple_pat_free() { check( r#" +//- minicore: sized, fn fn main() { let ($0, 1, 3); } @@ -2256,6 +2345,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { let (0$0, 1, 3); } @@ -2267,6 +2357,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { let ($0 1, 3); } @@ -2278,6 +2369,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { let (1, 3 $0); } @@ -2289,6 +2381,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { let (1, 3 $0,); } @@ -2300,6 +2393,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { let (1, 3 $0, ..); } @@ -2311,6 +2405,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { let (1, 3, .., $0); } @@ -2327,6 +2422,7 @@ fn main() { fn test_tuple_pat_expected() { check( r#" +//- minicore: sized, fn fn main() { let (0$0, 1, 3): (i32, i32, i32); } @@ -2338,6 +2434,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { let ($0, 1, 3): (i32, i32, i32); } @@ -2349,6 +2446,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { let (1, 3 $0): (i32,); } @@ -2360,6 +2458,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { let (1, 3 $0, ..): (i32, i32, i32, i32); } @@ -2371,6 +2470,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { let (1, 3, .., $0): (i32, i32, i32); } @@ -2385,6 +2485,7 @@ fn main() { fn test_tuple_pat_expected_inferred() { check( r#" +//- minicore: sized, fn fn main() { let (0$0, 1, 3) = (1, 2 ,3); } @@ -2396,6 +2497,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { let ($0 1, 3) = (1, 2, 3); } @@ -2408,6 +2510,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { let (1, 3 $0) = (1,); } @@ -2419,6 +2522,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { let (1, 3 $0, ..) = (1, 2, 3, 4); } @@ -2430,6 +2534,7 @@ fn main() { ); check( r#" +//- minicore: sized, fn fn main() { let (1, 3, .., $0) = (1, 2, 3); } @@ -2445,6 +2550,7 @@ fn main() { fn test_tuple_generic_param() { check( r#" +//- minicore: sized, fn struct S<T>(T); fn main() { @@ -2462,6 +2568,7 @@ fn main() { fn test_enum_generic_param() { check( r#" +//- minicore: sized, fn enum Option<T> { Some(T), None, @@ -2482,6 +2589,7 @@ fn main() { fn test_enum_variant_generic_param() { check( r#" +//- minicore: sized, fn enum Option<T> { Some(T), None, @@ -2502,6 +2610,7 @@ fn main() { fn test_generic_arg_with_default() { check( r#" +//- minicore: sized, fn struct S<T = u8> { field: T, } @@ -2518,6 +2627,7 @@ fn main() { check( r#" +//- minicore: sized, fn struct S<const C: u8 = 5> { field: C, } @@ -2532,4 +2642,27 @@ fn main() { "#]], ); } + + #[test] + fn test_async_function() { + check( + r#" +//- minicore: sized, fn, future, result +pub async fn conn_mut<F, T>(f: F) -> Result<T, i32> +where + F: FnOnce() -> T, +{ + Ok(f()) +} + +fn main() { + conn_mut($0) +} + "#, + expect![[r#" + async fn conn_mut<F: FnOnce() -> T, T>(f: F) -> Result<T, i32> + ^^^^ + "#]], + ); + } } |