aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
authoruHOOCCOOHu <[email protected]>2019-09-11 19:01:07 +0100
committeruHOOCCOOHu <[email protected]>2019-09-15 12:40:32 +0100
commit4926bed42680d329f906be93450bec6b2ba0e99b (patch)
tree455c0bc9d839a18fffda6d018bf41d1c58ebfa52 /crates/ra_hir/src/ty
parent2d79a1ad83cc39075c7c9e3230973013c8c58b17 (diff)
Support path starting with a type
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/infer.rs120
-rw-r--r--crates/ra_hir/src/ty/tests.rs58
2 files changed, 113 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
54mod unify; 55mod 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 }
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index f6a2a658f..1bd677cab 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -282,6 +282,64 @@ fn test() {
282} 282}
283 283
284#[test] 284#[test]
285fn infer_path_type() {
286 assert_snapshot!(
287 infer(r#"
288struct S;
289
290impl S {
291 fn foo() -> i32 { 1 }
292}
293
294fn test() {
295 S::foo();
296 <S>::foo();
297}
298"#),
299 @r###"
300 [41; 46) '{ 1 }': i32
301 [43; 44) '1': i32
302 [60; 93) '{ ...o(); }': ()
303 [66; 72) 'S::foo': fn foo() -> i32
304 [66; 74) 'S::foo()': i32
305 [80; 88) '<S>::foo': fn foo() -> i32
306 [80; 90) '<S>::foo()': i32
307"###
308 );
309}
310
311#[test]
312fn infer_slice_method() {
313 assert_snapshot!(
314 infer(r#"
315#[lang = "slice"]
316impl<T> [T] {
317 fn foo(&self) -> T {
318 loop {}
319 }
320}
321
322#[lang = "slice_alloc"]
323impl<T> [T] {}
324
325fn test() {
326 <[_]>::foo(b"foo");
327}
328"#),
329 @r###"
330 [45; 49) 'self': &[T]
331 [56; 79) '{ ... }': !
332 [66; 73) 'loop {}': !
333 [71; 73) '{}': ()
334 [133; 160) '{ ...o"); }': ()
335 [139; 149) '<[_]>::foo': fn foo<u8>(&[T]) -> T
336 [139; 157) '<[_]>:..."foo")': u8
337 [150; 156) 'b"foo"': &[u8]
338"###
339 );
340}
341
342#[test]
285fn infer_struct() { 343fn infer_struct() {
286 assert_snapshot!( 344 assert_snapshot!(
287 infer(r#" 345 infer(r#"