diff options
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r-- | crates/ra_hir_ty/src/display.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lib.rs | 31 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests.rs | 80 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/regression.rs | 36 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/simple.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 57 |
7 files changed, 199 insertions, 43 deletions
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs index dcca1bace..37def7c03 100644 --- a/crates/ra_hir_ty/src/display.rs +++ b/crates/ra_hir_ty/src/display.rs | |||
@@ -10,7 +10,7 @@ pub struct HirFormatter<'a, 'b, DB> { | |||
10 | buf: String, | 10 | buf: String, |
11 | curr_size: usize, | 11 | curr_size: usize, |
12 | max_size: Option<usize>, | 12 | max_size: Option<usize>, |
13 | should_display_default_types: bool, | 13 | omit_verbose_types: bool, |
14 | } | 14 | } |
15 | 15 | ||
16 | pub trait HirDisplay { | 16 | pub trait HirDisplay { |
@@ -20,7 +20,7 @@ pub trait HirDisplay { | |||
20 | where | 20 | where |
21 | Self: Sized, | 21 | Self: Sized, |
22 | { | 22 | { |
23 | HirDisplayWrapper(db, self, None, true) | 23 | HirDisplayWrapper(db, self, None, false) |
24 | } | 24 | } |
25 | 25 | ||
26 | fn display_truncated<'a, DB>( | 26 | fn display_truncated<'a, DB>( |
@@ -31,7 +31,7 @@ pub trait HirDisplay { | |||
31 | where | 31 | where |
32 | Self: Sized, | 32 | Self: Sized, |
33 | { | 33 | { |
34 | HirDisplayWrapper(db, self, max_size, false) | 34 | HirDisplayWrapper(db, self, max_size, true) |
35 | } | 35 | } |
36 | } | 36 | } |
37 | 37 | ||
@@ -74,8 +74,8 @@ where | |||
74 | } | 74 | } |
75 | } | 75 | } |
76 | 76 | ||
77 | pub fn should_display_default_types(&self) -> bool { | 77 | pub fn omit_verbose_types(&self) -> bool { |
78 | self.should_display_default_types | 78 | self.omit_verbose_types |
79 | } | 79 | } |
80 | } | 80 | } |
81 | 81 | ||
@@ -93,7 +93,7 @@ where | |||
93 | buf: String::with_capacity(20), | 93 | buf: String::with_capacity(20), |
94 | curr_size: 0, | 94 | curr_size: 0, |
95 | max_size: self.2, | 95 | max_size: self.2, |
96 | should_display_default_types: self.3, | 96 | omit_verbose_types: self.3, |
97 | }) | 97 | }) |
98 | } | 98 | } |
99 | } | 99 | } |
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index e97b81473..32c0d07a5 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -37,8 +37,8 @@ use test_utils::tested_by; | |||
37 | use super::{ | 37 | use super::{ |
38 | primitive::{FloatTy, IntTy}, | 38 | primitive::{FloatTy, IntTy}, |
39 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, | 39 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, |
40 | ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, | 40 | ApplicationTy, GenericPredicate, InEnvironment, ProjectionTy, Substs, TraitEnvironment, |
41 | TypeWalk, Uncertain, | 41 | TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, |
42 | }; | 42 | }; |
43 | use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; | 43 | use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; |
44 | 44 | ||
@@ -379,6 +379,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
379 | ) -> Ty { | 379 | ) -> Ty { |
380 | match assoc_ty { | 380 | match assoc_ty { |
381 | Some(res_assoc_ty) => { | 381 | Some(res_assoc_ty) => { |
382 | // FIXME: | ||
383 | // Check if inner_ty is is `impl Trait` and contained input TypeAlias id | ||
384 | // this is a workaround while Chalk assoc type projection doesn't always work yet, | ||
385 | // but once that is fixed I don't think we should keep this | ||
386 | // (we'll probably change how associated types are resolved anyway) | ||
387 | if let Ty::Opaque(ref predicates) = inner_ty { | ||
388 | for p in predicates.iter() { | ||
389 | if let GenericPredicate::Projection(projection) = p { | ||
390 | if projection.projection_ty.associated_ty == res_assoc_ty { | ||
391 | if let ty_app!(_, params) = &projection.ty { | ||
392 | if params.len() == 0 { | ||
393 | return projection.ty.clone(); | ||
394 | } | ||
395 | } | ||
396 | } | ||
397 | } | ||
398 | } | ||
399 | } | ||
400 | |||
382 | let ty = self.table.new_type_var(); | 401 | let ty = self.table.new_type_var(); |
383 | let builder = Substs::build_for_def(self.db, res_assoc_ty) | 402 | let builder = Substs::build_for_def(self.db, res_assoc_ty) |
384 | .push(inner_ty) | 403 | .push(inner_ty) |
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 48abf97c9..55b6dd836 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -821,6 +821,8 @@ impl TypeWalk for Ty { | |||
821 | } | 821 | } |
822 | } | 822 | } |
823 | 823 | ||
824 | const TYPE_HINT_TRUNCATION: &str = "…"; | ||
825 | |||
824 | impl HirDisplay for &Ty { | 826 | impl HirDisplay for &Ty { |
825 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 827 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
826 | HirDisplay::hir_fmt(*self, f) | 828 | HirDisplay::hir_fmt(*self, f) |
@@ -830,7 +832,7 @@ impl HirDisplay for &Ty { | |||
830 | impl HirDisplay for ApplicationTy { | 832 | impl HirDisplay for ApplicationTy { |
831 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 833 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
832 | if f.should_truncate() { | 834 | if f.should_truncate() { |
833 | return write!(f, "…"); | 835 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
834 | } | 836 | } |
835 | 837 | ||
836 | match self.ctor { | 838 | match self.ctor { |
@@ -908,9 +910,7 @@ impl HirDisplay for ApplicationTy { | |||
908 | write!(f, "<")?; | 910 | write!(f, "<")?; |
909 | 911 | ||
910 | let mut non_default_parameters = Vec::with_capacity(self.parameters.len()); | 912 | let mut non_default_parameters = Vec::with_capacity(self.parameters.len()); |
911 | let parameters_to_write = if f.should_display_default_types() { | 913 | let parameters_to_write = if f.omit_verbose_types() { |
912 | self.parameters.0.as_ref() | ||
913 | } else { | ||
914 | match self | 914 | match self |
915 | .ctor | 915 | .ctor |
916 | .as_generic_def() | 916 | .as_generic_def() |
@@ -935,6 +935,8 @@ impl HirDisplay for ApplicationTy { | |||
935 | &non_default_parameters | 935 | &non_default_parameters |
936 | } | 936 | } |
937 | } | 937 | } |
938 | } else { | ||
939 | self.parameters.0.as_ref() | ||
938 | }; | 940 | }; |
939 | 941 | ||
940 | f.write_joined(parameters_to_write, ", ")?; | 942 | f.write_joined(parameters_to_write, ", ")?; |
@@ -959,9 +961,16 @@ impl HirDisplay for ApplicationTy { | |||
959 | let sig = self.parameters[0] | 961 | let sig = self.parameters[0] |
960 | .callable_sig(f.db) | 962 | .callable_sig(f.db) |
961 | .expect("first closure parameter should contain signature"); | 963 | .expect("first closure parameter should contain signature"); |
962 | write!(f, "|")?; | 964 | let return_type_hint = sig.ret().display(f.db); |
963 | f.write_joined(sig.params(), ", ")?; | 965 | if sig.params().is_empty() { |
964 | write!(f, "| -> {}", sig.ret().display(f.db))?; | 966 | write!(f, "|| -> {}", return_type_hint)?; |
967 | } else if f.omit_verbose_types() { | ||
968 | write!(f, "|{}| -> {}", TYPE_HINT_TRUNCATION, return_type_hint)?; | ||
969 | } else { | ||
970 | write!(f, "|")?; | ||
971 | f.write_joined(sig.params(), ", ")?; | ||
972 | write!(f, "| -> {}", return_type_hint)?; | ||
973 | }; | ||
965 | } | 974 | } |
966 | } | 975 | } |
967 | Ok(()) | 976 | Ok(()) |
@@ -971,7 +980,7 @@ impl HirDisplay for ApplicationTy { | |||
971 | impl HirDisplay for ProjectionTy { | 980 | impl HirDisplay for ProjectionTy { |
972 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 981 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
973 | if f.should_truncate() { | 982 | if f.should_truncate() { |
974 | return write!(f, "…"); | 983 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
975 | } | 984 | } |
976 | 985 | ||
977 | let trait_name = f.db.trait_data(self.trait_(f.db)).name.clone(); | 986 | let trait_name = f.db.trait_data(self.trait_(f.db)).name.clone(); |
@@ -989,7 +998,7 @@ impl HirDisplay for ProjectionTy { | |||
989 | impl HirDisplay for Ty { | 998 | impl HirDisplay for Ty { |
990 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 999 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
991 | if f.should_truncate() { | 1000 | if f.should_truncate() { |
992 | return write!(f, "…"); | 1001 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
993 | } | 1002 | } |
994 | 1003 | ||
995 | match self { | 1004 | match self { |
@@ -1074,7 +1083,7 @@ impl HirDisplay for Ty { | |||
1074 | impl TraitRef { | 1083 | impl TraitRef { |
1075 | fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result { | 1084 | fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result { |
1076 | if f.should_truncate() { | 1085 | if f.should_truncate() { |
1077 | return write!(f, "…"); | 1086 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
1078 | } | 1087 | } |
1079 | 1088 | ||
1080 | self.substs[0].hir_fmt(f)?; | 1089 | self.substs[0].hir_fmt(f)?; |
@@ -1108,7 +1117,7 @@ impl HirDisplay for &GenericPredicate { | |||
1108 | impl HirDisplay for GenericPredicate { | 1117 | impl HirDisplay for GenericPredicate { |
1109 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 1118 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
1110 | if f.should_truncate() { | 1119 | if f.should_truncate() { |
1111 | return write!(f, "…"); | 1120 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
1112 | } | 1121 | } |
1113 | 1122 | ||
1114 | match self { | 1123 | match self { |
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index d447b4571..d1f10e675 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs | |||
@@ -11,8 +11,8 @@ use std::fmt::Write; | |||
11 | use std::sync::Arc; | 11 | use std::sync::Arc; |
12 | 12 | ||
13 | use hir_def::{ | 13 | use hir_def::{ |
14 | body::BodySourceMap, child_by_source::ChildBySource, db::DefDatabase, keys, | 14 | body::BodySourceMap, child_by_source::ChildBySource, db::DefDatabase, item_scope::ItemScope, |
15 | nameres::CrateDefMap, AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, | 15 | keys, nameres::CrateDefMap, AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, |
16 | }; | 16 | }; |
17 | use hir_expand::InFile; | 17 | use hir_expand::InFile; |
18 | use insta::assert_snapshot; | 18 | use insta::assert_snapshot; |
@@ -163,35 +163,69 @@ fn visit_module( | |||
163 | module_id: LocalModuleId, | 163 | module_id: LocalModuleId, |
164 | cb: &mut dyn FnMut(DefWithBodyId), | 164 | cb: &mut dyn FnMut(DefWithBodyId), |
165 | ) { | 165 | ) { |
166 | for decl in crate_def_map[module_id].scope.declarations() { | 166 | visit_scope(db, crate_def_map, &crate_def_map[module_id].scope, cb); |
167 | match decl { | ||
168 | ModuleDefId::FunctionId(it) => cb(it.into()), | ||
169 | ModuleDefId::ConstId(it) => cb(it.into()), | ||
170 | ModuleDefId::StaticId(it) => cb(it.into()), | ||
171 | ModuleDefId::TraitId(it) => { | ||
172 | let trait_data = db.trait_data(it); | ||
173 | for &(_, item) in trait_data.items.iter() { | ||
174 | match item { | ||
175 | AssocItemId::FunctionId(it) => cb(it.into()), | ||
176 | AssocItemId::ConstId(it) => cb(it.into()), | ||
177 | AssocItemId::TypeAliasId(_) => (), | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | ModuleDefId::ModuleId(it) => visit_module(db, crate_def_map, it.local_id, cb), | ||
182 | _ => (), | ||
183 | } | ||
184 | } | ||
185 | for impl_id in crate_def_map[module_id].scope.impls() { | 167 | for impl_id in crate_def_map[module_id].scope.impls() { |
186 | let impl_data = db.impl_data(impl_id); | 168 | let impl_data = db.impl_data(impl_id); |
187 | for &item in impl_data.items.iter() { | 169 | for &item in impl_data.items.iter() { |
188 | match item { | 170 | match item { |
189 | AssocItemId::FunctionId(it) => cb(it.into()), | 171 | AssocItemId::FunctionId(it) => { |
190 | AssocItemId::ConstId(it) => cb(it.into()), | 172 | let def = it.into(); |
173 | cb(def); | ||
174 | let body = db.body(def); | ||
175 | visit_scope(db, crate_def_map, &body.item_scope, cb); | ||
176 | } | ||
177 | AssocItemId::ConstId(it) => { | ||
178 | let def = it.into(); | ||
179 | cb(def); | ||
180 | let body = db.body(def); | ||
181 | visit_scope(db, crate_def_map, &body.item_scope, cb); | ||
182 | } | ||
191 | AssocItemId::TypeAliasId(_) => (), | 183 | AssocItemId::TypeAliasId(_) => (), |
192 | } | 184 | } |
193 | } | 185 | } |
194 | } | 186 | } |
187 | |||
188 | fn visit_scope( | ||
189 | db: &TestDB, | ||
190 | crate_def_map: &CrateDefMap, | ||
191 | scope: &ItemScope, | ||
192 | cb: &mut dyn FnMut(DefWithBodyId), | ||
193 | ) { | ||
194 | for decl in scope.declarations() { | ||
195 | match decl { | ||
196 | ModuleDefId::FunctionId(it) => { | ||
197 | let def = it.into(); | ||
198 | cb(def); | ||
199 | let body = db.body(def); | ||
200 | visit_scope(db, crate_def_map, &body.item_scope, cb); | ||
201 | } | ||
202 | ModuleDefId::ConstId(it) => { | ||
203 | let def = it.into(); | ||
204 | cb(def); | ||
205 | let body = db.body(def); | ||
206 | visit_scope(db, crate_def_map, &body.item_scope, cb); | ||
207 | } | ||
208 | ModuleDefId::StaticId(it) => { | ||
209 | let def = it.into(); | ||
210 | cb(def); | ||
211 | let body = db.body(def); | ||
212 | visit_scope(db, crate_def_map, &body.item_scope, cb); | ||
213 | } | ||
214 | ModuleDefId::TraitId(it) => { | ||
215 | let trait_data = db.trait_data(it); | ||
216 | for &(_, item) in trait_data.items.iter() { | ||
217 | match item { | ||
218 | AssocItemId::FunctionId(it) => cb(it.into()), | ||
219 | AssocItemId::ConstId(it) => cb(it.into()), | ||
220 | AssocItemId::TypeAliasId(_) => (), | ||
221 | } | ||
222 | } | ||
223 | } | ||
224 | ModuleDefId::ModuleId(it) => visit_module(db, crate_def_map, it.local_id, cb), | ||
225 | _ => (), | ||
226 | } | ||
227 | } | ||
228 | } | ||
195 | } | 229 | } |
196 | 230 | ||
197 | fn ellipsize(mut text: String, max_len: usize) -> String { | 231 | fn ellipsize(mut text: String, max_len: usize) -> String { |
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs index 09d684ac2..8b3aa8564 100644 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ b/crates/ra_hir_ty/src/tests/regression.rs | |||
@@ -1,7 +1,8 @@ | |||
1 | use super::infer; | ||
2 | use insta::assert_snapshot; | 1 | use insta::assert_snapshot; |
3 | use test_utils::covers; | 2 | use test_utils::covers; |
4 | 3 | ||
4 | use super::infer; | ||
5 | |||
5 | #[test] | 6 | #[test] |
6 | fn bug_484() { | 7 | fn bug_484() { |
7 | assert_snapshot!( | 8 | assert_snapshot!( |
@@ -331,3 +332,36 @@ pub fn main_loop() { | |||
331 | "### | 332 | "### |
332 | ); | 333 | ); |
333 | } | 334 | } |
335 | |||
336 | #[test] | ||
337 | fn issue_2669() { | ||
338 | assert_snapshot!( | ||
339 | infer( | ||
340 | r#"trait A {} | ||
341 | trait Write {} | ||
342 | struct Response<T> {} | ||
343 | |||
344 | trait D { | ||
345 | fn foo(); | ||
346 | } | ||
347 | |||
348 | impl<T:A> D for Response<T> { | ||
349 | fn foo() { | ||
350 | end(); | ||
351 | fn end<W: Write>() { | ||
352 | let _x: T = loop {}; | ||
353 | } | ||
354 | } | ||
355 | }"# | ||
356 | ), | ||
357 | @r###" | ||
358 | [147; 262) '{ ... }': () | ||
359 | [161; 164) 'end': fn end<{unknown}>() -> () | ||
360 | [161; 166) 'end()': () | ||
361 | [199; 252) '{ ... }': () | ||
362 | [221; 223) '_x': ! | ||
363 | [230; 237) 'loop {}': ! | ||
364 | [235; 237) '{}': () | ||
365 | "### | ||
366 | ) | ||
367 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index 3e5e163e3..00134c99b 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -1518,6 +1518,7 @@ fn test() { | |||
1518 | [167; 179) 'GLOBAL_CONST': u32 | 1518 | [167; 179) 'GLOBAL_CONST': u32 |
1519 | [189; 191) 'id': u32 | 1519 | [189; 191) 'id': u32 |
1520 | [194; 210) 'Foo::A..._CONST': u32 | 1520 | [194; 210) 'Foo::A..._CONST': u32 |
1521 | [126; 128) '99': u32 | ||
1521 | "### | 1522 | "### |
1522 | ); | 1523 | ); |
1523 | } | 1524 | } |
@@ -1549,6 +1550,8 @@ fn test() { | |||
1549 | [233; 246) 'GLOBAL_STATIC': u32 | 1550 | [233; 246) 'GLOBAL_STATIC': u32 |
1550 | [256; 257) 'w': u32 | 1551 | [256; 257) 'w': u32 |
1551 | [260; 277) 'GLOBAL...IC_MUT': u32 | 1552 | [260; 277) 'GLOBAL...IC_MUT': u32 |
1553 | [118; 120) '99': u32 | ||
1554 | [161; 163) '99': u32 | ||
1552 | "### | 1555 | "### |
1553 | ); | 1556 | ); |
1554 | } | 1557 | } |
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index ae316922b..0bc72644a 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -38,6 +38,63 @@ mod future { | |||
38 | } | 38 | } |
39 | 39 | ||
40 | #[test] | 40 | #[test] |
41 | fn infer_async() { | ||
42 | let (db, pos) = TestDB::with_position( | ||
43 | r#" | ||
44 | //- /main.rs crate:main deps:std | ||
45 | |||
46 | async fn foo() -> u64 { | ||
47 | 128 | ||
48 | } | ||
49 | |||
50 | fn test() { | ||
51 | let r = foo(); | ||
52 | let v = r.await; | ||
53 | v<|>; | ||
54 | } | ||
55 | |||
56 | //- /std.rs crate:std | ||
57 | #[prelude_import] use future::*; | ||
58 | mod future { | ||
59 | trait Future { | ||
60 | type Output; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | "#, | ||
65 | ); | ||
66 | assert_eq!("u64", type_at_pos(&db, pos)); | ||
67 | } | ||
68 | |||
69 | #[test] | ||
70 | fn infer_desugar_async() { | ||
71 | let (db, pos) = TestDB::with_position( | ||
72 | r#" | ||
73 | //- /main.rs crate:main deps:std | ||
74 | |||
75 | async fn foo() -> u64 { | ||
76 | 128 | ||
77 | } | ||
78 | |||
79 | fn test() { | ||
80 | let r = foo(); | ||
81 | r<|>; | ||
82 | } | ||
83 | |||
84 | //- /std.rs crate:std | ||
85 | #[prelude_import] use future::*; | ||
86 | mod future { | ||
87 | trait Future { | ||
88 | type Output; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | "#, | ||
93 | ); | ||
94 | assert_eq!("impl Future<Output = u64>", type_at_pos(&db, pos)); | ||
95 | } | ||
96 | |||
97 | #[test] | ||
41 | fn infer_try() { | 98 | fn infer_try() { |
42 | let (db, pos) = TestDB::with_position( | 99 | let (db, pos) = TestDB::with_position( |
43 | r#" | 100 | r#" |