GithubHelp home page GithubHelp logo

Plan: Rust 2024 prelude about wg-async HOT 17 OPEN

tmandry avatar tmandry commented on July 17, 2024
Plan: Rust 2024 prelude

from wg-async.

Comments (17)

samsartor avatar samsartor commented on July 17, 2024 10

I just stumbled across this post and may actually have the answers available because of another project. Here are the top 50 trait names ranked by average number of explicit mentions in the the top ~1000 Rust projects on GitHub as of November 2022:

Trait NameAvg. Mentions per Project
1From30.6213
2Display18.4828
3Default17.368
4Debug15.9195
5Send5.63669
6Iterator5.58225
7Clone5.37988
8Drop4.52071
9PartialEq4.39408
10Error4.35266
11AsRef3.96686
12Sync3.55503
13TryFrom3.52899
14Deref2.91006
15Fn2.65917
16IntoIterator2.59408
17Into2.33018
18FromStr2.1787
19Eq2.15621
20Serialize2.11243
21Future1.7645
22Hash1.72071
23PartialOrd1.58225
24FnMut1.57988
25Write1.5432
26Deserialize1.52899
27Copy1.40355
28FnOnce1.3716
29Ord1.20592
30DerefMut1.17633
31Stream1.12071
32Parse0.942012
33Add0.926627
34Unpin0.822485
35Index0.790533
36Read0.76568
37ExactSizeIterator0.757396
38Visitor0.753846
39Encode0.659172
40Sealed0.63787
41Sub0.63432
42Deserializer0.598817
43Sized0.589349
44AsyncRead0.583432
45Mul0.571598
46FromIterator0.569231
47ToTokens0.564497
48AsyncWrite0.551479
49Arbitrary0.531361
50Service0.478107

Based on this, Display and Debug should really be in the prelude.Error is also pretty far up the list. But Future is on the cusp, just behind serde's Serialize trait (obviously not in the prelude) but ahead of some prelude traits like Ord, PartialOrd, FnMut, and Copy.

We can also do an over-time comparison between Future and other similar traits, such as Iterator. For a while it looked as if people would soon be mentioning the Future trait almost as much as Iterator, but the gap has widened since async/await was stabilized:
image

But looking at only projects with at least one usage of either, we can see that projects which write out Future at all tended to write it out a lot, almost more so than a project which similarly mentions the Iterator trait:
image

This obviously doesn't compare usage of the respective Iterator::* and Future::* methods when the traits themselves are unnamed (doing trait resolution was well beyond the project scope), but these plots do support the idea that pub use Future should be in the prelude as much as pub use Iterator if not as much as pub use Iterator as _.

We can also break down these mentions of the Future trait by their position in the syntax, to see that people are writing manual impl Future for T impls surprisingly often. The fn() -> impl/dyn Future was on the rise until async/await, then was largely replaced. On the other hand, use of f(_: impl/dyn Future) has been steadily increasing:
image

Compare this to the Iterator trait, where impl Iterator for T mentions dominate to a greater extent, and where the relative growth of the different syntaxes has remained fairly proportional after the -> impl Iterator syntax was stabilized:
image

We can also investigate why people still type out fn() -> impl Future at all, when async is available. It is about half as popular as before the async syntax was stabilized. But notice that people customize the lifetimes on returned futures just as much as before:
image

My take from this is that having Future in the prelude would be nice for a lot of projects even if async/await has reduced that need somewhat. However, other traits might be more important to add.

from wg-async.

nrc avatar nrc commented on July 17, 2024 2

