aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-11-29 19:34:02 +0000
committerGitHub <[email protected]>2019-11-29 19:34:02 +0000
commit10c8e5eecb97f8f89e599d27df658cbcc3015c8e (patch)
treef93ef014cc82793949e8567634cec341ffc58d62 /crates/ra_hir_ty
parent8b278b1ab660df0728508e45e88ac769a2e03a58 (diff)
parent2cb684bbce1c487b2efb5a8154afe66e4907ceac (diff)
Merge #2445
2445: Infer range types r=flodiebold a=oxalica Co-authored-by: oxalica <[email protected]>
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.rs39
-rw-r--r--crates/ra_hir_ty/src/tests.rs50
3 files changed, 125 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..4014f4732 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -12,6 +12,7 @@ use hir_def::{
12 AdtId, ContainerId, Lookup, StructFieldId, 12 AdtId, ContainerId, Lookup, StructFieldId,
13}; 13};
14use hir_expand::name::{self, Name}; 14use hir_expand::name::{self, Name};
15use ra_syntax::ast::RangeOp;
15 16
16use crate::{ 17use crate::{
17 autoderef, db::HirDatabase, method_resolution, op, traits::InEnvironment, utils::variant_data, 18 autoderef, db::HirDatabase, method_resolution, op, traits::InEnvironment, utils::variant_data,
@@ -415,6 +416,44 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
415 } 416 }
416 _ => Ty::Unknown, 417 _ => Ty::Unknown,
417 }, 418 },
419 Expr::Range { lhs, rhs, range_type } => {
420 let lhs_ty = lhs.map(|e| self.infer_expr(e, &Expectation::none()));
421 let rhs_expect = lhs_ty
422 .as_ref()
423 .map_or_else(Expectation::none, |ty| Expectation::has_type(ty.clone()));
424 let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect));
425 match (range_type, lhs_ty, rhs_ty) {
426 (RangeOp::Exclusive, None, None) => match self.resolve_range_full() {
427 Some(adt) => Ty::simple(TypeCtor::Adt(adt)),
428 None => Ty::Unknown,
429 },
430 (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() {
431 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty),
432 None => Ty::Unknown,
433 },
434 (RangeOp::Inclusive, None, Some(ty)) => {
435 match self.resolve_range_to_inclusive() {
436 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty),
437 None => Ty::Unknown,
438 }
439 }
440 (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() {
441 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty),
442 None => Ty::Unknown,
443 },
444 (RangeOp::Inclusive, Some(_), Some(ty)) => {
445 match self.resolve_range_inclusive() {
446 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty),
447 None => Ty::Unknown,
448 }
449 }
450 (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() {
451 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty),
452 None => Ty::Unknown,
453 },
454 (RangeOp::Inclusive, _, None) => Ty::Unknown,
455 }
456 }
418 Expr::Index { base, index } => { 457 Expr::Index { base, index } => {
419 let _base_ty = self.infer_expr(*base, &Expectation::none()); 458 let _base_ty = self.infer_expr(*base, &Expectation::none());
420 let _index_ty = self.infer_expr(*index, &Expectation::none()); 459 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#"