diff options
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r-- | crates/ra_hir_ty/src/_match.rs | 29 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests.rs | 27 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/macros.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/regression.rs | 29 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 38 |
5 files changed, 101 insertions, 26 deletions
diff --git a/crates/ra_hir_ty/src/_match.rs b/crates/ra_hir_ty/src/_match.rs index 779e78574..149f65042 100644 --- a/crates/ra_hir_ty/src/_match.rs +++ b/crates/ra_hir_ty/src/_match.rs | |||
@@ -573,14 +573,20 @@ pub(crate) fn is_useful( | |||
573 | matrix: &Matrix, | 573 | matrix: &Matrix, |
574 | v: &PatStack, | 574 | v: &PatStack, |
575 | ) -> MatchCheckResult<Usefulness> { | 575 | ) -> MatchCheckResult<Usefulness> { |
576 | // Handle the special case of enums with no variants. In that case, no match | 576 | // Handle two special cases: |
577 | // arm is useful. | 577 | // - enum with no variants |
578 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(AdtId::EnumId(enum_id)), .. }) = | 578 | // - `!` type |
579 | cx.infer[cx.match_expr].strip_references() | 579 | // In those cases, no match arm is useful. |
580 | { | 580 | match cx.infer[cx.match_expr].strip_references() { |
581 | if cx.db.enum_data(*enum_id).variants.is_empty() { | 581 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(AdtId::EnumId(enum_id)), .. }) => { |
582 | if cx.db.enum_data(*enum_id).variants.is_empty() { | ||
583 | return Ok(Usefulness::NotUseful); | ||
584 | } | ||
585 | } | ||
586 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) => { | ||
582 | return Ok(Usefulness::NotUseful); | 587 | return Ok(Usefulness::NotUseful); |
583 | } | 588 | } |
589 | _ => (), | ||
584 | } | 590 | } |
585 | 591 | ||
586 | if v.is_empty() { | 592 | if v.is_empty() { |
@@ -1918,6 +1924,17 @@ mod tests { | |||
1918 | } | 1924 | } |
1919 | 1925 | ||
1920 | #[test] | 1926 | #[test] |
1927 | fn type_never() { | ||
1928 | let content = r" | ||
1929 | fn test_fn(never: !) { | ||
1930 | match never {} | ||
1931 | } | ||
1932 | "; | ||
1933 | |||
1934 | check_no_diagnostic(content); | ||
1935 | } | ||
1936 | |||
1937 | #[test] | ||
1921 | fn enum_never_ref() { | 1938 | fn enum_never_ref() { |
1922 | let content = r" | 1939 | let content = r" |
1923 | enum Never {} | 1940 | enum Never {} |
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index 588d81282..d60732e19 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs | |||
@@ -361,6 +361,33 @@ fn no_such_field_with_feature_flag_diagnostics() { | |||
361 | } | 361 | } |
362 | 362 | ||
363 | #[test] | 363 | #[test] |
364 | fn no_such_field_enum_with_feature_flag_diagnostics() { | ||
365 | let diagnostics = TestDB::with_files( | ||
366 | r#" | ||
367 | //- /lib.rs crate:foo cfg:feature=foo | ||
368 | enum Foo { | ||
369 | #[cfg(not(feature = "foo"))] | ||
370 | Buz, | ||
371 | #[cfg(feature = "foo")] | ||
372 | Bar, | ||
373 | Baz | ||
374 | } | ||
375 | |||
376 | fn test_fn(f: Foo) { | ||
377 | match f { | ||
378 | Foo::Bar => {}, | ||
379 | Foo::Baz => {}, | ||
380 | } | ||
381 | } | ||
382 | "#, | ||
383 | ) | ||
384 | .diagnostics() | ||
385 | .0; | ||
386 | |||
387 | assert_snapshot!(diagnostics, @r###""###); | ||
388 | } | ||
389 | |||
390 | #[test] | ||
364 | fn no_such_field_with_feature_flag_diagnostics_on_struct_lit() { | 391 | fn no_such_field_with_feature_flag_diagnostics_on_struct_lit() { |
365 | let diagnostics = TestDB::with_files( | 392 | let diagnostics = TestDB::with_files( |
366 | r#" | 393 | r#" |
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 29e38a06c..07398ddcc 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs | |||
@@ -269,7 +269,7 @@ fn test() { S.foo()<|>; } | |||
269 | } | 269 | } |
270 | 270 | ||
271 | #[test] | 271 | #[test] |
272 | fn infer_impl_items_generated_by_macros() { | 272 | fn infer_assoc_items_generated_by_macros() { |
273 | let t = type_at( | 273 | let t = type_at( |
274 | r#" | 274 | r#" |
275 | //- /main.rs | 275 | //- /main.rs |
@@ -288,7 +288,7 @@ fn test() { S.foo()<|>; } | |||
288 | } | 288 | } |
289 | 289 | ||
290 | #[test] | 290 | #[test] |
291 | fn infer_impl_items_generated_by_macros_chain() { | 291 | fn infer_assoc_items_generated_by_macros_chain() { |
292 | let t = type_at( | 292 | let t = type_at( |
293 | r#" | 293 | r#" |
294 | //- /main.rs | 294 | //- /main.rs |
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs index 8a1292c7a..115ad8328 100644 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ b/crates/ra_hir_ty/src/tests/regression.rs | |||
@@ -535,6 +535,35 @@ fn foo(b: Bar) { | |||
535 | } | 535 | } |
536 | 536 | ||
537 | #[test] | 537 | #[test] |
538 | fn issue_4235_name_conflicts() { | ||
539 | assert_snapshot!( | ||
540 | infer(r#" | ||
541 | struct FOO {} | ||
542 | static FOO:FOO = FOO {}; | ||
543 | |||
544 | impl FOO { | ||
545 | fn foo(&self) {} | ||
546 | } | ||
547 | |||
548 | fn main() { | ||
549 | let a = &FOO; | ||
550 | a.foo(); | ||
551 | } | ||
552 | "#), @r###" | ||
553 | 32..38 'FOO {}': FOO | ||
554 | 64..68 'self': &FOO | ||
555 | 70..72 '{}': () | ||
556 | 86..120 '{ ...o(); }': () | ||
557 | 96..97 'a': &FOO | ||
558 | 100..104 '&FOO': &FOO | ||
559 | 101..104 'FOO': FOO | ||
560 | 110..111 'a': &FOO | ||
561 | 110..117 'a.foo()': () | ||
562 | "### | ||
563 | ); | ||
564 | } | ||
565 | |||
566 | #[test] | ||
538 | fn issue_4053_diesel_where_clauses() { | 567 | fn issue_4053_diesel_where_clauses() { |
539 | assert_snapshot!( | 568 | assert_snapshot!( |
540 | infer(r#" | 569 | infer(r#" |
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index e555c879a..9d32cbc7a 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -2055,7 +2055,7 @@ fn test<I: Iterator<Item: Iterator<Item = u32>>>() { | |||
2055 | #[test] | 2055 | #[test] |
2056 | fn proc_macro_server_types() { | 2056 | fn proc_macro_server_types() { |
2057 | assert_snapshot!( | 2057 | assert_snapshot!( |
2058 | infer_with_mismatches(r#" | 2058 | infer(r#" |
2059 | macro_rules! with_api { | 2059 | macro_rules! with_api { |
2060 | ($S:ident, $self:ident, $m:ident) => { | 2060 | ($S:ident, $self:ident, $m:ident) => { |
2061 | $m! { | 2061 | $m! { |
@@ -2069,9 +2069,9 @@ macro_rules! with_api { | |||
2069 | } | 2069 | } |
2070 | macro_rules! associated_item { | 2070 | macro_rules! associated_item { |
2071 | (type TokenStream) => | 2071 | (type TokenStream) => |
2072 | (type TokenStream: 'static + Clone;); | 2072 | (type TokenStream: 'static;); |
2073 | (type Group) => | 2073 | (type Group) => |
2074 | (type Group: 'static + Clone;); | 2074 | (type Group: 'static;); |
2075 | ($($item:tt)*) => ($($item)*;) | 2075 | ($($item:tt)*) => ($($item)*;) |
2076 | } | 2076 | } |
2077 | macro_rules! declare_server_traits { | 2077 | macro_rules! declare_server_traits { |
@@ -2083,21 +2083,23 @@ macro_rules! declare_server_traits { | |||
2083 | } | 2083 | } |
2084 | 2084 | ||
2085 | $(pub trait $name: Types { | 2085 | $(pub trait $name: Types { |
2086 | $(associated_item!(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)?);)* | 2086 | $(associated_item!(fn $method($($arg: $arg_ty),*) $(-> $ret_ty)?);)* |
2087 | })* | 2087 | })* |
2088 | 2088 | ||
2089 | pub trait Server: Types $(+ $name)* {} | 2089 | pub trait Server: Types $(+ $name)* {} |
2090 | impl<S: Types $(+ $name)*> Server for S {} | 2090 | impl<S: Types $(+ $name)*> Server for S {} |
2091 | } | 2091 | } |
2092 | } | 2092 | } |
2093 | |||
2093 | with_api!(Self, self_, declare_server_traits); | 2094 | with_api!(Self, self_, declare_server_traits); |
2094 | struct Group {} | 2095 | struct G {} |
2095 | struct TokenStream {} | 2096 | struct T {} |
2096 | struct Rustc; | 2097 | struct Rustc; |
2097 | impl Types for Rustc { | 2098 | impl Types for Rustc { |
2098 | type TokenStream = TokenStream; | 2099 | type TokenStream = T; |
2099 | type Group = Group; | 2100 | type Group = G; |
2100 | } | 2101 | } |
2102 | |||
2101 | fn make<T>() -> T { loop {} } | 2103 | fn make<T>() -> T { loop {} } |
2102 | impl TokenStream for Rustc { | 2104 | impl TokenStream for Rustc { |
2103 | fn new() -> Self::TokenStream { | 2105 | fn new() -> Self::TokenStream { |
@@ -2105,17 +2107,17 @@ impl TokenStream for Rustc { | |||
2105 | make() | 2107 | make() |
2106 | } | 2108 | } |
2107 | } | 2109 | } |
2108 | "#, true), | 2110 | "#), |
2109 | @r###" | 2111 | @r###" |
2110 | 1115..1126 '{ loop {} }': T | 2112 | 1062..1073 '{ loop {} }': T |
2111 | 1117..1124 'loop {}': ! | 2113 | 1064..1071 'loop {}': ! |
2112 | 1122..1124 '{}': () | 2114 | 1069..1071 '{}': () |
2113 | 1190..1253 '{ ... }': {unknown} | 2115 | 1137..1200 '{ ... }': T |
2114 | 1204..1209 'group': {unknown} | 2116 | 1151..1156 'group': G |
2115 | 1225..1229 'make': fn make<{unknown}>() -> {unknown} | 2117 | 1172..1176 'make': fn make<G>() -> G |
2116 | 1225..1231 'make()': {unknown} | 2118 | 1172..1178 'make()': G |
2117 | 1241..1245 'make': fn make<{unknown}>() -> {unknown} | 2119 | 1188..1192 'make': fn make<T>() -> T |
2118 | 1241..1247 'make()': {unknown} | 2120 | 1188..1194 'make()': T |
2119 | "### | 2121 | "### |
2120 | ); | 2122 | ); |
2121 | } | 2123 | } |