rust-analyzer/crates/ra_hir_ty/src/tests/regression.rs

787 lines
15 KiB
Rust
Raw Normal View History

2019-12-03 12:38:54 +00:00
use insta::assert_snapshot;
2020-05-20 10:59:20 +00:00
use ra_db::fixture::WithFixture;
use test_utils::mark;
2019-12-03 12:38:54 +00:00
use crate::test_db::TestDB;
2020-05-20 10:59:20 +00:00
use super::infer;
2019-12-03 12:38:54 +00:00
#[test]
fn bug_484() {
assert_snapshot!(
infer(r#"
fn test() {
let x = if true {};
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
11..37 '{ l... {}; }': ()
20..21 'x': ()
24..34 'if true {}': ()
27..31 'true': bool
32..34 '{}': ()
2019-12-03 12:38:54 +00:00
"###
);
}
#[test]
fn no_panic_on_field_of_enum() {
assert_snapshot!(
infer(r#"
enum X {}
fn test(x: X) {
x.some_field;
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
20..21 'x': X
26..47 '{ ...eld; }': ()
32..33 'x': X
32..44 'x.some_field': {unknown}
2019-12-03 12:38:54 +00:00
"###
);
}
#[test]
fn bug_585() {
assert_snapshot!(
infer(r#"
fn test() {
X {};
match x {
A::B {} => (),
A::Y() => (),
}
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
11..89 '{ ... } }': ()
17..21 'X {}': {unknown}
27..87 'match ... }': ()
33..34 'x': {unknown}
45..52 'A::B {}': {unknown}
56..58 '()': ()
68..74 'A::Y()': {unknown}
78..80 '()': ()
2019-12-03 12:38:54 +00:00
"###
);
}
#[test]
fn bug_651() {
assert_snapshot!(
infer(r#"
fn quux() {
let y = 92;
1 + y;
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
11..41 '{ ...+ y; }': ()
21..22 'y': i32
25..27 '92': i32
33..34 '1': i32
33..38 '1 + y': i32
37..38 'y': i32
2019-12-03 12:38:54 +00:00
"###
);
}
#[test]
fn recursive_vars() {
2020-05-20 10:59:20 +00:00
mark::check!(type_var_cycles_resolve_completely);
mark::check!(type_var_cycles_resolve_as_possible);
2019-12-03 12:38:54 +00:00
assert_snapshot!(
infer(r#"
fn test() {
let y = unknown;
[y, &y];
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
11..48 '{ ...&y]; }': ()
21..22 'y': &{unknown}
25..32 'unknown': &{unknown}
38..45 '[y, &y]': [&&{unknown}; _]
39..40 'y': &{unknown}
42..44 '&y': &&{unknown}
43..44 'y': &{unknown}
2019-12-03 12:38:54 +00:00
"###
);
}
#[test]
fn recursive_vars_2() {
assert_snapshot!(
infer(r#"
fn test() {
let x = unknown;
let y = unknown;
[(x, y), (&y, &x)];
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
11..80 '{ ...x)]; }': ()
21..22 'x': &&{unknown}
25..32 'unknown': &&{unknown}
42..43 'y': &&{unknown}
46..53 'unknown': &&{unknown}
59..77 '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown}); _]
60..66 '(x, y)': (&&&{unknown}, &&&{unknown})
61..62 'x': &&{unknown}
64..65 'y': &&{unknown}
68..76 '(&y, &x)': (&&&{unknown}, &&&{unknown})
69..71 '&y': &&&{unknown}
70..71 'y': &&{unknown}
73..75 '&x': &&&{unknown}
74..75 'x': &&{unknown}
2019-12-03 12:38:54 +00:00
"###
);
}
#[test]
fn infer_std_crash_1() {
// caused stack overflow, taken from std
assert_snapshot!(
infer(r#"
enum Maybe<T> {
Real(T),
Fake,
}
fn write() {
match something_unknown {
Maybe::Real(ref mut something) => (),
}
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
54..139 '{ ... } }': ()
60..137 'match ... }': ()
66..83 'someth...nknown': Maybe<{unknown}>
94..124 'Maybe:...thing)': Maybe<{unknown}>
106..123 'ref mu...ething': &mut {unknown}
128..130 '()': ()
2019-12-03 12:38:54 +00:00
"###
);
}
#[test]
fn infer_std_crash_2() {
2020-05-20 10:59:20 +00:00
mark::check!(type_var_resolves_to_int_var);
2019-12-03 12:38:54 +00:00
// caused "equating two type variables, ...", taken from std
assert_snapshot!(
infer(r#"
fn test_line_buffer() {
&[0, b'\n', 1, b'\n'];
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
23..53 '{ ...n']; }': ()
29..50 '&[0, b...b'\n']': &[u8; _]
30..50 '[0, b'...b'\n']': [u8; _]
31..32 '0': u8
34..39 'b'\n'': u8
41..42 '1': u8
44..49 'b'\n'': u8
2019-12-03 12:38:54 +00:00
"###
);
}
#[test]
fn infer_std_crash_3() {
// taken from rustc
assert_snapshot!(
infer(r#"
pub fn compute() {
match nope!() {
SizeSkeleton::Pointer { non_zero: true, tail } => {}
}
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
18..108 '{ ... } }': ()
24..106 'match ... }': ()
30..37 'nope!()': {unknown}
48..94 'SizeSk...tail }': {unknown}
82..86 'true': bool
82..86 'true': bool
88..92 'tail': {unknown}
98..100 '{}': ()
2019-12-03 12:38:54 +00:00
"###
);
}
#[test]
fn infer_std_crash_4() {
// taken from rustc
assert_snapshot!(
infer(r#"
pub fn primitive_type() {
match *self {
BorrowedRef { type_: Primitive(p), ..} => {},
}
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
25..106 '{ ... } }': ()
31..104 'match ... }': ()
37..42 '*self': {unknown}
38..42 'self': {unknown}
53..91 'Borrow...), ..}': {unknown}
74..86 'Primitive(p)': {unknown}
84..85 'p': {unknown}
95..97 '{}': ()
2019-12-03 12:38:54 +00:00
"###
);
}
#[test]
fn infer_std_crash_5() {
// taken from rustc
assert_snapshot!(
infer(r#"
fn extra_compiler_flags() {
for content in doesnt_matter {
let name = if doesnt_matter {
first
} else {
&content
};
let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) {
name
} else {
content
};
}
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
27..323 '{ ... } }': ()
33..321 'for co... }': ()
37..44 'content': &{unknown}
48..61 'doesnt_matter': {unknown}
62..321 '{ ... }': ()
76..80 'name': &&{unknown}
83..167 'if doe... }': &&{unknown}
86..99 'doesnt_matter': bool
100..129 '{ ... }': &&{unknown}
114..119 'first': &&{unknown}
135..167 '{ ... }': &&{unknown}
149..157 '&content': &&{unknown}
150..157 'content': &{unknown}
182..189 'content': &{unknown}
192..314 'if ICE... }': &{unknown}
195..232 'ICE_RE..._VALUE': {unknown}
195..248 'ICE_RE...&name)': bool
242..247 '&name': &&&{unknown}
243..247 'name': &&{unknown}
249..277 '{ ... }': &&{unknown}
263..267 'name': &&{unknown}
283..314 '{ ... }': &{unknown}
297..304 'content': &{unknown}
2019-12-03 12:38:54 +00:00
"###
);
}
#[test]
fn infer_nested_generics_crash() {
// another crash found typechecking rustc
assert_snapshot!(
infer(r#"
struct Canonical<V> {
value: V,
}
struct QueryResponse<V> {
value: V,
}
fn test<R>(query_response: Canonical<QueryResponse<R>>) {
&query_response.value;
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
92..106 'query_response': Canonical<QueryResponse<R>>
137..167 '{ ...lue; }': ()
143..164 '&query....value': &QueryResponse<R>
144..158 'query_response': Canonical<QueryResponse<R>>
144..164 'query_....value': QueryResponse<R>
2019-12-03 12:38:54 +00:00
"###
);
}
2020-01-10 16:29:00 +00:00
#[test]
fn infer_paren_macro_call() {
assert_snapshot!(
infer(r#"
macro_rules! bar { () => {0u32} }
fn test() {
let a = (bar!());
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
!0..4 '0u32': u32
45..70 '{ ...()); }': ()
55..56 'a': u32
2020-01-10 16:29:00 +00:00
"###
);
}
2019-12-03 12:38:54 +00:00
#[test]
fn bug_1030() {
assert_snapshot!(infer(r#"
struct HashSet<T, H>;
struct FxHasher;
type FxHashSet<T> = HashSet<T, FxHasher>;
impl<T, H> HashSet<T, H> {
fn default() -> HashSet<T, H> {}
}
pub fn main_loop() {
FxHashSet::default();
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
144..146 '{}': ()
169..198 '{ ...t(); }': ()
175..193 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<{unknown}, FxHasher>
175..195 'FxHash...ault()': HashSet<{unknown}, FxHasher>
2019-12-03 12:38:54 +00:00
"###
);
}
#[test]
fn issue_2669() {
assert_snapshot!(
infer(
r#"trait A {}
trait Write {}
struct Response<T> {}
trait D {
fn foo();
}
impl<T:A> D for Response<T> {
fn foo() {
end();
fn end<W: Write>() {
let _x: T = loop {};
}
}
}"#
),
@r###"
2020-04-24 21:51:02 +00:00
147..262 '{ ... }': ()
161..164 'end': fn end<{unknown}>()
161..166 'end()': ()
199..252 '{ ... }': ()
221..223 '_x': !
230..237 'loop {}': !
235..237 '{}': ()
"###
)
}
#[test]
fn issue_2705() {
assert_snapshot!(
infer(r#"
trait Trait {}
fn test() {
<Trait<u32>>::foo()
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
26..53 '{ ...oo() }': ()
32..49 '<Trait...>::foo': {unknown}
32..51 '<Trait...:foo()': ()
"###
);
}
#[test]
fn issue_2683_chars_impl() {
let (db, pos) = TestDB::with_position(
r#"
//- /main.rs crate:main deps:std
fn test() {
let chars: std::str::Chars<'_>;
(chars.next(), chars.nth(1))<|>;
}
//- /std.rs crate:std
#[prelude_import]
use prelude::*;
pub mod prelude {
pub use crate::iter::Iterator;
pub use crate::option::Option;
}
pub mod iter {
pub use self::traits::Iterator;
pub mod traits {
pub use self::iterator::Iterator;
pub mod iterator {
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
fn nth(&mut self, n: usize) -> Option<Self::Item> {}
}
}
}
}
pub mod option {
pub enum Option<T> {}
}
pub mod str {
pub struct Chars<'a> {}
impl<'a> Iterator for Chars<'a> {
type Item = char;
fn next(&mut self) -> Option<char> {}
}
}
"#,
);
assert_eq!("(Option<char>, Option<char>)", super::type_at_pos(&db, pos));
}
2020-03-21 15:41:07 +00:00
#[test]
fn issue_3642_bad_macro_stackover() {
let (db, pos) = TestDB::with_position(
r#"
//- /main.rs
#[macro_export]
macro_rules! match_ast {
(match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
(match ($node:expr) {
$( ast::$ast:ident($it:ident) => $res:expr, )*
_ => $catch_all:expr $(,)?
}) => {{
$( if let Some($it) = ast::$ast::cast($node.clone()) { $res } else )*
{ $catch_all }
}};
}
fn main() {
let anchor<|> = match_ast! {
match parent {
as => {},
_ => return None
}
};
}"#,
);
assert_eq!("()", super::type_at_pos(&db, pos));
}
2020-04-17 12:36:44 +00:00
#[test]
fn issue_3999_slice() {
assert_snapshot!(
infer(r#"
fn foo(params: &[usize]) {
match params {
[ps @ .., _] => {}
}
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
8..14 'params': &[usize]
26..81 '{ ... } }': ()
32..79 'match ... }': ()
38..44 'params': &[usize]
55..67 '[ps @ .., _]': [usize]
65..66 '_': usize
71..73 '{}': ()
2020-04-17 12:36:44 +00:00
"###
);
}
#[test]
fn issue_3999_struct() {
// rust-analyzer should not panic on seeing this malformed
// record pattern.
assert_snapshot!(
infer(r#"
struct Bar {
a: bool,
}
fn foo(b: Bar) {
match b {
Bar { a: .. } => {},
}
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
36..37 'b': Bar
44..96 '{ ... } }': ()
50..94 'match ... }': ()
56..57 'b': Bar
68..81 'Bar { a: .. }': Bar
77..79 '..': bool
85..87 '{}': ()
2020-04-17 12:36:44 +00:00
"###
);
}
2020-05-04 16:29:47 +00:00
#[test]
fn issue_4235_name_conflicts() {
assert_snapshot!(
infer(r#"
struct FOO {}
static FOO:FOO = FOO {};
impl FOO {
fn foo(&self) {}
}
fn main() {
let a = &FOO;
a.foo();
}
"#), @r###"
32..38 'FOO {}': FOO
64..68 'self': &FOO
70..72 '{}': ()
86..120 '{ ...o(); }': ()
96..97 'a': &FOO
100..104 '&FOO': &FOO
101..104 'FOO': FOO
110..111 'a': &FOO
110..117 'a.foo()': ()
"###
);
}
2020-05-17 15:37:30 +00:00
#[test]
fn issue_4465_dollar_crate_at_type() {
assert_snapshot!(
infer(r#"
pub struct Foo {}
pub fn anything<T>() -> T {
loop {}
}
macro_rules! foo {
() => {{
let r: $crate::Foo = anything();
r
}};
}
fn main() {
let _a = foo!();
}
"#), @r###"
45..60 '{ loop {} }': T
51..58 'loop {}': !
56..58 '{}': ()
!0..31 '{letr:...g();r}': Foo
!4..5 'r': Foo
!18..26 'anything': fn anything<Foo>() -> Foo
!18..28 'anything()': Foo
!29..30 'r': Foo
164..188 '{ ...!(); }': ()
174..176 '_a': Foo
"###);
}
#[test]
fn issue_4053_diesel_where_clauses() {
assert_snapshot!(
infer(r#"
trait BoxedDsl<DB> {
type Output;
fn internal_into_boxed(self) -> Self::Output;
}
struct SelectStatement<From, Select, Distinct, Where, Order, LimitOffset, GroupBy, Locking> {
order: Order,
}
trait QueryFragment<DB: Backend> {}
trait Into<T> { fn into(self) -> T; }
impl<F, S, D, W, O, LOf, DB> BoxedDsl<DB>
for SelectStatement<F, S, D, W, O, LOf, G>
where
O: Into<dyn QueryFragment<DB>>,
{
type Output = XXX;
fn internal_into_boxed(self) -> Self::Output {
self.order.into();
}
}
"#),
@r###"
2020-04-24 21:51:02 +00:00
66..70 'self': Self
268..272 'self': Self
467..471 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}>
489..523 '{ ... }': ()
499..503 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}>
499..509 'self.order': O
499..516 'self.o...into()': dyn QueryFragment<DB>
"###
);
}
#[test]
fn issue_4953() {
assert_snapshot!(
infer(r#"
pub struct Foo(pub i64);
impl Foo {
fn test() -> Self { Self(0i64) }
}
"#),
@r###"
59..73 '{ Self(0i64) }': Foo
61..65 'Self': Foo(i64) -> Foo
61..71 'Self(0i64)': Foo
66..70 '0i64': i64
"###
);
assert_snapshot!(
infer(r#"
pub struct Foo<T>(pub T);
impl Foo<i64> {
fn test() -> Self { Self(0i64) }
}
"#),
@r###"
65..79 '{ Self(0i64) }': Foo<i64>
67..71 'Self': Foo<i64>(i64) -> Foo<i64>
67..77 'Self(0i64)': Foo<i64>
72..76 '0i64': i64
"###
);
}
#[test]
fn issue_4931() {
assert_snapshot!(
infer(r#"
trait Div<T> {
type Output;
}
trait CheckedDiv: Div<()> {}
trait PrimInt: CheckedDiv<Output = ()> {
fn pow(self);
}
fn check<T: PrimInt>(i: T) {
i.pow();
}
"#),
@r###"
118..122 'self': Self
149..150 'i': T
155..171 '{ ...w(); }': ()
161..162 'i': T
161..168 'i.pow()': ()
"###
);
}
#[test]
fn issue_4885() {
assert_snapshot!(
infer(r#"
#[lang = "coerce_unsized"]
pub trait CoerceUnsized<T> {}
trait Future {
type Output;
}
trait Foo<R> {
type Bar;
}
fn foo<R, K>(key: &K) -> impl Future<Output = K::Bar>
where
K: Foo<R>,
{
bar(key)
}
fn bar<R, K>(key: &K) -> impl Future<Output = K::Bar>
where
K: Foo<R>,
{
}
"#),
@r###"
137..140 'key': &K
199..215 '{ ...key) }': impl Future<Output = <K as Foo<R>>::Bar>
205..208 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar>
205..213 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar>
209..212 'key': &K
229..232 'key': &K
291..294 '{ }': ()
"###
);
}
#[test]
fn issue_4800() {
assert_snapshot!(
infer(r#"
trait Debug {}
struct Foo<T>;
type E1<T> = (T, T, T);
type E2<T> = E1<E1<E1<(T, T, T)>>>;
impl Debug for Foo<E2<()>> {}
struct Request;
pub trait Future {
type Output;
}
pub struct PeerSet<D>;
impl<D> Service<Request> for PeerSet<D>
where
D: Discover,
D::Key: Debug,
{
type Error = ();
type Future = dyn Future<Output = Self::Error>;
fn call(&mut self) -> Self::Future {
loop {}
}
}
pub trait Discover {
type Key;
}
pub trait Service<Request> {
type Error;
type Future: Future<Output = Self::Error>;
fn call(&mut self) -> Self::Future;
}
"#),
@r###"
380..384 'self': &mut PeerSet<D>
402..425 '{ ... }': dyn Future<Output = ()>
412..419 'loop {}': !
417..419 '{}': ()
576..580 'self': &mut Self
"###
);
}