owned this note
owned this note
Published
Linked with GitHub
# Libs-API Meeting 2025-09-23
###### tags: `Libs Meetings` `Minutes`
**Meeting Link**: https://meet.jit.si/rust-libs-meeting-crxoz2at8hiccp7b3ixf89qgxfymlbwr
**Attendees**: Amanieu, Josh, David Tolnay, The 8472, Tomas, Chris Denton, TC
## Agenda
- Triage
- Anything else?
## Triage
### FCPs
26 rust-lang/rust T-libs-api FCPs
- 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/143191 *Stabilize \`rwlock\_downgrade\` library feature* - (3 checkboxes left)
- merge rust.tf/145608 *Prevent downstream \`impl DerefMut for Pin\<LocalType\>\`* - (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/146560 *Add the \`cpuid\` target feature* - (8 checkboxes left)
- merge rust.tf/132968 *Tracking Issue for \`NonZero\<u\*\>::div\_ceil\`* - (3 checkboxes left)
- merge rust.tf/116258 *Tracking Issue for explicit\-endian String::from\_utf16* - (2 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/136306 *Tracking Issue for NEON fp16 intrinsics* - (3 checkboxes left)
- merge rust.tf/141994 *add Iterator::contains* - (3 checkboxes left)
- merge rust.tf/63569 * Tracking issue for \`#!\[feature(maybe\_uninit\_slice)\]\`* - (3 checkboxes left)
- merge rust.tf/145656 *Stabilize s390x \`vector\` target feature and \`is\_s390x\_feature\_detected!\` macro* - (4 checkboxes left)
- close rust.tf/136638 *warn on empty precision* - (4 checkboxes left)
- merge rust.tf/145628 *\[std\]\[BTree\] Fix behavior of \`::append\` to match documentation, \`::insert\`, and \`::extend\`* - (3 checkboxes left)
- merge rust.tf/145610 *Stabilize \`char\_max\_len\`* - (3 checkboxes left)
- merge rust.tf/145722 *implement Extend\<{Group, Literal, Punct, Ident}\> for TokenStream* - (3 checkboxes left)
- merge rust.tf/145948 *Stabilize 29 RISC\-V target features (\`riscv\_ratified\_v2\`)* - (5 checkboxes left)
- merge rust.tf/135889 *Tracking Issue for \`VecDeque::pop\_front\_if\` & \`VecDeque::pop\_back\_if\`* - (3 checkboxes left)
- merge rust.tf/126769 *Tracking Issue for \`substr\_range\` and related methods* - (4 checkboxes left)
- merge rust.tf/144090 *Make \`IoSlice\` and \`IoSliceMut\` methods unstably const* - (4 checkboxes left)
- merge rust.tf/146561 *Change \`Location\<'\_\>\` lifetime to \`'static\` in \`Panic\[Hook\]Info\`* - (4 checkboxes left)
- merge rust.tf/146705 *Tracking Issue for \`fmt\_from\_fn\`* - (3 checkboxes left)
- merge rust.tf/146882 *fully deprecate the legacy integral modules* - (3 checkboxes left)
1 rust-lang/stdarch T-libs-api FCPs
- merge github.com/rust-lang/stdarch/issues/1908 *Make some remaining X86 intrinsics safe* - (3 checkboxes left)
[BurntSushi (22)](https://rfcbot.rs/fcp/BurntSushi), [Amanieu (2)](https://rfcbot.rs/fcp/Amanieu), [nikomatsakis (4)](https://rfcbot.rs/fcp/nikomatsakis), [the8472 (13)](https://rfcbot.rs/fcp/the8472), [dtolnay (2)](https://rfcbot.rs/fcp/dtolnay), [m-ou-se (24)](https://rfcbot.rs/fcp/m-ou-se), [joshtriplett (17)](https://rfcbot.rs/fcp/joshtriplett), [traviscross (1)](https://rfcbot.rs/fcp/traviscross), [jackh726 (1)](https://rfcbot.rs/fcp/jackh726), [scottmcm (4)](https://rfcbot.rs/fcp/scottmcm), [tmandry (1)](https://rfcbot.rs/fcp/tmandry)
### (nominated) rust.tf/134645 *Tracking Issue for \`sync\_nonpoison\` and \`nonpoison\_{condvar,mutex,rwlock}\`*
Amanieu: It's not clear what the nomination is for.
The 8472: Probably because of teh comment before nomination?
Amanieu: But there's a gap of two weeks. I don't think we need to discuss, just ask what the nomination is for.
David: I think it's the forth paragraph here: https://github.com/rust-lang/rust/issues/134645#issuecomment-3240123147
> I think there are at least two ways to structure this: The first is having the `poison` and `nonpoison` modules complement each
> other perfectly, where a module in `poison` just means that there is a corresponding module in `nonpoison` (this would be Mutex, Condvar, and RwLock). Everything else would be outside of these modules.
Amanieu: I agree, that the poison and nonpoison modules should basically perfectly mirror each other.
Josh: Assuming there's nothing from the poison module that we want to deprecate. But I agree.
Amanieu: It wasn't clear whether we should have poisoning an nonpoisoning version of `Once`. Since `Once` has an API to skip the poisoning.
The 8472: We need to move stuff out/not move stuff into `nonpoison`, like `Barrier` since that has no mirror.
Amanieu: I'll reply with that.
Josh: Something that came up recently was: which approach we're using when we'd poison in nonpoison? Are we panicking?
Amanieu: Nonpoisoning doesn't track whether the lock was poisoned, we just acquire the lock.
Josh: Some people thought we didn't track it and others though we unwrapped silently.
Amanieu: It absolutely means "don't track it".
### (nominated) rust.tf/140042 *Library team consensus on promoting tier 3 riscv32 ESP\-IDF targets to tier 2 with std that has processes and signals support stubbed out*
Amanieu: The issue was whether to use `cfg(unix)` and last reply from April was we're not clear.
Josh: That was the last reply on this issue. This prompetd a zulip discussion. The folks who work on this target said they do use `cfg(unix)` for a reason. They're hoping to handle most things that make sense on unix and just not handling signals and not handling threads. That led us to say at least for internal purposes of the library is to share things with `unix`. Then jubilee brought up how this would work with the larger ecosystem. Whether we're prepared to ship this as unix and have the ecosystem deal with ESPIDF as a special platform.
Amanieu: I'm inclined to not do that.
The 8472: What do they do for signals?
Josh: They don't have the concept of signals. They don't have processes either.
The 8472: Since signals are in posix,
Amanieu: There are two examples: socket2 and rustix. They use `cfg(unix)`. They rely on this so it almost just works. So code like:
https://github.com/rust-lang/socket2/blob/36dec54c30c5ca0c711709b9e1f03b8cb8d155fa/src/lib.rs#L108
Amanieu: The main thing with cfg(unix) is you have BorrowedFd and everything that goes with it.
The 8472: So what is there that generally assumes "if unix then signals".
Amanieu: In practice nobode cares about signals. In reality, exponsing unix they can use RawFd, AsFd etc. On the other hand WASI has its own AsFd.
The 8472: Things like tokio don't have this. What happens when
Josh: I'd expect it to compile and silently not get signals at runtime. If it fails to compile, that would be more painful.
The 8427: That's exactly what I meant. We should check what the behaviour is for ESP-IDF.
Josh: My understanding based on the evaluation we did, unlike the wasm32-unknown-unknown targets, they're not introducing panics in functions that can't return errors.
The 8472: But if nix calls into libc and libs doesn't have the method, it would still have a compiler error.
Josh: As far as standard library goes, I don't think we're doing anything bonkers. But I don't know to what extend we are okay advertising what Rust exposing unix means. But I think that's more for a compiler team. For our case, I think we are in a place where we won't have weird compiler-time issues etc. But the rest is out of scope for the library team.
The 8472: We could also say libc provides stubs for the requried posix APIs for unix targets. But that would be .. an interesting choice. You mean we sholud forward this to compiler?
Josh: The recomendation to feed to the compiler team is: our scope is what the standard library exposes. And there, we don't have an issue with bumping the tier. But they should consider the potential impact on the ecosystem -- but that's not the API call.
Chris: Is the meaning of `unix` a Lang question as well?
Josh: That's been somewhat fuzzy. It's debatable what Lang and Compiler are responsible for. This is in a fuzzy area where `cfg(unix)` was never properly defined.
TC: The question here is whether we would writen in the language specification.
Josh: I'd expect cfg(unix) and cfg(windows) to be written in the Spec the same way of whether you have atomics.
TC: It wouldn't be in compiler's discretion to define semantics, that's the point.
Josh: Agreed. But it's not clear whether we've defined what the definitoin is but in the mean time people are adding more targets.
TC: I'd lang-nominate the question Chris asked (not this issue). It's lang's call to clarify.
Josh: I can write something up for this one.
### (nominated) rust.tf/142506 *Add \`Path::has\_trailing\_sep\` and related methods*
Amanieu: There was a libs api question about the specific behaviour of `trim_trailing_sep`: https://github.com/rust-lang/rust/pull/142506/files#diff-212737b68c4541123dae6916cdde516551e1fafcb343467bfe08a3d7ce72c517R2900
Amanieu: It's not clear what this means with the root.
Amanieu: For trim_trailing_separator: if the only thing you have in your path: do we link them as is or reduce them to a single slash?
The 8472: This method was not part of the ACP originally. Do we know where it came from?
The 8472: We could say "don't add this".
Amanieu: We could. I do think it's a useful thing to have. How do people feel?
Josh: Someone made a comment that posix doesn't actually let you change this. Posix allows you to treat `/` differently from `//`.
Amanieu: But `///` is equivalent to `/`.
Josh: That's true.
The 8472: What's the purpose for this? If you trim it from the root, you get an empty path.
Josh: Yeah, root will have to keep having a special meaning. I think we should just keep the correct behavior as it's been proposed.
Amanieu: I'm happy with that.
### (nominated) rust.tf/145504 *Add some conversion trait impls*
Amanieu: This adds a bunch of `AsRef`, `AsMut` and `From` impls. Which I'm not generally in favour of.
Josh: It's unfortunate this is one big issue.
Amanieu: I don't like `AsRef` and `AsMut` in general.
The 8472: We have people use them so it doesn't have them blocknig addition of new uses on that ground. You would have to outline a plan of what we do about them. Or have a policy of adding them narrowly.
Josh: Looking at the list of items here I don't seem any that are problemating. The only one needing a set of eyes double-checking is corner cases around having a `&mut MaybeUninit` but I don't think the proposed impls here have that problem.
Josh: But that seems fine.
The 8472: The `AsMut<str> for AsceeChar` what would you use it for?
Josh: In general, `&mut str` is a valid type. You can mutate things in space but you can't change the length. You could e.g. change the case of a string (if its ASCII).
The 8472: But what would a single-character mut str be? I would expect an array of AsciiChr
Josh: That would also work. If you want to propose that.
The 8472: Why propose this one or not the slice/array variety? What's motivating this usecase over the array one? That's not explained.
Josh: Do we expect people to use this implicitly or have them call a function? We have precedent for a function treating treating a single `T` as an `[T]`.
Amanieu: My main objection is that for all of these traits there's an explicit method that does these things. And using the explict method would always be cleare.
Josh: The main reason these traits exist is for people to write a generic function. E.g. "I'll deel with any `AsRef<str>`".
TC: Right, to build on that, my philosophical concept of our language is that if you can implement a trait in a sensible way, you should implement the trait, since we want people to be able to think and work in a generic context. The presence of similar inherent methods doesn't affect this.
Josh: I think The 8472's point is valid in that we should add these to an array of characters not just single characters.
Amanieu: I think we do.
The 8472: I don't see them on AsRef/AsMut.
Josh: We don't have AsRef traits for a single AsciiChar.
Amanieu: We have: `impl From<&[Char]> for &str { ... }`
Josh: That argues we should have: `impl AsRef<str> for [Char]` and `for [Char; N]`.
Josh: It seems all the ones other than those two methods are fine. We could say that and mention that those two should also have methods for arrays.
The 8472: My question is: why are these proposed and not the others. What is the motivation?
Josh: I would expect the motivation is `as_str` exists for an individual char and if so, then `AsRef<str>` should exist too.
The 8472: The author din't explain that so that's speculation.
TC: Does it matter? If Josh has his own motivation, isn't that as good as the author's?
Josh: I'd like to know what the author's motivation is?
The 8472: Maybe they have a specific use case I'm missing. Maybe they just looked through the API and just looked at what's missing and haven't thought about the bigger picture. Depending on which, we could say either "this doesn't make sense" or "okay, you have a use case, maybe we could generalise it" etc. Hard to analyse the proposal.
Josh: I could write a proposal for accepting the ones that are not contentious and ask for motivation behind the AsciiChar ones. The 8472: if you want to post follow-up feel free.
The 8472: The next one is for `MaybeUninit`. Did doing this via a conversion trait ever come up? How does this fit into the general MaybeUninit API? We do have `transpose` which is unstable.
Josh: This is something where having a `From` and `AsRef` would be a substantial usability imporovement.
The 8472: The author did bring that up in the tracking issue for `transpose`: https://github.com/rust-lang/rust/issues/96097
The 8472: I see, this one comes from the tracking issue but we didn't discuss it. It's surprising it never came up before.
TC: I vaguely recall us discussing this and saying roughly, "it's not what the author asked for here; someone could ask for it later".
The 8472: I see, so we didn't explicitly rejected it or said it has to be a method. Okay.
The 8472: Okay, then the rest seems fine.
### (nominated) rust.tf/145665 *Don't require \`T: RefUnwindSafe\` for \`vec::IntoIter\<T\>: UnwindSafe\`*
Amanieu: We can skip this one and FCP it. IntoIter is fully `UnwindSafe` not just `RefUnwindSafe`.
### (nominated) rust.tf/146013 *Add \`From\` impls for wrapper types*
Amanieu: I'm generally okay with most of these. The `Copy` bounds on `ManuallyDrop` have been added because there were some crater failures. I don't think this should only be for `T: Copy`. It should be no all `T`. If that's having issues, these shouldn't be there at all.
The 8472: I asked for motivation and these were mainly for consistency.
Amanieu: I don't think the ones for LazyCell/LazyLock would be useful. We can have them though, it wouldn't hurt.
The 8472: Can we scope the impl to a specific generic arguent.
Amanieu: I think we can leave it as is. I'd just remove the `ManuallyDrop` if we can't have it for all T.
Josh: It would be dangerous for all T so I think we should just drop it.
Josh: I agree with the premise that `LazyCell` and `LazyLock` wouldn't hurt. But they seem questionable enough so I'd just drop them until someone asks for them.
Amanieu: The `F` in Lazy Cell/Lock defaults to a function pointer. So I think it's still fine to leave them in. It's still just `ManuallyDrop` that I'd remove. Especially since the `Copy` bound on `ManuallyDrop` means that the type doesn't have `Drop`. In which case why are you using `ManuallyDrop` in the first case.
Amanieu: Are we happy to start FCP for eveything except `ManuallyDrop`?
Josh: Go for it.
### (nominated) rust.tf/146099 *Stabilize \`debug\_closure\_helpers\`*
Amanieu: We already have an FCP started for `FromFn`. Do we alse want the underscore helpers?
David: I think having both is good.
Amanieu: I'm happy to go with it but I don't want to be the only one.
The 8472: The last time we discussed this was a language feature to have a shorter way to imlement ?? method traits.
Amanieu: We did briefly mentioned that Java had this but I don't think this is a language feature.
The 8472: They're just proposing this because they don't want to write
Amanieu: That's a separate tracking issue. This is for adding the `*_with` functions.
Josh: These seem broadly fine.
### (nominated) rust.tf/146660 *Tracking issue for release notes of #146410: Iterator repeat: no infinite loop for \`last\` and \`count\`*
Amanieu: This is an iterator that implements DoubleEnded iterator with infinity items. The issue is that the iterator has `last` and `count` methods.
Amanieu: I approved this but then tihs technically fon through an FCP. Previously, `last` and `cound` would go into infinite loop. With this change `count` panics and `last` implements the last element.
Josh: Removing the infinite loop makes sense. Count would be infinite so it makes sense that it should panic. The question is: do we return the one element or should you panic?
Amanieu: There should be `last` because it implements DoubleEndedIterator and it implements next_back.
Josh: Since this is a double-ended iterator, I withdraw my concern.
Amanieu: Do we need an FCP for this?
Josh: This seems like a user-visible behavior change. So it should have been an FCP, but do we want to start one retroactively? I propose we start an FCP and everyone here who isn't against it would check their boxes.
Amanieu: Should we have a more general statement
Josh: It's safe to say if you implement DoubleEndedIterator it makes sense to for it to return the same thing as `next_back`.
The 8472: The difference is that it exhausts the iterator.
Amanieu: Also, there's a separate change to make `fold` not panic.
Josh: `fold` says it walks the iterator and could loop infinitely.
### (nominated) rust.tf/146841 *Stabilise \`rotate\_left\` and \`rotate\_right\` in \`\[\_\]\`.*
Amanieu started an FCP.
### (nominated) rust.tf/libs638 *Add memory prefetching to \`core::hint\`*
Amanieu: this adds prefetch read data, prefetch write data and prefetch ??. I like this but I don't like the naming of the Locality enum (which says whatch cache level we want this to prefetch to).
The 8472: On the LLVM level is it UB to pass some other value?
Amanieu: I think we should make this a nonexhaustive enume. The naming for the locality hints should be L1, L2, L3 and NonTemporal the possibility of adding more later.
The 8472: That's how the CPUs actually implement it, right?
Amanieu: Yes. It may not map to exactly this, but it makes it easier to explain to people.
Josh: It definitely needs to be nonexhaustive. My only concern is: we try to do this portably. I expect there's going to be continuous drive to add new values.
The 8472: We should probably ask the more exotic architecture experts (e.g. GPUs, RISC-V)
Amanieu: Arm has all of these options. The non-temporal hints it has orthogonal non-temporal L1, L2, L3.
Josh: One thing we may wish to do in addition is stating explicitly that what underlying prefetch operations these map to may change in the future. We need to make sure this is in the docs so we can remap these in the future.
Josh: This enum doen't inherently have to be value-less. We could have `Locality` and a locality that can contain a non-temporal flag or similar.
The 8472: It doesn't even have to be in the enum. It could be in another argument.
Josh: Doing it in the argument risks exploding into multiple axes.
Amanieu: The LLVM hint only supports these four options I mentioned earlier.
The 8472: Then we should just ping some GPU folks if they have anything?
Josh: Looks like x86 has similar things to what LLVM provides.
Josh: It seems pretty reasonable for now that we introduce a prefetch operation with approximately these hints as an ACP. And before stabililization we can reach out to the GPU folks.
Amanieu: We can have this hint and the target-specific hint in std::arch.
Josh: But yes, making the change to having a non-temporal option makes sense.
### (waiting on team) rust.tf/139087 *Fallback \`{float}\` to \`f32\` when \`f32: From\<{float}\>\` and add \`impl From\<f16\> for f32\`*
### (waiting on team) rust.tf/145608 *Prevent downstream \`impl DerefMut for Pin\<LocalType\>\`*
### (waiting on team) rust.tf/145722 *implement Extend\<{Group, Literal, Punct, Ident}\> for TokenStream*
### (waiting on team) rust.tf/146009 *Implement \`Receiver\` for \`Exclusive\`*
### (new change proposal) rust.tf/libs659 *Generalize ExactSizeIterator to QuantifiedIterator*
The 8472: I remember there being previous attempts at having infinite iterator, empty iterator.
Amanieu: Looking at the motivation, does it implement the ExactSizeIterator?
The 8472: We don't have a notion of infinite iterators. So we don't have a blanket that takes form of an infinite iterator into an `ExactSizeIterator`. We only have ExactSizeIterator for concrete cases where you directly nest Repeat exactly inside Take. If you e.g. add Map after Repeat, it doesn't work. And they're not just proposing take but also zipping an infinite with finite iterator and stuff like that.
The 8472: The generalization would be empty.
Amanieu: If you're chaining something you know it's empty..
The 8472: I don't know when people would use empty.
Amanieu: What does `Quantified`mean? Not infinite?
The 8472: That we have precise estimate. But it doesn't necessarily fit into a `usize`.
Amanieu: Right, so the size is either exact or infinite.
The 8472: Or empty. The author isn't proposing it but there was another PR proposing it.
https://github.com/rust-lang/rust/pull/90093
The 8472: A cycling of an EmptyIterator would yield an EmptyIterator for example.
Amanieu: I see how this would work. Could we just use an associated constant?
The 8472: Probably but that makes `where` clauses problematic.
Amanieu: Can we use where clauses with ??
The 8472: With generic expressions, but those are not stable.
Amanieu: How would this work in the public interface? It needs to propagate the exact size property.
The 8472: ExactSizeIterator isn't a marker, right?
Amanieu: Counterpoint: take_exact panics if you don't have enough items in the input.
Josh: I'd be tempted to call it `require`, but `take_exact` seems fine.
Amanieu: I guess ExactSizeIterator would be implemented on Take only if the internal iterator is Quantified?
The 8472: Yeah. Because it's a new trait, it wouldn't work for user implementations for existing custom ExactSizeIterators.
Josh: This seems like it's trying to approximate dependent typing but not quite.
Amanieu: Not exactly. The implementation is removing all the explicit implementations of ExactSizeIter from the standard library and it has a blanket implementation for all iterators that implemt QuantifiedIterator.
The 8472: I don't think that's backwards compatible. The user wouldn't implemnet it and the adaptors would lose the ExactSizeIterator. This would need specialization with associated items and const generic expressions. That's at least one language feature we're waiting a long time on.
Amanieu: So: `take_exact`?
The 8472: If it could return a `Result`.
Amanieu: No, it returns an iterator. So it'd have to be a panic.
The 8472: And it doesn't solve the zip case.
Amanieu: Don't we have ZipExact or something?
The 8472: itertools has it. But I don't know if that's an ExactSizeIterator.
Amanieu: And panics if they're not the same length. I think it'd be a better alternative solution.
The 8472: No it wouldn't help with zipping a `Repeat`. There was a performance issue where someone was repeating over an array. They needed a zipping of an finite and infinite iterator. So it seems like a real pattern that people want to do.
The 8472: I think it breaking user types is a showstopper. We should send the user back to the drawing board.
The 8472: I'll reply.
### (new change proposal) rust.tf/libs658 *ACP: Add \`extend\_front\`, \`extend\_from\_within\`, \`extend\_from\_within\_front\`, \`prepend\` and \`splice\` to \`VecDeque\`*
Amanieu: That should be `extend_front_from_within`. What does splice do?
The 8472: You remove some elements and replace them with others?
Amanieu: All these seem reasonable except for the naming of `extend_from_within` -> `extend_front_from_within`
The 8472: There's also a pull request where they asked whether we should have an `ExtendFront` trait?
Amanieu: I don't think there's many cases where you want to extend front?
The 8472: LinkedList?
Amanieu: To move this forward, I'm really happy on everything else. Let's not block on this and have it as a method for now and block it during stabilization. Everything else seems reasonable.
The 8472: Splice adds a whole bunch of complexity. We would have to add Drain.
Amanieu: We already have Drain
The 8472: What's from_within_front?
Josh: There's also a question from the ACP: "Should `extend_front` act like repeated pushes to the front of the queue?" I think the answer is no but we should discuss it.
The 8472: If you take an iterator one item at the time and don't insert them in reverse order, you have to insert them far away ahead from the queue and flush them.
Josh: If you're extending them from an iterator I agree you need to push them one at a time. If you're prepending a whole array, you should memcpy and not reverse it.
Amanieu: Should we add specialization for arrays? That would optimize it to two mem copies.
The 8472: They're talking about extend_front but that's not part of the solution sketch but part of the PR.
Josh: Why don't we answer the concretely posed questions?
Amanieu: Right now it's just a method in the PR. I'm happy about having the method.
The 8472: But the ACP isn't discussing this. They haven't sketched it properly but they're asking us to discuss it.
```rust
VecDeque {
pub fn extend_front<I: IntoIterator<Item = T>>(&mut self, iter: I) {...}
}
```
The 8472: The ACP is also about this but they only spelled it out in prose, not in the code block.
Amanieu: "extend allows iterators that yield &T where T is Clone, should extend_front do too?": I'd say no for that one.
Amanieu: "Does this need a whole new trait like Extend or only a method on VecDeque?" No.
Aamnieu: "Should extend_front act like repeated pushes to the front of the queue?" You do need to know the exact length of the thing.
The 8472: I'm not sure what the best way to do this is. Currently the PR pushes one thing at a time and has a specialization for a RevIterator.
Amanieu: So it's pushing things in reverse order.
Teh 8472: Yes.
Amanieu: I think that's probably very confusing. I'd expect `extend_from_within` to preserve order. I would expect it to grab a slice of stuff and memcpy it to the front.
The 8472: That's a different method.
Amanieu: That's the same concept. I would name this `extend_front_from_within`.
The 8472: If you build a LIFO queue (I use a VecDequeue at work at that). Pushing in reverse order makes sense in that use case. But of course there can be other usecases where you want to have a chunk at a front.
Amanieu: I suppose for arbitrary iterators the reverse order makes sense.
The 8472: We could insert slices and then swap each slice element around. It's not as nice as a memcpy but still more efficient than doing it one at a time.
Amanieu: The real question is: what ordering makes sense? If we pick particular orderir, we need to be consistent with from_within.
The 8472: I think that's more a question of naming.
Amanieu: Can we call it `extend_front_reversed` just to make it clear that one's inserting in reversed order.
The 8472: It depends on what people actually use it for.
Josh: This seems like something where I could see both use cases being useful. But rather than providing two separate top-level functions. If you want to take another object and apply it one-by-one to the front of yours, it wouldn't be that hard to provide ??. Couldn't we have separate methods for an iterator that pushes one at the time and another method that pushes an array at the front of VecDeque. We shouldn't have a reversed function for the non-iterator case.
Josh:
Function 1: extend_front that takes an iterator and prepends each element one-by-one. If you want to prepend every element from another collection, in reverse, just call extend_front with `that.into_iter()`.
Function 2: (insert name here) that takes a slice/array/VecDeque/whatever and prepends the whole thing as a chunk, without reversing it.
Amanieu: This is logically equivalent to extend_front and you add .rev() to the iterator.
Josh: What I'm saying is, rather than doing this to iterators and then trying to undo it for cases where you want to have memcpy, we could just have the second function that the ACP is proposing.
Josh: We have just one method that takes iterator and does the prepending. And I don't think we should add specialization. Instead you would call `prepend` for that. Nobody should write extend_from(slice_iterator.rev()).
The 8472: People write generic code that ends up doing exactly that.
Amanieu: What if you wanted to write ??
Josh: I'm not objecting to the specialization. I'm objecting to the specialization being the only thing that prepends the whole slice in the original order.
The 8472: Yes, we often have this -- where we have an easy specific function, but we also cover the generic case via specialization.
Josh: Right now the ACP is proposing a `prepend` method that prepends an entire VecDeque and that seems like a good idea. `prepend_from_slice` seems similarly reasonable for same reason we have `extend_from_slice`.
Josh: So I'm suggesting: `prepend` as a function that would take the trait ??
Amanieu: Why not have `prepend` take any DoubleEnded iterator? I'm worried about the consistency between `prepend` and `append`. Append takes `&mut self`.
Amanieu: It takes a mutable reference so it steals the elements from the VecDeque.
The 8472: The original keeps its allocation which is useful when you transfer it from buffer to buffer.
Josh: Effectively `prepend` acts like `drain`?
Amanieu: If drain was double-ended which ~~I don't think it is~~. (it is)
Josh: Is the proposal that `prepend` goes in the same order as the other collection?
Amanieu: Yes.
Josh: As opposed to `extend_front` which takes an Iterator.
Amanieu: For `extend_front` the only sane semantics is adding items one at a time.
Josh: That could be subject for optimization for data structurse and types that could be easily reversed.
Josh: So which parts do we want to approve today? `prepend` using a double-ended iterator?
Amanieu: Are we happy to break consistency with `prepend` and `append`? I feel `append` is basically deprecated in favour of `Drain`. If we say `prepend`
Josh: We could add an `append_something` that takes an iterator and uses specialization.
The 8472: We need specializations for prepending `Drain` to be as efficient as `append`. Append is always just a memcpy.
Amanieu: If we say `prepend` takes DoubleIterator. And the items appear in the same order as the original iterator.
Josh: right.
Amanieu: `extend_front` reverses the order.
Josh: right.
Amanieu: and `prepend_from_within` and `extend_from_within` would keep the same semantics
```rust
impl<T> VecDeque<T> {
pub fn prepend<I>(&mut self, other: I)
where
I: IntoIterator<Item = T>,
I::Iter: DoubleEndedIterator {
self.extend_front(other.into_iter().rev())
}
pub fn extend_front<I>(&mut self, other: I)
where
I: IntoIterator<Item = T>;
pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, A>
where
R: RangeBounds<usize>,
I: IntoIterator<Item = T>;
}
impl<T: Clone> VecDeque<T> {
pub fn extend_from_within<R>(&mut self, src: R)
where
R: RangeBounds<usize>;
pub fn prepend_from_within<R>(&mut self, src: R)
where
R: RangeBounds<usize>;
}
```
The 8472: We'd have to document people have to combine it with `drain` to transfer the ownership of the elements.
Amanieu: or IntoIter if you don't want to keep the original iterator.
Josh: both `extend_from_within` and `prepend_from_within` don't reverse the order, right? Adding items in the same order to the back or front of the VecDeque. You're not proposing to add a method that reverses the items.
Amanieu: Yes.
Josh: If you want to take a big collection and stick it into front, you have to call `prepend` but then you need the DoubleEnded iterator.
Amanieu: I will reply to this one.
### (new change proposal) rust.tf/libs656 *implement Default for more iterators*
The 8472: The autor said they plan to adjust the ACP and need time to do that. We can skip this one.
### (new change proposal) rust.tf/libs653 *ACP: Add 1 type parameter to \`RangeBounds\<Start, End = Start\>\` and all existing range types*
Josh: I think this largely boils down to writing a range that doesn't have the same type no both types. Is it possible to do that without triggering massive inference behaviours?
The 8472: That's like the allocator on Vec.
Amanieu: The default works permanently. You're not allowed to override the default unless you enable the feature. Inference doesn't use the default.
Josh: 2 differnt aspects: we've not yet stabilized the new Range types and we could fix it there if we wanted to. And range bounds: we don't have to change the existing trait for this. We could add a new RangeBounds trait that's for a differnt int case. And have RangeBounds for the case where both types are the same and that wouldn't break inference.
Amanieu: There's only one implementation of Index trait on slice. Right now that implements any type that implements RangeBounds.
Josh: Right. I just made a connection that this isn't something we could implement over an edition. Because it's a trait impl.
The 8472: They're proposing to change slice indexing.
Josh: There is a separate fact people want to change indexing to a trait that allows you to index with a variety of index types.
Amaineu: The response here should be: "try it and see how much of the universe this breaks".
The 8472: I don't think this will see much use in the standard library.
Amanieu: n-relative indexing would be nice to have. So we could use this in the standard library. See kennytm's comment:
https://github.com/rust-lang/libs-team/issues/653#issuecomment-3297358795
The 8472: Okay, might be interesting.
### (new change proposal) rust.tf/libs652 *ACP: iN::from\_sign\_and\_magnitude*
Josh: If we had completely generic integers or pattern types,
The 8472: Isn't this just `check_negative`?
Josh: It's a type-changing check_negative. It goes from unsigned to signed.
Amanieu: This just saves you typing, really. Also I find it weird to convert a true/false into a sign.
Josh: That's valid. The responses propes `with_sign` which seem better.
Amanieu: I don't like the bool. But without the bool, this is pointless because making it into an enum is more trouble.
Josh: What you want here is an "i1"
Amanieu: that's -1/0/1
Josh: Someone posted `checked_sub_unsigned`
https://github.com/rust-lang/libs-team/issues/652#issuecomment-3289625950
Amanieu: API-wise this is just difficult to read.
Josh: I can write-up a summary of what we just talked about.
### (new change proposal) rust.tf/libs651 *ACP: Add API to write formatted data directly into a \`Vec\<u8\>\`*
The 8472: I think there's a bunch of related proposals
Amanieu: What needs to happen is io::Write needs to be a subtrait of fmt::Write. Anything you can write bytes into we can write a string into. I don't know how to do that in a backwards-compatible way. Also fmt::Write has a different error type.
Josh: If we had suffix macros that would be convenient for this. But without that adding another Write variant seems not great.
Amanieu: `FmtBuffer` is bad.
Amanieu: If we implement fmt::Write for `Vec<u8>`,what happens?
The 8472: related ACP: https://github.com/rust-lang/libs-team/issues/133
Josh: Today may import fmt::io::Write and fmt::Write, there's no ambiguity.
Amanieu: I wish we had designed the whole thing differently but I don't know how to do this in a backwards-compatible way.
Josh: If we assume we can't do this using the `write!` macro in a backwards compatible way, what is the least awful way to implement it?
The 8472: What's so bad about a wrapper type if you can wrap it around a `&mut` and a tuple constructor?
Josh: Even without the tuple constructor you can have a ?? method ??
The 8472: I was thinking about a more general way to provide io::Write. I linked the past proposal. The only change I would make to make it a tuple constructor to have a shorthand.
Josh: Call it something like `fmt::Writer` and give it a tuple constructor? +1 on that.
Amanieu: I'd really like to try and find a better solution for the `write!` macro.
Josh: Keep in mind we have editions. We can change the macro in an edition. We can't change the trait.
Amanieu: Proposal: we have a single trait. The destination of the `write` macro must implement this one trait. That trait means you can write bytes into it. This trait has an associated error type. And has a write_str method. Takes some bytes and returns a result of unit of associated error type.
Josh: I assume it does write_all so it doesn't have to deal with partial writes?
Amanieu: yes.
Amanieu: Then something like a string or vec could implement the trait with error type of `!` whereas something like io would implement an error.
The 8472: Wouldn't the problem be you pay string validation costs when writing into a string? The interface takes bytes but in practice you write strings.
Amanieu: It could take str because this trait is used for string formatting.
Josh: There is a separate thing where it would be nice to have a macro for binary formatting. But that's the question for another day.
Amanieu: That means you don't need the Write trait anymore when writing the macro.
Josh: We wouldn't necessarily have to have blanket impls for both io::Write and fmt::Write but we could have a blanket impl for one of them.
Amanieu: I would love to have the impls for both. And that's the thing I haven't figured out yet.
Amanieu: Any Display impl can chose to emit an error.
Josh: But in practice we never expect it and wouldn't cope with it.
Josh: I think we want the blanket impl to go in the other direction. But that would absolutely break the universe. You'd have the blanket impl go from this new thing to std::fmt::write. The obvious thougt would be we give this thing a new name and expect the ecosystem to migrate to it? We could call it `W` instead of `Write`.
It would be a massive migration to the ecosystem but doable?
Amanieu: We could provide a wrapper type that takes a reference to a fmt::Write and maps it into the new trait. Or the other way around.
Josh: Yeah, we could. And you don't need the adaptor if you provide a direct impl yourself.
Josh: IT seems there are 2 separate things here: 1. ambiguity between io::Write and fmt::Write. And 2. is the associated error type.
Amanieu: correct.
Josh: We could solve one of the problems over an edition. We could say we always use fmt::Write. And if you want the `write` method, you have to use `fmt::Write`
Amanieu: yes.
Josh: The other one is: how horrible would be to migrate `fmt::Write` to have the associated error type. Can we make that migration compatibly. What if the `write` argument grew an optional error type defaulting to fmt error. But you could implement it with other things including infallible.
Josh: Sorry, that wouldn't work because we don't want a generic but an associated type.
Amanieu: But even the associated type would have issues.
Josh: Under what circumstances anyone errors in fmt::error.
Amanieu: Never. The documentation says you should never do this. The standard library never does this.
Josh: The only time we provide a formatting error in the standard library would be if a Display impl outside of standard library would retourn an error.
Josh: and fmt::Error is opaque, no?
Amanieu: No, it's a unit struct.
(discussion to be continued elsewhere?)
For the actual ACP: we don't have an answer yet. We should pursue the answer in another meeting.
Amanieu: We could have a small meeting to get the initial stuff out.
The 8472: We can also start a zulip thread to have other people to contribute.
Josh: There does't seem to be a big design space here. We know what we want to do, the main issue is compatibility.
The 8472: Could we have a wrapper type without designing the migration?
Josh: Can we respond to https://github.com/rust-lang/libs-team/issues/133 say we want FmtWriter and the tuple struct?
Amanieu: I'd rather wait for having a clear design on how we're going to move forward before replying.
Separate meeting: Josh, Amanieu.
TODO: Tomas can schedule. (Josh: had a lot of luck using cal.com -- if multiple people all use cal.com, you can open a URL for a cal that uses this person + this person + this person it'll find a use time when all people are available)
### (new change proposal) rust.tf/libs650 *Add direct access to the thread id*
### (new change proposal) rust.tf/libs649 *Non\-panicking version of Vec::remove*
Josh: Seems fine. Exact correct signature and name.
### (new change proposal) rust.tf/libs647 *Add \`Waker::from\_fn\_ptr\`*
### (new change proposal) rust.tf/libs646 *ACP: Vec::remove\_ascending*
### (stalled change proposal) rust.tf/libs462 *impl fmt::Write for BufWriter*
### (stalled change proposal) rust.tf/libs262 *Add infallible variant of RangeFrom::next()*
### (stalled change proposal) rust.tf/libs395 *\`impl core::str::Pattern for \[&str; N\]\`*
### (stalled change proposal) rust.tf/libs360 *make FromResidual #\[fundamental\]*
### (stalled change proposal) rust.tf/libs261 *add \`write\_fmt\` method to String, to make \`write!\` macro work without imports*
### (stalled change proposal) rust.tf/libs131 *Add \`std::fs::rename\_noreplace\`*
### (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/libs348 *std::os::unix::env::{argc, argv}*
### (stalled change proposal) rust.tf/libs452 *ACP: Implement \`TryFromIterator\<T\>\` trait to compliment \`FromIterator\<T\>\` trait.*
### (stalled change proposal) rust.tf/libs336 *Add \`or\_try\_\*\` variants for HashMap and BTreeMap Entry APIs*
_Generated by [fully-automatic-rust-libs-team-triage-meeting-agenda-generator](https://github.com/rust-lang/libs-team/tree/main/tools/agenda-generator)_