diff options
Diffstat (limited to 'crates/hir_ty')
-rw-r--r-- | crates/hir_ty/src/diagnostics/match_check.rs | 40 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 3 | ||||
-rw-r--r-- | crates/hir_ty/src/lower.rs | 12 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/macros.rs | 123 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 43 |
5 files changed, 186 insertions, 35 deletions
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index 5a5cdcbf3..9cb472b51 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs | |||
@@ -539,7 +539,7 @@ impl Matrix { | |||
539 | if let Some(Pat::Or(pat_ids)) = row.get_head().map(|pat_id| pat_id.as_pat(cx)) { | 539 | if let Some(Pat::Or(pat_ids)) = row.get_head().map(|pat_id| pat_id.as_pat(cx)) { |
540 | // Or patterns are expanded here | 540 | // Or patterns are expanded here |
541 | for pat_id in pat_ids { | 541 | for pat_id in pat_ids { |
542 | self.0.push(PatStack::from_pattern(pat_id)); | 542 | self.0.push(row.replace_head_with([pat_id].iter())); |
543 | } | 543 | } |
544 | } else { | 544 | } else { |
545 | self.0.push(row); | 545 | self.0.push(row); |
@@ -1085,6 +1085,20 @@ fn main() { | |||
1085 | } | 1085 | } |
1086 | 1086 | ||
1087 | #[test] | 1087 | #[test] |
1088 | fn or_pattern_no_diagnostic() { | ||
1089 | check_diagnostics( | ||
1090 | r#" | ||
1091 | enum Either {A, B} | ||
1092 | |||
1093 | fn main() { | ||
1094 | match (Either::A, Either::B) { | ||
1095 | (Either::A | Either::B, _) => (), | ||
1096 | } | ||
1097 | }"#, | ||
1098 | ) | ||
1099 | } | ||
1100 | |||
1101 | #[test] | ||
1088 | fn mismatched_types() { | 1102 | fn mismatched_types() { |
1089 | // Match statements with arms that don't match the | 1103 | // Match statements with arms that don't match the |
1090 | // expression pattern do not fire this diagnostic. | 1104 | // expression pattern do not fire this diagnostic. |
@@ -1336,30 +1350,6 @@ fn bang(never: !) { | |||
1336 | } | 1350 | } |
1337 | 1351 | ||
1338 | #[test] | 1352 | #[test] |
1339 | fn or_pattern_panic() { | ||
1340 | check_diagnostics( | ||
1341 | r#" | ||
1342 | pub enum Category { Infinity, Zero } | ||
1343 | |||
1344 | fn panic(a: Category, b: Category) { | ||
1345 | match (a, b) { | ||
1346 | (Category::Zero | Category::Infinity, _) => (), | ||
1347 | (_, Category::Zero | Category::Infinity) => (), | ||
1348 | } | ||
1349 | |||
1350 | // FIXME: This is a false positive, but the code used to cause a panic in the match checker, | ||
1351 | // so this acts as a regression test for that. | ||
1352 | match (a, b) { | ||
1353 | //^^^^^^ Missing match arm | ||
1354 | (Category::Infinity, Category::Infinity) | (Category::Zero, Category::Zero) => (), | ||
1355 | (Category::Infinity | Category::Zero, _) => (), | ||
1356 | } | ||
1357 | } | ||
1358 | "#, | ||
1359 | ); | ||
1360 | } | ||
1361 | |||
1362 | #[test] | ||
1363 | fn unknown_type() { | 1353 | fn unknown_type() { |
1364 | check_diagnostics( | 1354 | check_diagnostics( |
1365 | r#" | 1355 | r#" |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 3f3187ea2..6279aa572 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -119,6 +119,8 @@ impl<'a> InferenceContext<'a> { | |||
119 | } | 119 | } |
120 | 120 | ||
121 | fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { | 121 | fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { |
122 | self.db.check_canceled(); | ||
123 | |||
122 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 124 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
123 | let ty = match &body[tgt_expr] { | 125 | let ty = match &body[tgt_expr] { |
124 | Expr::Missing => self.err_ty(), | 126 | Expr::Missing => self.err_ty(), |
@@ -767,6 +769,7 @@ impl<'a> InferenceContext<'a> { | |||
767 | None => self.table.new_float_var(), | 769 | None => self.table.new_float_var(), |
768 | }, | 770 | }, |
769 | }, | 771 | }, |
772 | Expr::MacroStmts { tail } => self.infer_expr(*tail, expected), | ||
770 | }; | 773 | }; |
771 | // use a new type variable if we got unknown here | 774 | // use a new type variable if we got unknown here |
772 | let ty = self.insert_type_vars_shallow(ty); | 775 | let ty = self.insert_type_vars_shallow(ty); |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index c87789d45..afbfa12d5 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -15,7 +15,7 @@ use hir_def::{ | |||
15 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, | 15 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, |
16 | path::{GenericArg, Path, PathSegment, PathSegments}, | 16 | path::{GenericArg, Path, PathSegment, PathSegments}, |
17 | resolver::{HasResolver, Resolver, TypeNs}, | 17 | resolver::{HasResolver, Resolver, TypeNs}, |
18 | type_ref::{TypeBound, TypeRef}, | 18 | type_ref::{TraitRef as HirTraitRef, TypeBound, TypeRef}, |
19 | AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, | 19 | AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, |
20 | GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, | 20 | GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, |
21 | TypeAliasId, TypeParamId, UnionId, VariantId, | 21 | TypeAliasId, TypeParamId, UnionId, VariantId, |
@@ -667,14 +667,10 @@ impl<'a> TyLoweringContext<'a> { | |||
667 | 667 | ||
668 | fn lower_trait_ref( | 668 | fn lower_trait_ref( |
669 | &self, | 669 | &self, |
670 | type_ref: &TypeRef, | 670 | trait_ref: &HirTraitRef, |
671 | explicit_self_ty: Option<Ty>, | 671 | explicit_self_ty: Option<Ty>, |
672 | ) -> Option<TraitRef> { | 672 | ) -> Option<TraitRef> { |
673 | let path = match type_ref { | 673 | self.lower_trait_ref_from_path(&trait_ref.path, explicit_self_ty) |
674 | TypeRef::Path(path) => path, | ||
675 | _ => return None, | ||
676 | }; | ||
677 | self.lower_trait_ref_from_path(path, explicit_self_ty) | ||
678 | } | 674 | } |
679 | 675 | ||
680 | fn trait_ref_substs_from_path( | 676 | fn trait_ref_substs_from_path( |
@@ -1253,7 +1249,7 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde | |||
1253 | let generics = generics(db.upcast(), impl_id.into()); | 1249 | let generics = generics(db.upcast(), impl_id.into()); |
1254 | let ctx = | 1250 | let ctx = |
1255 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | 1251 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
1256 | Binders::new(generics.len(), ctx.lower_ty(&impl_data.target_type)) | 1252 | Binders::new(generics.len(), ctx.lower_ty(&impl_data.self_ty)) |
1257 | } | 1253 | } |
1258 | 1254 | ||
1259 | pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty { | 1255 | pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty { |
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index 7eda51866..3eb01dbd0 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -135,7 +135,88 @@ fn infer_path_qualified_macros_expanded() { | |||
135 | } | 135 | } |
136 | 136 | ||
137 | #[test] | 137 | #[test] |
138 | fn expr_macro_expanded_in_various_places() { | 138 | fn expr_macro_def_expanded_in_various_places() { |
139 | check_infer( | ||
140 | r#" | ||
141 | macro spam() { | ||
142 | 1isize | ||
143 | } | ||
144 | |||
145 | fn spam() { | ||
146 | spam!(); | ||
147 | (spam!()); | ||
148 | spam!().spam(spam!()); | ||
149 | for _ in spam!() {} | ||
150 | || spam!(); | ||
151 | while spam!() {} | ||
152 | break spam!(); | ||
153 | return spam!(); | ||
154 | match spam!() { | ||
155 | _ if spam!() => spam!(), | ||
156 | } | ||
157 | spam!()(spam!()); | ||
158 | Spam { spam: spam!() }; | ||
159 | spam!()[spam!()]; | ||
160 | await spam!(); | ||
161 | spam!() as usize; | ||
162 | &spam!(); | ||
163 | -spam!(); | ||
164 | spam!()..spam!(); | ||
165 | spam!() + spam!(); | ||
166 | } | ||
167 | "#, | ||
168 | expect![[r#" | ||
169 | !0..6 '1isize': isize | ||
170 | !0..6 '1isize': isize | ||
171 | !0..6 '1isize': isize | ||
172 | !0..6 '1isize': isize | ||
173 | !0..6 '1isize': isize | ||
174 | !0..6 '1isize': isize | ||
175 | !0..6 '1isize': isize | ||
176 | !0..6 '1isize': isize | ||
177 | !0..6 '1isize': isize | ||
178 | !0..6 '1isize': isize | ||
179 | !0..6 '1isize': isize | ||
180 | !0..6 '1isize': isize | ||
181 | !0..6 '1isize': isize | ||
182 | !0..6 '1isize': isize | ||
183 | !0..6 '1isize': isize | ||
184 | !0..6 '1isize': isize | ||
185 | !0..6 '1isize': isize | ||
186 | !0..6 '1isize': isize | ||
187 | !0..6 '1isize': isize | ||
188 | !0..6 '1isize': isize | ||
189 | !0..6 '1isize': isize | ||
190 | !0..6 '1isize': isize | ||
191 | !0..6 '1isize': isize | ||
192 | !0..6 '1isize': isize | ||
193 | !0..6 '1isize': isize | ||
194 | 39..442 '{ ...!(); }': () | ||
195 | 73..94 'spam!(...am!())': {unknown} | ||
196 | 100..119 'for _ ...!() {}': () | ||
197 | 104..105 '_': {unknown} | ||
198 | 117..119 '{}': () | ||
199 | 124..134 '|| spam!()': || -> isize | ||
200 | 140..156 'while ...!() {}': () | ||
201 | 154..156 '{}': () | ||
202 | 161..174 'break spam!()': ! | ||
203 | 180..194 'return spam!()': ! | ||
204 | 200..254 'match ... }': isize | ||
205 | 224..225 '_': isize | ||
206 | 259..275 'spam!(...am!())': {unknown} | ||
207 | 281..303 'Spam {...m!() }': {unknown} | ||
208 | 309..325 'spam!(...am!()]': {unknown} | ||
209 | 350..366 'spam!(... usize': usize | ||
210 | 372..380 '&spam!()': &isize | ||
211 | 386..394 '-spam!()': isize | ||
212 | 400..416 'spam!(...pam!()': {unknown} | ||
213 | 422..439 'spam!(...pam!()': isize | ||
214 | "#]], | ||
215 | ); | ||
216 | } | ||
217 | |||
218 | #[test] | ||
219 | fn expr_macro_rules_expanded_in_various_places() { | ||
139 | check_infer( | 220 | check_infer( |
140 | r#" | 221 | r#" |
141 | macro_rules! spam { | 222 | macro_rules! spam { |
@@ -226,12 +307,49 @@ fn expr_macro_expanded_in_stmts() { | |||
226 | "#, | 307 | "#, |
227 | expect![[r#" | 308 | expect![[r#" |
228 | !0..8 'leta=();': () | 309 | !0..8 'leta=();': () |
310 | !0..8 'leta=();': () | ||
311 | !3..4 'a': () | ||
312 | !5..7 '()': () | ||
229 | 57..84 '{ ...); } }': () | 313 | 57..84 '{ ...); } }': () |
230 | "#]], | 314 | "#]], |
231 | ); | 315 | ); |
232 | } | 316 | } |
233 | 317 | ||
234 | #[test] | 318 | #[test] |
319 | fn recurisve_macro_expanded_in_stmts() { | ||
320 | check_infer( | ||
321 | r#" | ||
322 | macro_rules! ng { | ||
323 | ([$($tts:tt)*]) => { | ||
324 | $($tts)*; | ||
325 | }; | ||
326 | ([$($tts:tt)*] $head:tt $($rest:tt)*) => { | ||
327 | ng! { | ||
328 | [$($tts)* $head] $($rest)* | ||
329 | } | ||
330 | }; | ||
331 | } | ||
332 | fn foo() { | ||
333 | ng!([] let a = 3); | ||
334 | let b = a; | ||
335 | } | ||
336 | "#, | ||
337 | expect![[r#" | ||
338 | !0..7 'leta=3;': {unknown} | ||
339 | !0..7 'leta=3;': {unknown} | ||
340 | !0..13 'ng!{[leta=3]}': {unknown} | ||
341 | !0..13 'ng!{[leta=]3}': {unknown} | ||
342 | !0..13 'ng!{[leta]=3}': {unknown} | ||
343 | !3..4 'a': i32 | ||
344 | !5..6 '3': i32 | ||
345 | 196..237 '{ ...= a; }': () | ||
346 | 229..230 'b': i32 | ||
347 | 233..234 'a': i32 | ||
348 | "#]], | ||
349 | ); | ||
350 | } | ||
351 | |||
352 | #[test] | ||
235 | fn recursive_inner_item_macro_rules() { | 353 | fn recursive_inner_item_macro_rules() { |
236 | check_infer( | 354 | check_infer( |
237 | r#" | 355 | r#" |
@@ -246,7 +364,8 @@ fn recursive_inner_item_macro_rules() { | |||
246 | "#, | 364 | "#, |
247 | expect![[r#" | 365 | expect![[r#" |
248 | !0..1 '1': i32 | 366 | !0..1 '1': i32 |
249 | !0..7 'mac!($)': {unknown} | 367 | !0..26 'macro_...>{1};}': {unknown} |
368 | !0..26 'macro_...>{1};}': {unknown} | ||
250 | 107..143 '{ ...!(); }': () | 369 | 107..143 '{ ...!(); }': () |
251 | 129..130 'a': i32 | 370 | 129..130 'a': i32 |
252 | "#]], | 371 | "#]], |
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 2ba97f814..65b71fdfa 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -3370,3 +3370,46 @@ fn test() { | |||
3370 | "#]], | 3370 | "#]], |
3371 | ) | 3371 | ) |
3372 | } | 3372 | } |
3373 | |||
3374 | #[test] | ||
3375 | fn qualified_path_as_qualified_trait() { | ||
3376 | check_infer( | ||
3377 | r#" | ||
3378 | mod foo { | ||
3379 | |||
3380 | pub trait Foo { | ||
3381 | type Target; | ||
3382 | } | ||
3383 | pub trait Bar { | ||
3384 | type Output; | ||
3385 | fn boo() -> Self::Output { | ||
3386 | loop {} | ||
3387 | } | ||
3388 | } | ||
3389 | } | ||
3390 | |||
3391 | struct F; | ||
3392 | impl foo::Foo for F { | ||
3393 | type Target = (); | ||
3394 | } | ||
3395 | impl foo::Bar for F { | ||
3396 | type Output = <F as foo::Foo>::Target; | ||
3397 | } | ||
3398 | |||
3399 | fn foo() { | ||
3400 | use foo::Bar; | ||
3401 | let x = <F as Bar>::boo(); | ||
3402 | } | ||
3403 | |||
3404 | "#, | ||
3405 | expect![[r#" | ||
3406 | 132..163 '{ ... }': Bar::Output<Self> | ||
3407 | 146..153 'loop {}': ! | ||
3408 | 151..153 '{}': () | ||
3409 | 306..358 '{ ...o(); }': () | ||
3410 | 334..335 'x': () | ||
3411 | 338..353 '<F as Bar>::boo': fn boo<F>() -> <F as Bar>::Output | ||
3412 | 338..355 '<F as ...:boo()': () | ||
3413 | "#]], | ||
3414 | ); | ||
3415 | } | ||