2019-12-05 22:02:31 +00:00
|
|
|
use super::infer_with_mismatches;
|
2019-09-18 16:36:12 +00:00
|
|
|
use insta::assert_snapshot;
|
|
|
|
use test_utils::covers;
|
|
|
|
|
|
|
|
// Infer with some common definitions and impls.
|
|
|
|
fn infer(source: &str) -> String {
|
|
|
|
let defs = r#"
|
|
|
|
#[lang = "sized"]
|
|
|
|
pub trait Sized {}
|
|
|
|
#[lang = "unsize"]
|
|
|
|
pub trait Unsize<T: ?Sized> {}
|
|
|
|
#[lang = "coerce_unsized"]
|
|
|
|
pub trait CoerceUnsized<T> {}
|
|
|
|
|
|
|
|
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
|
|
|
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
|
|
|
|
"#;
|
|
|
|
|
|
|
|
// Append to the end to keep positions unchanged.
|
|
|
|
super::infer(&format!("{}{}", source, defs))
|
|
|
|
}
|
|
|
|
|
2019-09-25 21:56:55 +00:00
|
|
|
#[test]
|
|
|
|
fn infer_block_expr_type_mismatch() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer(r#"
|
|
|
|
fn test() {
|
|
|
|
let a: i32 = { 1i64 };
|
|
|
|
}
|
|
|
|
"#),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
11..41 '{ ...4 }; }': ()
|
|
|
|
21..22 'a': i32
|
|
|
|
30..38 '{ 1i64 }': i64
|
|
|
|
32..36 '1i64': i64
|
2019-09-25 21:56:55 +00:00
|
|
|
"###);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn coerce_places() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer(r#"
|
|
|
|
struct S<T> { a: T }
|
|
|
|
|
|
|
|
fn f<T>(_: &[T]) -> T { loop {} }
|
|
|
|
fn g<T>(_: S<&[T]>) -> T { loop {} }
|
|
|
|
|
|
|
|
fn gen<T>() -> *mut [T; 2] { loop {} }
|
|
|
|
fn test1<U>() -> *mut [U] {
|
|
|
|
gen()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn test2() {
|
|
|
|
let arr: &[u8; 1] = &[1];
|
|
|
|
|
|
|
|
let a: &[_] = arr;
|
|
|
|
let b = f(arr);
|
|
|
|
let c: &[_] = { arr };
|
|
|
|
let d = g(S { a: arr });
|
|
|
|
let e: [&[_]; 1] = [arr];
|
|
|
|
let f: [&[_]; 2] = [arr; 2];
|
|
|
|
let g: (&[_], &[_]) = (arr, arr);
|
|
|
|
}
|
|
|
|
"#),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
31..32 '_': &[T]
|
|
|
|
45..56 '{ loop {} }': T
|
|
|
|
47..54 'loop {}': !
|
|
|
|
52..54 '{}': ()
|
|
|
|
65..66 '_': S<&[T]>
|
|
|
|
82..93 '{ loop {} }': T
|
|
|
|
84..91 'loop {}': !
|
|
|
|
89..91 '{}': ()
|
|
|
|
122..133 '{ loop {} }': *mut [T; _]
|
|
|
|
124..131 'loop {}': !
|
|
|
|
129..131 '{}': ()
|
|
|
|
160..173 '{ gen() }': *mut [U]
|
|
|
|
166..169 'gen': fn gen<U>() -> *mut [U; _]
|
|
|
|
166..171 'gen()': *mut [U; _]
|
|
|
|
186..420 '{ ...rr); }': ()
|
|
|
|
196..199 'arr': &[u8; _]
|
|
|
|
212..216 '&[1]': &[u8; _]
|
|
|
|
213..216 '[1]': [u8; _]
|
|
|
|
214..215 '1': u8
|
|
|
|
227..228 'a': &[u8]
|
|
|
|
237..240 'arr': &[u8; _]
|
|
|
|
250..251 'b': u8
|
|
|
|
254..255 'f': fn f<u8>(&[u8]) -> u8
|
|
|
|
254..260 'f(arr)': u8
|
|
|
|
256..259 'arr': &[u8; _]
|
|
|
|
270..271 'c': &[u8]
|
|
|
|
280..287 '{ arr }': &[u8]
|
|
|
|
282..285 'arr': &[u8; _]
|
|
|
|
297..298 'd': u8
|
|
|
|
301..302 'g': fn g<u8>(S<&[u8]>) -> u8
|
|
|
|
301..316 'g(S { a: arr })': u8
|
|
|
|
303..315 'S { a: arr }': S<&[u8]>
|
|
|
|
310..313 'arr': &[u8; _]
|
|
|
|
326..327 'e': [&[u8]; _]
|
|
|
|
341..346 '[arr]': [&[u8]; _]
|
|
|
|
342..345 'arr': &[u8; _]
|
|
|
|
356..357 'f': [&[u8]; _]
|
|
|
|
371..379 '[arr; 2]': [&[u8]; _]
|
|
|
|
372..375 'arr': &[u8; _]
|
|
|
|
377..378 '2': usize
|
|
|
|
389..390 'g': (&[u8], &[u8])
|
|
|
|
407..417 '(arr, arr)': (&[u8], &[u8])
|
|
|
|
408..411 'arr': &[u8; _]
|
|
|
|
413..416 'arr': &[u8; _]
|
2019-09-25 21:56:55 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-09-18 16:36:12 +00:00
|
|
|
#[test]
|
|
|
|
fn infer_let_stmt_coerce() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer(r#"
|
|
|
|
fn test() {
|
|
|
|
let x: &[i32] = &[1];
|
|
|
|
}
|
|
|
|
"#),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
11..40 '{ ...[1]; }': ()
|
|
|
|
21..22 'x': &[i32]
|
|
|
|
33..37 '&[1]': &[i32; _]
|
|
|
|
34..37 '[1]': [i32; _]
|
|
|
|
35..36 '1': i32
|
2019-09-18 16:36:12 +00:00
|
|
|
"###);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn infer_custom_coerce_unsized() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer(r#"
|
|
|
|
struct A<T: ?Sized>(*const T);
|
|
|
|
struct B<T: ?Sized>(*const T);
|
|
|
|
struct C<T: ?Sized> { inner: *const T }
|
|
|
|
|
|
|
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
|
|
|
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {}
|
|
|
|
|
|
|
|
fn foo1<T>(x: A<[T]>) -> A<[T]> { x }
|
|
|
|
fn foo2<T>(x: B<[T]>) -> B<[T]> { x }
|
|
|
|
fn foo3<T>(x: C<[T]>) -> C<[T]> { x }
|
|
|
|
|
|
|
|
fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) {
|
|
|
|
let d = foo1(a);
|
|
|
|
let e = foo2(b);
|
|
|
|
let f = foo3(c);
|
|
|
|
}
|
|
|
|
"#),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
258..259 'x': A<[T]>
|
|
|
|
279..284 '{ x }': A<[T]>
|
|
|
|
281..282 'x': A<[T]>
|
|
|
|
296..297 'x': B<[T]>
|
|
|
|
317..322 '{ x }': B<[T]>
|
|
|
|
319..320 'x': B<[T]>
|
|
|
|
334..335 'x': C<[T]>
|
|
|
|
355..360 '{ x }': C<[T]>
|
|
|
|
357..358 'x': C<[T]>
|
|
|
|
370..371 'a': A<[u8; _]>
|
|
|
|
385..386 'b': B<[u8; _]>
|
|
|
|
400..401 'c': C<[u8; _]>
|
|
|
|
415..481 '{ ...(c); }': ()
|
|
|
|
425..426 'd': A<[{unknown}]>
|
|
|
|
429..433 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]>
|
|
|
|
429..436 'foo1(a)': A<[{unknown}]>
|
|
|
|
434..435 'a': A<[u8; _]>
|
|
|
|
446..447 'e': B<[u8]>
|
|
|
|
450..454 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]>
|
|
|
|
450..457 'foo2(b)': B<[u8]>
|
|
|
|
455..456 'b': B<[u8; _]>
|
|
|
|
467..468 'f': C<[u8]>
|
|
|
|
471..475 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]>
|
|
|
|
471..478 'foo3(c)': C<[u8]>
|
|
|
|
476..477 'c': C<[u8; _]>
|
2019-09-18 16:36:12 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn infer_if_coerce() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer(r#"
|
|
|
|
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
|
|
|
fn test() {
|
|
|
|
let x = if true {
|
|
|
|
foo(&[1])
|
|
|
|
} else {
|
|
|
|
&[1]
|
|
|
|
};
|
|
|
|
}
|
|
|
|
"#),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
11..12 'x': &[T]
|
|
|
|
28..39 '{ loop {} }': &[T]
|
|
|
|
30..37 'loop {}': !
|
|
|
|
35..37 '{}': ()
|
|
|
|
50..126 '{ ... }; }': ()
|
|
|
|
60..61 'x': &[i32]
|
|
|
|
64..123 'if tru... }': &[i32]
|
|
|
|
67..71 'true': bool
|
|
|
|
72..97 '{ ... }': &[i32]
|
|
|
|
82..85 'foo': fn foo<i32>(&[i32]) -> &[i32]
|
|
|
|
82..91 'foo(&[1])': &[i32]
|
|
|
|
86..90 '&[1]': &[i32; _]
|
|
|
|
87..90 '[1]': [i32; _]
|
|
|
|
88..89 '1': i32
|
|
|
|
103..123 '{ ... }': &[i32; _]
|
|
|
|
113..117 '&[1]': &[i32; _]
|
|
|
|
114..117 '[1]': [i32; _]
|
|
|
|
115..116 '1': i32
|
2019-09-25 21:56:55 +00:00
|
|
|
"###
|
2019-09-18 16:36:12 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn infer_if_else_coerce() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer(r#"
|
|
|
|
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
|
|
|
fn test() {
|
|
|
|
let x = if true {
|
|
|
|
&[1]
|
|
|
|
} else {
|
|
|
|
foo(&[1])
|
|
|
|
};
|
|
|
|
}
|
|
|
|
"#),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
11..12 'x': &[T]
|
|
|
|
28..39 '{ loop {} }': &[T]
|
|
|
|
30..37 'loop {}': !
|
|
|
|
35..37 '{}': ()
|
|
|
|
50..126 '{ ... }; }': ()
|
|
|
|
60..61 'x': &[i32]
|
|
|
|
64..123 'if tru... }': &[i32]
|
|
|
|
67..71 'true': bool
|
|
|
|
72..92 '{ ... }': &[i32; _]
|
|
|
|
82..86 '&[1]': &[i32; _]
|
|
|
|
83..86 '[1]': [i32; _]
|
|
|
|
84..85 '1': i32
|
|
|
|
98..123 '{ ... }': &[i32]
|
|
|
|
108..111 'foo': fn foo<i32>(&[i32]) -> &[i32]
|
|
|
|
108..117 'foo(&[1])': &[i32]
|
|
|
|
112..116 '&[1]': &[i32; _]
|
|
|
|
113..116 '[1]': [i32; _]
|
|
|
|
114..115 '1': i32
|
2019-09-25 21:56:55 +00:00
|
|
|
"###
|
2019-09-18 16:36:12 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn infer_match_first_coerce() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer(r#"
|
|
|
|
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
|
|
|
fn test(i: i32) {
|
|
|
|
let x = match i {
|
|
|
|
2 => foo(&[2]),
|
|
|
|
1 => &[1],
|
|
|
|
_ => &[3],
|
|
|
|
};
|
|
|
|
}
|
|
|
|
"#),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
11..12 'x': &[T]
|
|
|
|
28..39 '{ loop {} }': &[T]
|
|
|
|
30..37 'loop {}': !
|
|
|
|
35..37 '{}': ()
|
|
|
|
48..49 'i': i32
|
|
|
|
56..150 '{ ... }; }': ()
|
|
|
|
66..67 'x': &[i32]
|
|
|
|
70..147 'match ... }': &[i32]
|
|
|
|
76..77 'i': i32
|
|
|
|
88..89 '2': i32
|
|
|
|
88..89 '2': i32
|
|
|
|
93..96 'foo': fn foo<i32>(&[i32]) -> &[i32]
|
|
|
|
93..102 'foo(&[2])': &[i32]
|
|
|
|
97..101 '&[2]': &[i32; _]
|
|
|
|
98..101 '[2]': [i32; _]
|
|
|
|
99..100 '2': i32
|
|
|
|
112..113 '1': i32
|
|
|
|
112..113 '1': i32
|
|
|
|
117..121 '&[1]': &[i32; _]
|
|
|
|
118..121 '[1]': [i32; _]
|
|
|
|
119..120 '1': i32
|
|
|
|
131..132 '_': i32
|
|
|
|
136..140 '&[3]': &[i32; _]
|
|
|
|
137..140 '[3]': [i32; _]
|
|
|
|
138..139 '3': i32
|
2019-09-18 16:36:12 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn infer_match_second_coerce() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer(r#"
|
|
|
|
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
|
|
|
fn test(i: i32) {
|
|
|
|
let x = match i {
|
|
|
|
1 => &[1],
|
|
|
|
2 => foo(&[2]),
|
|
|
|
_ => &[3],
|
|
|
|
};
|
|
|
|
}
|
|
|
|
"#),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
11..12 'x': &[T]
|
|
|
|
28..39 '{ loop {} }': &[T]
|
|
|
|
30..37 'loop {}': !
|
|
|
|
35..37 '{}': ()
|
|
|
|
48..49 'i': i32
|
|
|
|
56..150 '{ ... }; }': ()
|
|
|
|
66..67 'x': &[i32]
|
|
|
|
70..147 'match ... }': &[i32]
|
|
|
|
76..77 'i': i32
|
|
|
|
88..89 '1': i32
|
|
|
|
88..89 '1': i32
|
|
|
|
93..97 '&[1]': &[i32; _]
|
|
|
|
94..97 '[1]': [i32; _]
|
|
|
|
95..96 '1': i32
|
|
|
|
107..108 '2': i32
|
|
|
|
107..108 '2': i32
|
|
|
|
112..115 'foo': fn foo<i32>(&[i32]) -> &[i32]
|
|
|
|
112..121 'foo(&[2])': &[i32]
|
|
|
|
116..120 '&[2]': &[i32; _]
|
|
|
|
117..120 '[2]': [i32; _]
|
|
|
|
118..119 '2': i32
|
|
|
|
131..132 '_': i32
|
|
|
|
136..140 '&[3]': &[i32; _]
|
|
|
|
137..140 '[3]': [i32; _]
|
|
|
|
138..139 '3': i32
|
2019-09-18 16:36:12 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn coerce_merge_one_by_one1() {
|
|
|
|
covers!(coerce_merge_fail_fallback);
|
|
|
|
|
|
|
|
assert_snapshot!(
|
|
|
|
infer(r#"
|
|
|
|
fn test() {
|
|
|
|
let t = &mut 1;
|
|
|
|
let x = match 1 {
|
|
|
|
1 => t as *mut i32,
|
|
|
|
2 => t as &i32,
|
|
|
|
_ => t as *const i32,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
"#),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
11..145 '{ ... }; }': ()
|
|
|
|
21..22 't': &mut i32
|
|
|
|
25..31 '&mut 1': &mut i32
|
|
|
|
30..31 '1': i32
|
|
|
|
41..42 'x': *const i32
|
|
|
|
45..142 'match ... }': *const i32
|
|
|
|
51..52 '1': i32
|
|
|
|
63..64 '1': i32
|
|
|
|
63..64 '1': i32
|
|
|
|
68..69 't': &mut i32
|
|
|
|
68..81 't as *mut i32': *mut i32
|
|
|
|
91..92 '2': i32
|
|
|
|
91..92 '2': i32
|
|
|
|
96..97 't': &mut i32
|
|
|
|
96..105 't as &i32': &i32
|
|
|
|
115..116 '_': i32
|
|
|
|
120..121 't': &mut i32
|
|
|
|
120..135 't as *const i32': *const i32
|
2019-09-18 16:36:12 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
2019-12-05 22:02:31 +00:00
|
|
|
|
2019-12-20 17:27:51 +00:00
|
|
|
#[test]
|
|
|
|
fn return_coerce_unknown() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer_with_mismatches(r#"
|
|
|
|
fn foo() -> u32 {
|
|
|
|
return unknown;
|
|
|
|
}
|
|
|
|
"#, true),
|
|
|
|
@r###"
|
2020-05-08 15:36:11 +00:00
|
|
|
17..40 '{ ...own; }': u32
|
2020-04-24 21:51:02 +00:00
|
|
|
23..37 'return unknown': !
|
|
|
|
30..37 'unknown': u32
|
2019-12-20 17:27:51 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-12-05 22:02:31 +00:00
|
|
|
#[test]
|
|
|
|
fn coerce_autoderef() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer_with_mismatches(r#"
|
|
|
|
struct Foo;
|
|
|
|
fn takes_ref_foo(x: &Foo) {}
|
|
|
|
fn test() {
|
|
|
|
takes_ref_foo(&Foo);
|
|
|
|
takes_ref_foo(&&Foo);
|
|
|
|
takes_ref_foo(&&&Foo);
|
|
|
|
}
|
|
|
|
"#, true),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
30..31 'x': &Foo
|
|
|
|
39..41 '{}': ()
|
|
|
|
52..133 '{ ...oo); }': ()
|
|
|
|
58..71 'takes_ref_foo': fn takes_ref_foo(&Foo)
|
|
|
|
58..77 'takes_...(&Foo)': ()
|
|
|
|
72..76 '&Foo': &Foo
|
|
|
|
73..76 'Foo': Foo
|
|
|
|
83..96 'takes_ref_foo': fn takes_ref_foo(&Foo)
|
|
|
|
83..103 'takes_...&&Foo)': ()
|
|
|
|
97..102 '&&Foo': &&Foo
|
|
|
|
98..102 '&Foo': &Foo
|
|
|
|
99..102 'Foo': Foo
|
|
|
|
109..122 'takes_ref_foo': fn takes_ref_foo(&Foo)
|
|
|
|
109..130 'takes_...&&Foo)': ()
|
|
|
|
123..129 '&&&Foo': &&&Foo
|
|
|
|
124..129 '&&Foo': &&Foo
|
|
|
|
125..129 '&Foo': &Foo
|
|
|
|
126..129 'Foo': Foo
|
2019-12-05 22:02:31 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
2019-12-08 10:23:05 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn coerce_autoderef_generic() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer_with_mismatches(r#"
|
|
|
|
struct Foo;
|
|
|
|
fn takes_ref<T>(x: &T) -> T { *x }
|
|
|
|
fn test() {
|
|
|
|
takes_ref(&Foo);
|
|
|
|
takes_ref(&&Foo);
|
|
|
|
takes_ref(&&&Foo);
|
|
|
|
}
|
|
|
|
"#, true),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
29..30 'x': &T
|
|
|
|
41..47 '{ *x }': T
|
|
|
|
43..45 '*x': T
|
|
|
|
44..45 'x': &T
|
|
|
|
58..127 '{ ...oo); }': ()
|
|
|
|
64..73 'takes_ref': fn takes_ref<Foo>(&Foo) -> Foo
|
|
|
|
64..79 'takes_ref(&Foo)': Foo
|
|
|
|
74..78 '&Foo': &Foo
|
|
|
|
75..78 'Foo': Foo
|
|
|
|
85..94 'takes_ref': fn takes_ref<&Foo>(&&Foo) -> &Foo
|
|
|
|
85..101 'takes_...&&Foo)': &Foo
|
|
|
|
95..100 '&&Foo': &&Foo
|
|
|
|
96..100 '&Foo': &Foo
|
|
|
|
97..100 'Foo': Foo
|
|
|
|
107..116 'takes_ref': fn takes_ref<&&Foo>(&&&Foo) -> &&Foo
|
|
|
|
107..124 'takes_...&&Foo)': &&Foo
|
|
|
|
117..123 '&&&Foo': &&&Foo
|
|
|
|
118..123 '&&Foo': &&Foo
|
|
|
|
119..123 '&Foo': &Foo
|
|
|
|
120..123 'Foo': Foo
|
2019-12-08 10:23:05 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
2019-12-20 15:41:32 +00:00
|
|
|
|
2020-02-29 14:31:07 +00:00
|
|
|
#[test]
|
|
|
|
fn coerce_autoderef_block() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer_with_mismatches(r#"
|
|
|
|
struct String {}
|
|
|
|
#[lang = "deref"]
|
|
|
|
trait Deref { type Target; }
|
|
|
|
impl Deref for String { type Target = str; }
|
|
|
|
fn takes_ref_str(x: &str) {}
|
|
|
|
fn returns_string() -> String { loop {} }
|
|
|
|
fn test() {
|
|
|
|
takes_ref_str(&{ returns_string() });
|
|
|
|
}
|
|
|
|
"#, true),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
127..128 'x': &str
|
|
|
|
136..138 '{}': ()
|
|
|
|
169..180 '{ loop {} }': String
|
|
|
|
171..178 'loop {}': !
|
|
|
|
176..178 '{}': ()
|
|
|
|
191..236 '{ ... }); }': ()
|
|
|
|
197..210 'takes_ref_str': fn takes_ref_str(&str)
|
|
|
|
197..233 'takes_...g() })': ()
|
|
|
|
211..232 '&{ ret...ng() }': &String
|
|
|
|
212..232 '{ retu...ng() }': String
|
|
|
|
214..228 'returns_string': fn returns_string() -> String
|
|
|
|
214..230 'return...ring()': String
|
2020-02-29 14:31:07 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-12-20 15:41:32 +00:00
|
|
|
#[test]
|
|
|
|
fn closure_return_coerce() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer_with_mismatches(r#"
|
|
|
|
fn foo() {
|
|
|
|
let x = || {
|
|
|
|
if true {
|
|
|
|
return &1u32;
|
|
|
|
}
|
|
|
|
&&1u32
|
|
|
|
};
|
|
|
|
}
|
|
|
|
"#, true),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
10..106 '{ ... }; }': ()
|
|
|
|
20..21 'x': || -> &u32
|
|
|
|
24..103 '|| { ... }': || -> &u32
|
|
|
|
27..103 '{ ... }': &u32
|
|
|
|
37..82 'if tru... }': ()
|
|
|
|
40..44 'true': bool
|
2020-05-08 15:36:11 +00:00
|
|
|
45..82 '{ ... }': ()
|
2020-04-24 21:51:02 +00:00
|
|
|
59..71 'return &1u32': !
|
|
|
|
66..71 '&1u32': &u32
|
|
|
|
67..71 '1u32': u32
|
|
|
|
91..97 '&&1u32': &&u32
|
|
|
|
92..97 '&1u32': &u32
|
|
|
|
93..97 '1u32': u32
|
2019-12-20 15:41:32 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
2019-12-20 17:53:40 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn coerce_fn_item_to_fn_ptr() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer_with_mismatches(r#"
|
|
|
|
fn foo(x: u32) -> isize { 1 }
|
|
|
|
fn test() {
|
|
|
|
let f: fn(u32) -> isize = foo;
|
|
|
|
}
|
|
|
|
"#, true),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
8..9 'x': u32
|
|
|
|
25..30 '{ 1 }': isize
|
|
|
|
27..28 '1': isize
|
|
|
|
41..79 '{ ...foo; }': ()
|
|
|
|
51..52 'f': fn(u32) -> isize
|
|
|
|
73..76 'foo': fn foo(u32) -> isize
|
2019-12-20 17:53:40 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn coerce_closure_to_fn_ptr() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer_with_mismatches(r#"
|
|
|
|
fn test() {
|
|
|
|
let f: fn(u32) -> isize = |x| { 1 };
|
|
|
|
}
|
|
|
|
"#, true),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
11..55 '{ ...1 }; }': ()
|
|
|
|
21..22 'f': fn(u32) -> isize
|
|
|
|
43..52 '|x| { 1 }': |u32| -> isize
|
|
|
|
44..45 'x': u32
|
|
|
|
47..52 '{ 1 }': isize
|
|
|
|
49..50 '1': isize
|
2019-12-20 17:53:40 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
2020-02-16 11:57:19 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn coerce_placeholder_ref() {
|
|
|
|
// placeholders should unify, even behind references
|
|
|
|
assert_snapshot!(
|
|
|
|
infer_with_mismatches(r#"
|
|
|
|
struct S<T> { t: T }
|
|
|
|
impl<TT> S<TT> {
|
|
|
|
fn get(&self) -> &TT {
|
|
|
|
&self.t
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#, true),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
51..55 'self': &S<TT>
|
|
|
|
64..87 '{ ... }': &TT
|
|
|
|
74..81 '&self.t': &TT
|
|
|
|
75..79 'self': &S<TT>
|
|
|
|
75..81 'self.t': TT
|
2020-02-16 11:57:19 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
2020-02-21 17:24:18 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn coerce_unsize_array() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer_with_mismatches(r#"
|
|
|
|
#[lang = "unsize"]
|
|
|
|
pub trait Unsize<T> {}
|
|
|
|
#[lang = "coerce_unsized"]
|
|
|
|
pub trait CoerceUnsized<T> {}
|
|
|
|
|
|
|
|
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
|
|
|
|
|
|
|
fn test() {
|
|
|
|
let f: &[usize] = &[1, 2, 3];
|
|
|
|
}
|
|
|
|
"#, true),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
162..199 '{ ... 3]; }': ()
|
|
|
|
172..173 'f': &[usize]
|
|
|
|
186..196 '&[1, 2, 3]': &[usize; _]
|
|
|
|
187..196 '[1, 2, 3]': [usize; _]
|
|
|
|
188..189 '1': usize
|
|
|
|
191..192 '2': usize
|
|
|
|
194..195 '3': usize
|
2020-02-21 17:24:18 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn coerce_unsize_trait_object() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer_with_mismatches(r#"
|
|
|
|
#[lang = "unsize"]
|
|
|
|
pub trait Unsize<T> {}
|
|
|
|
#[lang = "coerce_unsized"]
|
|
|
|
pub trait CoerceUnsized<T> {}
|
|
|
|
|
|
|
|
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
|
|
|
|
2020-02-21 20:49:02 +00:00
|
|
|
trait Foo<T, U> {}
|
|
|
|
trait Bar<U, T, X>: Foo<T, U> {}
|
|
|
|
trait Baz<T, X>: Bar<usize, T, X> {}
|
|
|
|
|
|
|
|
struct S<T, X>;
|
|
|
|
impl<T, X> Foo<T, usize> for S<T, X> {}
|
|
|
|
impl<T, X> Bar<usize, T, X> for S<T, X> {}
|
|
|
|
impl<T, X> Baz<T, X> for S<T, X> {}
|
2020-02-21 17:24:18 +00:00
|
|
|
|
|
|
|
fn test() {
|
2020-02-21 20:49:02 +00:00
|
|
|
let obj: &dyn Baz<i8, i16> = &S;
|
|
|
|
let obj: &dyn Bar<_, _, _> = obj;
|
|
|
|
let obj: &dyn Foo<_, _> = obj;
|
|
|
|
let obj2: &dyn Baz<i8, i16> = &S;
|
|
|
|
let _: &dyn Foo<_, _> = obj2;
|
2020-02-21 17:24:18 +00:00
|
|
|
}
|
|
|
|
"#, true),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
388..573 '{ ...bj2; }': ()
|
|
|
|
398..401 'obj': &dyn Baz<i8, i16>
|
|
|
|
423..425 '&S': &S<i8, i16>
|
|
|
|
424..425 'S': S<i8, i16>
|
|
|
|
435..438 'obj': &dyn Bar<usize, i8, i16>
|
|
|
|
460..463 'obj': &dyn Baz<i8, i16>
|
|
|
|
473..476 'obj': &dyn Foo<i8, usize>
|
|
|
|
495..498 'obj': &dyn Bar<usize, i8, i16>
|
|
|
|
508..512 'obj2': &dyn Baz<i8, i16>
|
|
|
|
534..536 '&S': &S<i8, i16>
|
|
|
|
535..536 'S': S<i8, i16>
|
|
|
|
546..547 '_': &dyn Foo<i8, usize>
|
|
|
|
566..570 'obj2': &dyn Baz<i8, i16>
|
2020-02-21 17:24:18 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-02-22 12:14:39 +00:00
|
|
|
#[test]
|
|
|
|
fn coerce_unsize_super_trait_cycle() {
|
|
|
|
assert_snapshot!(
|
|
|
|
infer_with_mismatches(r#"
|
|
|
|
#[lang = "unsize"]
|
|
|
|
pub trait Unsize<T> {}
|
|
|
|
#[lang = "coerce_unsized"]
|
|
|
|
pub trait CoerceUnsized<T> {}
|
|
|
|
|
|
|
|
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
|
|
|
|
|
|
|
trait A {}
|
|
|
|
trait B: C + A {}
|
|
|
|
trait C: B {}
|
|
|
|
trait D: C
|
|
|
|
|
|
|
|
struct S;
|
|
|
|
impl A for S {}
|
|
|
|
impl B for S {}
|
|
|
|
impl C for S {}
|
|
|
|
impl D for S {}
|
|
|
|
|
|
|
|
fn test() {
|
|
|
|
let obj: &dyn D = &S;
|
|
|
|
let obj: &dyn A = obj;
|
|
|
|
}
|
|
|
|
"#, true),
|
|
|
|
@r###"
|
2020-04-24 21:51:02 +00:00
|
|
|
292..348 '{ ...obj; }': ()
|
|
|
|
302..305 'obj': &dyn D
|
|
|
|
316..318 '&S': &S
|
|
|
|
317..318 'S': S
|
|
|
|
328..331 'obj': &dyn A
|
|
|
|
342..345 'obj': &dyn D
|
2020-02-22 12:14:39 +00:00
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-02-21 17:24:18 +00:00
|
|
|
#[ignore]
|
|
|
|
#[test]
|
|
|
|
fn coerce_unsize_generic() {
|
|
|
|
// FIXME: Implement this
|
|
|
|
// https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions
|
|
|
|
assert_snapshot!(
|
|
|
|
infer_with_mismatches(r#"
|
|
|
|
#[lang = "unsize"]
|
|
|
|
pub trait Unsize<T> {}
|
|
|
|
#[lang = "coerce_unsized"]
|
|
|
|
pub trait CoerceUnsized<T> {}
|
|
|
|
|
|
|
|
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
|
|
|
|
|
|
|
struct Foo<T> { t: T };
|
|
|
|
struct Bar<T>(Foo<T>);
|
|
|
|
|
|
|
|
fn test() {
|
|
|
|
let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
|
|
|
|
let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
|
|
|
|
}
|
|
|
|
"#, true),
|
|
|
|
@r###"
|
|
|
|
"###
|
|
|
|
);
|
|
|
|
}
|