--- title: Libs-API Meeting 2025-07-08 tags: ["T-libs-api", "Libs Meetings", "triage-meeting", "minutes"] date: 2025-07-08 discussion: https://rust-lang.zulipchat.com/#narrow/channel/259402-t-libs.2Fmeetings/topic/Meeting.202025-07-08/ url: https://hackmd.io/ScUxzssgT2iJjwDawIByFA --- # Libs-API Meeting 2025-07-08 ###### tags: `Libs Meetings` `Minutes` **Meeting Link**: https://meet.jit.si/rust-libs-meeting-crxoz2at8hiccp7b3ixf89qgxfymlbwr **Attendees**: Josh Triplett, Tomas, Amanieu, David, Nurzhan Saken, The 8472, Chris Denton, TC, Martin, ## Agenda - Triage - Anything else? NOTE: Tomas will be out next week (from 2025-07-14 to 2025-07-17). ## Triage ### FCPs 1 rust-lang/rfcs T-libs-api FCPs - merge rust.tf/rfc3809 *RFC: enable \`derive(From)\` for single\-field structs* - (2 checkboxes left) 17 rust-lang/rust T-libs-api FCPs - merge rust.tf/141555 *Tracking Issue for \`#!\[feature(const\_float\_round\_methods)\]\`* - (3 checkboxes left) - merge rust.tf/80437 *Tracking Issue for \`box\_into\_inner\`* - (1 checkboxes left) - merge rust.tf/140808 *Implement Default for &Option* - (3 checkboxes left) - merge rust.tf/133289 *Tracking Issue for \`const\_array\_each\_ref\`* - (4 checkboxes left) - merge rust.tf/143191 *Stabilize \`rwlock\_downgrade\` library feature* - (3 checkboxes left) - merge rust.tf/143289 *Remove \`\[T\]::array\_chunks(\_mut)\`* - (3 checkboxes left) - merge rust.tf/106418 *Implement \`PartialOrd\` and \`Ord\` for \`Discriminant\`* - (2 checkboxes left) - merge rust.tf/65816 *Tracking issue for \`vec\_into\_raw\_parts\`* - (3 checkboxes left) - merge rust.tf/139087 *Fallback \`{float}\` to \`f32\` when \`f32: From\<{float}\>\` and add \`impl From\<f16\> for f32\`* - (5 checkboxes left) - merge rust.tf/129333 *Tracking Issue for \`lazy\_get\`* - (3 checkboxes left) - merge rust.tf/127213 *Tracking Issue for AVX512\_FP16 intrinsics* - (3 checkboxes left) - merge rust.tf/136306 *Tracking Issue for NEON fp16 intrinsics* - (3 checkboxes left) - merge rust.tf/141520 *Tracking Issue for const {OsString, PathBuf}::new* - (3 checkboxes left) - merge rust.tf/70530 *Tracking Issue for {BTreeMap,BTreeSet}::extract\_if* - (3 checkboxes left) - merge rust.tf/141994 *add Iterator::contains* - (4 checkboxes left) - merge rust.tf/141744 *Stabilize \`ip\_from\`* - (3 checkboxes left) - merge rust.tf/140956 *\`impl PartialEq\<{str,String}\> for {Path,PathBuf}\`* - (3 checkboxes left) [m-ou-se (15)](https://rfcbot.rs/fcp/m-ou-se), [BurntSushi (15)](https://rfcbot.rs/fcp/BurntSushi), [joshtriplett (14)](https://rfcbot.rs/fcp/joshtriplett), [dtolnay (1)](https://rfcbot.rs/fcp/dtolnay), [Amanieu (3)](https://rfcbot.rs/fcp/Amanieu), [scottmcm (1)](https://rfcbot.rs/fcp/scottmcm), [jackh726 (1)](https://rfcbot.rs/fcp/jackh726), [tmandry (1)](https://rfcbot.rs/fcp/tmandry), [nikomatsakis (3)](https://rfcbot.rs/fcp/nikomatsakis) ### (nominated) rust.tf/libs311 *ACP: Pattern methods for \`OsStr\` without \`OsStr\` patterns* Amanieu: Wasn't supposed to be nominated. Nothing to discuss here. ### (nominated) rust.tf/130703 *Tracking Issue for secure random data generation in \`std\`* Amanieu: Talk with Josh. ### (nominated) rust.tf/135120 *Tracking Issue for \`const\_slice\_reverse\`* Amanieu: Seems trivial. Any objections. Slice::reverse has been in since 1.0 FCP Merge ### (nominated) rust.tf/138217 *Turn \`Cow::is\_borrowed,is\_owned\` into associated functions.* Amanieu: We discussed this last week and didn't remove the label. ### (nominated) rust.tf/140808 *Implement Default for &Option* Amanieu: FCP started. Amanieu: Who's working on const traits? TC: Oli, fee1-dead, and CE. David: We should mention them on the PR. (TC will ping them.) ### (nominated) rust.tf/142849 *Add \`Write\` implementation for \`\[MaybeUninit\<u8\>\]\`* Amanieu: Discussed this last week, asked for a code example. There's an ongoing discussion in Zulip on `ReadBuf`. It is something you can write data into so technically we could? Amanieu: I'm inclined to accept this. The 8472: Have you read hanna's concern? It composes poorly because . If it's within the same crate, `MaybeUninit` is created and passed back that's fine because you can audit your code. But if you pass it to a third party code, you have to trust that the number of bytes is actually initialized. Amanieu: In practice this is only going to be useful in cases of "I want to format a string in this buffer. Let me write the bytes into this buffer". The 8472: Then you'll need to trust format to return the correct number of bytes. Any bug in there would become a soundness bug. Josh: That seemed like the primary reason we last time we talked about this to integrate it with something like `BorrowedBuf` which would mark the bytes as initialized. The 8472: I agree with Josh -- it's a "I want `BorrowedBuf` without writing `BorrowedBuf`". Amanieu: Based on the discusison on Zulip maybe we'll have a verison of `BorrowedBuf` without writing unitialized bytes ?? Josh: That seems potentially reasonable but I'd like to see what the API looks like. Seems likely we'll see almost entirely what we have minus all the initialization code and tracking filled vs. unfilled. The 8472: There was also a proposal for a separate Read trait that only uses a buffer and doesn't have the `[u8]` methods and a blanket impl that implements the old read. Josh: Just realised that with a `BorrowedBuf` that's ??. If you have a `Vec` you could easiley have a `BorrowedBuf` pointing to the vector where the `capacity` becomes the unitialized size and the data would become the initialized content. There's value in being able to turn a `Vec` into `BorrowedBuf`. Amanieu: That's a common usecase. Although, Vec would have an implementation that's separate. Josh: What I was thinking more about reading from a Vec instead of writing. You have a Vec, it's already got the capacity you wanted to. You wish to do a read operation on it. BorrowedBuf would let you pass that Vec into a read buf. The 8472: Seems like a tangent. Amanieu: For this specific one. Should we say we prefer a work on simpler ReadBuf and get an ACP written up? The 8472: Agreed. Josh: Let's make sure an ACP happen. Someone's already working on that. Amanieu: They're already in discussion with this. Conclusion: We decided to reject this because of the potential soundness issue mentioned by hana. We would instead like to see a new proposal on ReadBuf based on discussions in Zulip that removes the tracking of unitialized data. The 8472: I think there's more work to be done there than just removing the unitialized data tracking. --- (follow-up in the ACP meeting) TC: Similar to Amanieu, my inclination was to have a `Write` implementation on slice too. Amanieu: It's not something I feel very strongly about, it's a week inclination to accept it. Allowing write on slices is something we probably wouldn't have accepted if we had a proper cursor in the API. TC: There are of course ways to misuse it and maybe better ways for someone to do this in a general case. The 8472: The correct way to do this is some sort of written bytes tracking buffer that does this safely. And that's what BufRead or proposed alternatives is. So why should we give this to users when we're at least planning to have a better alternative on stable. The implementation itself isn't unsafe but to do anything with it requires unsafe. Doesn't seem great if the aim is to providing a safe alternative. TC: I didn't read the ask as providing a safe alternative. More like making the current unsafe task more erconomic. TC: Seems like the author had some worries about `BorrowedBuf`. The 8472: That's what the zulip thread is about. The author is there. TC: Yes, like Amanieu's inclination, it feels like "why not do it?", if not just out of consistency. The 8472: If we're ever going to have ?? in the standard library than it makes sense to provide it. But we're working on a better alternative. TC: The argument of "if we had a better alternative we wouldn't have implemented `Write` on `[u8]`" then it makes more sense to me. But when you already have it on `[u8]` then having `[MaybeUninit<u8>]` makes sense (having a safe and unsafe alternative). I think that's what the author was trying to ask for here, making the unsafe code more egonomic. The 8472: If the Buffer API existed, would they have still want this or would they use the Buffer API instead? I can't immediately think of a scenario where you'd need the unsafe variant. TC: Interesting question. ### (nominated) rust.tf/143471 *Is mutex poisoning guaranteed to always work properly?* (note: this builds on the rust.tf/143612 *Nested panics and \`std::thread::panicking\`* discussion below) The 8472: We can fix this using a `DropGuard` and checking the entry. Amanieu: I think we already do that. The 8472: And is that not enough? Amanieu: We check `std::thread::panicking` before. We poison the mutex when the guard is drop if the thread was not panicking before and it is panicking now. Josh: If we had the new mechanism we'd proposed, we'd poison if you call unwind_drop and not when you call drop? Amanieu: That wouldn't work if people put a MutexGuard in their own strut, because it only works for top-level types. Josh: It seems very likely people will want to know this for non-top-level types. Amanieu: Then you need a copletely separate codegen of drop in place ?? code path. Josh: Not saying that's an obvious solution, just that it leads to this obvious problem. Amanieu: Yeah, but I think posioning is broken anyway. Josh: People do often embed some helper type in their own type so they will want to be able to know this. Amanieu: I think we can probably make that work for the fields as well. In which case mutex posioning will be fixed. I'll reply to this one saying it will be fixed by the same proposal. ### (nominated) rust.tf/143612 *Nested panics and \`std::thread::panicking\`* Amanieu: The core issue is that if there's a panic and the panic executes a drop and inside a drop you call another function, `std::thread::panicking` is true because there's a panic being handled on the track even though the function is a normal function. Causes a lot of issues, notably the `ScopeGuard`. Because it has a code that says "execute this macro" only on the unwind path not on the normal path. If there's a panic being handled above the stack, the code would be executed even in the normal path which usually leads to a double-free. David: Is this specific to `catch_unwind`? Amanieu: You don't need any catch_unwind to trigger this. Just to be inside a drop that's being executed as part of unwinding. Chris: Do you rely on the current behaviour at all? Amanieu: The problem is the current API as it is is not fixable. We need to deprecate it / design a new API. The 8472: Do we need to do abort? There's two panics happening at the same time? Josh: Not in this scenario: there's only one panic happening. Amanieu: There's also the issue that if we're unwinding due to a C++ execution, the counter is not increased and we're panicing is not set to true. Josh: That aside. The description here of effectively saying "were you panicking where you started" vs. "are you panicking now" seems almost fine but we have to handle nested panics. Josh: The proposal written 17 hours ago for panic tracking mechanism looked promising at least. Amanieu: I'd prefer a more radical solution. Not attempt to track panics at all. Instead tell people what they really want: is this drop being executed for normal reasons or is it executed from an unwind path? Josh: So you're imagining some way when you're inside a drop to know what caused the drop. Notably, that'd only apply on the outermost object. Amanieu: That's basically what Java does with the `finally` section (that runs regardless of an exception). Josh: How would you describe this API working? ```rust pub trait Drop { const fn drop(&mut self); // TC: Require pinning if explicitly implemented? const fn unwind_drop(&mut self) { Drop::drop(self) } } ``` (Plus some heavy special-casing in codegen.) Amanieu: That seems good. But I'm concerned about the codegen impact. Josh: Yes, codegen runs hot. Josh: There will probably be a lot of bikeshedding on trying to fix a lot of other drop-related issues here. We should resist that and only focus on this issue. Amanieu: What's the lang process for this? Does it need an RFC? Josh: The first step would be an issue nominated for a vibe check. Could be this issue if you write it up. Or a separate issue. And naminate it for discussion. TC: Is there a full design already or is this an ask for the design? Amanieu: I can provide the design. Amanieu: And after that, we'd deprecated `std::thread::panicking` because that's a footgun. Josh: Does a line 152 look like an accurate description of your proposal (modulo special casing)? Amanieu: Yes. TC: The idea here that `unwind_drop` is the one that's called in that case. If we're adding a new one here, that would ideally be a `Pin<&mut self>`. Josh: That's the the bikeshedding I mentioned. TC: We should think about it when adding new surface area here. Amanieu: That would require a new trait addition so that's orthogonal. Josh: It's also not clear to me what the state of the main drop proposal is. Josh: TC, how would you write the body of the drop proposal if you changed the signature of the unwind drop? TC: We can say "if you're implementing `unwind_drop` explicitly, then both signatures must be written `&pin mut self`. Kind of like what we're doing on pin-ergonomics where you have to implement pined drop to implement `!Unpin` for the type. Josh: At least in theory, given how much magic `drop` is going to need anyway to avoid the overhead here, it seems like a small addition. In that case drop and unwind_drop would have different signatures. But can we not mix the complexities right in? Josh: We need to defer this until we have the vibe check about this proposal. Any change to go in that direction will have the net effect of introducing `Pin` to a couple orders of magnitude to people who never had to deal with it before. TC: Agreed, but that's hopefully going to be mitigated by the pin-ergonomics work. Amanieu: I'll write this up. (Note previous item and discussion about making it work for fields as well.) ### (waiting on team) rust.tf/65816 *Tracking issue for \`vec\_into\_raw\_parts\`* Amanieu: I think we've resolved this and it's on FCP now so I'll change this label to waiting on FCP. ### (waiting on team) rust.tf/139087 *Fallback \`{float}\` to \`f32\` when \`f32: From\<{float}\>\` and add \`impl From\<f16\> for f32\`* Amanieu: This one is still waiting on Lang. ### (new change proposal) rust.tf/libs614 *ACP: mpsc/mpmc Reciever Peeking* The 8472: There's a long thread. I think we can just close it. Amanieu: We can just close this. ### (new change proposal) rust.tf/libs613 *ACP: Peekable::map\_next\_if* Amanieu: We have .nex_if that takes a closure, inspects the next element and returns a bool. This proposes something that looks at the next element and returns an `Option`. Seems weird to call this a `map` since it takes the input by reference so it can't mutate it. Could be useful, it's also a bit awkward. The 8472: If the function returns `None` than you can get the item out by value by calling `next`. But mapping newer returns anything by calling by value. Should it maybe return it in `Result` where it puts the value back? Amanieu: But when it panics? The 8472: Then it consumes the value. Amanieu: But they want the value to be put back. The 8472: If you return a Result then it returns the value back on the error case. Amanieu: We had something similar proposed earlier: https://github.com/rust-lang/libs-team/issues/557 `next_unpeek`. The 8472: It feels like people want a sort of a list where they want to push and pop items rather than having an iterator. Amanieu: The `next_unpeek` ACP is accepted. Should we ask the author of `map_next_if` whether that addresses their issue? https://github.com/rust-lang/libs-team/issues/557 The 8472: This feels like it's operator on a stack rather than an iterator. Amaniou: Proposal: we ask whether `peek_slot` addresses their issue. TC+The 8472: Agreed. TC: I'm reading 613 ACP more carefully. This is well-motivated. We have `next_if` and you think "yeah, that kind of calls for a more compositional alternative". Seems unfortunate from the perspective of multiplying the API surface. But this is something we do elsewhere, and I can see why you'd want to reach for it in this case. Amanieu: The naming seems hard; not sure how to do better. TC: The obvious alternative is putting the `map` at the end (`next_if_map`) or in the middle, `next_map_if`. Amanieu: It's taking it by reference, it's not mapping it. The 8472: The `map_or_ref` on `Cell` does that. Amanieu: Right. But that's from a reference to a reference. You're mapping from an outer struct to just a field from a struct. It's a proper map because it gives you a reference too. The 8472: What's the reason for not doing the owned version? It's listed in the alternatives, but they're not explaining why that's not the preferred variant. The 8472: They'd need to write an extra `ok_or` in the closure to pass the value back. I guess it can be a bit more difficult to use. TC: Yeah good question. Why not the owned version? The 8472: The real-world examples actually adds a match statement or a function that has the arguments tailored to the interface. TC: When I said this is a well-motivated I was thinking of the owned version. If that doesn't work for the author I'd like to hear the details of that. Amanieu: As an alternative, `next_slot` which takes a `&mut Option<Item>`. It returns whatever you want, you can take the thing out, put something else back in or just leave it as it is. The 8472: That doesn't provide the mapping to the ?? type? Amanieu: Right. Nevermind. Amanieu: I don't know what to do here. The 8472: We can ask why not the owned version? TC: We can say we're inclined to accept of the owned version and ask whether they have any examples that wouldn't work. Amanieu: I'm not fond of using `Result` that way. The 8472: Looking at the real-world examples, in every case the closure is quite complicated and always includes a match statement or similar. So switching from `Option` to `Result` wouldn't be that much more complicated. And that would work for the owned version because the `Err` just passes the value back. Amanieu: What I don't like is that the `Err` type isn't really an error. It's more of an `Either` rather than `Result`. The 8472: Maybe we could use `ControlFlow`? Amanieu: That just feels wrong. Here we're not really talking about a loop and continuing. It's still bad but better than `Result`. TC: From the perspective of the closure that's being called, you're expressing that an error case happened and you're putting back the value. We do that somewhere else too. Amanieu: Atomic `compare_and_change`? The 8472: That's semantically a look. Amanieu: And also semantically an error case. The 8472: We could call it something like `try_next`? Amanieu: I think `ControlFlow` is a good idea. Let's go with `ControlFlow`. TC: Once again, from the perspective of the closure it makes sense. The 8472: `Try` doesn't sound so bad. Amanieu: The `Try` trait doesn't useful. You can do that with just `Result` too. The 8472: But you don't like `Result`. TC: How would that work? The closure wolud return `impl Try` or something like that? The 8472: Yeah. TC: You'd have to return the `impl Try` and you'd constraint the output and constraint the residual. The residual would be `I::Item`? The 8472: Yeah. TC: I kind of like it if it works. If the ergonomics are okay. We'd have to run some examples. If you had references you'd run into problems with the higher kinded ?? story. But with owned values would you still have issues returning the opaque type from the closure. The 8472: `Try` is still unstable. TC: You can use either `Result` or `ControlFlow`. `Option` returns `Try` but you'd never satisfy the residual. TC: It's kind of appealing conceptually if it works. Someone would need to verify this. Exactly what we're trying to express with the closure is `impl Try`. It's a very tight conceptual mapping. Amanieu: Practically speaking this only works with `Result` or `ControlFlow`. The 8472: But that's only because `Try` is unstable. Amanieu: I'm happy to withdraw my objection. TC: Is it forward-compatible to change this into `impl Trait`? Amanieu: If someone is providing generic methods, it could definitely be a breaking change. TC: Yeah, I'm happy enough with a `Result`. And we'd name it `map_next_if` or `next_if_map` or `next_map_if`. The 8472: The residual has the complication in that it's not exactly the type you'd return. I'm not sure we can constraint the type bounds exactly. TC: I think you could but it's a little bit tricky. The 8472: Let's ask why they're not proposing the reference one and not the owned one. TC: If we just did the owned one, what would we want to call it? We have `filter_map` and we put `map` at the end. We have `next_if` here, `if` is kind of like `filter` so analogously, we'd say `next_if_map`. Amanieu: I wouldn't call it `filter_map` because that would conflict with `Iterator::map`. How about `try_next_map`? `peek_map`? TC: It's not a peek, we're consuming the value. Amanieu: `next_if_map` TC: I'll write up the ACP acceptance. ### (new change proposal) rust.tf/libs610 *ACP: Add a \`oneshot\` channel* Amanieu: We accepted this last week and didn't assign someone to write the message. The 8472: I can reply. ### (new change proposal) rust.tf/libs603 *A \`Static\` receiver type for dyn\-trait methods that do not take values* Amanieu: Still under discussion, let's let it cook a little bit. ### (new change proposal) rust.tf/libs602 *ACP: add \`array::from\_raw\_parts()\`* Amanieu: Do we want to close this or accept `cast_array`? The 8472: `cast_array` seems fine. ```rust // Also *mut T and NonNull<T> impl<T> *const T { fn cast_array<const N: usize>(self) -> *const [T; N]; } ``` Josh: I support adding `cast_array`. Wonder if we want to see `read_array` too. But for now, add `cast_array` and see how it's used before adding more. Amanieu: Accepted the ACP (`cast_array`). ### (new change proposal) rust.tf/libs587 *ACP: \`try\_exact\_div\` method on \`NonZero\<{integer}\>\`* Amanieu: This one's waiting on author. ### (new change proposal) rust.tf/libs578 *ACP: hash\_map! macro to create \`HashMap\`s such as \`vec!\`* Amanieu: We bikeshed a lot about the separator (arrow or colon). The 8472: I think the other team members have opinions on that. We should skip it. ### (new change proposal) rust.tf/libs577 *Option::try\_get\_or\_insert\_with* Amanieu: I think this is just Accept. TC: Yes. Almost anywhere we have a method like this there's a reasonable case for a try version. TC: Is the solution sketch wrong? Amanieu: We're going with kennytm's version of the `Try` trait. The 8472: I'd have liked to see some users for that. Amanieu: I think I wanted this some time in the path but I don't remember. The 8472: It's like the `Entry` API on maps, right? ### (new change proposal) rust.tf/libs575 *ACP: \`Option::update\_or\_default\`* Amanieu: `get_or_insert_default`? The 8472: It mutates in place, doesn't return anything. `update_or_insert_default`, yeah. The 8472: Since the `Option` is guaranteed to be `Some` afterwards, we can return a reference so the user doesn't need to immediately `unwrap` afterwards. Amanieu: (looking for any precedents for this) The 8472: `map_or_default` is the closest we have. Or the `map_entry_or_default` on maps again. Amanieu: That's not quite what they want. The 8472: Default is useful for numbers where you initialize with 0 (or an empty String/Vec) where you can add the next values later. Amanieu: This method is extremely specific: "if there's something, map it. If there is nothing, insert default". That feels explicit enough where it just needs to be a match. The 8472: If the default is the initial constructor for the item (instead of explicitly calling `new`), often I have some kind of transaction tracking where the constructor initializes the UUId and the initial state. If a new thing comes in, initialize it, get then new state. It would make more sense if it returns a reference where you could use it afterwards. Amanieu: At that point it's equivalent to `.as_mut().map().get_or_insert_default()`. The 8472: A match would also do here. Amanieu: I feel `match` is actually clearer in this example. The 8472: It moves the value out and puts it back in. Anything that returns a `&mut` would make this more complicated. Amanieu: Why would it make it more complicated? After this method executes, it's going to be `Some` so you might as well get the reference. The 8472: Didn't we want something like this for `Cell::update`? Amanieu: We chose to restruct `Cell::update` only on `Copy` types. If you want to use something else, you need to do `.take()` and do it yourself. The 8472: I can kind of see the usecase but not really. TC: Why do you need it by value here? If you have a mutable reference, the only thing you can't do is.. what? You can move out of the mutable reference by swapping it. Feels like this should just be using a mutable reference. And that avoids the panicking problems, right? Amanieu: I see what you mean. So we don't want to implicitly do the "remove the item from the Option" because of the footgun if the closure panics (and the option will end up None). TC: And that's why we can use the mutable reference. That's what `update` means. Amanieu: The second signature: I can image a `.update()` method. And then you'd get the ??. The 8472: There are differences around inserting the default first. E.g. inrementing the counter: when you default to `0` you immediately increment it to `1` or insert `0` the first time. TC: What are the two cases you're distinguishing here? The 8472: Doing the default first and then doing the update. Amanieu: It's `.as_mut().map()` -- means you operate on a mutable reference. Or: `.take().map()` and then assign the result back. And for the `default_map` you just add the default in. I think this is clearer than the `update_or_default`. The 8472: The `Entry` API for hashmaps has a `and_modify` method. TC: Regardless of what else we do, we probably need `.update()` on `Option`. I know I've wanted that before. Amanieu: That's `.as_mut().map()`. TC: But discarding the return type. That's kind of like `.as_ref().for_each()` if we had `for_each` on `Option`. Amanieu: two approaches: one that takes a mutable reference and the other takes the value out temporarily. ```rust! opt.as_mut().map(|x: &mut T| { .. }); opt = opt.take().map(|x: T| { .. }); opt.get_or_insert_default() ``` The 8472: But that means you cannot chain them. The proposal aims to make them chainable. Neither of these proposals are chainable. Amanieu: `update` would also not be chainable, it would return a `()`. TC: You could make the `update` chainable by returning the entire outer option. The 8472: Just `&mut self`. The 8472: If you do an update that returns a reference, then you do get_or_insert_default then you get the `Some` value. No need to unwrap or match or anything. So I think replicating the `Entry` API or equivalent should dbo it. Amanieu: `and_modify_or_insert_default`? The 8472: It's essentially an Entry API for a single entry. It's basically maniuplating the "value" part of a `HashMap` not the key. Yeah, I think we could do that. Amanieu: Do you want to propose that! The 8472: Ok. ### (stalled change proposal) rust.tf/libs261 *add \`write\_fmt\` method to String, to make \`write!\` macro work without imports* ### (stalled change proposal) rust.tf/libs462 *impl fmt::Write for BufWriter* ### (stalled change proposal) rust.tf/libs483 *\`Box::new\_from\_ref\` for making a \`Box\<T\>\` from a \`&T\` where \`T: CloneToUninit + ?Sized\` (and \`Rc\` and \`Arc\`)* ### (stalled change proposal) rust.tf/libs363 *Un\-specialize impl ToString* The 8472: It starts with "by adding a new method on Display". Amanieu: We already do that. The 8472: I think that was a mistake. I see `to_string` more of a serialisation and `Display` is for humans. And sometimes they're not the same. Amanieu: Don't we have a special implementation of `Display` for `String`? That just passing the raw string into `fmt::Arguments`. Amanieu: No, we have an `as_str` method that returns a `&'static str`. Nevermind. Amanieu: So you think we should just reject this? The 8472: I'm not sure what we should do. We're stuck with the mistake we made. Should we double-down? Or fix this? Amanieu: What if we made it permanently unstable? The 8472: The ideal is that users can use it when it's stabilized? Amanieu: Or is it more about performance / compilation time. The 8472: Some of the examples are for external crates such as `arrayvec`. If so than it have to be stable. TC: I'm sympathetic to the motivation. People want to avoid the formatting machinery. The standard library wants to avoid it to, so it uses specialization. But others can't do that, so this is asking for something that we can stabilize -- that doesn't lean on specialization -- so others can avoid this machinery too. That's a coherent motivation. Whether this is the right solution to that motivation needs more analysis. The 8472: I don't understand the design between `ToString` and `Display`. They're separate traits. I guess users can implement `ToString` and not `Display`. That doesn't seem like a good design. Either one should be a subtrait of the other or they should be orthogonal. Amanieu: Obviously `ToString` as a trait has been a mistake. You should have had `to_string` method on `Display`. Either we completely tie them together or we don't at all. The 8472: Yeah. The 8472: So, does it make sense to have types saying "I can be converted to a string but I'm not necessarily meant to be displayed to humans". Amanieu: I understand, but at this point it seems too late. The 8472: something something Edition? TC: We can treat `Display` as having been polluted. Say `Display` would be non-human one, and we'd add `HumanDisplay`, and then do some migration, maybe using editions. Amanieu: We already have `Debug`. The 8472: We have `Debug` for developers and `Display` for end-users. The 8472: You can always write a dedicated method or `Display` adapters like we do on `Path`. But it's sub-optimal that we cannot express them ??. If you have a JSON structure, `to_string` would imply it's JSON but `Display` could display it differently to humans. Amanieu: I don't think this is a problem that users actually have. If you need formatting, use the `format!` macro and format it however you want. The 8472: I think because we had it since 1.0 we're coping with it. But the situation is not ideal. TC: Also look at the comment at @CAD97 about `MaybeUninit<u8>`: https://github.com/rust-lang/libs-team/issues/363#issuecomment-2028819128 Amanieu: That's the `ReadBuf` discussion all over again. TC: Exactly. The 8472: Feels like there will be a more general buffer ??. Is that meant to be an implementation detail or a public API? Amanieu: `TempBuffer` is basically a `WriteCursor` The 8472: Yeah, `TempBuffer` is in the public proposal. The 8472: If we double-down on `Display` and `ToString` being joined at the hip, I guess we could do more of this. Amanieu: This method works with `dyn Display`. That's an advantage over specialization. You can skip the formatting if you have `dyn Display` and the actual type as a string. The 8472: But then we can't make the formatting error an associated error type. All the formatting error would have to be the same type. Amanieu: That's already the case. The 8472: I mean the `TryToStrError` Amanieu: That can't fail. The 8472: It can if the buffer is too small. Amanieu: So, conclusion? The 8472: I'm not decided. If we stick to `Display` and `ToString` being tightly related, this kind of make sense. But ideally we'd fix them and then it doesn't. But if we don't see a way to fix them, then ok. Amanieu: I don't thing we're ever going to be able to disentangle `Display` and `ToString`. The 8472: It covers more cases, `dyn Display` works, we could stabilize it. TC: That sounds to me like "ACP accepted" for nightly experimentation, inclusive of handling what CAD97 mentioned about staying zero-cost by dealing in `MaybeUninit`. Amanieu: I can see one alternative here: this specifically has `TryToStr`. Alternatively we can have `as_str` method which requires the string to be in memory. The 8472: Then we'd still have specializization ?? Amanieu: Can the `TempBuf` be a string? Why does it have to be a `[u8]`. The 8472: The idea is to be on the stack for composing some larger strings. Amanieu: The signature feels awkward. Where is this going to be used? It can be used by ToString. So either Amanieu: It seems like `TempBuf` is useless with the size being known at compile time. Guess you can always return an error. Amanieu: I'm going to ping Guillume Gomez who's worked on the `NumBuffer` proposal, see what he things. [...] The 8472: The lifetime is of the `fmt::TempBuffer`. Amanieu: And self. The 8472: Ah, I see. Amanieu: `TempBuffer` is only used for `u8` and `char`. The 8472: We'd have to write it out for `Box<str>`. Amanieu: It is a pain though. Amanieu: I feel even if we keep this unstable there may be benefits but it's hard to tell. The 8472: The only benefit would be `dyn Display`. Everything else would be done with specialization. Amanieu: Would this have impact on compile times? Generating new methods on `Display`. It would need a perf run. The 8472: If is unstable, I don't know how often `dyn Display` is used in the ecosystem and how much it'd be a performance bottleneck. Amanieu: I think it's used quite often but we don't typically use `to_string` on it so it's hard to tell. The 8472: If we keep it unstable, we can cover more cases with specialization. If it's made stable then it's useful for end-users. Amanieu: I'll nominate it for next meeting so more people can take a look. TC: If the motivation is compelling we can state that and highlight the concerns. Amanieu: I think it's a lot of work and the motivation is not compelling. The 8472: How big is the performance bottleneck? Has someone measured it? If someone uses the `arrayvec` crate and has a performance bottleneck, that would be useful. The motivation is performance so we need numbers. TC: That's reasonable: more details and examples, use cases. If we ask now and state the concerns, there will be more data by next week. The 8472: I can try writing something, I'm not sure how much it'll help. TC: Give it a try. It's always encouraging to contributors showing how much thought we put into it. And that will come through in your writing. ### (stalled change proposal) rust.tf/libs379 *Combine, an iterator adapter which statefully maps multiple input iterations to a single output iteration* ### (stalled change proposal) rust.tf/libs296 *ACP: Designing an alternative \`FromStr\`* ### (stalled change proposal) rust.tf/libs438 *ACP: \`ForwardInit\<'a, T\>\` to complement \`MaybeUninit\<T\>\`* ### (stalled change proposal) rust.tf/libs452 *ACP: Implement \`TryFromIterator\<T\>\` trait to compliment \`FromIterator\<T\>\` trait.* ### (stalled change proposal) rust.tf/libs484 *Support \`vec!\[const { ... }; n\]\` syntax for creating a \`Vec\` of non\-\`Clone\` values* ### (stalled change proposal) rust.tf/libs133 *Add fmt::Write to io::Write adapter* _Generated by [fully-automatic-rust-libs-team-triage-meeting-agenda-generator](https://github.com/rust-lang/libs-team/tree/main/tools/agenda-generator)_