use crate::{ GenericDefId, ModuleDefId, expr_store::pretty::{print_function, print_struct}, nameres::crate_def_map, test_db::TestDB, }; use expect_test::{Expect, expect}; use test_fixture::WithFixture; use super::super::*; fn lower_and_print(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let db = TestDB::with_files(ra_fixture); let krate = db.fetch_test_crate(); let def_map = crate_def_map(&db, krate); let mut defs = vec![]; for (_, module) in def_map.modules() { for decl in module.scope.declarations() { let def: GenericDefId = match decl { ModuleDefId::ModuleId(_) => continue, ModuleDefId::FunctionId(id) => id.into(), ModuleDefId::AdtId(id) => id.into(), ModuleDefId::ConstId(id) => id.into(), ModuleDefId::StaticId(id) => id.into(), ModuleDefId::TraitId(id) => id.into(), ModuleDefId::TypeAliasId(id) => id.into(), ModuleDefId::EnumVariantId(_) => continue, ModuleDefId::BuiltinType(_) => continue, ModuleDefId::MacroId(_) => continue, }; defs.push(def); } } let mut out = String::new(); for def in defs { match def { GenericDefId::AdtId(adt_id) => match adt_id { crate::AdtId::StructId(struct_id) => { out += &print_struct( &db, struct_id, &db.struct_signature(struct_id), Edition::CURRENT, ); } crate::AdtId::UnionId(_id) => (), crate::AdtId::EnumId(_id) => (), }, GenericDefId::ConstId(_id) => (), GenericDefId::FunctionId(function_id) => { out += &print_function( &db, function_id, &db.function_signature(function_id), Edition::CURRENT, ) } GenericDefId::ImplId(_id) => (), GenericDefId::StaticId(_id) => (), GenericDefId::TraitId(_id) => (), GenericDefId::TypeAliasId(_id) => (), } } expect.assert_eq(&out); } #[test] fn structs() { lower_and_print( r" struct S { field: foo, } struct S(i32, u32, &'static str); #[repr(Rust)] struct S; struct S<'a, 'b, T: Clone, const C: usize = 3, X = ()> where X: Default, for<'a, 'c> fn() -> i32: for<'b> Trait<'a, Item = Boo>; #[repr(C, packed)] struct S {} ", expect![[r#" struct S {...} struct S(...) ; struct S; struct S<'a, 'b, T, const C: usize = 3, X = ()> where T: Clone, X: Default, for<'a, 'c> fn() -> i32: for<'b> Trait::<'a, Item = Boo> ; #[repr(C)] #[repr(pack(1))] struct S {...} "#]], ); } #[test] fn functions() { lower_and_print( r#" fn foo<'a, const C: usize = 314235, T: Trait = B>(Struct { foo: bar }: &Struct, _: (), a: u32) -> &'a dyn Fn() -> i32 where (): Default {} const async unsafe extern "C" fn a() {} fn ret_impl_trait() -> impl Trait {} "#, expect![[r#" fn foo<'a, const C: usize = 314235, T = B>(&Struct, (), u32) -> &'a dyn Fn::<(), Output = i32> where T: Trait::, (): Default {...} const async unsafe extern "C" fn a() -> impl ::core::future::Future:: {...} fn ret_impl_trait() -> impl Trait {...} "#]], ); } #[test] fn argument_position_impl_trait_functions() { lower_and_print( r" fn impl_trait_args(_: impl Trait) {} fn impl_trait_args2(_: impl Trait) {} fn impl_trait_ret() -> impl Trait {} fn impl_trait_ret2() -> impl Trait {} fn not_allowed1(f: impl Fn(impl Foo)) { let foo = S; f(foo); } // This caused stack overflow in #17498 fn not_allowed2(f: impl Fn(&impl Foo)) { let foo = S; f(&foo); } fn not_allowed3(bar: impl Bar) {} // This also caused stack overflow fn not_allowed4(bar: impl Bar<&impl Foo>) {} fn allowed1(baz: impl Baz) {} fn allowed2<'a>(baz: impl Baz) {} fn allowed3(baz: impl Baz>) {} ", expect![[r#" fn impl_trait_args(Param[1]) where Param[1]: Trait {...} fn impl_trait_args2(Param[1]) where Param[1]: Trait::<{error}> {...} fn impl_trait_ret() -> impl Trait {...} fn impl_trait_ret2() -> impl Trait::<{error}> {...} fn not_allowed1(Param[0]) where Param[0]: Fn::<({error}), Output = ()> {...} fn not_allowed2(Param[0]) where Param[0]: Fn::<(&{error}), Output = ()> {...} fn not_allowed3(Param[0]) where Param[0]: Bar::<{error}> {...} fn not_allowed4(Param[0]) where Param[0]: Bar::<&{error}> {...} fn allowed1(Param[1]) where Param[0]: Foo, Param[1]: Baz:: {...} fn allowed2<'a, Param[0], Param[1]>(Param[1]) where Param[0]: Foo, Param[0]: 'a, Param[1]: Baz:: {...} fn allowed3(Param[1]) where Param[0]: Foo, Param[1]: Baz::> {...} "#]], ); } #[test] fn regression_21138() { lower_and_print( r#" fn foo(v: for<'a> Trait1 + Trait2) {} "#, expect![[r#" fn foo(dyn for<'a> Trait1 + Trait2) {...} "#]], ); }