mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-08 19:28:54 +00:00
2604 lines
48 KiB
Rust
2604 lines
48 KiB
Rust
use insta::assert_snapshot;
|
|
use ra_db::fixture::WithFixture;
|
|
use test_utils::mark;
|
|
|
|
use crate::test_db::TestDB;
|
|
|
|
use super::{infer, infer_with_mismatches, type_at, type_at_pos};
|
|
|
|
#[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<Output = u64>", 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<i32, u64> = 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<O, E> {
|
|
Ok(O),
|
|
Err(E)
|
|
}
|
|
|
|
impl<O, E> crate::ops::Try for Result<O, E> {
|
|
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<T> {}
|
|
impl<T> Vec<T> {
|
|
fn new() -> Self { Vec {} }
|
|
fn push(&mut self, t: T) { }
|
|
}
|
|
|
|
impl<T> crate::iter::IntoIterator for Vec<T> {
|
|
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<T> {}
|
|
struct S<T>(T);
|
|
impl<U> Trait<U> for S<U> {}
|
|
fn foo<T: Trait<u32>>(t: T) {}
|
|
fn test() {
|
|
let s = S(unknown);
|
|
foo(s);
|
|
}
|
|
"#),
|
|
@r###"
|
|
86..87 't': T
|
|
92..94 '{}': ()
|
|
105..144 '{ ...(s); }': ()
|
|
115..116 's': S<u32>
|
|
119..120 'S': S<u32>(u32) -> S<u32>
|
|
119..129 'S(unknown)': S<u32>
|
|
121..128 'unknown': u32
|
|
135..138 'foo': fn foo<S<u32>>(S<u32>)
|
|
135..141 'foo(s)': ()
|
|
139..140 's': S<u32>
|
|
"###
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn infer_from_bound_2() {
|
|
assert_snapshot!(
|
|
infer(r#"
|
|
trait Trait<T> {}
|
|
struct S<T>(T);
|
|
impl<U> Trait<U> for S<U> {}
|
|
fn foo<U, T: Trait<U>>(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<u32>
|
|
125..126 'S': S<u32>(u32) -> S<u32>
|
|
125..135 'S(unknown)': S<u32>
|
|
127..134 'unknown': u32
|
|
145..146 'x': u32
|
|
154..157 'foo': fn foo<u32, S<u32>>(S<u32>) -> u32
|
|
154..160 'foo(s)': u32
|
|
158..159 's': S<u32>
|
|
"###
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn trait_default_method_self_bound_implements_trait() {
|
|
mark::check!(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() {
|
|
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<T: Iterable>() {
|
|
let x: <S as Iterable>::Item = 1;
|
|
let y: <T as Iterable>::Item = no_matter;
|
|
let z: T::Item = no_matter;
|
|
let a: <T>::Item = no_matter;
|
|
}
|
|
"#),
|
|
@r###"
|
|
108..261 '{ ...ter; }': ()
|
|
118..119 'x': u32
|
|
145..146 '1': u32
|
|
156..157 'y': Iterable::Item<T>
|
|
183..192 'no_matter': Iterable::Item<T>
|
|
202..203 'z': Iterable::Item<T>
|
|
215..224 'no_matter': Iterable::Item<T>
|
|
234..235 'a': Iterable::Item<T>
|
|
249..258 'no_matter': Iterable::Item<T>
|
|
"###
|
|
);
|
|
}
|
|
|
|
#[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: Iterable>(t: T) -> T::Item {}
|
|
fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {}
|
|
fn foo3<T: Iterable>(t: 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>(S) -> <S as Iterable>::Item
|
|
248..255 'foo1(S)': u32
|
|
253..254 'S': S
|
|
265..266 'y': u32
|
|
269..273 'foo2': fn foo2<S>(S) -> <S as Iterable>::Item
|
|
269..276 'foo2(S)': u32
|
|
274..275 'S': S
|
|
286..287 'z': u32
|
|
290..294 'foo3': fn foo3<S>(S) -> <S as Iterable>::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<T: Iterable<Item=u32>>() {
|
|
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<u32> 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<Idx> {
|
|
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<T> ops::Index<u32> for [T] {
|
|
type Output = T;
|
|
}
|
|
|
|
#[prelude_import] use ops::*;
|
|
mod ops {
|
|
#[lang = "index"]
|
|
pub trait Index<Idx> {
|
|
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<T>;
|
|
impl<T> Deref for Arc<T> {
|
|
type Target = T;
|
|
}
|
|
|
|
struct S;
|
|
impl S {
|
|
fn foo(&self) -> u128 {}
|
|
}
|
|
|
|
fn test(s: Arc<S>) {
|
|
(*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<T>;
|
|
fn new_arc<T>() -> Arc<T> {}
|
|
impl<T> Deref for Arc<T> {
|
|
type Target = T;
|
|
}
|
|
|
|
struct S;
|
|
fn foo(a: Arc<S>) {}
|
|
|
|
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<T>;
|
|
impl<T> Deref for Arc<T> {
|
|
type Target = T;
|
|
}
|
|
|
|
struct S;
|
|
impl S {
|
|
fn foo(&self) -> u128 {}
|
|
}
|
|
|
|
fn test(s: Arc<S>) {
|
|
(*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<T> {}
|
|
impl Trait<u32> for S {}
|
|
|
|
fn foo<T: Trait<U>, 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<T> {}
|
|
impl Trait<isize> for S {}
|
|
|
|
struct O;
|
|
impl O {
|
|
fn foo<T: Trait<U>, 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<T> {}
|
|
impl Trait<i64> for S {}
|
|
|
|
impl S {
|
|
fn foo<U>(&self) -> U where Self: Trait<U> {}
|
|
}
|
|
|
|
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<T> {}
|
|
impl Trait<&str> for S {}
|
|
|
|
struct O<T>;
|
|
impl<U, T: Trait<U>> O<T> {
|
|
fn foo(&self) -> U {}
|
|
}
|
|
|
|
fn test(o: O<S>) {
|
|
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<T> Trait for T where T: Clone {}
|
|
fn test<T: Clone>(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<T> Trait for T where T: Clone {}
|
|
fn test<T>(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: Trait>(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) { 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<T> Deref for T where T: Trait {
|
|
type Target = i128;
|
|
}
|
|
fn test<T: Trait>(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<T>;
|
|
|
|
impl<T> ApplyL for RefMutL<T> {
|
|
type Out = <T as ApplyL>::Out;
|
|
}
|
|
|
|
fn test<T: ApplyL>() {
|
|
let y: <RefMutL<T> as ApplyL>::Out = no_matter;
|
|
y<|>;
|
|
}
|
|
"#,
|
|
);
|
|
// inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types].
|
|
assert_eq!(t, "ApplyL::Out<T>");
|
|
}
|
|
|
|
#[test]
|
|
fn associated_type_placeholder_2() {
|
|
let t = type_at(
|
|
r#"
|
|
//- /main.rs
|
|
pub trait ApplyL {
|
|
type Out;
|
|
}
|
|
fn foo<T: ApplyL>(t: T) -> <T as ApplyL>::Out;
|
|
|
|
fn test<T: ApplyL>(t: T) {
|
|
let y = foo(t);
|
|
y<|>;
|
|
}
|
|
"#,
|
|
);
|
|
assert_eq!(t, "ApplyL::Out<T>");
|
|
}
|
|
|
|
#[test]
|
|
fn argument_impl_trait() {
|
|
assert_snapshot!(
|
|
infer_with_mismatches(r#"
|
|
trait Trait<T> {
|
|
fn foo(&self) -> T;
|
|
fn foo2(&self) -> i64;
|
|
}
|
|
fn bar(x: impl Trait<u16>) {}
|
|
struct S<T>(T);
|
|
impl<T> Trait<T> for S<T> {}
|
|
|
|
fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
|
|
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<u16>
|
|
98..100 '{}': ()
|
|
155..156 'x': impl Trait<u64>
|
|
175..176 'y': &impl Trait<u32>
|
|
196..324 '{ ...2(); }': ()
|
|
202..203 'x': impl Trait<u64>
|
|
209..210 'y': &impl Trait<u32>
|
|
220..221 'z': S<u16>
|
|
224..225 'S': S<u16>(u16) -> S<u16>
|
|
224..228 'S(1)': S<u16>
|
|
226..227 '1': u16
|
|
234..237 'bar': fn bar(S<u16>)
|
|
234..240 'bar(z)': ()
|
|
238..239 'z': S<u16>
|
|
246..247 'x': impl Trait<u64>
|
|
246..253 'x.foo()': u64
|
|
259..260 'y': &impl Trait<u32>
|
|
259..266 'y.foo()': u32
|
|
272..273 'z': S<u16>
|
|
272..279 'z.foo()': u16
|
|
285..286 'x': impl Trait<u64>
|
|
285..293 'x.foo2()': i64
|
|
299..300 'y': &impl Trait<u32>
|
|
299..307 'y.foo2()': i64
|
|
313..314 'z': S<u16>
|
|
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<T>(x: impl Trait) -> T { loop {} }
|
|
}
|
|
fn foo<T>(x: impl Trait) -> T { loop {} }
|
|
struct S;
|
|
impl Trait for S {}
|
|
struct F;
|
|
impl Foo for F {}
|
|
|
|
fn test() {
|
|
Foo::bar(S);
|
|
<F as Foo>::bar(S);
|
|
F::bar(S);
|
|
Foo::bar::<u32>(S);
|
|
<F as Foo>::bar::<u32>(S);
|
|
|
|
foo(S);
|
|
foo::<u32>(S);
|
|
foo::<u32, i32>(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 '<F as Foo>::bar': fn bar<F, {unknown}>(S) -> {unknown}
|
|
324..342 '<F as ...bar(S)': {unknown}
|
|
340..341 'S': S
|
|
348..354 'F::bar': fn bar<F, {unknown}>(S) -> {unknown}
|
|
348..357 'F::bar(S)': {unknown}
|
|
355..356 'S': S
|
|
363..378 'Foo::bar::<u32>': fn bar<{unknown}, u32>(S) -> u32
|
|
363..381 'Foo::b...32>(S)': u32
|
|
379..380 'S': S
|
|
387..409 '<F as ...:<u32>': fn bar<F, u32>(S) -> u32
|
|
387..412 '<F as ...32>(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::<u32>': fn foo<u32>(S) -> u32
|
|
431..444 'foo::<u32>(S)': u32
|
|
442..443 'S': S
|
|
450..465 'foo::<u32, i32>': fn foo<u32>(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<T>;
|
|
impl<T> F<T> {
|
|
fn foo<U>(self, x: impl Trait) -> (T, U) { loop {} }
|
|
}
|
|
|
|
fn test() {
|
|
F.foo(S);
|
|
F::<u32>.foo(S);
|
|
F::<u32>.foo::<i32>(S);
|
|
F::<u32>.foo::<i32, u32>(S); // extraneous argument should be ignored
|
|
}
|
|
"#, true),
|
|
@r###"
|
|
88..92 'self': F<T>
|
|
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::<u32>': F<u32>
|
|
164..179 'F::<u32>.foo(S)': (u32, {unknown})
|
|
177..178 'S': S
|
|
185..193 'F::<u32>': F<u32>
|
|
185..207 'F::<u3...32>(S)': (u32, i32)
|
|
205..206 'S': S
|
|
213..221 'F::<u32>': F<u32>
|
|
213..240 'F::<u3...32>(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<T> {
|
|
fn foo(&self) -> T;
|
|
fn foo2(&self) -> i64;
|
|
}
|
|
fn bar() -> impl Trait<u64> {}
|
|
|
|
fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
|
|
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<u64>
|
|
131..132 'y': &impl Trait<u64>
|
|
152..269 '{ ...2(); }': ()
|
|
158..159 'x': impl Trait<u64>
|
|
165..166 'y': &impl Trait<u64>
|
|
176..177 'z': impl Trait<u64>
|
|
180..183 'bar': fn bar() -> impl Trait<u64>
|
|
180..185 'bar()': impl Trait<u64>
|
|
191..192 'x': impl Trait<u64>
|
|
191..198 'x.foo()': u64
|
|
204..205 'y': &impl Trait<u64>
|
|
204..211 'y.foo()': u64
|
|
217..218 'z': impl Trait<u64>
|
|
217..224 'z.foo()': u64
|
|
230..231 'x': impl Trait<u64>
|
|
230..238 'x.foo2()': i64
|
|
244..245 'y': &impl Trait<u64>
|
|
244..252 'y.foo2()': i64
|
|
258..259 'z': impl Trait<u64>
|
|
258..266 'z.foo2()': i64
|
|
"###
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn dyn_trait() {
|
|
assert_snapshot!(
|
|
infer(r#"
|
|
trait Trait<T> {
|
|
fn foo(&self) -> T;
|
|
fn foo2(&self) -> i64;
|
|
}
|
|
fn bar() -> dyn Trait<u64> {}
|
|
|
|
fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) {
|
|
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<u64>
|
|
129..130 'y': &dyn Trait<u64>
|
|
149..266 '{ ...2(); }': ()
|
|
155..156 'x': dyn Trait<u64>
|
|
162..163 'y': &dyn Trait<u64>
|
|
173..174 'z': dyn Trait<u64>
|
|
177..180 'bar': fn bar() -> dyn Trait<u64>
|
|
177..182 'bar()': dyn Trait<u64>
|
|
188..189 'x': dyn Trait<u64>
|
|
188..195 'x.foo()': u64
|
|
201..202 'y': &dyn Trait<u64>
|
|
201..208 'y.foo()': u64
|
|
214..215 'z': dyn Trait<u64>
|
|
214..221 'z.foo()': u64
|
|
227..228 'x': dyn Trait<u64>
|
|
227..235 'x.foo2()': i64
|
|
241..242 'y': &dyn Trait<u64>
|
|
241..249 'y.foo2()': i64
|
|
255..256 'z': dyn Trait<u64>
|
|
255..263 'z.foo2()': i64
|
|
"###
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn dyn_trait_in_impl() {
|
|
assert_snapshot!(
|
|
infer(r#"
|
|
trait Trait<T, U> {
|
|
fn foo(&self) -> (T, U);
|
|
}
|
|
struct S<T, U> {}
|
|
impl<T, U> S<T, U> {
|
|
fn bar(&self) -> &dyn Trait<T, U> { loop {} }
|
|
}
|
|
trait Trait2<T, U> {
|
|
fn baz(&self) -> (T, U);
|
|
}
|
|
impl<T, U> Trait2<T, U> for dyn Trait<T, U> { }
|
|
|
|
fn test(s: S<u32, i32>) {
|
|
s.bar().baz();
|
|
}
|
|
"#),
|
|
@r###"
|
|
33..37 'self': &Self
|
|
103..107 'self': &S<T, U>
|
|
129..140 '{ loop {} }': &dyn Trait<T, U>
|
|
131..138 'loop {}': !
|
|
136..138 '{}': ()
|
|
176..180 'self': &Self
|
|
252..253 's': S<u32, i32>
|
|
268..290 '{ ...z(); }': ()
|
|
274..275 's': S<u32, i32>
|
|
274..281 's.bar()': &dyn Trait<u32, i32>
|
|
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: Trait>(t: T) -> <T as Trait>::Type {}
|
|
fn get2<U, T: Trait<Type = U>>(t: T) -> U {}
|
|
fn set<T: Trait<Type = u64>>(t: T) -> T {t}
|
|
|
|
struct S<T>;
|
|
impl<T> Trait for S<T> { type Type = T; }
|
|
|
|
fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) {
|
|
get(x);
|
|
get2(x);
|
|
get(y);
|
|
get2(y);
|
|
get(set(S));
|
|
get2(set(S));
|
|
get2(S::<str>);
|
|
}
|
|
"#),
|
|
@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<Type = i64>
|
|
290..398 '{ ...r>); }': ()
|
|
296..299 'get': fn get<T>(T) -> <T as Trait>::Type
|
|
296..302 'get(x)': u32
|
|
300..301 'x': T
|
|
308..312 'get2': fn get2<u32, T>(T) -> u32
|
|
308..315 'get2(x)': u32
|
|
313..314 'x': T
|
|
321..324 'get': fn get<impl Trait<Type = i64>>(impl Trait<Type = i64>) -> <impl Trait<Type = i64> as Trait>::Type
|
|
321..327 'get(y)': i64
|
|
325..326 'y': impl Trait<Type = i64>
|
|
333..337 'get2': fn get2<i64, impl Trait<Type = i64>>(impl Trait<Type = i64>) -> i64
|
|
333..340 'get2(y)': i64
|
|
338..339 'y': impl Trait<Type = i64>
|
|
346..349 'get': fn get<S<u64>>(S<u64>) -> <S<u64> as Trait>::Type
|
|
346..357 'get(set(S))': u64
|
|
350..353 'set': fn set<S<u64>>(S<u64>) -> S<u64>
|
|
350..356 'set(S)': S<u64>
|
|
354..355 'S': S<u64>
|
|
363..367 'get2': fn get2<u64, S<u64>>(S<u64>) -> u64
|
|
363..375 'get2(set(S))': u64
|
|
368..371 'set': fn set<S<u64>>(S<u64>) -> S<u64>
|
|
368..374 'set(S)': S<u64>
|
|
372..373 'S': S<u64>
|
|
381..385 'get2': fn get2<str, S<str>>(S<str>) -> str
|
|
381..395 'get2(S::<str>)': str
|
|
386..394 'S::<str>': S<str>
|
|
"###
|
|
);
|
|
}
|
|
|
|
#[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<L> {}
|
|
fn foo() -> impl Iterator<Item = SyntaxNode<RustLanguage>> {}
|
|
|
|
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<T: Iterator> IntoIterator for T {
|
|
type Item = <T as Iterator>::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<T> {
|
|
fn foo(self) -> T;
|
|
}
|
|
impl<T, U> Trait2<T> for U where U: Trait1<Type = T> {}
|
|
|
|
fn test<T: Trait1<Type = u32>>(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<T: foo::Trait>(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<T: Trait1, U: Trait2>(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<T: A>(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<U, T: Trait<Type = U>>(t: T) -> U {}
|
|
fn set<T: Trait<Type = u64>>(t: T) -> T {t}
|
|
|
|
struct S<T>;
|
|
impl<T> SuperTrait for S<T> { type Type = T; }
|
|
impl<T> Trait for S<T> {}
|
|
|
|
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<u64, S<u64>>(S<u64>) -> u64
|
|
265..277 'get2(set(S))': u64
|
|
270..273 'set': fn set<S<u64>>(S<u64>) -> S<u64>
|
|
270..276 'set(S)': S<u64>
|
|
274..275 'S': S<u64>
|
|
"###
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn fn_trait() {
|
|
assert_snapshot!(
|
|
infer(r#"
|
|
trait FnOnce<Args> {
|
|
type Output;
|
|
|
|
fn call_once(self, args: Args) -> <Self as FnOnce<Args>>::Output;
|
|
}
|
|
|
|
fn test<F: FnOnce(u32, u64) -> 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 fn_ptr_and_item() {
|
|
assert_snapshot!(
|
|
infer(r#"
|
|
#[lang="fn_once"]
|
|
trait FnOnce<Args> {
|
|
type Output;
|
|
|
|
fn call_once(self, args: Args) -> Self::Output;
|
|
}
|
|
|
|
trait Foo<T> {
|
|
fn foo(&self) -> T;
|
|
}
|
|
|
|
struct Bar<T>(T);
|
|
|
|
impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> {
|
|
fn foo(&self) -> (A1, R) {}
|
|
}
|
|
|
|
enum Opt<T> { None, Some(T) }
|
|
impl<T> Opt<T> {
|
|
fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> {}
|
|
}
|
|
|
|
fn test() {
|
|
let bar: Bar<fn(u8) -> u32>;
|
|
bar.foo();
|
|
|
|
let opt: Opt<u8>;
|
|
let f: fn(u8) -> u32;
|
|
opt.map(f);
|
|
}
|
|
"#),
|
|
@r###"
|
|
75..79 'self': Self
|
|
81..85 'args': Args
|
|
140..144 'self': &Self
|
|
244..248 'self': &Bar<F>
|
|
261..263 '{}': ()
|
|
347..351 'self': Opt<T>
|
|
353..354 'f': F
|
|
369..371 '{}': ()
|
|
385..501 '{ ...(f); }': ()
|
|
395..398 'bar': Bar<fn(u8) -> u32>
|
|
424..427 'bar': Bar<fn(u8) -> u32>
|
|
424..433 'bar.foo()': {unknown}
|
|
444..447 'opt': Opt<u8>
|
|
466..467 'f': fn(u8) -> u32
|
|
488..491 'opt': Opt<u8>
|
|
488..498 'opt.map(f)': Opt<FnOnce::Output<fn(u8) -> u32, (u8,)>>
|
|
496..497 'f': fn(u8) -> u32
|
|
"###
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn fn_trait_deref_with_ty_default() {
|
|
assert_snapshot!(
|
|
infer(r#"
|
|
#[lang = "deref"]
|
|
trait Deref {
|
|
type Target;
|
|
|
|
fn deref(&self) -> &Self::Target;
|
|
}
|
|
|
|
#[lang="fn_once"]
|
|
trait FnOnce<Args> {
|
|
type Output;
|
|
|
|
fn call_once(self, args: Args) -> Self::Output;
|
|
}
|
|
|
|
struct Foo;
|
|
|
|
impl Foo {
|
|
fn foo(&self) -> usize {}
|
|
}
|
|
|
|
struct Lazy<T, F = fn() -> T>(F);
|
|
|
|
impl<T, F> Lazy<T, F> {
|
|
pub fn new(f: F) -> Lazy<T, F> {}
|
|
}
|
|
|
|
impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
|
|
type Target = T;
|
|
}
|
|
|
|
fn test() {
|
|
let lazy1: Lazy<Foo, _> = 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<Foo, _> = Lazy::new(make_foo_fn_ptr);
|
|
let r2 = lazy2.foo();
|
|
}
|
|
"#),
|
|
@r###"
|
|
65..69 'self': &Self
|
|
166..170 'self': Self
|
|
172..176 'args': Args
|
|
240..244 'self': &Foo
|
|
255..257 '{}': ()
|
|
335..336 'f': F
|
|
355..357 '{}': ()
|
|
444..690 '{ ...o(); }': ()
|
|
454..459 'lazy1': Lazy<Foo, fn() -> T>
|
|
476..485 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T>
|
|
476..493 'Lazy::...| Foo)': Lazy<Foo, fn() -> T>
|
|
486..492 '|| Foo': || -> T
|
|
489..492 'Foo': Foo
|
|
503..505 'r1': {unknown}
|
|
508..513 'lazy1': Lazy<Foo, fn() -> T>
|
|
508..519 'lazy1.foo()': {unknown}
|
|
561..576 'make_foo_fn_ptr': fn() -> Foo
|
|
592..603 'make_foo_fn': fn make_foo_fn() -> Foo
|
|
613..618 'lazy2': Lazy<Foo, fn() -> T>
|
|
635..644 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T>
|
|
635..661 'Lazy::...n_ptr)': Lazy<Foo, fn() -> T>
|
|
645..660 'make_foo_fn_ptr': fn() -> Foo
|
|
671..673 'r2': {unknown}
|
|
676..681 'lazy2': Lazy<Foo, fn() -> T>
|
|
676..687 'lazy2.foo()': {unknown}
|
|
550..552 '{}': ()
|
|
"###
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn closure_1() {
|
|
assert_snapshot!(
|
|
infer(r#"
|
|
#[lang = "fn_once"]
|
|
trait FnOnce<Args> {
|
|
type Output;
|
|
}
|
|
|
|
enum Option<T> { Some(T), None }
|
|
impl<T> Option<T> {
|
|
fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {}
|
|
}
|
|
|
|
fn test() {
|
|
let x = Option::Some(1u32);
|
|
x.map(|v| v + 1);
|
|
x.map(|_v| 1u64);
|
|
let y: Option<i64> = x.map(|_v| 1);
|
|
}
|
|
"#),
|
|
@r###"
|
|
148..152 'self': Option<T>
|
|
154..155 'f': F
|
|
173..175 '{}': ()
|
|
189..308 '{ ... 1); }': ()
|
|
199..200 'x': Option<u32>
|
|
203..215 'Option::Some': Some<u32>(u32) -> Option<u32>
|
|
203..221 'Option...(1u32)': Option<u32>
|
|
216..220 '1u32': u32
|
|
227..228 'x': Option<u32>
|
|
227..243 'x.map(...v + 1)': Option<u32>
|
|
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<u32>
|
|
249..265 'x.map(... 1u64)': Option<u64>
|
|
255..264 '|_v| 1u64': |u32| -> u64
|
|
256..258 '_v': u32
|
|
260..264 '1u64': u64
|
|
275..276 'y': Option<i64>
|
|
292..293 'x': Option<u32>
|
|
292..305 'x.map(|_v| 1)': Option<i64>
|
|
298..304 '|_v| 1': |u32| -> i64
|
|
299..301 '_v': u32
|
|
303..304 '1': i64
|
|
"###
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn closure_2() {
|
|
assert_snapshot!(
|
|
infer(r#"
|
|
trait FnOnce<Args> {
|
|
type Output;
|
|
}
|
|
|
|
fn test<F: FnOnce(u32) -> 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<Args> {
|
|
type Output;
|
|
}
|
|
|
|
fn foo1<T, U, F: FnOnce(T) -> U>(x: T, f: F) -> U {}
|
|
fn foo2<T, U, F: FnOnce(T) -> U>(f: F, x: T) -> U {}
|
|
|
|
struct S;
|
|
impl S {
|
|
fn method(self) -> u64;
|
|
|
|
fn foo1<T, U, F: FnOnce(T) -> U>(self, x: T, f: F) -> U {}
|
|
fn foo2<T, U, F: FnOnce(T) -> 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<S, u64, |S| -> 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<S, u64, |S| -> 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<T: Trait>() 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<T> {
|
|
type Item;
|
|
}
|
|
|
|
trait Trait2 {
|
|
fn foo(&self) -> u32;
|
|
}
|
|
|
|
fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, 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: <Self>::Item) { let y = x; }
|
|
}
|
|
"#,
|
|
), @r###"
|
|
54..58 'self': &Self
|
|
60..61 'x': Trait::Item<Self>
|
|
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 unselected_projection_chalk_fold() {
|
|
let t = type_at(
|
|
r#"
|
|
//- /main.rs
|
|
trait Interner {}
|
|
trait Fold<I: Interner, TI = I> {
|
|
type Result;
|
|
}
|
|
|
|
struct Ty<I: Interner> {}
|
|
impl<I: Interner, TI: Interner> Fold<I, TI> for Ty<I> {
|
|
type Result = Ty<TI>;
|
|
}
|
|
|
|
fn fold<I: Interner, T>(interner: &I, t: T) -> T::Result
|
|
where
|
|
T: Fold<I, I>,
|
|
{
|
|
loop {}
|
|
}
|
|
|
|
fn foo<I: Interner>(interner: &I, t: Ty<I>) {
|
|
fold(interner, t)<|>;
|
|
}
|
|
"#,
|
|
);
|
|
assert_eq!(t, "Ty<I>");
|
|
}
|
|
|
|
#[test]
|
|
fn trait_impl_self_ty() {
|
|
let t = type_at(
|
|
r#"
|
|
//- /main.rs
|
|
trait Trait<T> {
|
|
fn foo(&self);
|
|
}
|
|
|
|
struct S;
|
|
|
|
impl Trait<Self> 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<T>;
|
|
|
|
impl Trait for S<Self> {}
|
|
|
|
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<T> {}
|
|
|
|
fn test<T: Trait>() where T: Trait2<T::Item> {
|
|
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<T> {
|
|
type Item;
|
|
}
|
|
|
|
fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> {
|
|
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<T> {
|
|
fn foo(&self) -> T;
|
|
}
|
|
|
|
// workaround for Chalk assoc type normalization problems
|
|
pub struct S<T>;
|
|
impl<T: Iterator> Iterator for S<T> {
|
|
type Item = <T as Iterator>::Item;
|
|
}
|
|
|
|
fn test<I: Iterator<Item: OtherTrait<u32>>>() {
|
|
let x: <S<I> 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<I: Iterator<Item: Iterator<Item = u32>>>() {
|
|
let x: <<I as Iterator>::Item as Iterator>::Item;
|
|
x<|>;
|
|
}
|
|
"#,
|
|
);
|
|
assert_eq!(t, "u32");
|
|
}
|
|
|
|
#[test]
|
|
fn proc_macro_server_types() {
|
|
assert_snapshot!(
|
|
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<S: Types $(+ $name)*> 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>() -> T { loop {} }
|
|
impl TokenStream for Rustc {
|
|
fn new() -> Self::TokenStream {
|
|
let group: Self::Group = make();
|
|
make()
|
|
}
|
|
}
|
|
"#),
|
|
@r###"
|
|
1062..1073 '{ loop {} }': T
|
|
1064..1071 'loop {}': !
|
|
1069..1071 '{}': ()
|
|
1137..1200 '{ ... }': T
|
|
1151..1156 'group': G
|
|
1172..1176 'make': fn make<G>() -> G
|
|
1172..1178 'make()': G
|
|
1188..1192 'make': fn make<T>() -> T
|
|
1188..1194 'make()': T
|
|
"###
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn unify_impl_trait() {
|
|
assert_snapshot!(
|
|
infer_with_mismatches(r#"
|
|
trait Trait<T> {}
|
|
|
|
fn foo(x: impl Trait<u32>) { loop {} }
|
|
fn bar<T>(x: impl Trait<T>) -> T { loop {} }
|
|
|
|
struct S<T>(T);
|
|
impl<T> Trait<T> for S<T> {}
|
|
|
|
fn default<T>() -> T { loop {} }
|
|
|
|
fn test() -> impl Trait<i32> {
|
|
let s1 = S(default());
|
|
foo(s1);
|
|
let x: i32 = bar(S(default()));
|
|
S(default())
|
|
}
|
|
"#, true),
|
|
@r###"
|
|
27..28 'x': impl Trait<u32>
|
|
47..58 '{ loop {} }': ()
|
|
49..56 'loop {}': !
|
|
54..56 '{}': ()
|
|
69..70 'x': impl Trait<T>
|
|
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<u32>
|
|
229..230 'S': S<u32>(u32) -> S<u32>
|
|
229..241 'S(default())': S<u32>
|
|
231..238 'default': fn default<u32>() -> u32
|
|
231..240 'default()': u32
|
|
247..250 'foo': fn foo(S<u32>)
|
|
247..254 'foo(s1)': ()
|
|
251..253 's1': S<u32>
|
|
264..265 'x': i32
|
|
273..276 'bar': fn bar<i32>(S<i32>) -> i32
|
|
273..290 'bar(S(...lt()))': i32
|
|
277..278 'S': S<i32>(i32) -> S<i32>
|
|
277..289 'S(default())': S<i32>
|
|
279..286 'default': fn default<i32>() -> 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<Args> {
|
|
type Output;
|
|
}
|
|
|
|
trait T {
|
|
type O;
|
|
}
|
|
|
|
impl T for () {
|
|
type O = ();
|
|
}
|
|
|
|
fn f<X, 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<u32>;
|
|
}
|
|
pub trait OtherTrait<T> {
|
|
fn foo(&self) -> T;
|
|
}
|
|
|
|
// this is just a workaround for chalk#234
|
|
pub struct S<T>;
|
|
impl<T: Trait> Trait for S<T> {
|
|
type Item = <T as Trait>::Item;
|
|
}
|
|
|
|
fn test<T: Trait>() {
|
|
let y: <S<T> 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<T> {}
|
|
#[lang = "deref"]
|
|
trait Deref {
|
|
type Target;
|
|
}
|
|
impl<T> Deref for Box<T> {
|
|
type Target = T;
|
|
}
|
|
trait Trait {
|
|
fn foo(&self);
|
|
}
|
|
|
|
fn test(x: Box<dyn Trait>) {
|
|
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<Args> {
|
|
type Output;
|
|
}
|
|
#[lang = "fn_mut"]
|
|
trait FnMut<Args>: FnOnce<Args> { }
|
|
|
|
enum Option<T> { Some(T), None }
|
|
use Option::*;
|
|
|
|
pub trait Iterator {
|
|
type Item;
|
|
|
|
fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
|
|
where
|
|
F: FnMut(Self::Item) -> Option<B>,
|
|
{ loop {} }
|
|
|
|
fn for_each<F>(self, f: F)
|
|
where
|
|
F: FnMut(Self::Item),
|
|
{ loop {} }
|
|
}
|
|
|
|
pub trait IntoIterator {
|
|
type Item;
|
|
type IntoIter: Iterator<Item = Self::Item>;
|
|
fn into_iter(self) -> Self::IntoIter;
|
|
}
|
|
|
|
pub struct FilterMap<I, F> { }
|
|
impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
|
|
where
|
|
F: FnMut(I::Item) -> Option<B>,
|
|
{
|
|
type Item = B;
|
|
}
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
impl<I: Iterator> IntoIterator for I {
|
|
type Item = I::Item;
|
|
type IntoIter = I;
|
|
|
|
fn into_iter(self) -> I {
|
|
self
|
|
}
|
|
}
|
|
|
|
struct Vec<T> {}
|
|
impl<T> Vec<T> {
|
|
fn new() -> Self { loop {} }
|
|
}
|
|
|
|
impl<T> IntoIterator for Vec<T> {
|
|
type Item = T;
|
|
type IntoIter = IntoIter<T>;
|
|
}
|
|
|
|
pub struct IntoIter<T> { }
|
|
impl<T> Iterator for IntoIter<T> {
|
|
type Item = T;
|
|
}
|
|
|
|
fn main() {
|
|
Vec::<i32>::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<Self, F>
|
|
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<T>
|
|
960..967 'loop {}': !
|
|
965..967 '{}': ()
|
|
1156..1287 '{ ... }); }': ()
|
|
1162..1177 'Vec::<i32>::new': fn new<i32>() -> Vec<i32>
|
|
1162..1179 'Vec::<...:new()': Vec<i32>
|
|
1162..1191 'Vec::<...iter()': IntoIter<i32>
|
|
1162..1256 'Vec::<...one })': FilterMap<IntoIter<i32>, |i32| -> Option<u32>>
|
|
1162..1284 'Vec::<... y; })': ()
|
|
1210..1255 '|x| if...None }': |i32| -> Option<u32>
|
|
1211..1212 'x': i32
|
|
1214..1255 'if x >...None }': Option<u32>
|
|
1217..1218 'x': i32
|
|
1217..1222 'x > 0': bool
|
|
1221..1222 '0': i32
|
|
1223..1241 '{ Some...u32) }': Option<u32>
|
|
1225..1229 'Some': Some<u32>(u32) -> Option<u32>
|
|
1225..1239 'Some(x as u32)': Option<u32>
|
|
1230..1231 'x': i32
|
|
1230..1238 'x as u32': u32
|
|
1247..1255 '{ None }': Option<u32>
|
|
1249..1253 'None': Option<u32>
|
|
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<T:A> 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
|
|
"###
|
|
);
|
|
}
|