# Libs-API Meeting 2023-11-28 ###### tags: `Libs Meetings` `Minutes` **Meeting Link**: https://meet.jit.si/rust-libs-meeting-crxoz2at8hiccp7b3ixf89qgxfymlbwr **Attendees**: Amanieu, David, Mara, The 8472, Chris Denton, Urgau ## Agenda - Triage - Anything else? ## Triage ### FCPs 19 rust-lang/rust T-libs-api FCPs - merge rust.tf/80437 *Tracking Issue for \`box\_into\_inner\`* - (1 checkboxes left) - merge rust.tf/52331 *Correcting Path::components on Redox* - (5 checkboxes left) - merge rust.tf/82901 *Tracking Issue for \`Option::get\_or\_insert\_default\`* - (2 checkboxes left) - merge rust.tf/83871 *Tracking Issue for CharIndices::offset function* - (3 checkboxes left) - merge rust.tf/117824 *Stabilize \`ptr::{from\_ref, from\_mut}\`* - (3 checkboxes left) - merge rust.tf/66359 *Tracking issue for \`any::type\_name\_of\_val\`* - (3 checkboxes left) - merge rust.tf/99262 *Tracking Issue for \`io\_error\_downcast\`* - (4 checkboxes left) - merge rust.tf/106655 *Tracking Issue for \`#!\[feature(offset\_of)\]\`* - (0 checkboxes left) - merge rust.tf/62726 *Tracking issue for io\_slice\_advance* - (3 checkboxes left) - merge rust.tf/106418 *Implement \`PartialOrd\` and \`Ord\` for \`Discriminant\`* - (0 checkboxes left) - merge rust.tf/76118 *Tracking Issue for \`array\_methods\`* - (3 checkboxes left) - merge rust.tf/109402 *Implement owned ops for \`HashSet\` and \`BTreeSet\`* - (4 checkboxes left) - merge rust.tf/116113 * Generalize \`{Rc,Arc}::make\_mut()\` to unsized types.* - (4 checkboxes left) - merge rust.tf/113833 *\`std::error::Error\` \-\> Trait Implementations: lifetimes consistency improvement* - (3 checkboxes left) - merge rust.tf/115974 *Split core's PanicInfo and std's PanicInfo* - (3 checkboxes left) - merge rust.tf/93610 *Tracking Issue for \`arc\_unwrap\_or\_clone\`* - (3 checkboxes left) - merge rust.tf/101288 *Tracking Issue for \`{char, u8}::is\_ascii\_octdigit\`* - (3 checkboxes left) - merge rust.tf/117468 *Stabilize Wasm relaxed SIMD* - (5 checkboxes left) - merge rust.tf/101196 *Tracking Issue for \`Ready::into\_inner()\`* - (2 checkboxes left) [dtolnay (3)](https://rfcbot.rs/fcp/dtolnay), [joshtriplett (13)](https://rfcbot.rs/fcp/joshtriplett), [m-ou-se (11)](https://rfcbot.rs/fcp/m-ou-se), [BurntSushi (7)](https://rfcbot.rs/fcp/BurntSushi), [Amanieu (13)](https://rfcbot.rs/fcp/Amanieu) ### (nominated) rust.tf/libs175 *Creating \`PhantomUnSend\` and \`PhantomUnSync\`* Amanieu: looks good? Mara: Check with lang first about negative impls? Josh: full-blown negaitve impls? Or just .. ? Mara: Just `impl !Send for .. {}` and `impl !Sync for .. {}`. Josh: Let me look into that. David: Agree that not having these types is preferrable. Filling them in in constructors is annoying, same for ignoring them in Debug impls Amanieu: if we don't get negative impls, these types are better than using PhantomData for this. Amanieu to place a comment on https://github.com/rust-lang/rust/issues/68318 ### (nominated) rust.tf/libs191 *Add LocalWaker support* David: This is the planned followup to our earlier breaking change to allow non-Send/Sync Wakers/Context. Mara: Has the async-wg been involved in this? https://github.com/rust-lang/rust/pull/95985#issuecomment-1295924153 > Tyler: "wg-async is in favor of this change. Context was never intended to be Send and Sync. If we can get away with fixing this now, we should do it." Mara: What is exactly the proposed API here? ACPs need to provide a concrete sketch of the entire proposed API. Amanieu: Context can be constructed from a waker (Context::from_waker), and has a method that returns the waker (waker). What does that do if there is no Send/Sync waker? David: ACP says that .waker() will panic if you only have a local waker. David: The stuff in a context is runtime-specific. It's in character for things to panic if you mix the wrong future with the wrong runtime. Mara replied, pinging the async wg. ### (nominated) rust.tf/79024 *Tracking Issue for #!\[feature(async\_iterator)\]* David: withoutboats asked me to please make sure this is on our radar. Blog post from withoutboats endorsing stabilization of AsyncIterator: https://without.boats/blog/poll-next/ This definition of AsyncIterator is equivalent to the Stream trait which has been in futures crate for many years Josh: let's not block on some pie-in-the-sky keyword generics proposal to make Iterator both sync and async. But the specific proposal of having AsyncIterator have async fn next: we are stabilizing async fn in traits *now*, it is not far future. It is now up to the async working group whether we do or don't do it that way; there is no language blocker for using async fn here. Josh: I would set a pretty high bar for "this has to be more complicated for everyone" just to have a faster stabilization Mara: boats is saying that even with `async fn next`, `next_poll` is still better. See the diagram in the blog post: `AsyncIterator::next_poll` results in a single (pinned) state machine staying alive for the entire iteration. `async fn next` is more complicated. Mara: the point in the post about this not just being the async version of iterator but instead being the *product* of Iterator and Future, resonates with me Mara: The blog post only went out yesterday. Wait to see how others respond? David: How long do we need to wait before gauging reaction? Mara: A week? Allow the async wg to meet? Josh: I appreciate the argument made in boats' blog post regarding one state machine rather than two, but I don't buy that the post has identified a fatal flaw with the async fn next approach that *definitely* leaves only the Pin-and-Poll-based approach viable. I would want to hear from the async wg if there is some other easier proposal if async fn has been ruled out, but easier to integrate than current AsyncIterator Mara: Yosh (async-wg) has read the blog post and doesn't agree. Working on a detailed response to it. Josh: do we have agreement that keyword generics is not something we want to block on before stabilizing *some* interface for `AsyncIterator`? Mara: seems like it all comes down to a fundamental difference in vision for async Rust (wg vs boats+) and we end up in the middle, needing to pick one or the other (eventually) Amanieu: can we let this evolve outside the standard library? Amanieu: are both of these approaches available outside the standard library today? Josh: poll_next: yes, async fn next: not to my knowledge `Stream` has been in `futures` since 2016 Josh: I am a big proponent of things being tested outside the standard library beforehand. On the other hand there is a huge cost of the ecosystem transitioning between traits, maybe too much to ask in this situation. It's possible if we need experience with usability issues related to async fn next, we may need some way to get that experience without iterating on a foundational ecosystem trait through an external crate. Mara: Yosh and TC could join this meeting right now to talk about this Mara: Invited them. *TC and Yosh joined* TC: We were just on a call to discuss this. Yosh: we can share an overview of our would-be-responses, but not ready to share public, so not in meeting notes. Josh: I see the justification to work on other async features like async drop first, but ecosystem is telling us please hurry up and stabilize traits that we can all converge on; that can happen sooner Josh: reading boats' post, it feels like there is not a lot of effort to engage with the thrust of the argument from async wg. It points out a downside and claims therefore we can't have nice things. I would desire that a response from async wg engages with the details of boats post TC: Yosh plans to push a meta-point that we shouldn't do anything here until we solve some of the more foundational issues. This comes from experience in the Node ecosystem where everything multiplied by 3. We're faced with a multiplicative explosion of traits. It's worth stepping back from the details of async iterator to consider broader points about how we want to tackle such scenario in general (explosion of traits in ecosystem or standard library). Mara: Hearing contradictory perspective from 2 sides: high pressure to stabilize async iterator asap, vs async iterator is not a big deal, not so important to do very soon Yosh: Nobody disputes async iterator is very important, but is it #1 on our list or #3 on our list. What is the risk of stabilizing vs gain of stabilizing. We have a trait in the ecosystem that serves this purpose already. Compared to async closures/drop which are fundamental new capabilities. I want to start by solving the things that pose the highest risk first. Mara: If it's just minor convenience, how can it be so important to boats to stabilize something? To the point of writing 6000 works advocating that? TC: it's about different executors agreeing on the same trait. 8472: Can they agree on a library crate providing a trait (e.g. the `Stream` trait from the futures ecosystem)? Josh: But Tokio has refused to agree on that. Josh: If we want any hope of actual standardization between runtimes, we need to provide something for them soon. TC: This is an area where Yosh and boats agree. Async Rust should be a part of Rust. Not "if you're using async, you're using Tokio, not Rust". It's important to Yosh and everyone here. Without a trait in std, Tokio kind of wins by default. What do we do that doesn't block us from doing it the right way long term? Yosh: I spent a month and a half prepping my RustConf talk and thought a recording would go up in October, but it has still not gone up. Unless you were at RustConf you can't see it. The talk laid out some roadmap for this stuff. Might be achievable in months. Josh: I believe you that a couple of months of technical work would get us to a prototype effect generics system along the lines of what you have been talking about. But there is no way we will be done arguing about the details of effects and how to use them in that timeframe. What the details should be and whether it's a thing we want to do in the first place. That's the long pole much more so than the technical work. I don't believe we should block AsyncIterator/AsyncRead/AsyncWrite on keyword generics. We should make it as usable as possible. Whether that means async fn next or some other design, I hope we make a very usable design that doesn't stop us from retrofitting keyword generics in the future so that `async Iterator` and `AsyncIterator` can be the "same" trait. But we should not go into this with the desire to do `async Iterator` as the initial thing that lands. TC: On the lang side it would be very optimistic to think that anything related to effects could land on a months timeline. What Yosh has in mind is a much narrower design than what people might be thinking now. 8472: Are AsyncRead/AsyncWrite blocked on async Drop to support completion I/O? Yosh: I sort of see them as separable. AsyncRead would be a straightforward async version of read and there might be something else more focused on the completion I/O reading use case. Yosh: There is a difference in framing: should we design asyncrony as a language feature or a library feature. My driving design is that all features of the language should be available in ordinary Rust, async Rust, fallible Rust, etc. But just like with platform portability, some things are unique to one platform / one effect, and we shouldn't be opposed to making available extension points to capitalize on those. TC: So should completion be tied into `async Read` or are those decoupled use cases? Yosh: If you are on an io-uring platform, the standard trait should be able to be based on that internally. If you aren't, then not necessarily. Yosh: If you consider async Rust a brand new language and design dedicated APIs for that use case, you get subtle divergence and incompatibilities. Effect generics is a way to avoid that, instead stearing us toward consistency between async and non-async in many aspects. Yosh: I'm willing to cede ground on a fully generic effect approach to these traits as long as we build on the principle of maximum consistency between code written under the different effects. TC: Lang and libs think in terms of tradeoffs: not stabilizing something now means the ecosystem takes some divergent direction, what is the cost/benefit of that. The async working group owes those teams an assessment of those tradeoffs. Mara: the Stream trait from futures is already the basis of so much ecosystem stuff. What I'm hearing on reasons to not stabilize an equivalent trait doesn't come down to any problem with that trait's design itself, but to things around vision about async Rust. TC: It's still up to Yosh and I to flesh out how async generators will fit into this in both possibilities (async fn next and poll_next). Yosh: I talked about that topic with Niko. Features need to be usable on their own. All sub-features of async should be usable on their own without a reliance on async generators being available. TC: to clarify Yosh's point: the ergonomics of Pin and how you would write futures by hand is unergonomic, and translating that unergonomics to async iterator is promulgating a design error. Yosh: Your average Rust user will never be able to write pinned state machines by hand. Even if async generators are available, the Rust user using that fancy feature still gets Pin in their face all the time if that's what the lowering of async generators are based on. Similar to how Pin ends up in your face occasionally when using async fn and async blocks even without writing manual futures. Yosh: I don't feel we have the full interactions mapped out between Pin and the other things we also care about. When Pin gets rough, it gets just about as rough as anything can get (like ask-Ralf level issues). Yosh: We can improve Pin but a better thing is not putting Pin in any more public APIs. We reduce the needs to address the issues with Pin (it buys us time) Yosh: The number of iterators that want to be self-referential is far smaller than the total number of iterators. We can solve the non-self-referential case first and come back to self-referentials much later. TC: The onus is on us (async wg) to write out the use cases that would require pinning. It's not just self-referential. Also certain kinds of channels (intrusive data structures?) TC: If we were all writing futures by hand, a lot fewer of the futures would be self-referential. Most self-referential futures are only so because of reliance on async syntax. It will be equally widespread to trip into your generators being self-referential with an async generator syntax. Maybe async generators shouldn't even be async iterators, with async iterators being non-self-referential only. TC: The key pressures are executor portability and multiplicative expansion and Pin ergonomics. For executor portability: couldn't an ecosystem trait address this? Uncertain. ### (nominated) rust.tf/86026 *Tracking Issue for \`Bound::map\`* ### (nominated) rust.tf/105135 *Tracking Issue for \`file\_create\_new\`* FCP finished. Should be merged? ### (nominated) rust.tf/115386 *PartialEq: handle longer transitive chains* ### (nominated) rust.tf/117758 *Add lint against ambiguous wide pointer comparisons* ### (nominated) rust.tf/118108 *PartialOrd: transitivity and duality are required only if the corresponding impls exist* ### (new change proposal) rust.tf/libs297 *Sugar for special\-casing last iteration* ### (new change proposal) rust.tf/libs298 *Constructive/Destructive Interference Size Padding* ### (new change proposal) rust.tf/libs303 *\[ACP\] Impl \`iter::Sum\` (and \`iter::Product\`) for \`num::Saturating\<u\*\>\`* ### (new change proposal) rust.tf/libs304 *ACP: Avoid the common mistake of \`for x in 0u8..\`* ### (new change proposal) rust.tf/libs305 *ACP: Impl From\<&T\> for &\[T\]* ### (stalled change proposal) rust.tf/libs131 *Add \`std::fs::rename\_noreplace\`* ### (stalled change proposal) rust.tf/libs164 *Add methods for use cases that \`align\_to\` does not cover* ### (stalled change proposal) rust.tf/libs155 *Arbitrary alternate flags in \`std::fmt::Formatter\`* ### (stalled change proposal) rust.tf/libs124 *Integrate \`Error\` trait with panic interfaces* ### (stalled change proposal) rust.tf/libs111 *Restructure ptr\_metadata to minimal support* _Generated by [fully-automatic-rust-libs-team-triage-meeting-agenda-generator](https://github.com/rust-lang/libs-team/tree/main/tools/agenda-generator)_