From 6a77ec7bbe6ddbf663dce9529d11d1bb56c5489a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 13 Aug 2020 16:35:29 +0200 Subject: Rename ra_hir_ty -> hir_ty --- crates/hir_ty/src/tests/traits.rs | 3113 +++++++++++++++++++++++++++++++++++++ 1 file changed, 3113 insertions(+) create mode 100644 crates/hir_ty/src/tests/traits.rs (limited to 'crates/hir_ty/src/tests/traits.rs') diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs new file mode 100644 index 000000000..526e61caf --- /dev/null +++ b/crates/hir_ty/src/tests/traits.rs @@ -0,0 +1,3113 @@ +use expect::expect; +use test_utils::mark; + +use super::{check_infer, check_infer_with_mismatches, check_types}; + +#[test] +fn infer_await() { + check_types( + r#" +//- /main.rs crate:main deps:core +struct IntFuture; + +impl Future for IntFuture { + type Output = u64; +} + +fn test() { + let r = IntFuture; + let v = r.await; + v; +} //^ u64 + +//- /core.rs crate:core +#[prelude_import] use future::*; +mod future { + #[lang = "future_trait"] + trait Future { + type Output; + } +} +"#, + ); +} + +#[test] +fn infer_async() { + check_types( + r#" +//- /main.rs crate:main deps:core +async fn foo() -> u64 { + 128 +} + +fn test() { + let r = foo(); + let v = r.await; + v; +} //^ u64 + +//- /core.rs crate:core +#[prelude_import] use future::*; +mod future { + #[lang = "future_trait"] + trait Future { + type Output; + } +} +"#, + ); +} + +#[test] +fn infer_desugar_async() { + check_types( + r#" +//- /main.rs crate:main deps:core +async fn foo() -> u64 { + 128 +} + +fn test() { + let r = foo(); + r; +} //^ impl Future + +//- /core.rs crate:core +#[prelude_import] use future::*; +mod future { + trait Future { + type Output; + } +} + +"#, + ); +} + +#[test] +fn infer_try() { + check_types( + r#" +//- /main.rs crate:main deps:core +fn test() { + let r: Result = Result::Ok(1); + let v = r?; + v; +} //^ i32 + +//- /core.rs crate:core +#[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; + } +} +"#, + ); +} + +#[test] +fn infer_for_loop() { + check_types( + r#" +//- /main.rs crate:main deps:core,alloc +use alloc::collections::Vec; + +fn test() { + let v = Vec::new(); + v.push("foo"); + for x in v { + x; + } //^ &str +} + +//- /core.rs crate:core +#[prelude_import] use iter::*; +mod iter { + trait IntoIterator { + type Item; + } +} + +//- /alloc.rs crate:alloc deps:core +mod collections { + struct Vec {} + impl Vec { + fn new() -> Self { Vec {} } + fn push(&mut self, t: T) { } + } + + impl IntoIterator for Vec { + type Item=T; + } +} +"#, + ); +} + +#[test] +fn infer_ops_neg() { + check_types( + 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; +} //^ Foo + +//- /std.rs crate:std +#[prelude_import] use ops::*; +mod ops { + #[lang = "neg"] + pub trait Neg { + type Output; + } +} +"#, + ); +} + +#[test] +fn infer_ops_not() { + check_types( + 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; +} //^ Foo + +//- /std.rs crate:std +#[prelude_import] use ops::*; +mod ops { + #[lang = "not"] + pub trait Not { + type Output; + } +} +"#, + ); +} + +#[test] +fn infer_from_bound_1() { + check_infer( + r#" + trait Trait {} + struct S(T); + impl Trait for S {} + fn foo>(t: T) {} + fn test() { + let s = S(unknown); + foo(s); + } + "#, + expect![[r#" + 85..86 't': T + 91..93 '{}': () + 104..143 '{ ...(s); }': () + 114..115 's': S + 118..119 'S': S(u32) -> S + 118..128 'S(unknown)': S + 120..127 'unknown': u32 + 134..137 'foo': fn foo>(S) + 134..140 'foo(s)': () + 138..139 's': S + "#]], + ); +} + +#[test] +fn infer_from_bound_2() { + check_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); + } + "#, + expect![[r#" + 86..87 't': T + 97..99 '{}': () + 110..162 '{ ...(s); }': () + 120..121 's': S + 124..125 'S': S(u32) -> S + 124..134 'S(unknown)': S + 126..133 'unknown': u32 + 144..145 'x': u32 + 153..156 'foo': fn foo>(S) -> u32 + 153..159 'foo(s)': u32 + 157..158 's': S + "#]], + ); +} + +#[test] +fn trait_default_method_self_bound_implements_trait() { + mark::check!(trait_self_implements_self); + check_infer( + r#" + trait Trait { + fn foo(&self) -> i64; + fn bar(&self) -> { + let x = self.foo(); + } + } + "#, + expect![[r#" + 26..30 'self': &Self + 52..56 'self': &Self + 61..96 '{ ... }': () + 75..76 'x': i64 + 79..83 'self': &Self + 79..89 'self.foo()': i64 + "#]], + ); +} + +#[test] +fn trait_default_method_self_bound_implements_super_trait() { + check_infer( + r#" + trait SuperTrait { + fn foo(&self) -> i64; + } + trait Trait: SuperTrait { + fn bar(&self) -> { + let x = self.foo(); + } + } + "#, + expect![[r#" + 31..35 'self': &Self + 85..89 'self': &Self + 94..129 '{ ... }': () + 108..109 'x': i64 + 112..116 'self': &Self + 112..122 'self.foo()': i64 + "#]], + ); +} + +#[test] +fn infer_project_associated_type() { + check_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; + } + "#, + expect![[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() { + check_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); + } + "#, + expect![[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() { + check_infer( + r#" + trait Iterable { + type Item; + } + fn test>() { + let y: T::Item = unknown; + } + "#, + expect![[r#" + 67..100 '{ ...own; }': () + 77..78 'y': u32 + 90..97 'unknown': u32 + "#]], + ); +} + +#[test] +fn infer_const_body() { + check_infer( + r#" + const A: u32 = 1 + 1; + static B: u64 = { let x = 1; x }; + "#, + expect![[r#" + 15..16 '1': u32 + 15..20 '1 + 1': u32 + 19..20 '1': u32 + 38..54 '{ let ...1; x }': u64 + 44..45 'x': u64 + 48..49 '1': u64 + 51..52 'x': u64 + "#]], + ); +} + +#[test] +fn tuple_struct_fields() { + check_infer( + r#" + struct S(i32, u64); + fn test() -> u64 { + let a = S(4, 6); + let b = a.0; + a.1 + } + "#, + expect![[r#" + 37..86 '{ ... a.1 }': u64 + 47..48 'a': S + 51..52 'S': S(i32, u64) -> S + 51..58 'S(4, 6)': S + 53..54 '4': i32 + 56..57 '6': u64 + 68..69 'b': i32 + 72..73 'a': S + 72..75 'a.0': i32 + 81..82 'a': S + 81..84 'a.1': u64 + "#]], + ); +} + +#[test] +fn tuple_struct_with_fn() { + check_infer( + r#" + struct S(fn(u32) -> u64); + fn test() -> u64 { + let a = S(|i| 2*i); + let b = a.0(4); + a.0(2) + } + "#, + expect![[r#" + 43..101 '{ ...0(2) }': u64 + 53..54 'a': S + 57..58 'S': S(fn(u32) -> u64) -> S + 57..67 'S(|i| 2*i)': S + 59..66 '|i| 2*i': |u32| -> u64 + 60..61 'i': u32 + 63..64 '2': u32 + 63..66 '2*i': u32 + 65..66 'i': u32 + 77..78 'b': u64 + 81..82 'a': S + 81..84 'a.0': fn(u32) -> u64 + 81..87 'a.0(4)': u64 + 85..86 '4': u32 + 93..94 'a': S + 93..96 'a.0': fn(u32) -> u64 + 93..99 'a.0(2)': u64 + 97..98 '2': u32 + "#]], + ); +} + +#[test] +fn indexing_arrays() { + check_infer( + "fn main() { &mut [9][2]; }", + expect![[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() { + check_types( + 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; +} //^ Foo + +//- /std.rs crate:std +#[prelude_import] use ops::*; +mod ops { + #[lang = "index"] + pub trait Index { + type Output; + } +} +"#, + ); +} + +#[test] +fn infer_ops_index_int() { + check_types( + r#" +//- /main.rs crate:main deps:std +struct Bar; +struct Foo; + +impl std::ops::Index for Bar { + type Output = Foo; +} + +struct Range; +impl std::ops::Index for Bar { + type Output = Bar; +} + +fn test() { + let a = Bar; + let b = a[1]; + b; + //^ Foo +} + +//- /std.rs crate:std +#[prelude_import] use ops::*; +mod ops { + #[lang = "index"] + pub trait Index { + type Output; + } +} +"#, + ); +} + +#[test] +fn infer_ops_index_autoderef() { + check_types( + r#" +//- /main.rs crate:main deps:std +fn test() { + let a = &[1u32, 2, 3]; + let b = a[1u32]; + b; +} //^ u32 + +//- /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; + } +} +"#, + ); +} + +#[test] +fn deref_trait() { + check_types( + r#" +#[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()); +} //^ (S, u128) +"#, + ); +} + +#[test] +fn deref_trait_with_inference_var() { + check_types( + 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); + //^ S + foo(a); +} +"#, + ); +} + +#[test] +fn deref_trait_infinite_recursion() { + check_types( + r#" +#[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(); +} //^ {unknown} +"#, + ); +} + +#[test] +fn deref_trait_with_question_mark_size() { + check_types( + r#" +#[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()); +} //^ (S, u128) +"#, + ); +} + +#[test] +fn obligation_from_function_clause() { + check_types( + r#" +struct S; + +trait Trait {} +impl Trait for S {} + +fn foo, U>(t: T) -> U {} + +fn test(s: S) { + (foo(s)); +} //^ u32 +"#, + ); +} + +#[test] +fn obligation_from_method_clause() { + check_types( + 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); +} //^ isize +"#, + ); +} + +#[test] +fn obligation_from_self_method_clause() { + check_types( + r#" +struct S; + +trait Trait {} +impl Trait for S {} + +impl S { + fn foo(&self) -> U where Self: Trait {} +} + +fn test() { + S.foo(); +} //^ i64 +"#, + ); +} + +#[test] +fn obligation_from_impl_clause() { + check_types( + r#" +struct S; + +trait Trait {} +impl Trait<&str> for S {} + +struct O; +impl> O { + fn foo(&self) -> U {} +} + +fn test(o: O) { + o.foo(); +} //^ &str +"#, + ); +} + +#[test] +fn generic_param_env_1() { + check_types( + r#" +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(); } + //^ u128 +"#, + ); +} + +#[test] +fn generic_param_env_1_not_met() { + check_types( + 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(); } + //^ {unknown} +"#, + ); +} + +#[test] +fn generic_param_env_2() { + check_types( + r#" +trait Trait { fn foo(self) -> u128; } +struct S; +impl Trait for S {} +fn test(t: T) { t.foo(); } + //^ u128 +"#, + ); +} + +#[test] +fn generic_param_env_2_not_met() { + check_types( + r#" +trait Trait { fn foo(self) -> u128; } +struct S; +impl Trait for S {} +fn test(t: T) { t.foo(); } + //^ {unknown} +"#, + ); +} + +#[test] +fn generic_param_env_deref() { + check_types( + r#" +#[lang = "deref"] +trait Deref { + type Target; +} +trait Trait {} +impl Deref for T where T: Trait { + type Target = i128; +} +fn test(t: T) { (*t); } + //^ i128 +"#, + ); +} + +#[test] +fn associated_type_placeholder() { + // 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]. + check_types( + r#" +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; +} //^ ApplyL::Out +"#, + ); +} + +#[test] +fn associated_type_placeholder_2() { + check_types( + r#" +pub trait ApplyL { + type Out; +} +fn foo(t: T) -> ::Out; + +fn test(t: T) { + let y = foo(t); + y; +} //^ ApplyL::Out +"#, + ); +} + +#[test] +fn argument_impl_trait() { + check_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(); + } + "#, + expect![[r#" + 29..33 'self': &Self + 54..58 'self': &Self + 77..78 'x': impl Trait + 97..99 '{}': () + 154..155 'x': impl Trait + 174..175 'y': &impl Trait + 195..323 '{ ...2(); }': () + 201..202 'x': impl Trait + 208..209 'y': &impl Trait + 219..220 'z': S + 223..224 'S': S(u16) -> S + 223..227 'S(1)': S + 225..226 '1': u16 + 233..236 'bar': fn bar(S) + 233..239 'bar(z)': () + 237..238 'z': S + 245..246 'x': impl Trait + 245..252 'x.foo()': u64 + 258..259 'y': &impl Trait + 258..265 'y.foo()': u32 + 271..272 'z': S + 271..278 'z.foo()': u16 + 284..285 'x': impl Trait + 284..292 'x.foo2()': i64 + 298..299 'y': &impl Trait + 298..306 'y.foo2()': i64 + 312..313 'z': S + 312..320 'z.foo2()': i64 + "#]], + ); +} + +#[test] +fn argument_impl_trait_type_args_1() { + check_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 + } + "#, + expect![[r#" + 155..156 'x': impl Trait + 175..186 '{ loop {} }': T + 177..184 'loop {}': ! + 182..184 '{}': () + 199..200 'x': impl Trait + 219..230 '{ loop {} }': T + 221..228 'loop {}': ! + 226..228 '{}': () + 300..509 '{ ... i32 }': () + 306..314 'Foo::bar': fn bar<{unknown}, {unknown}>(S) -> {unknown} + 306..317 'Foo::bar(S)': {unknown} + 315..316 'S': S + 323..338 '::bar': fn bar(S) -> {unknown} + 323..341 '(S) -> {unknown} + 347..356 'F::bar(S)': {unknown} + 354..355 'S': S + 362..377 'Foo::bar::': fn bar<{unknown}, u32>(S) -> u32 + 362..380 'Foo::b...32>(S)': u32 + 378..379 'S': S + 386..408 '': fn bar(S) -> u32 + 386..411 '(S)': u32 + 409..410 'S': S + 418..421 'foo': fn foo<{unknown}>(S) -> {unknown} + 418..424 'foo(S)': {unknown} + 422..423 'S': S + 430..440 'foo::': fn foo(S) -> u32 + 430..443 'foo::(S)': u32 + 441..442 'S': S + 449..464 'foo::': fn foo(S) -> u32 + 449..467 'foo::<...32>(S)': u32 + 465..466 'S': S + "#]], + ); +} + +#[test] +fn argument_impl_trait_type_args_2() { + check_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 + } + "#, + expect![[r#" + 87..91 'self': F + 93..94 'x': impl Trait + 118..129 '{ loop {} }': (T, U) + 120..127 'loop {}': ! + 125..127 '{}': () + 143..283 '{ ...ored }': () + 149..150 'F': F<{unknown}> + 149..157 'F.foo(S)': ({unknown}, {unknown}) + 155..156 'S': S + 163..171 'F::': F + 163..178 'F::.foo(S)': (u32, {unknown}) + 176..177 'S': S + 184..192 'F::': F + 184..206 'F::(S)': (u32, i32) + 204..205 'S': S + 212..220 'F::': F + 212..239 'F::(S)': (u32, i32) + 237..238 'S': S + "#]], + ); +} + +#[test] +fn argument_impl_trait_to_fn_pointer() { + check_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; + } + "#, + expect![[r#" + 22..23 'x': impl Trait + 37..48 '{ loop {} }': () + 39..46 'loop {}': ! + 44..46 '{}': () + 90..123 '{ ...foo; }': () + 100..101 'f': fn(S) + 117..120 'foo': fn foo(S) + "#]], + ); +} + +#[test] +fn impl_trait() { + check_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(); + } + "#, + expect![[r#" + 29..33 'self': &Self + 54..58 'self': &Self + 98..100 '{}': () + 110..111 'x': impl Trait + 130..131 'y': &impl Trait + 151..268 '{ ...2(); }': () + 157..158 'x': impl Trait + 164..165 'y': &impl Trait + 175..176 'z': impl Trait + 179..182 'bar': fn bar() -> impl Trait + 179..184 'bar()': impl Trait + 190..191 'x': impl Trait + 190..197 'x.foo()': u64 + 203..204 'y': &impl Trait + 203..210 'y.foo()': u64 + 216..217 'z': impl Trait + 216..223 'z.foo()': u64 + 229..230 'x': impl Trait + 229..237 'x.foo2()': i64 + 243..244 'y': &impl Trait + 243..251 'y.foo2()': i64 + 257..258 'z': impl Trait + 257..265 'z.foo2()': i64 + "#]], + ); +} + +#[test] +fn simple_return_pos_impl_trait() { + mark::check!(lower_rpit); + check_infer( + r#" + trait Trait { + fn foo(&self) -> T; + } + fn bar() -> impl Trait { loop {} } + + fn test() { + let a = bar(); + a.foo(); + } + "#, + expect![[r#" + 29..33 'self': &Self + 71..82 '{ loop {} }': ! + 73..80 'loop {}': ! + 78..80 '{}': () + 94..129 '{ ...o(); }': () + 104..105 'a': impl Trait + 108..111 'bar': fn bar() -> impl Trait + 108..113 'bar()': impl Trait + 119..120 'a': impl Trait + 119..126 'a.foo()': u64 + "#]], + ); +} + +#[test] +fn more_return_pos_impl_trait() { + check_infer( + r#" + trait Iterator { + type Item; + fn next(&mut self) -> Self::Item; + } + trait Trait { + fn foo(&self) -> T; + } + fn bar() -> (impl Iterator>, impl Trait) { loop {} } + fn baz(t: T) -> (impl Iterator>, impl Trait) { loop {} } + + fn test() { + let (a, b) = bar(); + a.next().foo(); + b.foo(); + let (c, d) = baz(1u128); + c.next().foo(); + d.foo(); + } + "#, + expect![[r#" + 49..53 'self': &mut Self + 101..105 'self': &Self + 184..195 '{ loop {} }': ({unknown}, {unknown}) + 186..193 'loop {}': ! + 191..193 '{}': () + 206..207 't': T + 268..279 '{ loop {} }': ({unknown}, {unknown}) + 270..277 'loop {}': ! + 275..277 '{}': () + 291..413 '{ ...o(); }': () + 301..307 '(a, b)': (impl Iterator>, impl Trait) + 302..303 'a': impl Iterator> + 305..306 'b': impl Trait + 310..313 'bar': fn bar() -> (impl Iterator>, impl Trait) + 310..315 'bar()': (impl Iterator>, impl Trait) + 321..322 'a': impl Iterator> + 321..329 'a.next()': impl Trait + 321..335 'a.next().foo()': u32 + 341..342 'b': impl Trait + 341..348 'b.foo()': u64 + 358..364 '(c, d)': (impl Iterator>, impl Trait) + 359..360 'c': impl Iterator> + 362..363 'd': impl Trait + 367..370 'baz': fn baz(u128) -> (impl Iterator>, impl Trait) + 367..377 'baz(1u128)': (impl Iterator>, impl Trait) + 371..376 '1u128': u128 + 383..384 'c': impl Iterator> + 383..391 'c.next()': impl Trait + 383..397 'c.next().foo()': u128 + 403..404 'd': impl Trait + 403..410 'd.foo()': u128 + "#]], + ); +} + +#[test] +fn dyn_trait() { + check_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(); + } + "#, + expect![[r#" + 29..33 'self': &Self + 54..58 'self': &Self + 97..99 '{}': () + 109..110 'x': dyn Trait + 128..129 'y': &dyn Trait + 148..265 '{ ...2(); }': () + 154..155 'x': dyn Trait + 161..162 'y': &dyn Trait + 172..173 'z': dyn Trait + 176..179 'bar': fn bar() -> dyn Trait + 176..181 'bar()': dyn Trait + 187..188 'x': dyn Trait + 187..194 'x.foo()': u64 + 200..201 'y': &dyn Trait + 200..207 'y.foo()': u64 + 213..214 'z': dyn Trait + 213..220 'z.foo()': u64 + 226..227 'x': dyn Trait + 226..234 'x.foo2()': i64 + 240..241 'y': &dyn Trait + 240..248 'y.foo2()': i64 + 254..255 'z': dyn Trait + 254..262 'z.foo2()': i64 + "#]], + ); +} + +#[test] +fn dyn_trait_in_impl() { + check_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(); + } + "#, + expect![[r#" + 32..36 'self': &Self + 102..106 'self': &S + 128..139 '{ loop {} }': &dyn Trait + 130..137 'loop {}': ! + 135..137 '{}': () + 175..179 'self': &Self + 251..252 's': S + 267..289 '{ ...z(); }': () + 273..274 's': S + 273..280 's.bar()': &dyn Trait + 273..286 's.bar().baz()': (u32, i32) + "#]], + ); +} + +#[test] +fn dyn_trait_bare() { + check_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(); + } + "#, + expect![[r#" + 26..30 'self': &Self + 60..62 '{}': () + 72..73 'x': dyn Trait + 82..83 'y': &dyn Trait + 100..175 '{ ...o(); }': () + 106..107 'x': dyn Trait + 113..114 'y': &dyn Trait + 124..125 'z': dyn Trait + 128..131 'bar': fn bar() -> dyn Trait + 128..133 'bar()': dyn Trait + 139..140 'x': dyn Trait + 139..146 'x.foo()': u64 + 152..153 'y': &dyn Trait + 152..159 'y.foo()': u64 + 165..166 'z': dyn Trait + 165..172 'z.foo()': u64 + "#]], + ); +} + +#[test] +fn weird_bounds() { + check_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) {} + "#, + expect![[r#" + 23..24 'a': impl Trait + {error} + 50..51 'b': impl {error} + 69..70 'c': impl Trait + 86..87 'd': impl {error} + 107..108 'e': impl {error} + 123..124 'f': impl Trait + {error} + 147..149 '{}': () + "#]], + ); +} + +#[test] +#[ignore] +fn error_bound_chalk() { + check_types( + r#" +trait Trait { + fn foo(&self) -> u32 {} +} + +fn test(x: (impl Trait + UnknownTrait)) { + x.foo(); +} //^ u32 +"#, + ); +} + +#[test] +fn assoc_type_bindings() { + check_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::); + } + "#, + expect![[r#" + 49..50 't': T + 77..79 '{}': () + 111..112 't': T + 122..124 '{}': () + 154..155 't': T + 165..168 '{t}': T + 166..167 't': T + 256..257 'x': T + 262..263 'y': impl Trait + 289..397 '{ ...r>); }': () + 295..298 'get': fn get(T) -> ::Type + 295..301 'get(x)': u32 + 299..300 'x': T + 307..311 'get2': fn get2(T) -> u32 + 307..314 'get2(x)': u32 + 312..313 'x': T + 320..323 'get': fn get>(impl Trait) -> as Trait>::Type + 320..326 'get(y)': i64 + 324..325 'y': impl Trait + 332..336 'get2': fn get2>(impl Trait) -> i64 + 332..339 'get2(y)': i64 + 337..338 'y': impl Trait + 345..348 'get': fn get>(S) -> as Trait>::Type + 345..356 'get(set(S))': u64 + 349..352 'set': fn set>(S) -> S + 349..355 'set(S)': S + 353..354 'S': S + 362..366 'get2': fn get2>(S) -> u64 + 362..374 'get2(set(S))': u64 + 367..370 'set': fn set>(S) -> S + 367..373 'set(S)': S + 371..372 'S': S + 380..384 'get2': fn get2>(S) -> str + 380..394 'get2(S::)': str + 385..393 'S::': S + "#]], + ); +} + +#[test] +fn impl_trait_assoc_binding_projection_bug() { + check_types( + 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(); + } //^ {unknown} +} + +//- /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; + } +} +"#, + ); +} + +#[test] +fn projection_eq_within_chalk() { + check_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(); + } + "#, + expect![[r#" + 61..65 'self': Self + 163..164 'x': T + 169..185 '{ ...o(); }': () + 175..176 'x': T + 175..182 'x.foo()': u32 + "#]], + ); +} + +#[test] +fn where_clause_trait_in_scope_for_method_resolution() { + check_types( + r#" +mod foo { + trait Trait { + fn foo(&self) -> u32 {} + } +} + +fn test(x: T) { + x.foo(); +} //^ u32 +"#, + ); +} + +#[test] +fn super_trait_method_resolution() { + check_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(); + } + "#, + expect![[r#" + 49..53 'self': &Self + 62..64 '{}': () + 181..182 'x': T + 187..188 'y': U + 193..222 '{ ...o(); }': () + 199..200 'x': T + 199..206 'x.foo()': u32 + 212..213 'y': U + 212..219 'y.foo()': u32 + "#]], + ); +} + +#[test] +fn super_trait_impl_trait_method_resolution() { + check_infer( + r#" + mod foo { + trait SuperTrait { + fn foo(&self) -> u32 {} + } + } + trait Trait1: foo::SuperTrait {} + + fn test(x: &impl Trait1) { + x.foo(); + } + "#, + expect![[r#" + 49..53 'self': &Self + 62..64 '{}': () + 115..116 'x': &impl Trait1 + 132..148 '{ ...o(); }': () + 138..139 'x': &impl Trait1 + 138..145 'x.foo()': u32 + "#]], + ); +} + +#[test] +fn super_trait_cycle() { + // This just needs to not crash + check_infer( + r#" + trait A: B {} + trait B: A {} + + fn test(x: T) { + x.foo(); + } + "#, + expect![[r#" + 43..44 'x': T + 49..65 '{ ...o(); }': () + 55..56 'x': T + 55..62 'x.foo()': {unknown} + "#]], + ); +} + +#[test] +fn super_trait_assoc_type_bounds() { + check_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)); + } + "#, + expect![[r#" + 102..103 't': T + 113..115 '{}': () + 145..146 't': T + 156..159 '{t}': T + 157..158 't': T + 258..279 '{ ...S)); }': () + 264..268 'get2': fn get2>(S) -> u64 + 264..276 'get2(set(S))': u64 + 269..272 'set': fn set>(S) -> S + 269..275 'set(S)': S + 273..274 'S': S + "#]], + ); +} + +#[test] +fn fn_trait() { + check_infer( + r#" + trait FnOnce { + type Output; + + fn call_once(self, args: Args) -> >::Output; + } + + fn test u128>(f: F) { + f.call_once((1, 2)); + } + "#, + expect![[r#" + 56..60 'self': Self + 62..66 'args': Args + 149..150 'f': F + 155..183 '{ ...2)); }': () + 161..162 'f': F + 161..180 'f.call...1, 2))': u128 + 173..179 '(1, 2)': (u32, u64) + 174..175 '1': u32 + 177..178 '2': u64 + "#]], + ); +} + +#[test] +fn fn_ptr_and_item() { + check_infer( + r#" + #[lang="fn_once"] + trait FnOnce { + type Output; + + fn call_once(self, args: Args) -> Self::Output; + } + + trait Foo { + fn foo(&self) -> T; + } + + struct Bar(T); + + impl R> Foo<(A1, R)> for Bar { + fn foo(&self) -> (A1, R) {} + } + + enum Opt { None, Some(T) } + impl Opt { + fn map U>(self, f: F) -> Opt {} + } + + fn test() { + let bar: Bar u32>; + bar.foo(); + + let opt: Opt; + let f: fn(u8) -> u32; + opt.map(f); + } + "#, + expect![[r#" + 74..78 'self': Self + 80..84 'args': Args + 139..143 'self': &Self + 243..247 'self': &Bar + 260..262 '{}': () + 346..350 'self': Opt + 352..353 'f': F + 368..370 '{}': () + 384..500 '{ ...(f); }': () + 394..397 'bar': Bar u32> + 423..426 'bar': Bar u32> + 423..432 'bar.foo()': (u8, u32) + 443..446 'opt': Opt + 465..466 'f': fn(u8) -> u32 + 487..490 'opt': Opt + 487..497 'opt.map(f)': Opt + 495..496 'f': fn(u8) -> u32 + "#]], + ); +} + +#[test] +fn fn_trait_deref_with_ty_default() { + check_infer( + r#" + #[lang = "deref"] + trait Deref { + type Target; + + fn deref(&self) -> &Self::Target; + } + + #[lang="fn_once"] + trait FnOnce { + type Output; + + fn call_once(self, args: Args) -> Self::Output; + } + + struct Foo; + + impl Foo { + fn foo(&self) -> usize {} + } + + struct Lazy T>(F); + + impl Lazy { + pub fn new(f: F) -> Lazy {} + } + + impl T> Deref for Lazy { + type Target = T; + } + + fn test() { + let lazy1: Lazy = Lazy::new(|| Foo); + let r1 = lazy1.foo(); + + fn make_foo_fn() -> Foo {} + let make_foo_fn_ptr: fn() -> Foo = make_foo_fn; + let lazy2: Lazy = Lazy::new(make_foo_fn_ptr); + let r2 = lazy2.foo(); + } + "#, + expect![[r#" + 64..68 'self': &Self + 165..169 'self': Self + 171..175 'args': Args + 239..243 'self': &Foo + 254..256 '{}': () + 334..335 'f': F + 354..356 '{}': () + 443..689 '{ ...o(); }': () + 453..458 'lazy1': Lazy Foo> + 475..484 'Lazy::new': fn new Foo>(|| -> Foo) -> Lazy Foo> + 475..492 'Lazy::...| Foo)': Lazy Foo> + 485..491 '|| Foo': || -> Foo + 488..491 'Foo': Foo + 502..504 'r1': usize + 507..512 'lazy1': Lazy Foo> + 507..518 'lazy1.foo()': usize + 560..575 'make_foo_fn_ptr': fn() -> Foo + 591..602 'make_foo_fn': fn make_foo_fn() -> Foo + 612..617 'lazy2': Lazy Foo> + 634..643 'Lazy::new': fn new Foo>(fn() -> Foo) -> Lazy Foo> + 634..660 'Lazy::...n_ptr)': Lazy Foo> + 644..659 'make_foo_fn_ptr': fn() -> Foo + 670..672 'r2': usize + 675..680 'lazy2': Lazy Foo> + 675..686 'lazy2.foo()': usize + 549..551 '{}': () + "#]], + ); +} + +#[test] +fn closure_1() { + check_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); + } + "#, + expect![[r#" + 147..151 'self': Option + 153..154 'f': F + 172..174 '{}': () + 188..307 '{ ... 1); }': () + 198..199 'x': Option + 202..214 'Option::Some': Some(u32) -> Option + 202..220 'Option...(1u32)': Option + 215..219 '1u32': u32 + 226..227 'x': Option + 226..242 'x.map(...v + 1)': Option + 232..241 '|v| v + 1': |u32| -> u32 + 233..234 'v': u32 + 236..237 'v': u32 + 236..241 'v + 1': u32 + 240..241 '1': u32 + 248..249 'x': Option + 248..264 'x.map(... 1u64)': Option + 254..263 '|_v| 1u64': |u32| -> u64 + 255..257 '_v': u32 + 259..263 '1u64': u64 + 274..275 'y': Option + 291..292 'x': Option + 291..304 'x.map(|_v| 1)': Option + 297..303 '|_v| 1': |u32| -> i64 + 298..300 '_v': u32 + 302..303 '1': i64 + "#]], + ); +} + +#[test] +fn closure_2() { + check_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; + } + "#, + expect![[r#" + 72..73 'f': F + 78..154 '{ ...+ v; }': () + 84..85 'f': F + 84..88 'f(1)': {unknown} + 86..87 '1': i32 + 98..99 'g': |u64| -> i32 + 102..111 '|v| v + 1': |u64| -> i32 + 103..104 'v': u64 + 106..107 'v': u64 + 106..111 'v + 1': i32 + 110..111 '1': i32 + 117..118 'g': |u64| -> i32 + 117..124 'g(1u64)': i32 + 119..123 '1u64': u64 + 134..135 'h': |u128| -> u128 + 138..151 '|v| 1u128 + v': |u128| -> u128 + 139..140 'v': u128 + 142..147 '1u128': u128 + 142..151 '1u128 + v': u128 + 150..151 'v': u128 + "#]], + ); +} + +#[test] +fn closure_as_argument_inference_order() { + check_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); + } + "#, + expect![[r#" + 94..95 'x': T + 100..101 'f': F + 111..113 '{}': () + 147..148 'f': F + 153..154 'x': T + 164..166 '{}': () + 201..205 'self': S + 253..257 'self': S + 259..260 'x': T + 265..266 'f': F + 276..278 '{}': () + 316..320 'self': S + 322..323 'f': F + 328..329 'x': T + 339..341 '{}': () + 355..514 '{ ... S); }': () + 365..367 'x1': u64 + 370..374 'foo1': fn foo1 u64>(S, |S| -> u64) -> u64 + 370..393 'foo1(S...hod())': u64 + 375..376 'S': S + 378..392 '|s| s.method()': |S| -> u64 + 379..380 's': S + 382..383 's': S + 382..392 's.method()': u64 + 403..405 'x2': u64 + 408..412 'foo2': fn foo2 u64>(|S| -> u64, S) -> u64 + 408..431 'foo2(|...(), S)': u64 + 413..427 '|s| s.method()': |S| -> u64 + 414..415 's': S + 417..418 's': S + 417..427 's.method()': u64 + 429..430 'S': S + 441..443 'x3': u64 + 446..447 'S': S + 446..471 'S.foo1...hod())': u64 + 453..454 'S': S + 456..470 '|s| s.method()': |S| -> u64 + 457..458 's': S + 460..461 's': S + 460..470 's.method()': u64 + 481..483 'x4': u64 + 486..487 'S': S + 486..511 'S.foo2...(), S)': u64 + 493..507 '|s| s.method()': |S| -> u64 + 494..495 's': S + 497..498 's': S + 497..507 's.method()': u64 + 509..510 'S': S + "#]], + ); +} + +#[test] +fn fn_item_fn_trait() { + check_types( + r#" +#[lang = "fn_once"] +trait FnOnce { + type Output; +} + +struct S; + +fn foo() -> S {} + +fn takes_closure U>(f: F) -> U { f() } + +fn test() { + takes_closure(foo); +} //^^^^^^^^^^^^^^^^^^ S +"#, + ); +} + +#[test] +fn unselected_projection_in_trait_env_1() { + check_types( + 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(); +} //^ u32 +"#, + ); +} + +#[test] +fn unselected_projection_in_trait_env_2() { + check_types( + r#" +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(); +} //^ u32 +"#, + ); +} + +#[test] +fn unselected_projection_on_impl_self() { + check_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; } + } + "#, + expect![[r#" + 40..44 'self': &Self + 46..47 'x': Trait::Item + 126..130 'self': &S + 132..133 'x': u32 + 147..161 '{ let y = x; }': () + 153..154 'y': u32 + 157..158 'x': u32 + 228..232 'self': &S2 + 234..235 'x': i32 + 251..265 '{ let y = x; }': () + 257..258 'y': i32 + 261..262 'x': i32 + "#]], + ); +} + +#[test] +fn unselected_projection_on_trait_self() { + check_types( + r#" +trait Trait { + type Item; + + fn f(&self) -> Self::Item { loop {} } +} + +struct S; +impl Trait for S { + type Item = u32; +} + +fn test() { + S.f(); +} //^ u32 +"#, + ); +} + +#[test] +fn unselected_projection_chalk_fold() { + check_types( + r#" +trait Interner {} +trait Fold { + type Result; +} + +struct Ty {} +impl Fold for Ty { + type Result = Ty; +} + +fn fold(interner: &I, t: T) -> T::Result +where + T: Fold, +{ + loop {} +} + +fn foo(interner: &I, t: Ty) { + fold(interner, t); +} //^ Ty +"#, + ); +} + +#[test] +fn trait_impl_self_ty() { + check_types( + r#" +trait Trait { + fn foo(&self); +} + +struct S; + +impl Trait for S {} + +fn test() { + S.foo(); +} //^ () +"#, + ); +} + +#[test] +fn trait_impl_self_ty_cycle() { + check_types( + r#" +trait Trait { + fn foo(&self); +} + +struct S; + +impl Trait for S {} + +fn test() { + S.foo(); +} //^ {unknown} +"#, + ); +} + +#[test] +fn unselected_projection_in_trait_env_cycle_1() { + // this is a legitimate cycle + check_types( + r#" +trait Trait { + type Item; +} + +trait Trait2 {} + +fn test() where T: Trait2 { + let x: T::Item = no_matter; +} //^ {unknown} +"#, + ); +} + +#[test] +fn unselected_projection_in_trait_env_cycle_2() { + // this is a legitimate cycle + check_types( + r#" +//- /main.rs +trait Trait { + type Item; +} + +fn test() where T: Trait, U: Trait { + let x: T::Item = no_matter; +} //^ {unknown} +"#, + ); +} + +#[test] +fn inline_assoc_type_bounds_1() { + check_types( + r#" +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(); +} //^ u32 +"#, + ); +} + +#[test] +fn inline_assoc_type_bounds_2() { + check_types( + r#" +trait Iterator { + type Item; +} + +fn test>>() { + let x: <::Item as Iterator>::Item; + x; +} //^ u32 +"#, + ); +} + +#[test] +fn proc_macro_server_types() { + check_infer( + 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;); + (type Group) => + (type Group: 'static;); + ($($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($($arg: $arg_ty),*) $(-> $ret_ty)?);)* + })* + + pub trait Server: Types $(+ $name)* {} + impl Server for S {} + } + } + + with_api!(Self, self_, declare_server_traits); + struct G {} + struct T {} + struct Rustc; + impl Types for Rustc { + type TokenStream = T; + type Group = G; + } + + fn make() -> T { loop {} } + impl TokenStream for Rustc { + fn new() -> Self::TokenStream { + let group: Self::Group = make(); + make() + } + } + "#, + expect![[r#" + 1061..1072 '{ loop {} }': T + 1063..1070 'loop {}': ! + 1068..1070 '{}': () + 1136..1199 '{ ... }': T + 1150..1155 'group': G + 1171..1175 'make': fn make() -> G + 1171..1177 'make()': G + 1187..1191 'make': fn make() -> T + 1187..1193 'make()': T + "#]], + ); +} + +#[test] +fn unify_impl_trait() { + check_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()) + } + "#, + expect![[r#" + 26..27 'x': impl Trait + 46..57 '{ loop {} }': () + 48..55 'loop {}': ! + 53..55 '{}': () + 68..69 'x': impl Trait + 91..102 '{ loop {} }': T + 93..100 'loop {}': ! + 98..100 '{}': () + 171..182 '{ loop {} }': T + 173..180 'loop {}': ! + 178..180 '{}': () + 213..309 '{ ...t()) }': S<{unknown}> + 223..225 's1': S + 228..229 'S': S(u32) -> S + 228..240 'S(default())': S + 230..237 'default': fn default() -> u32 + 230..239 'default()': u32 + 246..249 'foo': fn foo(S) + 246..253 'foo(s1)': () + 250..252 's1': S + 263..264 'x': i32 + 272..275 'bar': fn bar(S) -> i32 + 272..289 'bar(S(...lt()))': i32 + 276..277 'S': S(i32) -> S + 276..288 'S(default())': S + 278..285 'default': fn default() -> i32 + 278..287 'default()': i32 + 295..296 'S': S<{unknown}>({unknown}) -> S<{unknown}> + 295..307 'S(default())': S<{unknown}> + 297..304 'default': fn default<{unknown}>() -> {unknown} + 297..306 'default()': {unknown} + "#]], + ); +} + +#[test] +fn assoc_types_from_bounds() { + check_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; }); + } + "#, + expect![[r#" + 133..135 '_v': F + 178..181 '{ }': () + 193..224 '{ ... }); }': () + 199..209 'f::<(), _>': fn f<(), |&()| -> ()>(|&()| -> ()) + 199..221 'f::<()... z; })': () + 210..220 '|z| { z; }': |&()| -> () + 211..212 'z': &() + 214..220 '{ z; }': () + 216..217 'z': &() + "#]], + ); +} + +#[test] +fn associated_type_bound() { + check_types( + r#" +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(); +} //^ u32 +"#, + ); +} + +#[test] +fn dyn_trait_through_chalk() { + check_types( + r#" +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(); +} //^ () +"#, + ); +} + +#[test] +fn string_to_owned() { + check_types( + r#" +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(); +} //^ String +"#, + ); +} + +#[test] +fn iterator_chain() { + check_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; }); + } + "#, + expect![[r#" + 226..230 'self': Self + 232..233 'f': F + 317..328 '{ loop {} }': FilterMap + 319..326 'loop {}': ! + 324..326 '{}': () + 349..353 'self': Self + 355..356 'f': F + 405..416 '{ loop {} }': () + 407..414 'loop {}': ! + 412..414 '{}': () + 525..529 'self': Self + 854..858 'self': I + 865..885 '{ ... }': I + 875..879 'self': I + 944..955 '{ loop {} }': Vec + 946..953 'loop {}': ! + 951..953 '{}': () + 1142..1269 '{ ... }); }': () + 1148..1163 'Vec::::new': fn new() -> Vec + 1148..1165 'Vec::<...:new()': Vec + 1148..1177 'Vec::<...iter()': IntoIter + 1148..1240 'Vec::<...one })': FilterMap, |i32| -> Option> + 1148..1266 'Vec::<... y; })': () + 1194..1239 '|x| if...None }': |i32| -> Option + 1195..1196 'x': i32 + 1198..1239 'if x >...None }': Option + 1201..1202 'x': i32 + 1201..1206 'x > 0': bool + 1205..1206 '0': i32 + 1207..1225 '{ Some...u32) }': Option + 1209..1213 'Some': Some(u32) -> Option + 1209..1223 'Some(x as u32)': Option + 1214..1215 'x': i32 + 1214..1222 'x as u32': u32 + 1231..1239 '{ None }': Option + 1233..1237 'None': Option + 1255..1265 '|y| { y; }': |u32| -> () + 1256..1257 'y': u32 + 1259..1265 '{ y; }': () + 1261..1262 'y': u32 + "#]], + ); +} + +#[test] +fn nested_assoc() { + check_types( + r#" +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(); +} //^ Foo +"#, + ); +} + +#[test] +fn trait_object_no_coercion() { + check_infer_with_mismatches( + r#" + trait Foo {} + + fn foo(x: &dyn Foo) {} + + fn test(x: &dyn Foo) { + foo(x); + } + "#, + expect![[r#" + 21..22 'x': &dyn Foo + 34..36 '{}': () + 46..47 'x': &dyn Foo + 59..74 '{ foo(x); }': () + 65..68 'foo': fn foo(&dyn Foo) + 65..71 'foo(x)': () + 69..70 'x': &dyn Foo + "#]], + ); +} + +#[test] +fn builtin_copy() { + check_infer_with_mismatches( + r#" + #[lang = "copy"] + trait Copy {} + + struct IsCopy; + impl Copy for IsCopy {} + struct NotCopy; + + trait Test { fn test(&self) -> bool; } + impl Test for T {} + + fn test() { + IsCopy.test(); + NotCopy.test(); + (IsCopy, IsCopy).test(); + (IsCopy, NotCopy).test(); + } + "#, + expect![[r#" + 110..114 'self': &Self + 166..267 '{ ...t(); }': () + 172..178 'IsCopy': IsCopy + 172..185 'IsCopy.test()': bool + 191..198 'NotCopy': NotCopy + 191..205 'NotCopy.test()': {unknown} + 211..227 '(IsCop...sCopy)': (IsCopy, IsCopy) + 211..234 '(IsCop...test()': bool + 212..218 'IsCopy': IsCopy + 220..226 'IsCopy': IsCopy + 240..257 '(IsCop...tCopy)': (IsCopy, NotCopy) + 240..264 '(IsCop...test()': {unknown} + 241..247 'IsCopy': IsCopy + 249..256 'NotCopy': NotCopy + "#]], + ); +} + +#[test] +fn builtin_fn_def_copy() { + check_infer_with_mismatches( + r#" + #[lang = "copy"] + trait Copy {} + + fn foo() {} + fn bar(T) -> T {} + struct Struct(usize); + enum Enum { Variant(usize) } + + trait Test { fn test(&self) -> bool; } + impl Test for T {} + + fn test() { + foo.test(); + bar.test(); + Struct.test(); + Enum::Variant.test(); + } + "#, + expect![[r#" + 41..43 '{}': () + 60..61 'T': {unknown} + 68..70 '{}': () + 68..70: expected T, got () + 145..149 'self': &Self + 201..281 '{ ...t(); }': () + 207..210 'foo': fn foo() + 207..217 'foo.test()': bool + 223..226 'bar': fn bar<{unknown}>({unknown}) -> {unknown} + 223..233 'bar.test()': bool + 239..245 'Struct': Struct(usize) -> Struct + 239..252 'Struct.test()': bool + 258..271 'Enum::Variant': Variant(usize) -> Enum + 258..278 'Enum::...test()': bool + "#]], + ); +} + +#[test] +fn builtin_fn_ptr_copy() { + check_infer_with_mismatches( + r#" + #[lang = "copy"] + trait Copy {} + + trait Test { fn test(&self) -> bool; } + impl Test for T {} + + fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) { + f1.test(); + f2.test(); + f3.test(); + } + "#, + expect![[r#" + 54..58 'self': &Self + 108..110 'f1': fn() + 118..120 'f2': fn(usize) -> u8 + 139..141 'f3': fn(u8, u8) -> &u8 + 162..210 '{ ...t(); }': () + 168..170 'f1': fn() + 168..177 'f1.test()': bool + 183..185 'f2': fn(usize) -> u8 + 183..192 'f2.test()': bool + 198..200 'f3': fn(u8, u8) -> &u8 + 198..207 'f3.test()': bool + "#]], + ); +} + +#[test] +fn builtin_sized() { + check_infer_with_mismatches( + r#" + #[lang = "sized"] + trait Sized {} + + trait Test { fn test(&self) -> bool; } + impl Test for T {} + + fn test() { + 1u8.test(); + (*"foo").test(); // not Sized + (1u8, 1u8).test(); + (1u8, *"foo").test(); // not Sized + } + "#, + expect![[r#" + 56..60 'self': &Self + 113..228 '{ ...ized }': () + 119..122 '1u8': u8 + 119..129 '1u8.test()': bool + 135..150 '(*"foo").test()': {unknown} + 136..142 '*"foo"': str + 137..142 '"foo"': &str + 169..179 '(1u8, 1u8)': (u8, u8) + 169..186 '(1u8, ...test()': bool + 170..173 '1u8': u8 + 175..178 '1u8': u8 + 192..205 '(1u8, *"foo")': (u8, str) + 192..212 '(1u8, ...test()': {unknown} + 193..196 '1u8': u8 + 198..204 '*"foo"': str + 199..204 '"foo"': &str + "#]], + ); +} + +#[test] +fn integer_range_iterate() { + check_types( + r#" +//- /main.rs crate:main deps:core +fn test() { + for x in 0..100 { x; } +} //^ i32 + +//- /core.rs crate:core +pub mod ops { + pub struct Range { + pub start: Idx, + pub end: Idx, + } +} + +pub mod iter { + pub trait Iterator { + type Item; + } + + pub trait IntoIterator { + type Item; + type IntoIter: Iterator; + } + + impl IntoIterator for T where T: Iterator { + type Item = ::Item; + type IntoIter = Self; + } +} + +trait Step {} +impl Step for i32 {} +impl Step for i64 {} + +impl iter::Iterator for ops::Range { + type Item = A; +} +"#, + ); +} + +#[test] +fn infer_closure_arg() { + check_infer( + r#" + //- /lib.rs + + enum Option { + None, + Some(T) + } + + fn foo() { + let s = Option::None; + let f = |x: Option| {}; + (&f)(s) + } + "#, + expect![[r#" + 52..126 '{ ...)(s) }': () + 62..63 's': Option + 66..78 'Option::None': Option + 88..89 'f': |Option| -> () + 92..111 '|x: Op...2>| {}': |Option| -> () + 93..94 'x': Option + 109..111 '{}': () + 117..124 '(&f)(s)': () + 118..120 '&f': &|Option| -> () + 119..120 'f': |Option| -> () + 122..123 's': Option + "#]], + ); +} + +#[test] +fn infer_fn_trait_arg() { + check_infer( + r#" + //- /lib.rs deps:std + + #[lang = "fn_once"] + pub trait FnOnce { + type Output; + + extern "rust-call" fn call_once(&self, args: Args) -> Self::Output; + } + + #[lang = "fn"] + pub trait Fn:FnOnce { + extern "rust-call" fn call(&self, args: Args) -> Self::Output; + } + + enum Option { + None, + Some(T) + } + + fn foo(f: F) -> T + where + F: Fn(Option) -> T, + { + let s = None; + f(s) + } + "#, + expect![[r#" + 101..105 'self': &Self + 107..111 'args': Args + 220..224 'self': &Self + 226..230 'args': Args + 313..314 'f': F + 359..389 '{ ...f(s) }': T + 369..370 's': Option + 373..377 'None': Option + 383..384 'f': F + 383..387 'f(s)': T + 385..386 's': Option + "#]], + ); +} + +#[test] +fn infer_box_fn_arg() { + check_infer( + r#" + //- /lib.rs deps:std + + #[lang = "fn_once"] + pub trait FnOnce { + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; + } + + #[lang = "deref"] + pub trait Deref { + type Target: ?Sized; + + fn deref(&self) -> &Self::Target; + } + + #[lang = "owned_box"] + pub struct Box { + inner: *mut T, + } + + impl Deref for Box { + type Target = T; + + fn deref(&self) -> &T { + &self.inner + } + } + + enum Option { + None, + Some(T) + } + + fn foo() { + let s = Option::None; + let f: Box)> = box (|ps| {}); + f(&s) + } + "#, + expect![[r#" + 100..104 'self': Self + 106..110 'args': Args + 214..218 'self': &Self + 384..388 'self': &Box + 396..423 '{ ... }': &T + 406..417 '&self.inner': &*mut T + 407..411 'self': &Box + 407..417 'self.inner': *mut T + 478..575 '{ ...(&s) }': FnOnce::Output,)>, (&Option,)> + 488..489 's': Option + 492..504 'Option::None': Option + 514..515 'f': Box,)>> + 549..562 'box (|ps| {})': Box<|{unknown}| -> ()> + 554..561 '|ps| {}': |{unknown}| -> () + 555..557 'ps': {unknown} + 559..561 '{}': () + 568..569 'f': Box,)>> + 568..573 'f(&s)': FnOnce::Output,)>, (&Option,)> + 570..572 '&s': &Option + 571..572 's': Option + "#]], + ); +} + +#[test] +fn infer_dyn_fn_output() { + check_types( + r#" +#[lang = "fn_once"] +pub trait FnOnce { + type Output; + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +#[lang = "fn"] +pub trait Fn: FnOnce { + extern "rust-call" fn call(&self, args: Args) -> Self::Output; +} + +fn foo() { + let f: &dyn Fn() -> i32; + f(); + //^^^ i32 +}"#, + ); +} + +#[test] +fn infer_dyn_fn_once_output() { + check_types( + r#" +#[lang = "fn_once"] +pub trait FnOnce { + type Output; + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +fn foo() { + let f: dyn FnOnce() -> i32; + f(); + //^^^ i32 +}"#, + ); +} + +#[test] +fn variable_kinds_1() { + check_types( + r#" +trait Trait { fn get(self, t: T) -> T; } +struct S; +impl Trait for S {} +impl Trait for S {} +fn test() { + S.get(1); + //^^^^^^^^ u128 + S.get(1.); + //^^^^^^^^ f32 +} + "#, + ); +} + +#[test] +fn variable_kinds_2() { + check_types( + r#" +trait Trait { fn get(self) -> Self; } +impl Trait for u128 {} +impl Trait for f32 {} +fn test() { + 1.get(); + //^^^^^^^ u128 + (1.).get(); + //^^^^^^^^^^ f32 +} + "#, + ); +} + +#[test] +fn underscore_import() { + check_types( + r#" +mod tr { + pub trait Tr { + fn method(&self) -> u8 { 0 } + } +} + +struct Tr; +impl crate::tr::Tr for Tr {} + +use crate::tr::Tr as _; +fn test() { + Tr.method(); + //^^^^^^^^^^^ u8 +} + "#, + ); +} -- cgit v1.2.3 From b0fd3faf36c94c3fc52151c6aa82b36b43b7cceb Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 21 Aug 2020 13:19:31 +0200 Subject: Switch to expect_test from crates.io --- crates/hir_ty/src/tests/traits.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/hir_ty/src/tests/traits.rs') diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 526e61caf..1f1056962 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs @@ -1,4 +1,4 @@ -use expect::expect; +use expect_test::expect; use test_utils::mark; use super::{check_infer, check_infer_with_mismatches, check_types}; -- cgit v1.2.3