mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-27 20:35:09 +00:00
Merge #5458
5458: Use expect in some ra_hir_ty tests r=flodiebold a=lnicola Co-authored-by: Laurențiu Nicola <lnicola@dend.ro>
This commit is contained in:
commit
57664369af
3 changed files with 882 additions and 835 deletions
|
@ -10,6 +10,7 @@ mod display_source_code;
|
|||
|
||||
use std::sync::Arc;
|
||||
|
||||
use expect::Expect;
|
||||
use hir_def::{
|
||||
body::{BodySourceMap, SyntheticSyntax},
|
||||
child_by_source::ChildBySource,
|
||||
|
@ -344,3 +345,15 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
|
|||
assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events)
|
||||
}
|
||||
}
|
||||
|
||||
fn check_infer(ra_fixture: &str, expect: Expect) {
|
||||
let mut actual = infer(ra_fixture);
|
||||
actual.push('\n');
|
||||
expect.assert_eq(&actual);
|
||||
}
|
||||
|
||||
fn check_infer_with_mismatches(ra_fixture: &str, expect: Expect) {
|
||||
let mut actual = infer_with_mismatches(ra_fixture, true);
|
||||
actual.push('\n');
|
||||
expect.assert_eq(&actual);
|
||||
}
|
||||
|
|
|
@ -1,57 +1,40 @@
|
|||
use insta::assert_snapshot;
|
||||
use expect::expect;
|
||||
use test_utils::mark;
|
||||
|
||||
use super::infer_with_mismatches;
|
||||
|
||||
// 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))
|
||||
}
|
||||
use super::{check_infer, check_infer_with_mismatches};
|
||||
|
||||
#[test]
|
||||
fn infer_block_expr_type_mismatch() {
|
||||
assert_snapshot!(
|
||||
infer(r#"
|
||||
fn test() {
|
||||
check_infer(
|
||||
r"
|
||||
fn test() {
|
||||
let a: i32 = { 1i64 };
|
||||
}
|
||||
"#),
|
||||
@r###"
|
||||
}
|
||||
",
|
||||
expect![[r"
|
||||
10..40 '{ ...4 }; }': ()
|
||||
20..21 'a': i32
|
||||
29..37 '{ 1i64 }': i64
|
||||
31..35 '1i64': i64
|
||||
"###);
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coerce_places() {
|
||||
assert_snapshot!(
|
||||
infer(r#"
|
||||
struct S<T> { a: T }
|
||||
check_infer(
|
||||
r#"
|
||||
struct S<T> { a: T }
|
||||
|
||||
fn f<T>(_: &[T]) -> T { loop {} }
|
||||
fn g<T>(_: S<&[T]>) -> T { loop {} }
|
||||
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] {
|
||||
fn gen<T>() -> *mut [T; 2] { loop {} }
|
||||
fn test1<U>() -> *mut [U] {
|
||||
gen()
|
||||
}
|
||||
}
|
||||
|
||||
fn test2() {
|
||||
fn test2() {
|
||||
let arr: &[u8; 1] = &[1];
|
||||
|
||||
let a: &[_] = arr;
|
||||
|
@ -61,9 +44,19 @@ fn test2() {
|
|||
let e: [&[_]; 1] = [arr];
|
||||
let f: [&[_]; 2] = [arr; 2];
|
||||
let g: (&[_], &[_]) = (arr, arr);
|
||||
}
|
||||
"#),
|
||||
@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 {}
|
||||
"#,
|
||||
expect![[r"
|
||||
30..31 '_': &[T]
|
||||
44..55 '{ loop {} }': T
|
||||
46..53 'loop {}': !
|
||||
|
@ -108,20 +101,20 @@ fn test2() {
|
|||
406..416 '(arr, arr)': (&[u8], &[u8])
|
||||
407..410 'arr': &[u8; _]
|
||||
412..415 'arr': &[u8; _]
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn infer_let_stmt_coerce() {
|
||||
assert_snapshot!(
|
||||
infer(r#"
|
||||
fn test() {
|
||||
check_infer(
|
||||
r"
|
||||
fn test() {
|
||||
let x: &[isize] = &[1];
|
||||
let x: *const [isize] = &[1];
|
||||
}
|
||||
"#),
|
||||
@r###"
|
||||
}
|
||||
",
|
||||
expect![[r"
|
||||
10..75 '{ ...[1]; }': ()
|
||||
20..21 'x': &[isize]
|
||||
34..38 '&[1]': &[isize; _]
|
||||
|
@ -131,31 +124,43 @@ fn test() {
|
|||
68..72 '&[1]': &[isize; _]
|
||||
69..72 '[1]': [isize; _]
|
||||
70..71 '1': isize
|
||||
"###);
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[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 }
|
||||
check_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> {}
|
||||
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 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]>) {
|
||||
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###"
|
||||
}
|
||||
|
||||
|
||||
#[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 {}
|
||||
"#,
|
||||
expect![[r"
|
||||
257..258 'x': A<[T]>
|
||||
278..283 '{ x }': A<[T]>
|
||||
280..281 'x': A<[T]>
|
||||
|
@ -181,24 +186,30 @@ fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) {
|
|||
470..474 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]>
|
||||
470..477 'foo3(c)': C<[u8]>
|
||||
475..476 'c': C<[u8; _]>
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn infer_if_coerce() {
|
||||
assert_snapshot!(
|
||||
infer(r#"
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test() {
|
||||
let x = if true {
|
||||
foo(&[1])
|
||||
} else {
|
||||
&[1]
|
||||
};
|
||||
}
|
||||
"#),
|
||||
@r###"
|
||||
}
|
||||
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T: ?Sized> {}
|
||||
"#,
|
||||
expect![[r"
|
||||
10..11 'x': &[T]
|
||||
27..38 '{ loop {} }': &[T]
|
||||
29..36 'loop {}': !
|
||||
|
@ -217,24 +228,34 @@ fn test() {
|
|||
112..116 '&[1]': &[i32; _]
|
||||
113..116 '[1]': [i32; _]
|
||||
114..115 '1': i32
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn infer_if_else_coerce() {
|
||||
assert_snapshot!(
|
||||
infer(r#"
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test() {
|
||||
let x = if true {
|
||||
&[1]
|
||||
} else {
|
||||
foo(&[1])
|
||||
};
|
||||
}
|
||||
"#),
|
||||
@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 {}
|
||||
"#,
|
||||
expect![[r"
|
||||
10..11 'x': &[T]
|
||||
27..38 '{ loop {} }': &[T]
|
||||
29..36 'loop {}': !
|
||||
|
@ -253,24 +274,29 @@ fn test() {
|
|||
111..115 '&[1]': &[i32; _]
|
||||
112..115 '[1]': [i32; _]
|
||||
113..114 '1': i32
|
||||
"###
|
||||
);
|
||||
"]],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn infer_match_first_coerce() {
|
||||
assert_snapshot!(
|
||||
infer(r#"
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test(i: i32) {
|
||||
check_infer(
|
||||
r#"
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test(i: i32) {
|
||||
let x = match i {
|
||||
2 => foo(&[2]),
|
||||
1 => &[1],
|
||||
_ => &[3],
|
||||
};
|
||||
}
|
||||
"#),
|
||||
@r###"
|
||||
}
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T: ?Sized> {}
|
||||
"#,
|
||||
expect![[r"
|
||||
10..11 'x': &[T]
|
||||
27..38 '{ loop {} }': &[T]
|
||||
29..36 'loop {}': !
|
||||
|
@ -296,24 +322,34 @@ fn test(i: i32) {
|
|||
135..139 '&[3]': &[i32; _]
|
||||
136..139 '[3]': [i32; _]
|
||||
137..138 '3': i32
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn infer_match_second_coerce() {
|
||||
assert_snapshot!(
|
||||
infer(r#"
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test(i: i32) {
|
||||
check_infer(
|
||||
r#"
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test(i: i32) {
|
||||
let x = match i {
|
||||
1 => &[1],
|
||||
2 => foo(&[2]),
|
||||
_ => &[3],
|
||||
};
|
||||
}
|
||||
"#),
|
||||
@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 {}
|
||||
"#,
|
||||
expect![[r"
|
||||
10..11 'x': &[T]
|
||||
27..38 '{ loop {} }': &[T]
|
||||
29..36 'loop {}': !
|
||||
|
@ -339,7 +375,7 @@ fn test(i: i32) {
|
|||
135..139 '&[3]': &[i32; _]
|
||||
136..139 '[3]': [i32; _]
|
||||
137..138 '3': i32
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -347,18 +383,18 @@ fn test(i: i32) {
|
|||
fn coerce_merge_one_by_one1() {
|
||||
mark::check!(coerce_merge_fail_fallback);
|
||||
|
||||
assert_snapshot!(
|
||||
infer(r#"
|
||||
fn test() {
|
||||
check_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###"
|
||||
}
|
||||
",
|
||||
expect![[r"
|
||||
10..144 '{ ... }; }': ()
|
||||
20..21 't': &mut i32
|
||||
24..30 '&mut 1': &mut i32
|
||||
|
@ -377,39 +413,39 @@ fn test() {
|
|||
114..115 '_': i32
|
||||
119..120 't': &mut i32
|
||||
119..134 't as *const i32': *const i32
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_coerce_unknown() {
|
||||
assert_snapshot!(
|
||||
infer_with_mismatches(r#"
|
||||
fn foo() -> u32 {
|
||||
check_infer_with_mismatches(
|
||||
r"
|
||||
fn foo() -> u32 {
|
||||
return unknown;
|
||||
}
|
||||
"#, true),
|
||||
@r###"
|
||||
}
|
||||
",
|
||||
expect![[r"
|
||||
16..39 '{ ...own; }': u32
|
||||
22..36 'return unknown': !
|
||||
29..36 'unknown': u32
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coerce_autoderef() {
|
||||
assert_snapshot!(
|
||||
infer_with_mismatches(r#"
|
||||
struct Foo;
|
||||
fn takes_ref_foo(x: &Foo) {}
|
||||
fn test() {
|
||||
check_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###"
|
||||
}
|
||||
",
|
||||
expect![[r"
|
||||
29..30 'x': &Foo
|
||||
38..40 '{}': ()
|
||||
51..132 '{ ...oo); }': ()
|
||||
|
@ -428,23 +464,23 @@ fn test() {
|
|||
123..128 '&&Foo': &&Foo
|
||||
124..128 '&Foo': &Foo
|
||||
125..128 'Foo': Foo
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coerce_autoderef_generic() {
|
||||
assert_snapshot!(
|
||||
infer_with_mismatches(r#"
|
||||
struct Foo;
|
||||
fn takes_ref<T>(x: &T) -> T { *x }
|
||||
fn test() {
|
||||
check_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###"
|
||||
}
|
||||
",
|
||||
expect![[r"
|
||||
28..29 'x': &T
|
||||
40..46 '{ *x }': T
|
||||
42..44 '*x': T
|
||||
|
@ -465,25 +501,25 @@ fn test() {
|
|||
117..122 '&&Foo': &&Foo
|
||||
118..122 '&Foo': &Foo
|
||||
119..122 'Foo': Foo
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[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() {
|
||||
check_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###"
|
||||
}
|
||||
"#,
|
||||
expect![[r"
|
||||
126..127 'x': &str
|
||||
135..137 '{}': ()
|
||||
168..179 '{ loop {} }': String
|
||||
|
@ -496,24 +532,24 @@ fn test() {
|
|||
211..231 '{ retu...ng() }': String
|
||||
213..227 'returns_string': fn returns_string() -> String
|
||||
213..229 'return...ring()': String
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn closure_return_coerce() {
|
||||
assert_snapshot!(
|
||||
infer_with_mismatches(r#"
|
||||
fn foo() {
|
||||
check_infer_with_mismatches(
|
||||
r"
|
||||
fn foo() {
|
||||
let x = || {
|
||||
if true {
|
||||
return &1u32;
|
||||
}
|
||||
&&1u32
|
||||
};
|
||||
}
|
||||
"#, true),
|
||||
@r###"
|
||||
}
|
||||
",
|
||||
expect![[r"
|
||||
9..105 '{ ... }; }': ()
|
||||
19..20 'x': || -> &u32
|
||||
23..102 '|| { ... }': || -> &u32
|
||||
|
@ -527,47 +563,48 @@ fn foo() {
|
|||
90..96 '&&1u32': &&u32
|
||||
91..96 '&1u32': &u32
|
||||
92..96 '1u32': u32
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coerce_fn_item_to_fn_ptr() {
|
||||
assert_snapshot!(
|
||||
infer_with_mismatches(r#"
|
||||
fn foo(x: u32) -> isize { 1 }
|
||||
fn test() {
|
||||
check_infer_with_mismatches(
|
||||
r"
|
||||
fn foo(x: u32) -> isize { 1 }
|
||||
fn test() {
|
||||
let f: fn(u32) -> isize = foo;
|
||||
}
|
||||
"#, true),
|
||||
@r###"
|
||||
}
|
||||
",
|
||||
expect![[r"
|
||||
7..8 'x': u32
|
||||
24..29 '{ 1 }': isize
|
||||
26..27 '1': isize
|
||||
40..78 '{ ...foo; }': ()
|
||||
50..51 'f': fn(u32) -> isize
|
||||
72..75 'foo': fn foo(u32) -> isize
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coerce_fn_items_in_match_arms() {
|
||||
mark::check!(coerce_fn_reification);
|
||||
assert_snapshot!(
|
||||
infer_with_mismatches(r#"
|
||||
fn foo1(x: u32) -> isize { 1 }
|
||||
fn foo2(x: u32) -> isize { 2 }
|
||||
fn foo3(x: u32) -> isize { 3 }
|
||||
fn test() {
|
||||
|
||||
check_infer_with_mismatches(
|
||||
r"
|
||||
fn foo1(x: u32) -> isize { 1 }
|
||||
fn foo2(x: u32) -> isize { 2 }
|
||||
fn foo3(x: u32) -> isize { 3 }
|
||||
fn test() {
|
||||
let x = match 1 {
|
||||
1 => foo1,
|
||||
2 => foo2,
|
||||
_ => foo3,
|
||||
};
|
||||
}
|
||||
"#, true),
|
||||
@r###"
|
||||
}
|
||||
",
|
||||
expect![[r"
|
||||
8..9 'x': u32
|
||||
25..30 '{ 1 }': isize
|
||||
27..28 '1': isize
|
||||
|
@ -589,67 +626,67 @@ fn test() {
|
|||
159..163 'foo2': fn foo2(u32) -> isize
|
||||
173..174 '_': i32
|
||||
178..182 'foo3': fn foo3(u32) -> isize
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coerce_closure_to_fn_ptr() {
|
||||
assert_snapshot!(
|
||||
infer_with_mismatches(r#"
|
||||
fn test() {
|
||||
check_infer_with_mismatches(
|
||||
r"
|
||||
fn test() {
|
||||
let f: fn(u32) -> isize = |x| { 1 };
|
||||
}
|
||||
"#, true),
|
||||
@r###"
|
||||
}
|
||||
",
|
||||
expect![[r"
|
||||
10..54 '{ ...1 }; }': ()
|
||||
20..21 'f': fn(u32) -> isize
|
||||
42..51 '|x| { 1 }': |u32| -> isize
|
||||
43..44 'x': u32
|
||||
46..51 '{ 1 }': isize
|
||||
48..49 '1': isize
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[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> {
|
||||
check_infer_with_mismatches(
|
||||
r"
|
||||
struct S<T> { t: T }
|
||||
impl<TT> S<TT> {
|
||||
fn get(&self) -> &TT {
|
||||
&self.t
|
||||
}
|
||||
}
|
||||
"#, true),
|
||||
@r###"
|
||||
}
|
||||
",
|
||||
expect![[r"
|
||||
50..54 'self': &S<TT>
|
||||
63..86 '{ ... }': &TT
|
||||
73..80 '&self.t': &TT
|
||||
74..78 'self': &S<TT>
|
||||
74..80 'self.t': TT
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coerce_unsize_array() {
|
||||
assert_snapshot!(
|
||||
infer_with_mismatches(r#"
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
check_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 {}
|
||||
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
||||
|
||||
fn test() {
|
||||
fn test() {
|
||||
let f: &[usize] = &[1, 2, 3];
|
||||
}
|
||||
"#, true),
|
||||
@r###"
|
||||
}
|
||||
"#,
|
||||
expect![[r"
|
||||
161..198 '{ ... 3]; }': ()
|
||||
171..172 'f': &[usize]
|
||||
185..195 '&[1, 2, 3]': &[usize; _]
|
||||
|
@ -657,39 +694,39 @@ fn test() {
|
|||
187..188 '1': usize
|
||||
190..191 '2': usize
|
||||
193..194 '3': usize
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coerce_unsize_trait_object_simple() {
|
||||
assert_snapshot!(
|
||||
infer_with_mismatches(r#"
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
|
||||
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
||||
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
||||
|
||||
trait Foo<T, U> {}
|
||||
trait Bar<U, T, X>: Foo<T, U> {}
|
||||
trait Baz<T, X>: Bar<usize, T, X> {}
|
||||
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> {}
|
||||
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> {}
|
||||
|
||||
fn test() {
|
||||
fn test() {
|
||||
let obj: &dyn Baz<i8, i16> = &S;
|
||||
let obj: &dyn Bar<_, i8, i16> = &S;
|
||||
let obj: &dyn Foo<i8, _> = &S;
|
||||
}
|
||||
"#, true),
|
||||
@r###"
|
||||
}
|
||||
"#,
|
||||
expect![[r"
|
||||
424..539 '{ ... &S; }': ()
|
||||
434..437 'obj': &dyn Baz<i8, i16>
|
||||
459..461 '&S': &S<i8, i16>
|
||||
|
@ -700,7 +737,7 @@ fn test() {
|
|||
511..514 'obj': &dyn Foo<i8, usize>
|
||||
534..536 '&S': &S<i8, {unknown}>
|
||||
535..536 'S': S<i8, {unknown}>
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -709,35 +746,35 @@ fn test() {
|
|||
// it. We used to support it, but Chalk doesn't.
|
||||
#[ignore]
|
||||
fn coerce_unsize_trait_object_to_trait_object() {
|
||||
assert_snapshot!(
|
||||
infer_with_mismatches(r#"
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
|
||||
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
||||
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
||||
|
||||
trait Foo<T, U> {}
|
||||
trait Bar<U, T, X>: Foo<T, U> {}
|
||||
trait Baz<T, X>: Bar<usize, T, X> {}
|
||||
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> {}
|
||||
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> {}
|
||||
|
||||
fn test() {
|
||||
fn test() {
|
||||
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;
|
||||
}
|
||||
"#, true),
|
||||
@r###"
|
||||
}
|
||||
"#,
|
||||
expect![[r"
|
||||
424..609 '{ ...bj2; }': ()
|
||||
434..437 'obj': &dyn Baz<i8, i16>
|
||||
459..461 '&S': &S<i8, i16>
|
||||
|
@ -751,40 +788,40 @@ fn test() {
|
|||
571..572 'S': S<i8, i16>
|
||||
582..583 '_': &dyn Foo<i8, usize>
|
||||
602..606 'obj2': &dyn Baz<i8, i16>
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coerce_unsize_super_trait_cycle() {
|
||||
assert_snapshot!(
|
||||
infer_with_mismatches(r#"
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
|
||||
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
||||
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
||||
|
||||
trait A {}
|
||||
trait B: C + A {}
|
||||
trait C: B {}
|
||||
trait D: C
|
||||
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 {}
|
||||
struct S;
|
||||
impl A for S {}
|
||||
impl B for S {}
|
||||
impl C for S {}
|
||||
impl D for S {}
|
||||
|
||||
fn test() {
|
||||
fn test() {
|
||||
let obj: &dyn D = &S;
|
||||
let obj: &dyn A = &S;
|
||||
}
|
||||
"#, true),
|
||||
@r###"
|
||||
}
|
||||
"#,
|
||||
expect![[r"
|
||||
328..383 '{ ... &S; }': ()
|
||||
338..341 'obj': &dyn D
|
||||
352..354 '&S': &S
|
||||
|
@ -792,7 +829,7 @@ fn test() {
|
|||
364..367 'obj': &dyn A
|
||||
378..380 '&S': &S
|
||||
379..380 'S': S
|
||||
"###
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -801,24 +838,24 @@ fn 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> {}
|
||||
check_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 {}
|
||||
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
||||
|
||||
struct Foo<T> { t: T };
|
||||
struct Bar<T>(Foo<T>);
|
||||
struct Foo<T> { t: T };
|
||||
struct Bar<T>(Foo<T>);
|
||||
|
||||
fn test() {
|
||||
fn test() {
|
||||
let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
|
||||
let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
|
||||
}
|
||||
"#, true),
|
||||
@r###"
|
||||
"###
|
||||
}
|
||||
"#,
|
||||
expect![[r"
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use insta::assert_snapshot;
|
||||
use expect::expect;
|
||||
|
||||
use super::{check_types, infer_with_mismatches};
|
||||
use super::{check_infer_with_mismatches, check_types};
|
||||
|
||||
#[test]
|
||||
fn infer_never1() {
|
||||
|
@ -240,31 +240,29 @@ fn test(a: i32) {
|
|||
|
||||
#[test]
|
||||
fn diverging_expression_1() {
|
||||
let t = infer_with_mismatches(
|
||||
r#"
|
||||
//- /main.rs
|
||||
fn test1() {
|
||||
check_infer_with_mismatches(
|
||||
r"
|
||||
//- /main.rs
|
||||
fn test1() {
|
||||
let x: u32 = return;
|
||||
}
|
||||
fn test2() {
|
||||
}
|
||||
fn test2() {
|
||||
let x: u32 = { return; };
|
||||
}
|
||||
fn test3() {
|
||||
}
|
||||
fn test3() {
|
||||
let x: u32 = loop {};
|
||||
}
|
||||
fn test4() {
|
||||
}
|
||||
fn test4() {
|
||||
let x: u32 = { loop {} };
|
||||
}
|
||||
fn test5() {
|
||||
}
|
||||
fn test5() {
|
||||
let x: u32 = { if true { loop {}; } else { loop {}; } };
|
||||
}
|
||||
fn test6() {
|
||||
}
|
||||
fn test6() {
|
||||
let x: u32 = { let y: u32 = { loop {}; }; };
|
||||
}
|
||||
"#,
|
||||
true,
|
||||
);
|
||||
assert_snapshot!(t, @r###"
|
||||
}
|
||||
",
|
||||
expect![[r"
|
||||
11..39 '{ ...urn; }': ()
|
||||
21..22 'x': u32
|
||||
30..36 'return': !
|
||||
|
@ -299,22 +297,21 @@ fn test6() {
|
|||
292..304 '{ loop {}; }': u32
|
||||
294..301 'loop {}': !
|
||||
299..301 '{}': ()
|
||||
"###);
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diverging_expression_2() {
|
||||
let t = infer_with_mismatches(
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
//- /main.rs
|
||||
fn test1() {
|
||||
//- /main.rs
|
||||
fn test1() {
|
||||
// should give type mismatch
|
||||
let x: u32 = { loop {}; "foo" };
|
||||
}
|
||||
"#,
|
||||
true,
|
||||
);
|
||||
assert_snapshot!(t, @r###"
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
11..84 '{ ..." }; }': ()
|
||||
54..55 'x': u32
|
||||
63..81 '{ loop...foo" }': &str
|
||||
|
@ -323,38 +320,37 @@ fn test1() {
|
|||
74..79 '"foo"': &str
|
||||
63..81: expected u32, got &str
|
||||
74..79: expected u32, got &str
|
||||
"###);
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diverging_expression_3_break() {
|
||||
let t = infer_with_mismatches(
|
||||
r#"
|
||||
//- /main.rs
|
||||
fn test1() {
|
||||
check_infer_with_mismatches(
|
||||
r"
|
||||
//- /main.rs
|
||||
fn test1() {
|
||||
// should give type mismatch
|
||||
let x: u32 = { loop { break; } };
|
||||
}
|
||||
fn test2() {
|
||||
}
|
||||
fn test2() {
|
||||
// should give type mismatch
|
||||
let x: u32 = { for a in b { break; }; };
|
||||
// should give type mismatch as well
|
||||
let x: u32 = { for a in b {}; };
|
||||
// should give type mismatch as well
|
||||
let x: u32 = { for a in b { return; }; };
|
||||
}
|
||||
fn test3() {
|
||||
}
|
||||
fn test3() {
|
||||
// should give type mismatch
|
||||
let x: u32 = { while true { break; }; };
|
||||
// should give type mismatch as well -- there's an implicit break, even if it's never hit
|
||||
let x: u32 = { while true {}; };
|
||||
// should give type mismatch as well
|
||||
let x: u32 = { while true { return; }; };
|
||||
}
|
||||
"#,
|
||||
true,
|
||||
);
|
||||
assert_snapshot!(t, @r###"
|
||||
}
|
||||
",
|
||||
expect![[r"
|
||||
11..85 '{ ...} }; }': ()
|
||||
54..55 'x': u32
|
||||
63..82 '{ loop...k; } }': ()
|
||||
|
@ -408,5 +404,6 @@ fn test3() {
|
|||
407..433: expected u32, got ()
|
||||
546..564: expected u32, got ()
|
||||
624..651: expected u32, got ()
|
||||
"###);
|
||||
"]],
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue