diff options
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r-- | crates/ra_hir_ty/src/lib.rs | 14 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/method_resolution.rs | 31 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 132 |
4 files changed, 172 insertions, 15 deletions
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index ccc4348f4..daea02f88 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -808,15 +808,13 @@ impl Ty { | |||
808 | } | 808 | } |
809 | } | 809 | } |
810 | 810 | ||
811 | /// If this is an `impl Trait` or `dyn Trait`, returns that trait. | 811 | /// If this is a `dyn Trait`, returns that trait. |
812 | pub fn inherent_trait(&self) -> Option<TraitId> { | 812 | pub fn dyn_trait(&self) -> Option<TraitId> { |
813 | match self { | 813 | match self { |
814 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | 814 | Ty::Dyn(predicates) => predicates.iter().find_map(|pred| match pred { |
815 | predicates.iter().find_map(|pred| match pred { | 815 | GenericPredicate::Implemented(tr) => Some(tr.trait_), |
816 | GenericPredicate::Implemented(tr) => Some(tr.trait_), | 816 | _ => None, |
817 | _ => None, | 817 | }), |
818 | }) | ||
819 | } | ||
820 | _ => None, | 818 | _ => None, |
821 | } | 819 | } |
822 | } | 820 | } |
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 657284fd0..0851e16a8 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -408,8 +408,9 @@ fn iterate_trait_method_candidates<T>( | |||
408 | receiver_ty: Option<&Canonical<Ty>>, | 408 | receiver_ty: Option<&Canonical<Ty>>, |
409 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 409 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
410 | ) -> Option<T> { | 410 | ) -> Option<T> { |
411 | // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope | 411 | // if ty is `dyn Trait`, the trait doesn't need to be in scope |
412 | let inherent_trait = self_ty.value.inherent_trait().into_iter(); | 412 | let inherent_trait = |
413 | self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); | ||
413 | let env_traits = if let Ty::Placeholder(_) = self_ty.value { | 414 | let env_traits = if let Ty::Placeholder(_) = self_ty.value { |
414 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope | 415 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope |
415 | env.trait_predicates_for_self_ty(&self_ty.value) | 416 | env.trait_predicates_for_self_ty(&self_ty.value) |
@@ -601,11 +602,6 @@ pub fn implements_trait( | |||
601 | krate: CrateId, | 602 | krate: CrateId, |
602 | trait_: TraitId, | 603 | trait_: TraitId, |
603 | ) -> bool { | 604 | ) -> bool { |
604 | if ty.value.inherent_trait() == Some(trait_) { | ||
605 | // FIXME this is a bit of a hack, since Chalk should say the same thing | ||
606 | // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet | ||
607 | return true; | ||
608 | } | ||
609 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); | 605 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); |
610 | let solution = db.trait_solve(krate, goal); | 606 | let solution = db.trait_solve(krate, goal); |
611 | 607 | ||
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs index 67f964ab5..9c2c9e1d2 100644 --- a/crates/ra_hir_ty/src/tests/method_resolution.rs +++ b/crates/ra_hir_ty/src/tests/method_resolution.rs | |||
@@ -1096,3 +1096,34 @@ fn test() { (S {}).method()<|>; } | |||
1096 | ); | 1096 | ); |
1097 | assert_eq!(t, "()"); | 1097 | assert_eq!(t, "()"); |
1098 | } | 1098 | } |
1099 | |||
1100 | #[test] | ||
1101 | fn dyn_trait_super_trait_not_in_scope() { | ||
1102 | assert_snapshot!( | ||
1103 | infer(r#" | ||
1104 | mod m { | ||
1105 | pub trait SuperTrait { | ||
1106 | fn foo(&self) -> u32 { 0 } | ||
1107 | } | ||
1108 | } | ||
1109 | trait Trait: m::SuperTrait {} | ||
1110 | |||
1111 | struct S; | ||
1112 | impl m::SuperTrait for S {} | ||
1113 | impl Trait for S {} | ||
1114 | |||
1115 | fn test(d: &dyn Trait) { | ||
1116 | d.foo(); | ||
1117 | } | ||
1118 | "#), | ||
1119 | @r###" | ||
1120 | 52..56 'self': &Self | ||
1121 | 65..70 '{ 0 }': u32 | ||
1122 | 67..68 '0': u32 | ||
1123 | 177..178 'd': &dyn Trait | ||
1124 | 192..208 '{ ...o(); }': () | ||
1125 | 198..199 'd': &dyn Trait | ||
1126 | 198..205 'd.foo()': u32 | ||
1127 | "### | ||
1128 | ); | ||
1129 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 9d32cbc7a..c49aacf98 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -1617,6 +1617,138 @@ fn test<F: FnOnce(u32, u64) -> u128>(f: F) { | |||
1617 | } | 1617 | } |
1618 | 1618 | ||
1619 | #[test] | 1619 | #[test] |
1620 | fn fn_ptr_and_item() { | ||
1621 | assert_snapshot!( | ||
1622 | infer(r#" | ||
1623 | #[lang="fn_once"] | ||
1624 | trait FnOnce<Args> { | ||
1625 | type Output; | ||
1626 | |||
1627 | fn call_once(self, args: Args) -> Self::Output; | ||
1628 | } | ||
1629 | |||
1630 | trait Foo<T> { | ||
1631 | fn foo(&self) -> T; | ||
1632 | } | ||
1633 | |||
1634 | struct Bar<T>(T); | ||
1635 | |||
1636 | impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> { | ||
1637 | fn foo(&self) -> (A1, R) {} | ||
1638 | } | ||
1639 | |||
1640 | enum Opt<T> { None, Some(T) } | ||
1641 | impl<T> Opt<T> { | ||
1642 | fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> {} | ||
1643 | } | ||
1644 | |||
1645 | fn test() { | ||
1646 | let bar: Bar<fn(u8) -> u32>; | ||
1647 | bar.foo(); | ||
1648 | |||
1649 | let opt: Opt<u8>; | ||
1650 | let f: fn(u8) -> u32; | ||
1651 | opt.map(f); | ||
1652 | } | ||
1653 | "#), | ||
1654 | @r###" | ||
1655 | 75..79 'self': Self | ||
1656 | 81..85 'args': Args | ||
1657 | 140..144 'self': &Self | ||
1658 | 244..248 'self': &Bar<F> | ||
1659 | 261..263 '{}': () | ||
1660 | 347..351 'self': Opt<T> | ||
1661 | 353..354 'f': F | ||
1662 | 369..371 '{}': () | ||
1663 | 385..501 '{ ...(f); }': () | ||
1664 | 395..398 'bar': Bar<fn(u8) -> u32> | ||
1665 | 424..427 'bar': Bar<fn(u8) -> u32> | ||
1666 | 424..433 'bar.foo()': {unknown} | ||
1667 | 444..447 'opt': Opt<u8> | ||
1668 | 466..467 'f': fn(u8) -> u32 | ||
1669 | 488..491 'opt': Opt<u8> | ||
1670 | 488..498 'opt.map(f)': Opt<FnOnce::Output<fn(u8) -> u32, (u8,)>> | ||
1671 | 496..497 'f': fn(u8) -> u32 | ||
1672 | "### | ||
1673 | ); | ||
1674 | } | ||
1675 | |||
1676 | #[test] | ||
1677 | fn fn_trait_deref_with_ty_default() { | ||
1678 | assert_snapshot!( | ||
1679 | infer(r#" | ||
1680 | #[lang = "deref"] | ||
1681 | trait Deref { | ||
1682 | type Target; | ||
1683 | |||
1684 | fn deref(&self) -> &Self::Target; | ||
1685 | } | ||
1686 | |||
1687 | #[lang="fn_once"] | ||
1688 | trait FnOnce<Args> { | ||
1689 | type Output; | ||
1690 | |||
1691 | fn call_once(self, args: Args) -> Self::Output; | ||
1692 | } | ||
1693 | |||
1694 | struct Foo; | ||
1695 | |||
1696 | impl Foo { | ||
1697 | fn foo(&self) -> usize {} | ||
1698 | } | ||
1699 | |||
1700 | struct Lazy<T, F = fn() -> T>(F); | ||
1701 | |||
1702 | impl<T, F> Lazy<T, F> { | ||
1703 | pub fn new(f: F) -> Lazy<T, F> {} | ||
1704 | } | ||
1705 | |||
1706 | impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> { | ||
1707 | type Target = T; | ||
1708 | } | ||
1709 | |||
1710 | fn test() { | ||
1711 | let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo); | ||
1712 | let r1 = lazy1.foo(); | ||
1713 | |||
1714 | fn make_foo_fn() -> Foo {} | ||
1715 | let make_foo_fn_ptr: fn() -> Foo = make_foo_fn; | ||
1716 | let lazy2: Lazy<Foo, _> = Lazy::new(make_foo_fn_ptr); | ||
1717 | let r2 = lazy2.foo(); | ||
1718 | } | ||
1719 | "#), | ||
1720 | @r###" | ||
1721 | 65..69 'self': &Self | ||
1722 | 166..170 'self': Self | ||
1723 | 172..176 'args': Args | ||
1724 | 240..244 'self': &Foo | ||
1725 | 255..257 '{}': () | ||
1726 | 335..336 'f': F | ||
1727 | 355..357 '{}': () | ||
1728 | 444..690 '{ ...o(); }': () | ||
1729 | 454..459 'lazy1': Lazy<Foo, fn() -> T> | ||
1730 | 476..485 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T> | ||
1731 | 476..493 'Lazy::...| Foo)': Lazy<Foo, fn() -> T> | ||
1732 | 486..492 '|| Foo': || -> T | ||
1733 | 489..492 'Foo': Foo | ||
1734 | 503..505 'r1': {unknown} | ||
1735 | 508..513 'lazy1': Lazy<Foo, fn() -> T> | ||
1736 | 508..519 'lazy1.foo()': {unknown} | ||
1737 | 561..576 'make_foo_fn_ptr': fn() -> Foo | ||
1738 | 592..603 'make_foo_fn': fn make_foo_fn() -> Foo | ||
1739 | 613..618 'lazy2': Lazy<Foo, fn() -> T> | ||
1740 | 635..644 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T> | ||
1741 | 635..661 'Lazy::...n_ptr)': Lazy<Foo, fn() -> T> | ||
1742 | 645..660 'make_foo_fn_ptr': fn() -> Foo | ||
1743 | 671..673 'r2': {unknown} | ||
1744 | 676..681 'lazy2': Lazy<Foo, fn() -> T> | ||
1745 | 676..687 'lazy2.foo()': {unknown} | ||
1746 | 550..552 '{}': () | ||
1747 | "### | ||
1748 | ); | ||
1749 | } | ||
1750 | |||
1751 | #[test] | ||
1620 | fn closure_1() { | 1752 | fn closure_1() { |
1621 | assert_snapshot!( | 1753 | assert_snapshot!( |
1622 | infer(r#" | 1754 | infer(r#" |