Skip to content

Commit ad03e4d

Browse files
bors[bot]hban
andauthored
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]>
2 parents c6ed089 + 68db49c commit ad03e4d

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed

crates/ra_hir_ty/src/tests/traits.rs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,6 +1616,138 @@ fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
16161616
);
16171617
}
16181618

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+
16191751
#[test]
16201752
fn closure_1() {
16211753
assert_snapshot!(

0 commit comments

Comments
 (0)