aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty
diff options
context:
space:
mode:
authoroxalica <[email protected]>2019-11-28 19:10:16 +0000
committeroxalica <[email protected]>2019-11-28 19:10:16 +0000
commit4992d2bf79e9da6db759eb8e1715f90f31ec7eb9 (patch)
tree9396eb224a6865aa76c64937bc88c02b6ade04b8 /crates/ra_hir_ty
parent8b278b1ab660df0728508e45e88ac769a2e03a58 (diff)
Infer range types
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r--crates/ra_hir_ty/src/infer.rs36
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs41
-rw-r--r--crates/ra_hir_ty/src/tests.rs50
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]
225fn infer_ranges() {
226 let (db, pos) = TestDB::with_position(
227 r#"
228//- /main.rs crate:main deps:std
229fn 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::*;
243mod prelude {}
244
245pub 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]
225fn infer_while_let() { 275fn infer_while_let() {
226 let (db, pos) = TestDB::with_position( 276 let (db, pos) = TestDB::with_position(
227 r#" 277 r#"