Yeah, we should talk to the libs team about criteria. Personally, I think we probably don't want to add anything - I reckon a minority of programs involves async code at all and a small minority of those write impl Future or implement a future because most just use async and await. Furthermore, those that do use explicit futures tend to just use them in a few places rather than everywhere, so importing them manually doesn't seem onerous. I think this all applies even more strongly to IntoFuture (aiui, the most common usage is implicitly in await where it doesn't need to be imported at all)

from wg-async.

yoshuawuyts avatar yoshuawuyts commented on July 17, 2024 1

I'm currently thinking we should put the following traits forward for inclusion in the 2024 prelude:

  • Future
  • IntoFuture

This would mirror what we're including with Iterator / IntoIterator, and would hopefully be fairly uncontroversial. @rust-lang/wg-async WDYT?

from wg-async.

yoshuawuyts avatar yoshuawuyts commented on July 17, 2024 1

A lot of code imports futures::Future. Would putting Future in the prelude break this code?

I don't believe so. They both point to the same trait, so with the way imports work this would Just Work I believe: playground.

from wg-async.

taiki-e avatar taiki-e commented on July 17, 2024 1
  • Since task::{Context, Poll} is also needed to implement Future, including Future in the prelude would be of little use from the standpoint of eliminating import effort during manual implementation. (This also applies to Display and Debug mentioned by @samsartor, which need other items in the fmt module for implementation.)

  • The data provided by @yoshuawuyts does not appear to be very reliable, as we can see cases from the first page that clearly match irrelevant items (e.g., "S: futures::Stream" is considered to contain one ": Future", or "use futures::future::FutureExt;" is considered to contain three "Future"'s.). It should also be noted that the GitHhub search also searches forks by default.

  • If other async-related traits are added to the std (e.g., Stream/AsyncIterator), do we want to include them in the prelude as well?

    • If yes, should we repeat the same discussion in 3 years, or include it in prelude at stabilization?
    • If no, why is Future trait special and the others are not?
  • Other traits that are not included in std::prelude but are widely used are std::io traits, which have module-level prelude (std::io::prelude). The "only io-related code needs it" nature of io traits is somewhat similar to async-related traits, where "only async-related code needs it". Maybe we may want to consider the idea regarding module-level prelude (something like std::future::prelude::{Future, AsyncIterator}).

from wg-async.

yoshuawuyts avatar yoshuawuyts commented on July 17, 2024 1

If other async-related traits are added to the std (e.g., Stream/AsyncIterator), do we want to include them in the prelude as well?

  • If yes, should we repeat the same discussion in 3 years, or include it in prelude at stabilization?
  • If no, why is Future trait special and the others are not?

As far as I know the prelude isn't expanded in between editions, so yeah I think we should talk about whether there are things that would make sense to put in the prelude every ~3 years. That seems like a pretty good cadence to have a conversation?


To maybe look at this from a different angle: Future represents the reification of the async effect - which means that if we create a type using async {}, the only way we can refer to it in the type system is by using the impl Future notation (as both universal and existential). This is much the same as the "iteration" effect, which is reified as impl Iterator. Because async {} notation is globally available, it would make sense for impl Future notation to match. The key property here is not being able to implement Future, it's being able to name it.

from wg-async.

eholk avatar eholk commented on July 17, 2024

Seems reasonable to me. I'm regularly surprised that Future isn't in the prelude.

A lot of code imports futures::Future. Would putting Future in the prelude break this code?

from wg-async.

eholk avatar eholk commented on July 17, 2024

Playing devil's advocate for a bit, are Future and IntoFuture traits that really need to be in the prelude? Most people don't implement Future directly, and probably even fewer call poll or into_future directly, so maybe it's reasonable to leave these as an advanced feature that people implementing low level async code import but most programmers don't use?

Put another way, what capabilities do we enable by putting them in the prelude?

(edit: accidentally said standard library instead of prelude in the first sentence. It's fixed now)

from wg-async.

Noah-Kennedy avatar Noah-Kennedy commented on July 17, 2024

If not in the standard library, then where would they be?

from wg-async.

compiler-errors avatar compiler-errors commented on July 17, 2024

are Future and IntoFuture traits that really need to be in the standard library?

They certainly need to be in the standard library to support async and await desugaring.

Most people don't implement Future directly

Yeah, but I would assume more people using them as impl traits in return or arg position, like fn x() -> impl Future<Output = ..>, fn x(x: impl Future<Output = ..>) which would be helped by implementing

I can see how IntoFuture probably doesn't need to be in the prelude (since most people are just .awaiting on things), and I guess I could see Future also not being there.

from wg-async.

eholk avatar eholk commented on July 17, 2024

Oh sorry, I misspoke! I meant to ask whether we need Future and IntoFuture in the prelude, not the standard library. I'll edit my comment.

from wg-async.

eholk avatar eholk commented on July 17, 2024

Most people don't implement Future directly

Yeah, but I would assume more people using them as impl traits in return or arg position, like fn x() -> impl Future<Output = ..>, fn x(x: impl Future<Output = ..>) which would be helped by implementing

That's a good point.

I wonder what the bar is for including things in the prelude is? I'd assume it's for things that essentially all Rust programs will use. Almost every program uses Option and iterators, for example. There are still a sizeable number of programs that don't use async though and therefore don't need to use Future at all.

from wg-async.

yoshuawuyts avatar yoshuawuyts commented on July 17, 2024

I reckon a minority of programs involves async code at all and a small minority of those write impl Future or implement a future because most just use async and await.

This is something we can validate by searching GitHub:

GitHub code search does have a few limitations. For one the search is not case-sensitive. And it also includes lines which are part of comments. But if we interpret this as a rough indicator rather than a precise measurement, it would seem that Future is used about about half as often as iterator in bounds. And likely sees comparable usage elsewhere.

What I'm taking away from this is that the Future trait is probably used often enough that it would be justified for inclusion in the stdlib prelude. The most conservative interpretation of this is that Future is used about half as much as Iterator, one of the most used traits in the stdlib. By-volume that is a lot; and it would seem to me as enough to justify its inclusion. IntoFuture is most definitely used less than the other traits, but it's also only been part of stable Rust for months, not years like the other traits. At least to me it seems that if we're going to put up Future for consideration, IntoFuture should also just come with so it would continue mirroring the Iterator/IntoIterator trait set it was modeled after.

My goal with this comment was to specifically request input from the Async WG for which traits (or even types!) we may want to put forward for inclusion. Once we have a rough consensus among ourselves, I was planning to put it forward to the libs team as an ACP to formally clear the acceptance criteria with them.

from wg-async.

eholk avatar eholk commented on July 17, 2024

It's possible that once we have AsyncIterator we may see Future used a lot more too, depending on how the API shapes up.

from wg-async.

nrc avatar nrc commented on July 17, 2024

This is something we can validate by searching GitHub:

I get completely different numbers here and simply clicking these links gives me bogus results (e.g., results with "lang" and "rust" as the found text). I think that at least the repositories searched depends on the user. So I'm not sure these are reliable numbers. Given that GH search also counts forks as different repos, these are also going to be inaccurate that way too. I think a better count might be by downloading the source to the top 500 crates on crates.io and using grep? Or some similar exercise

from wg-async.

yoshuawuyts avatar yoshuawuyts commented on July 17, 2024

I get completely different numbers here and simply clicking these links gives me bogus results (e.g., results with "lang" and "rust" as the found text)

Oh it may be that you don't yet have access to the new code search feature. It's far more accurate than the previous search, and you can do things like lang:rust to scope it just to files written in Rust, and apply regular expressions to look for specific occurrences.

from wg-async.

yoshuawuyts avatar yoshuawuyts commented on July 17, 2024

The 2024 prelude is now available behind a flag on nightly. We should consider PR'ing Future and IntoFuture to it.

from wg-async.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.