use insta::assert_snapshot; use ra_db::fixture::WithFixture; use super::{infer, infer_with_mismatches, type_at, type_at_pos}; use crate::test_db::TestDB; #[test] fn infer_await() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:std struct IntFuture; impl Future for IntFuture { type Output = u64; } fn test() { let r = IntFuture; let v = r.await; v<|>; } //- /std.rs crate:std #[prelude_import] use future::*; mod future { #[lang = "future_trait"] trait Future { type Output; } } "#, ); assert_eq!("u64", type_at_pos(&db, pos)); } #[test] fn infer_async() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:std async fn foo() -> u64 { 128 } fn test() { let r = foo(); let v = r.await; v<|>; } //- /std.rs crate:std #[prelude_import] use future::*; mod future { #[lang = "future_trait"] trait Future { type Output; } } "#, ); assert_eq!("u64", type_at_pos(&db, pos)); } #[test] fn infer_desugar_async() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:std async fn foo() -> u64 { 128 } fn test() { let r = foo(); r<|>; } //- /std.rs crate:std #[prelude_import] use future::*; mod future { trait Future { type Output; } } "#, ); assert_eq!("impl Future", type_at_pos(&db, pos)); } #[test] fn infer_try() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:std fn test() { let r: Result = Result::Ok(1); let v = r?; v<|>; } //- /std.rs crate:std #[prelude_import] use ops::*; mod ops { trait Try { type Ok; type Error; } } #[prelude_import] use result::*; mod result { enum Result { Ok(O), Err(E) } impl crate::ops::Try for Result { type Ok = O; type Error = E; } } "#, ); assert_eq!("i32", type_at_pos(&db, pos)); } #[test] fn infer_for_loop() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:std use std::collections::Vec; fn test() { let v = Vec::new(); v.push("foo"); for x in v { x<|>; } } //- /std.rs crate:std #[prelude_import] use iter::*; mod iter { trait IntoIterator { type Item; } } mod collections { struct Vec {} impl Vec { fn new() -> Self { Vec {} } fn push(&mut self, t: T) { } } impl crate::iter::IntoIterator for Vec { type Item=T; } } "#, ); assert_eq!("&str", type_at_pos(&db, pos)); } #[test] fn infer_ops_neg() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:std struct Bar; struct Foo; impl std::ops::Neg for Bar { type Output = Foo; } fn test() { let a = Bar; let b = -a; b<|>; } //- /std.rs crate:std #[prelude_import] use ops::*; mod ops { #[lang = "neg"] pub trait Neg { type Output; } } "#, ); assert_eq!("Foo", type_at_pos(&db, pos)); } #[test] fn infer_ops_not() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:std struct Bar; struct Foo; impl std::ops::Not for Bar { type Output = Foo; } fn test() { let a = Bar; let b = !a; b<|>; } //- /std.rs crate:std #[prelude_import] use ops::*; mod ops { #[lang = "not"] pub trait Not { type Output; } } "#, ); assert_eq!("Foo", type_at_pos(&db, pos)); } #[test] fn infer_from_bound_1() { assert_snapshot!( infer(r#" trait Trait {} struct S(T); impl Trait for S {} fn foo>(t: T) {} fn test() { let s = S(unknown); foo(s); } "#), @r###" [86; 87) 't': T [92; 94) '{}': () [105; 144) '{ ...(s); }': () [115; 116) 's': S [119; 120) 'S': S(u32) -> S [119; 129) 'S(unknown)': S [121; 128) 'unknown': u32 [135; 138) 'foo': fn foo>(S) [135; 141) 'foo(s)': () [139; 140) 's': S "### ); } #[test] fn infer_from_bound_2() { assert_snapshot!( infer(r#" trait Trait {} struct S(T); impl Trait for S {} fn foo>(t: T) -> U {} fn test() { let s = S(unknown); let x: u32 = foo(s); } "#), @r###" [87; 88) 't': T [98; 100) '{}': () [111; 163) '{ ...(s); }': () [121; 122) 's': S [125; 126) 'S': S(u32) -> S [125; 135) 'S(unknown)': S [127; 134) 'unknown': u32 [145; 146) 'x': u32 [154; 157) 'foo': fn foo>(S) -> u32 [154; 160) 'foo(s)': u32 [158; 159) 's': S "### ); } #[test] fn trait_default_method_self_bound_implements_trait() { test_utils::covers!(trait_self_implements_self); assert_snapshot!( infer(r#" trait Trait { fn foo(&self) -> i64; fn bar(&self) -> { let x = self.foo(); } } "#), @r###" [27; 31) 'self': &Self [53; 57) 'self': &Self [62; 97) '{ ... }': () [76; 77) 'x': i64 [80; 84) 'self': &Self [80; 90) 'self.foo()': i64 "### ); } #[test] fn trait_default_method_self_bound_implements_super_trait() { test_utils::covers!(trait_self_implements_self); assert_snapshot!( infer(r#" trait SuperTrait { fn foo(&self) -> i64; } trait Trait: SuperTrait { fn bar(&self) -> { let x = self.foo(); } } "#), @r###" [32; 36) 'self': &Self [86; 90) 'self': &Self [95; 130) '{ ... }': () [109; 110) 'x': i64 [113; 117) 'self': &Self [113; 123) 'self.foo()': i64 "### ); } #[test] fn infer_project_associated_type() { assert_snapshot!( infer(r#" trait Iterable { type Item; } struct S; impl Iterable for S { type Item = u32; } fn test() { let x: ::Item = 1; let y: ::Item = no_matter; let z: T::Item = no_matter; let a: ::Item = no_matter; } "#), @r###" [108; 261) '{ ...ter; }': () [118; 119) 'x': u32 [145; 146) '1': u32 [156; 157) 'y': Iterable::Item [183; 192) 'no_matter': Iterable::Item [202; 203) 'z': Iterable::Item [215; 224) 'no_matter': Iterable::Item [234; 235) 'a': Iterable::Item [249; 258) 'no_matter': Iterable::Item "### ); } #[test] fn infer_return_associated_type() { assert_snapshot!( infer(r#" trait Iterable { type Item; } struct S; impl Iterable for S { type Item = u32; } fn foo1(t: T) -> T::Item {} fn foo2(t: T) -> ::Item {} fn foo3(t: T) -> ::Item {} fn test() { let x = foo1(S); let y = foo2(S); let z = foo3(S); } "#), @r###" [106; 107) 't': T [123; 125) '{}': () [147; 148) 't': T [178; 180) '{}': () [202; 203) 't': T [221; 223) '{}': () [234; 300) '{ ...(S); }': () [244; 245) 'x': u32 [248; 252) 'foo1': fn foo1(S) -> ::Item [248; 255) 'foo1(S)': u32 [253; 254) 'S': S [265; 266) 'y': u32 [269; 273) 'foo2': fn foo2(S) -> ::Item [269; 276) 'foo2(S)': u32 [274; 275) 'S': S [286; 287) 'z': u32 [290; 294) 'foo3': fn foo3(S) -> ::Item [290; 297) 'foo3(S)': u32 [295; 296) 'S': S "### ); } #[test] fn infer_associated_type_bound() { assert_snapshot!( infer(r#" trait Iterable { type Item; } fn test>() { let y: T::Item = unknown; } "#), @r###" [67; 100) '{ ...own; }': () [77; 78) 'y': u32 [90; 97) 'unknown': u32 "### ); } #[test] fn infer_const_body() { assert_snapshot!( infer(r#" const A: u32 = 1 + 1; static B: u64 = { let x = 1; x }; "#), @r###" [16; 17) '1': u32 [16; 21) '1 + 1': u32 [20; 21) '1': u32 [39; 55) '{ let ...1; x }': u64 [45; 46) 'x': u64 [49; 50) '1': u64 [52; 53) 'x': u64 "### ); } #[test] fn tuple_struct_fields() { assert_snapshot!( infer(r#" struct S(i32, u64); fn test() -> u64 { let a = S(4, 6); let b = a.0; a.1 } "#), @r###" [38; 87) '{ ... a.1 }': u64 [48; 49) 'a': S [52; 53) 'S': S(i32, u64) -> S [52; 59) 'S(4, 6)': S [54; 55) '4': i32 [57; 58) '6': u64 [69; 70) 'b': i32 [73; 74) 'a': S [73; 76) 'a.0': i32 [82; 83) 'a': S [82; 85) 'a.1': u64 "### ); } #[test] fn tuple_struct_with_fn() { assert_snapshot!( infer(r#" struct S(fn(u32) -> u64); fn test() -> u64 { let a = S(|i| 2*i); let b = a.0(4); a.0(2) } "#), @r###" [44; 102) '{ ...0(2) }': u64 [54; 55) 'a': S [58; 59) 'S': S(fn(u32) -> u64) -> S [58; 68) 'S(|i| 2*i)': S [60; 67) '|i| 2*i': |u32| -> u64 [61; 62) 'i': u32 [64; 65) '2': u32 [64; 67) '2*i': u32 [66; 67) 'i': u32 [78; 79) 'b': u64 [82; 83) 'a': S [82; 85) 'a.0': fn(u32) -> u64 [82; 88) 'a.0(4)': u64 [86; 87) '4': u32 [94; 95) 'a': S [94; 97) 'a.0': fn(u32) -> u64 [94; 100) 'a.0(2)': u64 [98; 99) '2': u32 "### ); } #[test] fn indexing_arrays() { assert_snapshot!( infer("fn main() { &mut [9][2]; }"), @r###" [10; 26) '{ &mut...[2]; }': () [12; 23) '&mut [9][2]': &mut {unknown} [17; 20) '[9]': [i32; _] [17; 23) '[9][2]': {unknown} [18; 19) '9': i32 [21; 22) '2': i32 "### ) } #[test] fn infer_ops_index() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:std struct Bar; struct Foo; impl std::ops::Index for Bar { type Output = Foo; } fn test() { let a = Bar; let b = a[1u32]; b<|>; } //- /std.rs crate:std #[prelude_import] use ops::*; mod ops { #[lang = "index"] pub trait Index { type Output; } } "#, ); assert_eq!("Foo", type_at_pos(&db, pos)); } #[test] fn infer_ops_index_autoderef() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:std fn test() { let a = &[1u32, 2, 3]; let b = a[1u32]; b<|>; } //- /std.rs crate:std impl ops::Index for [T] { type Output = T; } #[prelude_import] use ops::*; mod ops { #[lang = "index"] pub trait Index { type Output; } } "#, ); assert_eq!("u32", type_at_pos(&db, pos)); } #[test] fn deref_trait() { let t = type_at( r#" //- /main.rs #[lang = "deref"] trait Deref { type Target; fn deref(&self) -> &Self::Target; } struct Arc; impl Deref for Arc { type Target = T; } struct S; impl S { fn foo(&self) -> u128 {} } fn test(s: Arc) { (*s, s.foo())<|>; } "#, ); assert_eq!(t, "(S, u128)"); } #[test] fn deref_trait_with_inference_var() { let t = type_at( r#" //- /main.rs #[lang = "deref"] trait Deref { type Target; fn deref(&self) -> &Self::Target; } struct Arc; fn new_arc() -> Arc {} impl Deref for Arc { type Target = T; } struct S; fn foo(a: Arc) {} fn test() { let a = new_arc(); let b = (*a)<|>; foo(a); } "#, ); assert_eq!(t, "S"); } #[test] fn deref_trait_infinite_recursion() { let t = type_at( r#" //- /main.rs #[lang = "deref"] trait Deref { type Target; fn deref(&self) -> &Self::Target; } struct S; impl Deref for S { type Target = S; } fn test(s: S) { s.foo()<|>; } "#, ); assert_eq!(t, "{unknown}"); } #[test] fn deref_trait_with_question_mark_size() { let t = type_at( r#" //- /main.rs #[lang = "deref"] trait Deref { type Target; fn deref(&self) -> &Self::Target; } struct Arc; impl Deref for Arc { type Target = T; } struct S; impl S { fn foo(&self) -> u128 {} } fn test(s: Arc) { (*s, s.foo())<|>; } "#, ); assert_eq!(t, "(S, u128)"); } #[test] fn obligation_from_function_clause() { let t = type_at( r#" //- /main.rs struct S; trait Trait {} impl Trait for S {} fn foo, U>(t: T) -> U {} fn test(s: S) { foo(s)<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn obligation_from_method_clause() { let t = type_at( r#" //- /main.rs struct S; trait Trait {} impl Trait for S {} struct O; impl O { fn foo, U>(&self, t: T) -> U {} } fn test() { O.foo(S)<|>; } "#, ); assert_eq!(t, "isize"); } #[test] fn obligation_from_self_method_clause() { let t = type_at( r#" //- /main.rs struct S; trait Trait {} impl Trait for S {} impl S { fn foo(&self) -> U where Self: Trait {} } fn test() { S.foo()<|>; } "#, ); assert_eq!(t, "i64"); } #[test] fn obligation_from_impl_clause() { let t = type_at( r#" //- /main.rs struct S; trait Trait {} impl Trait<&str> for S {} struct O; impl> O { fn foo(&self) -> U {} } fn test(o: O) { o.foo()<|>; } "#, ); assert_eq!(t, "&str"); } #[test] fn generic_param_env_1() { let t = type_at( r#" //- /main.rs trait Clone {} trait Trait { fn foo(self) -> u128; } struct S; impl Clone for S {} impl Trait for T where T: Clone {} fn test(t: T) { t.foo()<|>; } "#, ); assert_eq!(t, "u128"); } #[test] fn generic_param_env_1_not_met() { let t = type_at( r#" //- /main.rs trait Clone {} trait Trait { fn foo(self) -> u128; } struct S; impl Clone for S {} impl Trait for T where T: Clone {} fn test(t: T) { t.foo()<|>; } "#, ); assert_eq!(t, "{unknown}"); } #[test] fn generic_param_env_2() { let t = type_at( r#" //- /main.rs trait Trait { fn foo(self) -> u128; } struct S; impl Trait for S {} fn test(t: T) { t.foo()<|>; } "#, ); assert_eq!(t, "u128"); } #[test] fn generic_param_env_2_not_met() { let t = type_at( r#" //- /main.rs trait Trait { fn foo(self) -> u128; } struct S; impl Trait for S {} fn test(t: T) { t.foo()<|>; } "#, ); assert_eq!(t, "{unknown}"); } #[test] fn generic_param_env_deref() { let t = type_at( r#" //- /main.rs #[lang = "deref"] trait Deref { type Target; } trait Trait {} impl Deref for T where T: Trait { type Target = i128; } fn test(t: T) { (*t)<|>; } "#, ); assert_eq!(t, "i128"); } #[test] fn associated_type_placeholder() { let t = type_at( r#" //- /main.rs pub trait ApplyL { type Out; } pub struct RefMutL; impl ApplyL for RefMutL { type Out = ::Out; } fn test() { let y: as ApplyL>::Out = no_matter; y<|>; } "#, ); // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types]. assert_eq!(t, "ApplyL::Out"); } #[test] fn associated_type_placeholder_2() { let t = type_at( r#" //- /main.rs pub trait ApplyL { type Out; } fn foo(t: T) -> ::Out; fn test(t: T) { let y = foo(t); y<|>; } "#, ); assert_eq!(t, "ApplyL::Out"); } #[test] fn argument_impl_trait() { assert_snapshot!( infer_with_mismatches(r#" trait Trait { fn foo(&self) -> T; fn foo2(&self) -> i64; } fn bar(x: impl Trait) {} struct S(T); impl Trait for S {} fn test(x: impl Trait, y: &impl Trait) { x; y; let z = S(1); bar(z); x.foo(); y.foo(); z.foo(); x.foo2(); y.foo2(); z.foo2(); } "#, true), @r###" [30; 34) 'self': &Self [55; 59) 'self': &Self [78; 79) 'x': impl Trait [98; 100) '{}': () [155; 156) 'x': impl Trait [175; 176) 'y': &impl Trait [196; 324) '{ ...2(); }': () [202; 203) 'x': impl Trait [209; 210) 'y': &impl Trait [220; 221) 'z': S [224; 225) 'S': S(u16) -> S [224; 228) 'S(1)': S [226; 227) '1': u16 [234; 237) 'bar': fn bar(S) [234; 240) 'bar(z)': () [238; 239) 'z': S [246; 247) 'x': impl Trait [246; 253) 'x.foo()': u64 [259; 260) 'y': &impl Trait [259; 266) 'y.foo()': u32 [272; 273) 'z': S [272; 279) 'z.foo()': u16 [285; 286) 'x': impl Trait [285; 293) 'x.foo2()': i64 [299; 300) 'y': &impl Trait [299; 307) 'y.foo2()': i64 [313; 314) 'z': S [313; 321) 'z.foo2()': i64 "### ); } #[test] fn argument_impl_trait_type_args_1() { assert_snapshot!( infer_with_mismatches(r#" trait Trait {} trait Foo { // this function has an implicit Self param, an explicit type param, // and an implicit impl Trait param! fn bar(x: impl Trait) -> T { loop {} } } fn foo(x: impl Trait) -> T { loop {} } struct S; impl Trait for S {} struct F; impl Foo for F {} fn test() { Foo::bar(S); ::bar(S); F::bar(S); Foo::bar::(S); ::bar::(S); foo(S); foo::(S); foo::(S); // we should ignore the extraneous i32 } "#, true), @r###" [156; 157) 'x': impl Trait [176; 187) '{ loop {} }': T [178; 185) 'loop {}': ! [183; 185) '{}': () [200; 201) 'x': impl Trait [220; 231) '{ loop {} }': T [222; 229) 'loop {}': ! [227; 229) '{}': () [301; 510) '{ ... i32 }': () [307; 315) 'Foo::bar': fn bar<{unknown}, {unknown}>(S) -> {unknown} [307; 318) 'Foo::bar(S)': {unknown} [316; 317) 'S': S [324; 339) '::bar': fn bar(S) -> {unknown} [324; 342) '(S) -> {unknown} [348; 357) 'F::bar(S)': {unknown} [355; 356) 'S': S [363; 378) 'Foo::bar::': fn bar<{unknown}, u32>(S) -> u32 [363; 381) 'Foo::b...32>(S)': u32 [379; 380) 'S': S [387; 409) '': fn bar(S) -> u32 [387; 412) '(S)': u32 [410; 411) 'S': S [419; 422) 'foo': fn foo<{unknown}>(S) -> {unknown} [419; 425) 'foo(S)': {unknown} [423; 424) 'S': S [431; 441) 'foo::': fn foo(S) -> u32 [431; 444) 'foo::(S)': u32 [442; 443) 'S': S [450; 465) 'foo::': fn foo(S) -> u32 [450; 468) 'foo::<...32>(S)': u32 [466; 467) 'S': S "### ); } #[test] fn argument_impl_trait_type_args_2() { assert_snapshot!( infer_with_mismatches(r#" trait Trait {} struct S; impl Trait for S {} struct F; impl F { fn foo(self, x: impl Trait) -> (T, U) { loop {} } } fn test() { F.foo(S); F::.foo(S); F::.foo::(S); F::.foo::(S); // extraneous argument should be ignored } "#, true), @r###" [88; 92) 'self': F [94; 95) 'x': impl Trait [119; 130) '{ loop {} }': (T, U) [121; 128) 'loop {}': ! [126; 128) '{}': () [144; 284) '{ ...ored }': () [150; 151) 'F': F<{unknown}> [150; 158) 'F.foo(S)': ({unknown}, {unknown}) [156; 157) 'S': S [164; 172) 'F::': F [164; 179) 'F::.foo(S)': (u32, {unknown}) [177; 178) 'S': S [185; 193) 'F::': F [185; 207) 'F::(S)': (u32, i32) [205; 206) 'S': S [213; 221) 'F::': F [213; 240) 'F::(S)': (u32, i32) [238; 239) 'S': S "### ); } #[test] fn argument_impl_trait_to_fn_pointer() { assert_snapshot!( infer_with_mismatches(r#" trait Trait {} fn foo(x: impl Trait) { loop {} } struct S; impl Trait for S {} fn test() { let f: fn(S) -> () = foo; } "#, true), @r###" [23; 24) 'x': impl Trait [38; 49) '{ loop {} }': () [40; 47) 'loop {}': ! [45; 47) '{}': () [91; 124) '{ ...foo; }': () [101; 102) 'f': fn(S) [118; 121) 'foo': fn foo(S) "### ); } #[test] #[ignore] fn impl_trait() { assert_snapshot!( infer(r#" trait Trait { fn foo(&self) -> T; fn foo2(&self) -> i64; } fn bar() -> impl Trait {} fn test(x: impl Trait, y: &impl Trait) { x; y; let z = bar(); x.foo(); y.foo(); z.foo(); x.foo2(); y.foo2(); z.foo2(); } "#), @r###" [30; 34) 'self': &Self [55; 59) 'self': &Self [99; 101) '{}': () [111; 112) 'x': impl Trait [131; 132) 'y': &impl Trait [152; 269) '{ ...2(); }': () [158; 159) 'x': impl Trait [165; 166) 'y': &impl Trait [176; 177) 'z': impl Trait [180; 183) 'bar': fn bar() -> impl Trait [180; 185) 'bar()': impl Trait [191; 192) 'x': impl Trait [191; 198) 'x.foo()': u64 [204; 205) 'y': &impl Trait [204; 211) 'y.foo()': u64 [217; 218) 'z': impl Trait [217; 224) 'z.foo()': u64 [230; 231) 'x': impl Trait [230; 238) 'x.foo2()': i64 [244; 245) 'y': &impl Trait [244; 252) 'y.foo2()': i64 [258; 259) 'z': impl Trait [258; 266) 'z.foo2()': i64 "### ); } #[test] fn dyn_trait() { assert_snapshot!( infer(r#" trait Trait { fn foo(&self) -> T; fn foo2(&self) -> i64; } fn bar() -> dyn Trait {} fn test(x: dyn Trait, y: &dyn Trait) { x; y; let z = bar(); x.foo(); y.foo(); z.foo(); x.foo2(); y.foo2(); z.foo2(); } "#), @r###" [30; 34) 'self': &Self [55; 59) 'self': &Self [98; 100) '{}': () [110; 111) 'x': dyn Trait [129; 130) 'y': &dyn Trait [149; 266) '{ ...2(); }': () [155; 156) 'x': dyn Trait [162; 163) 'y': &dyn Trait [173; 174) 'z': dyn Trait [177; 180) 'bar': fn bar() -> dyn Trait [177; 182) 'bar()': dyn Trait [188; 189) 'x': dyn Trait [188; 195) 'x.foo()': u64 [201; 202) 'y': &dyn Trait [201; 208) 'y.foo()': u64 [214; 215) 'z': dyn Trait [214; 221) 'z.foo()': u64 [227; 228) 'x': dyn Trait [227; 235) 'x.foo2()': i64 [241; 242) 'y': &dyn Trait [241; 249) 'y.foo2()': i64 [255; 256) 'z': dyn Trait [255; 263) 'z.foo2()': i64 "### ); } #[test] fn dyn_trait_in_impl() { assert_snapshot!( infer(r#" trait Trait { fn foo(&self) -> (T, U); } struct S {} impl S { fn bar(&self) -> &dyn Trait { loop {} } } trait Trait2 { fn baz(&self) -> (T, U); } impl Trait2 for dyn Trait { } fn test(s: S) { s.bar().baz(); } "#), @r###" [33; 37) 'self': &Self [103; 107) 'self': &S [129; 140) '{ loop {} }': &dyn Trait [131; 138) 'loop {}': ! [136; 138) '{}': () [176; 180) 'self': &Self [252; 253) 's': S [268; 290) '{ ...z(); }': () [274; 275) 's': S [274; 281) 's.bar()': &dyn Trait [274; 287) 's.bar().baz()': (u32, i32) "### ); } #[test] fn dyn_trait_bare() { assert_snapshot!( infer(r#" trait Trait { fn foo(&self) -> u64; } fn bar() -> Trait {} fn test(x: Trait, y: &Trait) -> u64 { x; y; let z = bar(); x.foo(); y.foo(); z.foo(); } "#), @r###" [27; 31) 'self': &Self [61; 63) '{}': () [73; 74) 'x': dyn Trait [83; 84) 'y': &dyn Trait [101; 176) '{ ...o(); }': () [107; 108) 'x': dyn Trait [114; 115) 'y': &dyn Trait [125; 126) 'z': dyn Trait [129; 132) 'bar': fn bar() -> dyn Trait [129; 134) 'bar()': dyn Trait [140; 141) 'x': dyn Trait [140; 147) 'x.foo()': u64 [153; 154) 'y': &dyn Trait [153; 160) 'y.foo()': u64 [166; 167) 'z': dyn Trait [166; 173) 'z.foo()': u64 "### ); } #[test] fn weird_bounds() { assert_snapshot!( infer(r#" trait Trait {} fn test(a: impl Trait + 'lifetime, b: impl 'lifetime, c: impl (Trait), d: impl ('lifetime), e: impl ?Sized, f: impl Trait + ?Sized) { } "#), @r###" [24; 25) 'a': impl Trait + {error} [51; 52) 'b': impl {error} [70; 71) 'c': impl Trait [87; 88) 'd': impl {error} [108; 109) 'e': impl {error} [124; 125) 'f': impl Trait + {error} [148; 151) '{ }': () "### ); } #[test] #[ignore] fn error_bound_chalk() { let t = type_at( r#" //- /main.rs trait Trait { fn foo(&self) -> u32 {} } fn test(x: (impl Trait + UnknownTrait)) { x.foo()<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn assoc_type_bindings() { assert_snapshot!( infer(r#" trait Trait { type Type; } fn get(t: T) -> ::Type {} fn get2>(t: T) -> U {} fn set>(t: T) -> T {t} struct S; impl Trait for S { type Type = T; } fn test>(x: T, y: impl Trait) { get(x); get2(x); get(y); get2(y); get(set(S)); get2(set(S)); get2(S::); } "#), @r###" [50; 51) 't': T [78; 80) '{}': () [112; 113) 't': T [123; 125) '{}': () [155; 156) 't': T [166; 169) '{t}': T [167; 168) 't': T [257; 258) 'x': T [263; 264) 'y': impl Trait [290; 398) '{ ...r>); }': () [296; 299) 'get': fn get(T) -> ::Type [296; 302) 'get(x)': u32 [300; 301) 'x': T [308; 312) 'get2': fn get2(T) -> u32 [308; 315) 'get2(x)': u32 [313; 314) 'x': T [321; 324) 'get': fn get>(impl Trait) -> as Trait>::Type [321; 327) 'get(y)': i64 [325; 326) 'y': impl Trait [333; 337) 'get2': fn get2>(impl Trait) -> i64 [333; 340) 'get2(y)': i64 [338; 339) 'y': impl Trait [346; 349) 'get': fn get>(S) -> as Trait>::Type [346; 357) 'get(set(S))': u64 [350; 353) 'set': fn set>(S) -> S [350; 356) 'set(S)': S [354; 355) 'S': S [363; 367) 'get2': fn get2>(S) -> u64 [363; 375) 'get2(set(S))': u64 [368; 371) 'set': fn set>(S) -> S [368; 374) 'set(S)': S [372; 373) 'S': S [381; 385) 'get2': fn get2>(S) -> str [381; 395) 'get2(S::)': str [386; 394) 'S::': S "### ); } #[test] fn impl_trait_assoc_binding_projection_bug() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:std pub trait Language { type Kind; } pub enum RustLanguage {} impl Language for RustLanguage { type Kind = SyntaxKind; } struct SyntaxNode {} fn foo() -> impl Iterator> {} trait Clone { fn clone(&self) -> Self; } fn api_walkthrough() { for node in foo() { node.clone()<|>; } } //- /std.rs crate:std #[prelude_import] use iter::*; mod iter { trait IntoIterator { type Item; } trait Iterator { type Item; } impl IntoIterator for T { type Item = ::Item; } } "#, ); assert_eq!("{unknown}", type_at_pos(&db, pos)); } #[test] fn projection_eq_within_chalk() { assert_snapshot!( infer(r#" trait Trait1 { type Type; } trait Trait2 { fn foo(self) -> T; } impl Trait2 for U where U: Trait1 {} fn test>(x: T) { x.foo(); } "#), @r###" [62; 66) 'self': Self [164; 165) 'x': T [170; 186) '{ ...o(); }': () [176; 177) 'x': T [176; 183) 'x.foo()': u32 "### ); } #[test] fn where_clause_trait_in_scope_for_method_resolution() { let t = type_at( r#" //- /main.rs mod foo { trait Trait { fn foo(&self) -> u32 {} } } fn test(x: T) { x.foo()<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn super_trait_method_resolution() { assert_snapshot!( infer(r#" mod foo { trait SuperTrait { fn foo(&self) -> u32 {} } } trait Trait1: foo::SuperTrait {} trait Trait2 where Self: foo::SuperTrait {} fn test(x: T, y: U) { x.foo(); y.foo(); } "#), @r###" [50; 54) 'self': &Self [63; 65) '{}': () [182; 183) 'x': T [188; 189) 'y': U [194; 223) '{ ...o(); }': () [200; 201) 'x': T [200; 207) 'x.foo()': u32 [213; 214) 'y': U [213; 220) 'y.foo()': u32 "### ); } #[test] fn super_trait_impl_trait_method_resolution() { assert_snapshot!( infer(r#" mod foo { trait SuperTrait { fn foo(&self) -> u32 {} } } trait Trait1: foo::SuperTrait {} fn test(x: &impl Trait1) { x.foo(); } "#), @r###" [50; 54) 'self': &Self [63; 65) '{}': () [116; 117) 'x': &impl Trait1 [133; 149) '{ ...o(); }': () [139; 140) 'x': &impl Trait1 [139; 146) 'x.foo()': u32 "### ); } #[test] fn super_trait_cycle() { // This just needs to not crash assert_snapshot!( infer(r#" trait A: B {} trait B: A {} fn test(x: T) { x.foo(); } "#), @r###" [44; 45) 'x': T [50; 66) '{ ...o(); }': () [56; 57) 'x': T [56; 63) 'x.foo()': {unknown} "### ); } #[test] fn super_trait_assoc_type_bounds() { assert_snapshot!( infer(r#" trait SuperTrait { type Type; } trait Trait where Self: SuperTrait {} fn get2>(t: T) -> U {} fn set>(t: T) -> T {t} struct S; impl SuperTrait for S { type Type = T; } impl Trait for S {} fn test() { get2(set(S)); } "#), @r###" [103; 104) 't': T [114; 116) '{}': () [146; 147) 't': T [157; 160) '{t}': T [158; 159) 't': T [259; 280) '{ ...S)); }': () [265; 269) 'get2': fn get2>(S) -> u64 [265; 277) 'get2(set(S))': u64 [270; 273) 'set': fn set>(S) -> S [270; 276) 'set(S)': S [274; 275) 'S': S "### ); } #[test] fn fn_trait() { assert_snapshot!( infer(r#" trait FnOnce { type Output; fn call_once(self, args: Args) -> >::Output; } fn test u128>(f: F) { f.call_once((1, 2)); } "#), @r###" [57; 61) 'self': Self [63; 67) 'args': Args [150; 151) 'f': F [156; 184) '{ ...2)); }': () [162; 163) 'f': F [162; 181) 'f.call...1, 2))': u128 [174; 180) '(1, 2)': (u32, u64) [175; 176) '1': u32 [178; 179) '2': u64 "### ); } #[test] fn closure_1() { assert_snapshot!( infer(r#" #[lang = "fn_once"] trait FnOnce { type Output; } enum Option { Some(T), None } impl Option { fn map U>(self, f: F) -> Option {} } fn test() { let x = Option::Some(1u32); x.map(|v| v + 1); x.map(|_v| 1u64); let y: Option = x.map(|_v| 1); } "#), @r###" [148; 152) 'self': Option [154; 155) 'f': F [173; 175) '{}': () [189; 308) '{ ... 1); }': () [199; 200) 'x': Option [203; 215) 'Option::Some': Some(u32) -> Option [203; 221) 'Option...(1u32)': Option [216; 220) '1u32': u32 [227; 228) 'x': Option [227; 243) 'x.map(...v + 1)': Option [233; 242) '|v| v + 1': |u32| -> u32 [234; 235) 'v': u32 [237; 238) 'v': u32 [237; 242) 'v + 1': u32 [241; 242) '1': u32 [249; 250) 'x': Option [249; 265) 'x.map(... 1u64)': Option [255; 264) '|_v| 1u64': |u32| -> u64 [256; 258) '_v': u32 [260; 264) '1u64': u64 [275; 276) 'y': Option [292; 293) 'x': Option [292; 305) 'x.map(|_v| 1)': Option [298; 304) '|_v| 1': |u32| -> i64 [299; 301) '_v': u32 [303; 304) '1': i64 "### ); } #[test] fn closure_2() { assert_snapshot!( infer(r#" trait FnOnce { type Output; } fn test u64>(f: F) { f(1); let g = |v| v + 1; g(1u64); let h = |v| 1u128 + v; } "#), @r###" [73; 74) 'f': F [79; 155) '{ ...+ v; }': () [85; 86) 'f': F [85; 89) 'f(1)': {unknown} [87; 88) '1': i32 [99; 100) 'g': |u64| -> i32 [103; 112) '|v| v + 1': |u64| -> i32 [104; 105) 'v': u64 [107; 108) 'v': u64 [107; 112) 'v + 1': i32 [111; 112) '1': i32 [118; 119) 'g': |u64| -> i32 [118; 125) 'g(1u64)': i32 [120; 124) '1u64': u64 [135; 136) 'h': |u128| -> u128 [139; 152) '|v| 1u128 + v': |u128| -> u128 [140; 141) 'v': u128 [143; 148) '1u128': u128 [143; 152) '1u128 + v': u128 [151; 152) 'v': u128 "### ); } #[test] fn closure_as_argument_inference_order() { assert_snapshot!( infer(r#" #[lang = "fn_once"] trait FnOnce { type Output; } fn foo1 U>(x: T, f: F) -> U {} fn foo2 U>(f: F, x: T) -> U {} struct S; impl S { fn method(self) -> u64; fn foo1 U>(self, x: T, f: F) -> U {} fn foo2 U>(self, f: F, x: T) -> U {} } fn test() { let x1 = foo1(S, |s| s.method()); let x2 = foo2(|s| s.method(), S); let x3 = S.foo1(S, |s| s.method()); let x4 = S.foo2(|s| s.method(), S); } "#), @r###" [95; 96) 'x': T [101; 102) 'f': F [112; 114) '{}': () [148; 149) 'f': F [154; 155) 'x': T [165; 167) '{}': () [202; 206) 'self': S [254; 258) 'self': S [260; 261) 'x': T [266; 267) 'f': F [277; 279) '{}': () [317; 321) 'self': S [323; 324) 'f': F [329; 330) 'x': T [340; 342) '{}': () [356; 515) '{ ... S); }': () [366; 368) 'x1': u64 [371; 375) 'foo1': fn foo1 u64>(S, |S| -> u64) -> u64 [371; 394) 'foo1(S...hod())': u64 [376; 377) 'S': S [379; 393) '|s| s.method()': |S| -> u64 [380; 381) 's': S [383; 384) 's': S [383; 393) 's.method()': u64 [404; 406) 'x2': u64 [409; 413) 'foo2': fn foo2 u64>(|S| -> u64, S) -> u64 [409; 432) 'foo2(|...(), S)': u64 [414; 428) '|s| s.method()': |S| -> u64 [415; 416) 's': S [418; 419) 's': S [418; 428) 's.method()': u64 [430; 431) 'S': S [442; 444) 'x3': u64 [447; 448) 'S': S [447; 472) 'S.foo1...hod())': u64 [454; 455) 'S': S [457; 471) '|s| s.method()': |S| -> u64 [458; 459) 's': S [461; 462) 's': S [461; 471) 's.method()': u64 [482; 484) 'x4': u64 [487; 488) 'S': S [487; 512) 'S.foo2...(), S)': u64 [494; 508) '|s| s.method()': |S| -> u64 [495; 496) 's': S [498; 499) 's': S [498; 508) 's.method()': u64 [510; 511) 'S': S "### ); } #[test] fn unselected_projection_in_trait_env_1() { let t = type_at( r#" //- /main.rs trait Trait { type Item; } trait Trait2 { fn foo(&self) -> u32; } fn test() where T::Item: Trait2 { let x: T::Item = no_matter; x.foo()<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn unselected_projection_in_trait_env_2() { let t = type_at( r#" //- /main.rs trait Trait { type Item; } trait Trait2 { fn foo(&self) -> u32; } fn test() where T::Item: Trait2, T: Trait, U: Trait<()> { let x: T::Item = no_matter; x.foo()<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn unselected_projection_on_impl_self() { assert_snapshot!(infer( r#" //- /main.rs trait Trait { type Item; fn f(&self, x: Self::Item); } struct S; impl Trait for S { type Item = u32; fn f(&self, x: Self::Item) { let y = x; } } struct S2; impl Trait for S2 { type Item = i32; fn f(&self, x: ::Item) { let y = x; } } "#, ), @r###" [54; 58) 'self': &Self [60; 61) 'x': Trait::Item [140; 144) 'self': &S [146; 147) 'x': u32 [161; 175) '{ let y = x; }': () [167; 168) 'y': u32 [171; 172) 'x': u32 [242; 246) 'self': &S2 [248; 249) 'x': i32 [265; 279) '{ let y = x; }': () [271; 272) 'y': i32 [275; 276) 'x': i32 "###); } #[test] fn unselected_projection_on_trait_self() { let t = type_at( r#" //- /main.rs trait Trait { type Item; fn f(&self) -> Self::Item { loop {} } } struct S; impl Trait for S { type Item = u32; } fn test() { S.f()<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn trait_impl_self_ty() { let t = type_at( r#" //- /main.rs trait Trait { fn foo(&self); } struct S; impl Trait for S {} fn test() { S.foo()<|>; } "#, ); assert_eq!(t, "()"); } #[test] fn trait_impl_self_ty_cycle() { let t = type_at( r#" //- /main.rs trait Trait { fn foo(&self); } struct S; impl Trait for S {} fn test() { S.foo()<|>; } "#, ); assert_eq!(t, "{unknown}"); } #[test] fn unselected_projection_in_trait_env_cycle_1() { let t = type_at( r#" //- /main.rs trait Trait { type Item; } trait Trait2 {} fn test() where T: Trait2 { let x: T::Item = no_matter<|>; } "#, ); // this is a legitimate cycle assert_eq!(t, "{unknown}"); } #[test] fn unselected_projection_in_trait_env_cycle_2() { let t = type_at( r#" //- /main.rs trait Trait { type Item; } fn test() where T: Trait, U: Trait { let x: T::Item = no_matter<|>; } "#, ); // this is a legitimate cycle assert_eq!(t, "{unknown}"); } #[test] fn inline_assoc_type_bounds_1() { let t = type_at( r#" //- /main.rs trait Iterator { type Item; } trait OtherTrait { fn foo(&self) -> T; } // workaround for Chalk assoc type normalization problems pub struct S; impl Iterator for S { type Item = ::Item; } fn test>>() { let x: as Iterator>::Item; x.foo()<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn inline_assoc_type_bounds_2() { let t = type_at( r#" //- /main.rs trait Iterator { type Item; } fn test>>() { let x: <::Item as Iterator>::Item; x<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn proc_macro_server_types() { assert_snapshot!( infer_with_mismatches(r#" macro_rules! with_api { ($S:ident, $self:ident, $m:ident) => { $m! { TokenStream { fn new() -> $S::TokenStream; }, Group { }, } }; } macro_rules! associated_item { (type TokenStream) => (type TokenStream: 'static + Clone;); (type Group) => (type Group: 'static + Clone;); ($($item:tt)*) => ($($item)*;) } macro_rules! declare_server_traits { ($($name:ident { $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)* }),* $(,)?) => { pub trait Types { $(associated_item!(type $name);)* } $(pub trait $name: Types { $(associated_item!(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)?);)* })* pub trait Server: Types $(+ $name)* {} impl Server for S {} } } with_api!(Self, self_, declare_server_traits); struct Group {} struct TokenStream {} struct Rustc; impl Types for Rustc { type TokenStream = TokenStream; type Group = Group; } fn make() -> T { loop {} } impl TokenStream for Rustc { fn new() -> Self::TokenStream { let group: Self::Group = make(); make() } } "#, true), @r###" [1115; 1126) '{ loop {} }': T [1117; 1124) 'loop {}': ! [1122; 1124) '{}': () [1190; 1253) '{ ... }': {unknown} [1204; 1209) 'group': {unknown} [1225; 1229) 'make': fn make<{unknown}>() -> {unknown} [1225; 1231) 'make()': {unknown} [1241; 1245) 'make': fn make<{unknown}>() -> {unknown} [1241; 1247) 'make()': {unknown} "### ); } #[test] fn unify_impl_trait() { assert_snapshot!( infer_with_mismatches(r#" trait Trait {} fn foo(x: impl Trait) { loop {} } fn bar(x: impl Trait) -> T { loop {} } struct S(T); impl Trait for S {} fn default() -> T { loop {} } fn test() -> impl Trait { let s1 = S(default()); foo(s1); let x: i32 = bar(S(default())); S(default()) } "#, true), @r###" [27; 28) 'x': impl Trait [47; 58) '{ loop {} }': () [49; 56) 'loop {}': ! [54; 56) '{}': () [69; 70) 'x': impl Trait [92; 103) '{ loop {} }': T [94; 101) 'loop {}': ! [99; 101) '{}': () [172; 183) '{ loop {} }': T [174; 181) 'loop {}': ! [179; 181) '{}': () [214; 310) '{ ...t()) }': S<{unknown}> [224; 226) 's1': S [229; 230) 'S': S(u32) -> S [229; 241) 'S(default())': S [231; 238) 'default': fn default() -> u32 [231; 240) 'default()': u32 [247; 250) 'foo': fn foo(S) [247; 254) 'foo(s1)': () [251; 253) 's1': S [264; 265) 'x': i32 [273; 276) 'bar': fn bar(S) -> i32 [273; 290) 'bar(S(...lt()))': i32 [277; 278) 'S': S(i32) -> S [277; 289) 'S(default())': S [279; 286) 'default': fn default() -> i32 [279; 288) 'default()': i32 [296; 297) 'S': S<{unknown}>({unknown}) -> S<{unknown}> [296; 308) 'S(default())': S<{unknown}> [298; 305) 'default': fn default<{unknown}>() -> {unknown} [298; 307) 'default()': {unknown} "### ); } #[test] fn assoc_types_from_bounds() { assert_snapshot!( infer(r#" //- /main.rs #[lang = "fn_once"] trait FnOnce { type Output; } trait T { type O; } impl T for () { type O = (); } fn f(_v: F) where X: T, F: FnOnce(&X::O), { } fn main() { f::<(), _>(|z| { z; }); } "#), @r###" [147; 149) '_v': F [192; 195) '{ }': () [207; 238) '{ ... }); }': () [213; 223) 'f::<(), _>': fn f<(), |&()| -> ()>(|&()| -> ()) [213; 235) 'f::<()... z; })': () [224; 234) '|z| { z; }': |&()| -> () [225; 226) 'z': &() [228; 234) '{ z; }': () [230; 231) 'z': &() "### ); } #[test] fn associated_type_bound() { let t = type_at( r#" //- /main.rs pub trait Trait { type Item: OtherTrait; } pub trait OtherTrait { fn foo(&self) -> T; } // this is just a workaround for chalk#234 pub struct S; impl Trait for S { type Item = ::Item; } fn test() { let y: as Trait>::Item = no_matter; y.foo()<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn dyn_trait_through_chalk() { let t = type_at( r#" //- /main.rs struct Box {} #[lang = "deref"] trait Deref { type Target; } impl Deref for Box { type Target = T; } trait Trait { fn foo(&self); } fn test(x: Box) { x.foo()<|>; } "#, ); assert_eq!(t, "()"); } #[test] fn string_to_owned() { let t = type_at( r#" //- /main.rs struct String {} pub trait ToOwned { type Owned; fn to_owned(&self) -> Self::Owned; } impl ToOwned for str { type Owned = String; } fn test() { "foo".to_owned()<|>; } "#, ); assert_eq!(t, "String"); } #[test] fn iterator_chain() { assert_snapshot!( infer(r#" //- /main.rs #[lang = "fn_once"] trait FnOnce { type Output; } #[lang = "fn_mut"] trait FnMut: FnOnce { } enum Option { Some(T), None } use Option::*; pub trait Iterator { type Item; fn filter_map(self, f: F) -> FilterMap where F: FnMut(Self::Item) -> Option, { loop {} } fn for_each(self, f: F) where F: FnMut(Self::Item), { loop {} } } pub trait IntoIterator { type Item; type IntoIter: Iterator; fn into_iter(self) -> Self::IntoIter; } pub struct FilterMap { } impl Iterator for FilterMap where F: FnMut(I::Item) -> Option, { type Item = B; } #[stable(feature = "rust1", since = "1.0.0")] impl IntoIterator for I { type Item = I::Item; type IntoIter = I; fn into_iter(self) -> I { self } } struct Vec {} impl Vec { fn new() -> Self { loop {} } } impl IntoIterator for Vec { type Item = T; type IntoIter = IntoIter; } pub struct IntoIter { } impl Iterator for IntoIter { type Item = T; } fn main() { Vec::::new().into_iter() .filter_map(|x| if x > 0 { Some(x as u32) } else { None }) .for_each(|y| { y; }); } "#), @r###" [240; 244) 'self': Self [246; 247) 'f': F [331; 342) '{ loop {} }': FilterMap [333; 340) 'loop {}': ! [338; 340) '{}': () [363; 367) 'self': Self [369; 370) 'f': F [419; 430) '{ loop {} }': () [421; 428) 'loop {}': ! [426; 428) '{}': () [539; 543) 'self': Self [868; 872) 'self': I [879; 899) '{ ... }': I [889; 893) 'self': I [958; 969) '{ loop {} }': Vec [960; 967) 'loop {}': ! [965; 967) '{}': () [1156; 1287) '{ ... }); }': () [1162; 1177) 'Vec::::new': fn new() -> Vec [1162; 1179) 'Vec::<...:new()': Vec [1162; 1191) 'Vec::<...iter()': IntoIter [1162; 1256) 'Vec::<...one })': FilterMap, |i32| -> Option> [1162; 1284) 'Vec::<... y; })': () [1210; 1255) '|x| if...None }': |i32| -> Option [1211; 1212) 'x': i32 [1214; 1255) 'if x >...None }': Option [1217; 1218) 'x': i32 [1217; 1222) 'x > 0': bool [1221; 1222) '0': i32 [1223; 1241) '{ Some...u32) }': Option [1225; 1229) 'Some': Some(u32) -> Option [1225; 1239) 'Some(x as u32)': Option [1230; 1231) 'x': i32 [1230; 1238) 'x as u32': u32 [1247; 1255) '{ None }': Option [1249; 1253) 'None': Option [1273; 1283) '|y| { y; }': |u32| -> () [1274; 1275) 'y': u32 [1277; 1283) '{ y; }': () [1279; 1280) 'y': u32 "### ); } #[test] fn nested_assoc() { let t = type_at( r#" //- /main.rs struct Bar; struct Foo; trait A { type OutputA; } impl A for Bar { type OutputA = Foo; } trait B { type Output; fn foo() -> Self::Output; } impl B for T { type Output = T::OutputA; fn foo() -> Self::Output { loop {} } } fn main() { Bar::foo()<|>; } "#, ); assert_eq!(t, "Foo"); } #[test] fn trait_object_no_coercion() { assert_snapshot!( infer_with_mismatches(r#" trait Foo {} fn foo(x: &dyn Foo) {} fn test(x: &dyn Foo) { foo(x); } "#, true), @r###" [22; 23) 'x': &dyn Foo [35; 37) '{}': () [47; 48) 'x': &dyn Foo [60; 75) '{ foo(x); }': () [66; 69) 'foo': fn foo(&dyn Foo) [66; 72) 'foo(x)': () [70; 71) 'x': &dyn Foo "### ); }