diff options
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r-- | crates/ra_hir_ty/src/infer.rs | 36 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 41 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests.rs | 50 |
3 files changed, 127 insertions, 0 deletions
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index f6283ab6d..fe259371f 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -577,6 +577,42 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
577 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; | 577 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; |
578 | Some(struct_.into()) | 578 | Some(struct_.into()) |
579 | } | 579 | } |
580 | |||
581 | fn resolve_range_full(&self) -> Option<AdtId> { | ||
582 | let path = known::std_ops_range_full(); | ||
583 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; | ||
584 | Some(struct_.into()) | ||
585 | } | ||
586 | |||
587 | fn resolve_range(&self) -> Option<AdtId> { | ||
588 | let path = known::std_ops_range(); | ||
589 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; | ||
590 | Some(struct_.into()) | ||
591 | } | ||
592 | |||
593 | fn resolve_range_inclusive(&self) -> Option<AdtId> { | ||
594 | let path = known::std_ops_range_inclusive(); | ||
595 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; | ||
596 | Some(struct_.into()) | ||
597 | } | ||
598 | |||
599 | fn resolve_range_from(&self) -> Option<AdtId> { | ||
600 | let path = known::std_ops_range_from(); | ||
601 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; | ||
602 | Some(struct_.into()) | ||
603 | } | ||
604 | |||
605 | fn resolve_range_to(&self) -> Option<AdtId> { | ||
606 | let path = known::std_ops_range_to(); | ||
607 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; | ||
608 | Some(struct_.into()) | ||
609 | } | ||
610 | |||
611 | fn resolve_range_to_inclusive(&self) -> Option<AdtId> { | ||
612 | let path = known::std_ops_range_to_inclusive(); | ||
613 | let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; | ||
614 | Some(struct_.into()) | ||
615 | } | ||
580 | } | 616 | } |
581 | 617 | ||
582 | /// The ID of a type variable. | 618 | /// The ID of a type variable. |
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 2f9ca4bbb..a00aa426a 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -415,6 +415,47 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
415 | } | 415 | } |
416 | _ => Ty::Unknown, | 416 | _ => Ty::Unknown, |
417 | }, | 417 | }, |
418 | Expr::RangeFull => match self.resolve_range_full() { | ||
419 | Some(adt) => Ty::simple(TypeCtor::Adt(adt)), | ||
420 | None => Ty::Unknown, | ||
421 | }, | ||
422 | Expr::Range { lhs, rhs } => { | ||
423 | let lhs_ty = self.infer_expr(*lhs, &Expectation::none()); | ||
424 | let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(lhs_ty)); | ||
425 | match self.resolve_range() { | ||
426 | Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), rhs_ty), | ||
427 | None => Ty::Unknown, | ||
428 | } | ||
429 | } | ||
430 | Expr::RangeInclusive { lhs, rhs } => { | ||
431 | let lhs_ty = self.infer_expr(*lhs, &Expectation::none()); | ||
432 | let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(lhs_ty)); | ||
433 | match self.resolve_range_inclusive() { | ||
434 | Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), rhs_ty), | ||
435 | None => Ty::Unknown, | ||
436 | } | ||
437 | } | ||
438 | Expr::RangeFrom { lhs } => { | ||
439 | let ty = self.infer_expr(*lhs, &Expectation::none()); | ||
440 | match self.resolve_range_from() { | ||
441 | Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), | ||
442 | None => Ty::Unknown, | ||
443 | } | ||
444 | } | ||
445 | Expr::RangeTo { rhs } => { | ||
446 | let ty = self.infer_expr(*rhs, &Expectation::none()); | ||
447 | match self.resolve_range_to() { | ||
448 | Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), | ||
449 | None => Ty::Unknown, | ||
450 | } | ||
451 | } | ||
452 | Expr::RangeToInclusive { rhs } => { | ||
453 | let ty = self.infer_expr(*rhs, &Expectation::none()); | ||
454 | match self.resolve_range_to_inclusive() { | ||
455 | Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), | ||
456 | None => Ty::Unknown, | ||
457 | } | ||
458 | } | ||
418 | Expr::Index { base, index } => { | 459 | Expr::Index { base, index } => { |
419 | let _base_ty = self.infer_expr(*base, &Expectation::none()); | 460 | let _base_ty = self.infer_expr(*base, &Expectation::none()); |
420 | let _index_ty = self.infer_expr(*index, &Expectation::none()); | 461 | let _index_ty = self.infer_expr(*index, &Expectation::none()); |
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index abbc1546c..4ba87e667 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs | |||
@@ -222,6 +222,56 @@ mod collections { | |||
222 | } | 222 | } |
223 | 223 | ||
224 | #[test] | 224 | #[test] |
225 | fn infer_ranges() { | ||
226 | let (db, pos) = TestDB::with_position( | ||
227 | r#" | ||
228 | //- /main.rs crate:main deps:std | ||
229 | fn test() { | ||
230 | let a = ..; | ||
231 | let b = 1..; | ||
232 | let c = ..2u32; | ||
233 | let d = 1..2usize; | ||
234 | let e = ..=10; | ||
235 | let f = 'a'..='z'; | ||
236 | |||
237 | let t = (a, b, c, d, e, f); | ||
238 | t<|>; | ||
239 | } | ||
240 | |||
241 | //- /std.rs crate:std | ||
242 | #[prelude_import] use prelude::*; | ||
243 | mod prelude {} | ||
244 | |||
245 | pub mod ops { | ||
246 | pub struct Range<Idx> { | ||
247 | pub start: Idx, | ||
248 | pub end: Idx, | ||
249 | } | ||
250 | pub struct RangeFrom<Idx> { | ||
251 | pub start: Idx, | ||
252 | } | ||
253 | struct RangeFull; | ||
254 | pub struct RangeInclusive<Idx> { | ||
255 | start: Idx, | ||
256 | end: Idx, | ||
257 | is_empty: u8, | ||
258 | } | ||
259 | pub struct RangeTo<Idx> { | ||
260 | pub end: Idx, | ||
261 | } | ||
262 | pub struct RangeToInclusive<Idx> { | ||
263 | pub end: Idx, | ||
264 | } | ||
265 | } | ||
266 | "#, | ||
267 | ); | ||
268 | assert_eq!( | ||
269 | "(RangeFull, RangeFrom<i32>, RangeTo<u32>, Range<usize>, RangeToInclusive<i32>, RangeInclusive<char>)", | ||
270 | type_at_pos(&db, pos), | ||
271 | ); | ||
272 | } | ||
273 | |||
274 | #[test] | ||
225 | fn infer_while_let() { | 275 | fn infer_while_let() { |
226 | let (db, pos) = TestDB::with_position( | 276 | let (db, pos) = TestDB::with_position( |
227 | r#" | 277 | r#" |