diff options
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 120 |
1 files changed, 55 insertions, 65 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index bf57bb3b7..3981de829 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -44,11 +44,12 @@ use crate::{ | |||
44 | generics::{GenericParams, HasGenericParams}, | 44 | generics::{GenericParams, HasGenericParams}, |
45 | name, | 45 | name, |
46 | nameres::Namespace, | 46 | nameres::Namespace, |
47 | path::{GenericArg, GenericArgs, PathKind, PathSegment}, | 47 | path::{GenericArg, GenericArgs, PathKind}, |
48 | resolve::{Resolver, TypeNs, ValueNs, ValueOrPartial}, | 48 | resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs}, |
49 | ty::infer::diagnostics::InferenceDiagnostic, | 49 | ty::infer::diagnostics::InferenceDiagnostic, |
50 | type_ref::{Mutability, TypeRef}, | 50 | type_ref::{Mutability, TypeRef}, |
51 | Adt, ConstData, DefWithBody, FnData, Function, HasBody, ImplItem, Name, Path, StructField, | 51 | Adt, ConstData, DefWithBody, Either, FnData, Function, HasBody, ImplItem, Name, Path, |
52 | StructField, | ||
52 | }; | 53 | }; |
53 | 54 | ||
54 | mod unify; | 55 | mod unify; |
@@ -470,9 +471,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
470 | let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?; | 471 | let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?; |
471 | 472 | ||
472 | let (value, self_subst) = match value_or_partial { | 473 | let (value, self_subst) = match value_or_partial { |
473 | ValueOrPartial::ValueNs(it) => (it, None), | 474 | ResolveValueResult::ValueNs(it) => (it, None), |
474 | ValueOrPartial::Partial(def, remaining_index) => { | 475 | ResolveValueResult::Partial(def, remaining_index) => { |
475 | self.resolve_assoc_item(def, path, remaining_index, id)? | 476 | self.resolve_assoc_item(Either::A(def), path, remaining_index, id)? |
477 | } | ||
478 | ResolveValueResult::TypeRef(type_ref) => { | ||
479 | let ty = self.make_ty(type_ref); | ||
480 | self.resolve_assoc_item(Either::B(ty), path, 0, id)? | ||
476 | } | 481 | } |
477 | }; | 482 | }; |
478 | 483 | ||
@@ -503,7 +508,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
503 | 508 | ||
504 | fn resolve_assoc_item( | 509 | fn resolve_assoc_item( |
505 | &mut self, | 510 | &mut self, |
506 | mut def: TypeNs, | 511 | mut def_or_ty: Either<TypeNs, Ty>, |
507 | path: &Path, | 512 | path: &Path, |
508 | remaining_index: usize, | 513 | remaining_index: usize, |
509 | id: ExprOrPatId, | 514 | id: ExprOrPatId, |
@@ -516,30 +521,33 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
516 | // resolve intermediate segments | 521 | // resolve intermediate segments |
517 | for (i, segment) in path.segments[remaining_index..].iter().enumerate() { | 522 | for (i, segment) in path.segments[remaining_index..].iter().enumerate() { |
518 | let is_last_segment = i == path.segments[remaining_index..].len() - 1; | 523 | let is_last_segment = i == path.segments[remaining_index..].len() - 1; |
519 | ty = { | 524 | ty = match def_or_ty { |
520 | let typable: TypableDef = match def { | 525 | Either::A(def) => { |
521 | TypeNs::Adt(it) => it.into(), | 526 | let typable: TypableDef = match def { |
522 | TypeNs::TypeAlias(it) => it.into(), | 527 | TypeNs::Adt(it) => it.into(), |
523 | TypeNs::BuiltinType(it) => it.into(), | 528 | TypeNs::TypeAlias(it) => it.into(), |
524 | // FIXME associated item of traits, generics, and Self | 529 | TypeNs::BuiltinType(it) => it.into(), |
525 | TypeNs::Trait(_) | TypeNs::GenericParam(_) | TypeNs::SelfType(_) => { | 530 | // FIXME associated item of traits, generics, and Self |
526 | return None; | 531 | TypeNs::Trait(_) | TypeNs::GenericParam(_) | TypeNs::SelfType(_) => { |
527 | } | 532 | return None; |
528 | // FIXME: report error here | 533 | } |
529 | TypeNs::EnumVariant(_) => return None, | 534 | // FIXME: report error here |
530 | }; | 535 | TypeNs::EnumVariant(_) => return None, |
531 | 536 | }; | |
532 | let ty = self.db.type_for_def(typable, Namespace::Types); | ||
533 | 537 | ||
534 | // For example, this substs will take `Gen::*<u32>*::make` | 538 | let ty = self.db.type_for_def(typable, Namespace::Types); |
535 | assert!(remaining_index > 0); | 539 | |
536 | let substs = Ty::substs_from_path_segment( | 540 | // For example, this substs will take `Gen::*<u32>*::make` |
537 | self.db, | 541 | assert!(remaining_index > 0); |
538 | &self.resolver, | 542 | let substs = Ty::substs_from_path_segment( |
539 | &path.segments[remaining_index + i - 1], | 543 | self.db, |
540 | typable, | 544 | &self.resolver, |
541 | ); | 545 | &path.segments[remaining_index + i - 1], |
542 | ty.subst(&substs) | 546 | typable, |
547 | ); | ||
548 | ty.subst(&substs) | ||
549 | } | ||
550 | Either::B(ty) => ty, | ||
543 | }; | 551 | }; |
544 | if is_last_segment { | 552 | if is_last_segment { |
545 | break; | 553 | break; |
@@ -550,15 +558,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
550 | log::debug!("looking for path segment: {:?}", segment); | 558 | log::debug!("looking for path segment: {:?}", segment); |
551 | 559 | ||
552 | let ty = mem::replace(&mut ty, Ty::Unknown); | 560 | let ty = mem::replace(&mut ty, Ty::Unknown); |
553 | def = ty.iterate_impl_items(self.db, krate, |item| { | 561 | def_or_ty = ty.iterate_impl_items(self.db, krate, |item| { |
554 | match item { | 562 | match item { |
555 | crate::ImplItem::Method(_) => None, | 563 | crate::ImplItem::Method(_) => None, |
556 | crate::ImplItem::Const(_) => None, | 564 | crate::ImplItem::Const(_) => None, |
557 | 565 | ||
558 | // FIXME: Resolve associated types | 566 | // FIXME: Resolve associated types |
559 | crate::ImplItem::TypeAlias(_) => { | 567 | crate::ImplItem::TypeAlias(_) => { |
560 | // Some(TypeNs::TypeAlias(..)) | 568 | // Some(Either::A(TypeNs::TypeAlias(..))) |
561 | None::<TypeNs> | 569 | None |
562 | } | 570 | } |
563 | } | 571 | } |
564 | })?; | 572 | })?; |
@@ -1434,56 +1442,38 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1434 | } | 1442 | } |
1435 | 1443 | ||
1436 | fn resolve_into_iter_item(&self) -> Option<TypeAlias> { | 1444 | fn resolve_into_iter_item(&self) -> Option<TypeAlias> { |
1437 | let into_iter_path = Path { | 1445 | let into_iter_path = Path::from_simple_segments( |
1438 | kind: PathKind::Abs, | 1446 | PathKind::Abs, |
1439 | segments: vec![ | 1447 | vec![name::STD, name::ITER, name::INTO_ITERATOR], |
1440 | PathSegment { name: name::STD, args_and_bindings: None }, | 1448 | ); |
1441 | PathSegment { name: name::ITER, args_and_bindings: None }, | ||
1442 | PathSegment { name: name::INTO_ITERATOR, args_and_bindings: None }, | ||
1443 | ], | ||
1444 | }; | ||
1445 | 1449 | ||
1446 | let trait_ = self.resolver.resolve_known_trait(self.db, &into_iter_path)?; | 1450 | let trait_ = self.resolver.resolve_known_trait(self.db, &into_iter_path)?; |
1447 | trait_.associated_type_by_name(self.db, &name::ITEM) | 1451 | trait_.associated_type_by_name(self.db, &name::ITEM) |
1448 | } | 1452 | } |
1449 | 1453 | ||
1450 | fn resolve_ops_try_ok(&self) -> Option<TypeAlias> { | 1454 | fn resolve_ops_try_ok(&self) -> Option<TypeAlias> { |
1451 | let ops_try_path = Path { | 1455 | let ops_try_path = |
1452 | kind: PathKind::Abs, | 1456 | Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::TRY]); |
1453 | segments: vec![ | ||
1454 | PathSegment { name: name::STD, args_and_bindings: None }, | ||
1455 | PathSegment { name: name::OPS, args_and_bindings: None }, | ||
1456 | PathSegment { name: name::TRY, args_and_bindings: None }, | ||
1457 | ], | ||
1458 | }; | ||
1459 | 1457 | ||
1460 | let trait_ = self.resolver.resolve_known_trait(self.db, &ops_try_path)?; | 1458 | let trait_ = self.resolver.resolve_known_trait(self.db, &ops_try_path)?; |
1461 | trait_.associated_type_by_name(self.db, &name::OK) | 1459 | trait_.associated_type_by_name(self.db, &name::OK) |
1462 | } | 1460 | } |
1463 | 1461 | ||
1464 | fn resolve_future_future_output(&self) -> Option<TypeAlias> { | 1462 | fn resolve_future_future_output(&self) -> Option<TypeAlias> { |
1465 | let future_future_path = Path { | 1463 | let future_future_path = Path::from_simple_segments( |
1466 | kind: PathKind::Abs, | 1464 | PathKind::Abs, |
1467 | segments: vec![ | 1465 | vec![name::STD, name::FUTURE_MOD, name::FUTURE_TYPE], |
1468 | PathSegment { name: name::STD, args_and_bindings: None }, | 1466 | ); |
1469 | PathSegment { name: name::FUTURE_MOD, args_and_bindings: None }, | ||
1470 | PathSegment { name: name::FUTURE_TYPE, args_and_bindings: None }, | ||
1471 | ], | ||
1472 | }; | ||
1473 | 1467 | ||
1474 | let trait_ = self.resolver.resolve_known_trait(self.db, &future_future_path)?; | 1468 | let trait_ = self.resolver.resolve_known_trait(self.db, &future_future_path)?; |
1475 | trait_.associated_type_by_name(self.db, &name::OUTPUT) | 1469 | trait_.associated_type_by_name(self.db, &name::OUTPUT) |
1476 | } | 1470 | } |
1477 | 1471 | ||
1478 | fn resolve_boxed_box(&self) -> Option<Adt> { | 1472 | fn resolve_boxed_box(&self) -> Option<Adt> { |
1479 | let boxed_box_path = Path { | 1473 | let boxed_box_path = Path::from_simple_segments( |
1480 | kind: PathKind::Abs, | 1474 | PathKind::Abs, |
1481 | segments: vec![ | 1475 | vec![name::STD, name::BOXED_MOD, name::BOX_TYPE], |
1482 | PathSegment { name: name::STD, args_and_bindings: None }, | 1476 | ); |
1483 | PathSegment { name: name::BOXED_MOD, args_and_bindings: None }, | ||
1484 | PathSegment { name: name::BOX_TYPE, args_and_bindings: None }, | ||
1485 | ], | ||
1486 | }; | ||
1487 | let struct_ = self.resolver.resolve_known_struct(self.db, &boxed_box_path)?; | 1477 | let struct_ = self.resolver.resolve_known_struct(self.db, &boxed_box_path)?; |
1488 | Some(Adt::Struct(struct_)) | 1478 | Some(Adt::Struct(struct_)) |
1489 | } | 1479 | } |