aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-05-18 08:44:44 +0100
committerGitHub <[email protected]>2020-05-18 08:44:44 +0100
commitad03e4de185f0f19ae75a8a9c4095ee1b0d82a47 (patch)
tree86f1b44509075a54f0887d56fe84e8ae42df5766 /crates
parentc6ed08967193cadc927dfaf422601bcd160a6fc9 (diff)
parent68db49c8534fa99768c7f600455ea76176f61994 (diff)
Merge #4493
4493: Provide builtin impls of Fn traits for fn-pointers r=flodiebold a=hban Meant to be, but isn't actually a fix for #2880. Consider this snippet: ```rust use std::marker::PhantomData; use std::ops::Deref; struct Lazy<T, F/* = fn() -> T*/>(F, PhantomData<T>); impl<T, F> Lazy<T, F> { pub fn new(f: F) -> Lazy<T, F> { Lazy(f, PhantomData) } } impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> { type Target = T; fn deref(&self) -> &T { todo!() } } fn test() { let lazy1: Lazy<u32, _> = Lazy::new(|| 0u32); let r1 = lazy1.to_string(); fn make_u32_fn() -> u32 { todo!() } let make_u32_fn_ptr: fn() -> u32 = make_u32_fn; let lazy2: Lazy<u32, _> = Lazy::new(make_u32_fn_ptr); let r2 = lazy2.to_string(); } ``` * On current master: * When type default is commented-out, `r1` is correctly inferred, `r2` in _{unknown}_. * When type default is not commented-out, both `r1` and `r2` are _{unknown}_. * With this PR: * When type default is commented-out, both `r1` and `r2` are correctly inferred. * When type default is not commented-out, both `r1` and `r2` are _{unknown}_. Well, it's a improvement at least. I guess this thing with type defaults is a different problem. I also tried add Fn impls for fn items, but wasn't successful. So this PR only adds those impls for fn pointers. Co-authored-by: Hrvoje Ban <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs132
1 files changed, 132 insertions, 0 deletions
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]
1620fn fn_ptr_and_item() {
1621 assert_snapshot!(
1622 infer(r#"
1623#[lang="fn_once"]
1624trait FnOnce<Args> {
1625 type Output;
1626
1627 fn call_once(self, args: Args) -> Self::Output;
1628}
1629
1630trait Foo<T> {
1631 fn foo(&self) -> T;
1632}
1633
1634struct Bar<T>(T);
1635
1636impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> {
1637 fn foo(&self) -> (A1, R) {}
1638}
1639
1640enum Opt<T> { None, Some(T) }
1641impl<T> Opt<T> {
1642 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> {}
1643}
1644
1645fn 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###"
165575..79 'self': Self
165681..85 'args': Args
1657140..144 'self': &Self
1658244..248 'self': &Bar<F>
1659261..263 '{}': ()
1660347..351 'self': Opt<T>
1661353..354 'f': F
1662369..371 '{}': ()
1663385..501 '{ ...(f); }': ()
1664395..398 'bar': Bar<fn(u8) -> u32>
1665424..427 'bar': Bar<fn(u8) -> u32>
1666424..433 'bar.foo()': {unknown}
1667444..447 'opt': Opt<u8>
1668466..467 'f': fn(u8) -> u32
1669488..491 'opt': Opt<u8>
1670488..498 'opt.map(f)': Opt<FnOnce::Output<fn(u8) -> u32, (u8,)>>
1671496..497 'f': fn(u8) -> u32
1672"###
1673 );
1674}
1675
1676#[test]
1677fn fn_trait_deref_with_ty_default() {
1678 assert_snapshot!(
1679 infer(r#"
1680#[lang = "deref"]
1681trait Deref {
1682 type Target;
1683
1684 fn deref(&self) -> &Self::Target;
1685}
1686
1687#[lang="fn_once"]
1688trait FnOnce<Args> {
1689 type Output;
1690
1691 fn call_once(self, args: Args) -> Self::Output;
1692}
1693
1694struct Foo;
1695
1696impl Foo {
1697 fn foo(&self) -> usize {}
1698}
1699
1700struct Lazy<T, F = fn() -> T>(F);
1701
1702impl<T, F> Lazy<T, F> {
1703 pub fn new(f: F) -> Lazy<T, F> {}
1704}
1705
1706impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
1707 type Target = T;
1708}
1709
1710fn 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###"
172165..69 'self': &Self
1722166..170 'self': Self
1723172..176 'args': Args
1724240..244 'self': &Foo
1725255..257 '{}': ()
1726335..336 'f': F
1727355..357 '{}': ()
1728444..690 '{ ...o(); }': ()
1729454..459 'lazy1': Lazy<Foo, fn() -> T>
1730476..485 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T>
1731476..493 'Lazy::...| Foo)': Lazy<Foo, fn() -> T>
1732486..492 '|| Foo': || -> T
1733489..492 'Foo': Foo
1734503..505 'r1': {unknown}
1735508..513 'lazy1': Lazy<Foo, fn() -> T>
1736508..519 'lazy1.foo()': {unknown}
1737561..576 'make_foo_fn_ptr': fn() -> Foo
1738592..603 'make_foo_fn': fn make_foo_fn() -> Foo
1739613..618 'lazy2': Lazy<Foo, fn() -> T>
1740635..644 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T>
1741635..661 'Lazy::...n_ptr)': Lazy<Foo, fn() -> T>
1742645..660 'make_foo_fn_ptr': fn() -> Foo
1743671..673 'r2': {unknown}
1744676..681 'lazy2': Lazy<Foo, fn() -> T>
1745676..687 'lazy2.foo()': {unknown}
1746550..552 '{}': ()
1747"###
1748 );
1749}
1750
1751#[test]
1620fn closure_1() { 1752fn closure_1() {
1621 assert_snapshot!( 1753 assert_snapshot!(
1622 infer(r#" 1754 infer(r#"