# Libs-API Meeting 2026-03-31
###### tags: `Libs Meetings` `Minutes`
**Meeting Link**: https://meet.jit.si/rust-libs-meeting-crxoz2at8hiccp7b3ixf89qgxfymlbwr
**Attendees**: Nia Espera, Josh Triplett, Amanieu, David Tolnay, Tomas Sedovic, The 8472, Josh Stone
## Agenda
- Triage
- Anything else?
## Triage
### FCPs
1 rust-lang/rfcs T-libs-api FCPs
- merge rust.tf/rfc3874 *build\-std: always* - (2 checkboxes left)
16 rust-lang/rust T-libs-api FCPs
- merge rust.tf/80437 *Tracking Issue for \`box\_into\_inner\`* - (1 checkboxes left)
- merge rust.tf/106418 *Implement \`PartialOrd\` and \`Ord\` for \`Discriminant\`* - (2 checkboxes left)
- merge rust.tf/116258 *Tracking Issue for explicit\-endian String::from\_utf16* - (1 checkboxes left)
- merge rust.tf/98407 *Tracking Issue for \`Exclusive\`* - (0 checkboxes left)
- merge rust.tf/140808 *Implement Default for &Option* - (1 checkboxes left)
- merge rust.tf/141994 *add Iterator::contains* - (1 checkboxes left)
- merge rust.tf/76314 *Tracking Issue for atomic\_from\_mut* - (1 checkboxes left)
- merge rust.tf/151379 *Stabilize \`VecDeque::truncate\_front\`* - (3 checkboxes left)
- merge rust.tf/149926 *Do not deduplicate captured args while expanding \`format\_args!\`* - (1 checkboxes left)
- merge rust.tf/111688 *Tracking Issue for ExitCodeExt on Windows* - (3 checkboxes left)
- merge rust.tf/109737 *Tracking Issue for \`once\_cell\_try\`* - (3 checkboxes left)
- merge rust.tf/121641 *Tracking Issue for \`OnceCell/Lock::get\_mut\_or\_init\`* - (3 checkboxes left)
- merge rust.tf/134021 *Implement \`IntoIterator\` for \`\[&\[mut\]\] Box\<\[T; N\], A\>\`* - (3 checkboxes left)
- merge rust.tf/139690 *\`impl Default for RepeatN\`* - (3 checkboxes left)
- merge rust.tf/153873 *deprecate \`std::char\` constants and functions* - (3 checkboxes left)
- merge rust.tf/138215 *Tracking Issue for integer formatting into a fixed\-size buffer* - (4 checkboxes left)
[dtolnay (2)](https://rfcbot.rs/fcp/dtolnay), [BurntSushi (9)](https://rfcbot.rs/fcp/BurntSushi), [Amanieu (2)](https://rfcbot.rs/fcp/Amanieu), [scottmcm (1)](https://rfcbot.rs/fcp/scottmcm), [nikomatsakis (1)](https://rfcbot.rs/fcp/nikomatsakis), [the8472 (11)](https://rfcbot.rs/fcp/the8472), [joshtriplett (8)](https://rfcbot.rs/fcp/joshtriplett), [weihanglo (1)](https://rfcbot.rs/fcp/weihanglo)
### (nominated) rust.tf/58041 *Expose core::intrinsics::volatile\_copy\_nonoverlapping\_memory as core::ptr::volatile\_copy\_nonoverlapping*
Amanieu: This is usually not what you want. You'd only want one side of the copy to be volatile, not both sides. Except in very rare cases.
Josh: It's reasonable to ask how much we mant copy from/to volatile vs. just having volatile.
Nia: I thnk volatiles are generalyl in relative fixed order ??
Amanieu: There are memcpy optimizations. You can do overlapping reads. You can write to the same memory multiple times. This is done to optimise handling teh tail-end of the copy. With volatile there's an implicit guarantee that you're only writng/reading to/from the memory only once.
Nia: What do you suggest?
Amanieu: I'm proposing having separate methods from reading from volatile memory and writing to volatile memory.
The 8472: Does it really matter for the usecases where you need performant volatile operations?
Amanieu: My understanding is volatile memcpy are either used incorrectly, or writing to GPU memory which is used with special caching that's incompatible with atomics
The 8472: You're getting special memory, do you need optimization of the read side?
...
Nia: We can also let the conversation cook a bit. There are opsem people talknig there.
Josh: There's discussion around reads and writes to the zero address, that's part of the motivation here.
The 8472: But you're probably not copying gigabytes of memory when doing that. That's probably some embedded device. So we don't need a super optimised memcpy there. It could just do the dump thing (read, write in a loop and dump).
Amanieu: Looking at the implementation. LLVM lowers this to a call to memcpy.
Josh: My understanding of the semantics is to promise to do teh access and not elide it or reorder it from the compiler perspective. It's not clear to me if a copy from memory needs to read from a granularity. I'd expect thist to be used in "I don't care how much you read but it needs to be done and must be done right here"
The 8472: In that case it sounds like we want to change the name as it's not doing volatile semantics?
Josh: Amanieu: in your proposal to separate the calls, what would you do if you need both ends volatile?
The 8472: Look at this comment in the ACP: https://github.com/rust-lang/rust/issues/58041#issuecomment-4162981370
> I don't mind having volatile_copy for copying between two chunks of volatile memory as long as we have the other 2 variants and the docs for volatile_copy clearly say that those are the ones you actually want to use most of the time.
Amanieu: I'd have three intrinsics. From, To and From+To.
The 8472: If there's no benefit for having the special variants, why do it? Are there any interactions between regular reads and volatile reads we'd need to avoid?
Amanieu: Normal reads are not allowed to access anything that's MMIO or not normal memory.
Amanieu: It's not clear what this even means. This operation doesn't even exist in C. What are the semantics of a volatile copy? Is it allowed to read the same memory multiple times as part of the copy? What's the access size?
Josh: "What's teh access size" encompasses several of these things. I'd be concerned about alignment. Are you allowed to read e.g. 12 bytes as "read the first 8 bytes and then read the alst 8 bytes"?
Amanieu: It's equivalesnt to unspecified volatile reads and volatile reads
The 8472: Wouldn't you get the same guarantees with compiler fences?
Amanieu: In C this is literally implementation-defined. The usecase here is to access GPU memory or uncached memory where memory ordering behaves differently.
The 8472: So the fences around that wouldn't solve that?
Amanieu: No, the optimizer is allowed to expect the memory behaves sanely
Nia: If it's GPU/uncached memory, multiple consequent reads on the same bytes might get different values.
The 8472: That's not just uncached, that would require multiple access. IT would require atomics
Nia: Volatile encompasses that. Volatile memory can change between reads even with no write between.
The 8472: Then we should guarantee our requirements as they're a subset of volatile.
Amanieu: If you look at the read_volatile docs: "when it's inside an allocation it behaves exactly like read, but it can use Rust to access memory outside of allocation"
Nia: To enumerate the properties we want, would it make sense to look at what LLVM expose and say these are the properties we uphold?
Amanieu: We'd need to see a draft.
Nia: We can return to this next week.
### (nominated) rust.tf/136909 *Tracking Issue for \`isolate\_most\_least\_significant\_one\`*
Josh: The comment last week was a stabilization report and Amaineu nominated this. I suppose the ask here is to stabilize this?
Amanieu: `isolate_highest_one` is sort of `previous_power_of_two`?
Josh: Sort of previous, but it's the current power of two if it is a power of two already
The 8472: `next_power_of_two` It gives you the highest `1` bit not as an index but as an integer with that bit set.
Josh: My understanding is `isolate` has the meaning of getting that particular bit
The 8472: Ok, if it
Amanieu: Should we also stabilize `highest_one` and `lowest_one` (#145203)?
Also `uint_bit_width`: https://github.com/rust-lang/rust/issues/142326
FCP opened for all 3
### (nominated) rust.tf/149926 `P-lang-drag-1` *Do not deduplicate captured args while expanding \`format\_args!\`*
Nomination from https://github.com/rust-lang/rust/pull/149926#event-22677014012 already has response
### (nominated) rust.tf/152480 *\`format\_args!\`: only de\-duplicate captured identifiers that refer to places*
### (nominated) rust.tf/153990 *Decide and document where stdarch intrinsics are allowed to diverge from asm behavior*
Nia: Last time we said let's see if it cooks more and unnominate if nothing happens. Nothing happended.
Amanieu: I'd un-nominate it. I don't think there's anything for us to discuss.
Josh: And say "please renominate if you need something from us"?
Nia: Yes
Amanieu: The subnormal behavior is poor, but we do what clang does
Amanieu: I propose our policy with stdarch is to do what clang does.
Nia: Yes
Josh: Or at least say we are allowed to do what clang does, but reserve the right to do something more reasonable.
### (nominated) rust.tf/153973 *std::process: fix UEFI ExitStatus::code() silent truncation of error …*
Nia: It unsets a bit it seems.
The 8472: Is'nt the problem we return `i32`? Don't we need new API to handle this losslessly?
Josh: I don't remember if they've done it, but I'd expect they could have an `ExitStatusExt` that's the full exit code. Same as `ExitStatusExt` on Unix provides ??
Nia: That makes sense.
The 8472: Is that a common pattern on the platform? But if they normally deal with 64-bit error codes, we may not need to do this
Nia: It is Option, ubt
Josh: There is `ExitStatusError` in addition `ExitStatus`
Amanieu: We have `ExitStatusExt` trait which is implemented for both `ExitStatusError` and `ExitStatus` on UNIX
Josh: So we should mirror that for UEFI
Amanieu: We don't have them for UEFI now
Josh: Proposal: accept this but also request implementing `ExitStatusExt`
The 8472: Is truncate / masking out the top bits the norm on that platform?
Nia: Assuming the PR author is correct, it seems this is the format of the error.
Nia: If the high bit signifies this as an error, then this is correct.
The 8472: What I'm asking is: because it's natively a 64-bit number, someone could be using the 32nd bit or even the higher bits which get masked out.
Nia: That's fair
Josh: We're already truncating the value. Can we do a more useful value separate from "here's the full code"?
Nia: I think it's still better to set that bit. If we have a concrete example of someone using the 32nd bit on 64 bits that would be a problem, but if you're doing that, that's inviting problems. I still think doing an Ext trait for status code to do the raw thing
The 8472: In the error case it truncates it, but in the success case it does (something else). It feels like this is a weird ad-hoc mapping.
Amanieu: The clean thing is to return `None`. If you'er receiving the code, the only thing you want to do is to print it. If you want to interpret it, you should be using the UEFI-specific call
Josh: The semantic for success in UEFI has the concept of a non-zero exit code that's a warning. 0 is success, positive is a warning, negative is an error.
Amanieu: I'm inclined to just return `None` here and force people to go through the Ext case.
Josh: There's two kinds of programs written for UEFI. One is "written for UEFI" and cares about UEFI exit code that should care about ExitStatusExt. The other is using existing programs and trying to compile them to UEFI. And in that scenaio we're not giving the full fidelity of UEFI exit code, but if your program is looking at e.g. 0, 1 or 2 that your program returns, you would benefit from this.
Nia: It's common for programs to use low numbers in the exit code to use for stuff. But I don't think there's a clean solution here. I'm still ligthly in favour of merging this but we definitely need an extension trait.
The 8472: What does the code do if it's a very large error value with some of the upper half of `u64` set? Then it truncate which it doesn't do in the success case. It is masking the top byte. If the top byte has additional `1`s, those get stripped. In the success case it trips the `try_from` and returns `None` instead. It's not checking just the high bit but checking the top byte and masking that. So some bits may be ignored.
Nia: I can ask the author to specifically only check that one bit and if anything else is net, we return `None`. Does that address your concern?
Amanieu: If it's an error, the code zeroes out the top bit and then returns that.
The 8472: Are negative values an error?
Amanieu: Device error is the top bit set and then `7`. The top bit is a bit field and the rest is an error code.
The 8472: Then right now it's ignoring some bits and returns an `i32` that doesn't match the `i64` semantics
Josh: It's using i32::try_from. So it doesn't truncate the error code in practice. It gives you `None` if it would have truncated. It gives you the ??
Nia: It's masking out the 1
Amanieu: I'm still inclined to change it from `as` to `try_from` i.e. return `None` and return the extension trait
Josh: Returning `None` always is less useful behavior. I'ts similar to Unix: strictly speaking it has complicated error code but most shell scripts return low error code.
Amanieu: I don't really care what `code` returns because people using UEFI should use the extension traits.
Josh: If they were written for UEFI
Amanieu: Process spawning is UEFI
Josh: Is UEFI's std capable of doing process spawning that's not UEFI specific? I thought it could do very basic process spawning.
Josh: I'm looking at line 253 and if that's just setting the high bit, it's done in a very convoluted way. Isn't this also just wrong? It's subtracting 8 from usize::BITS but the way it's shifting is `80` instead of `8`?
Amanieu: It cancels out. Not how I'd write it, but it is correct.
The 8472: This also confused me.
Amanieu: Can we suggest an extension trait for `ExitStatus`, `ExitStatusError` and exit code?
Josh: I'm writing that.
Nia: With that, would we be okay merging this?
Amanieu: I'm happy either way (merging or rejecting)
The 8472: Should we ping the target maintainer?
Nia: That's reasonable
Amanieu: Sure
### (nominated) rust.tf/154113 *std::net: clamp multicast ttl value to u8 max.*
Nia: The maximum value for ttl is 255
Josh: The concept of TTL is better checked for manpages for sockopt. But there are types on some platforms that use `int` but the underlying field is effectively a `u8`. So this seems fine.
The 8472: ISn't that just the IP TTL header field?
Josh: Yes.
The 8472: Yes, that's 8 bits
Amanieu: Yes, that's fine
Josh: +1 to the suggestion in the code for `unwrap_or`
Amanieu: Why not return an error?
Nia: That'd be a breaking change. We already accept bigger values.
Amanieu: This only does it for multicast TTL. How's normal TTL handled?
Josh: The normal should be as well. We should double-check the code.
Amanieu: We just past the `u32` directly to `setsocopt`
Nia: So we should fix that too.
The 8472: The kernel also pass ??
Amanieu: "if TTL value is greater than 255 return error"
Josh: I'm surprised we wrote this function to take `u32` instead of `u8`
Nia: So this is now broken. Are we in agreement to error on this?
the room: yes
### (nominated) rust.tf/154317 *Implement extract\_if for BinaryHeap*
The 8472: We have `extract_if` for other collections. This adds it to the `BinaryHeap`
Amanieu: After adding any elements it needs to rebuild the heap. The question is: is this useful? It can be implemented on stable relatively easiely.
JOsh: It effectively holds the reference to the heap and keeps it set to a zero length so it doesn't have to re-heapify it. You could convert it to a vec and then back, but this seems like a convenient method to do that.
Amanieu: The implementation is horrible: it sorts teh inner vector first, then extracts, then rebuilds the heap.
the room: *gasps*
Josh: I'd not expect this to be sorted. And you don't need to sort the entire array first. You can walk it in order.
Amanieu: I'd expect `extract_if` to go in the arbitrary order and rebuild the heap in the end
The 8472: They may want extract if not just to remove it but also have the output in order. `extract_if` is an iterator
Amanieu: That implementation is horribly slow and we should discourage that
the room: Lots of other ways to get that behavior
Amanieu: This is just a performance trap
Josh: Agreed
Nia: What do we do?
Josh: I think it's an implementation thing. We should ask them to walk it in arbitrary order rather than sorted order
Amanieu: And then you can wrap the `extract_if` of the underlying `Vec`
Nia: But API-wise it's fine?
Josh: It seems fine.
Amanieu: They say: https://github.com/rust-lang/rust/pull/154317#discussion_r3009913368
> I had considered trying to directly reuse the `Vec::extract_if` impl directly, but I was unable to figure out how to allocate an empty `Vec<T>` in an arbitrary allocator given only a reference to the allocator
Amanieu: https://github.com/rust-lang/rust/pull/154317#discussion_r3003319116
> BTreeMap's extract_if and Vec's take a range argument. I think it would make sense to do the same here, but let's raise that for T-libs-api to decide (I'll nominate this PR). We'll need to decide what the index units are -- probably usize offset?
Amanieu: It shouldn't take a range argument.
Nia: So we accept the API as is?
Josh: Yes
### (nominated) rust.tf/154356 *Add integer truncation and extension methods*
`usize` and `u128`.
Josh: the only item we need to discuss is which traits to implement for `usize`. In Rust `usize` is guaranteed to be at least 16 bits. In practice it's smaller or equivalent to `u128`. Amanieu and I were talking about always defining all the impls that work conditionally. But for today: would it be reasonable to assume that `usize` will be `<=` than `u128` and if there's a platform where that's not the case, do a conditional impl?
Amanieu: I see at the moment `isize` extends to `i128`.
Josh: It's the same deal.
Amanieu: I'd personally like for the available impls to depend on the target pointer width. So on 32-bit platforms you can extend usize to 32 but not on 64-bit platforms. However, outside of that wider conversation, I don't think it's worth adding these impls to `u128` because it's so rarely used in practice.
Amanieu: So I'd rather have the full conversation.
Josh: So if we aren't making all the impls conditional, it's not worth doing the incremental step of providing the 128-bit impl?
Amanieu: Yes.
The 8472: We should also ask Lang about their plans for forward compatibility of higher-bit platforms.
Josh: We can ask them, but it's up to the Libs-API to decide whether the interface for truncate/extend.
The 8472: Yes, but the future plans of how far Rust will grow is Lang's concerned
Josh: If someone came up about a 512-bit platform that got a large market adoption, we'd add it.
Josh: Do we want to consider having conditional impls on all the platforms? Do we want to say on 16-bit platforms based on usize being 16-bits etc.?
The 8472: What would that look like when people write code and still want to maintain portability. Deos that work auotomatically, will they have to write cfgs too?
Josh: They'd get the ipmls automatically. If they wanted portable code, they'd not rely on impls that are based on the platform size. They could choose on which impls to rely one.
The 8472: That sounds like it'd need crates.io/cargo support to mark your crate for what it supports. It would lead to ecosystem split
Josh: I get what you're saying. But today: you can write a crate that uses `std::os::linux` stuff and it won't run on anything else
The 8472: I have the same issue with that.
Josh: There's a cargo proposal for target OS -- that it would let you declare which targets a crate supports. But I don't think we need to settle that question here. Historically, we've used extension traits. We don't have that option here but we could choose to provide this or not.
Nia: I had the same portability concerns. I'm worried a lot of people might see this and go "nobody uses anything other than 64 bit anyway, and unconditionally import that". With linux it's more in your face, but the 64-bit people could not consider the implication. You already have conversion traits now.
Josh: The other thing people can and do today is write `as u64` and that will silently fail on a 128-bit platform.
Nia: Yes. And I don't like the `TryInto`/`From` because that's runtime. But I'd liek to have traits that you have to explicitly import or something.
Josh: We had outstanding proposals with Lang that boil down to being able to opt-into/out of certain platform support. With my lang hat on, that would take a long time. The advantage of what we talk here: if you do TryInto, you get error on runtime, if you do `as` you get truncation at runtime and if you do *this* you get a compile error. But that's good because you'll know
Nia: I don't want it to be easy to accidentally write this.
Amanieu: Proposal: we could consider lints for this.
Josh: I like that. We could e.g. allow by default 64 and 128-bit and warn by default 16-bit and 32-bit. Then you can declare what you allow/deny this at the top of your crate. But that'll take a while.
Josh: I propose ripping out the 128-bit impl for usize, merge this and look into the lint in parallel. Possible discuss it at the all hands.
Amanieu: Sure
Nia: I like the lint idea.
The 8472: Compiler failures have the problem for the users because they have to fix all their dependencies even if that code isn't use. But the lint you can suppress.
Josh: It means you can hook into the lint system in the future. E.g. there's been a long standing request to forbid unsafe code on dependencies. That's similar to this: can I force forbit non-128 on my dependencies?
The 8472: We could also go the other way and say "I don't care what happens"
Josh: I also expect the lints' defaults to vary on the platform.
Josh: I'd like to drop the u128 impl from this PR, ask someone to `r+` on this. And once that's in, separately propose the idea of adding a lint here. And that will be a lang+compiler matter. We could talk about that at the All Hands.
Amanieu: Once we have the lint, there's also no reason not to have the into impls as well.
Josh: This is probably going to end up being an RFC but Il'l do a vibe check with lang to not waste my time.
### (nominated) rust.tf/154443 *What do we guarantee for \`RangeIter::remainder\`?*
Amanieu: we cancelled the stabilization on `remainder` method
Amanieu: remainder lets you convert a range from an iterator back into a range for a portion of the range. I don't think it's needed. It wasn't needed for the old range types because they were iterators -- you just got teh range back.
Nia: Currently it panics on overflow.
Nia: `Option` makes some amount of sense. But there's some stuff about niche optimisation here. If we have a type that's well-formed we could have niche optimisation there.
Amanieu: I still think the correct answer is to not have the `remainder` method because no one should be using it. I'd never see myself using it.
The 8274: What's the motivation for this?
Josh: The main usecase I can imagine: loop over this iterator, break out of the loop and take the rest of what you have. I can see the argument for that.
The 8472: IF we leave it unstable, we can say we wait until someone shows up who needs it.
Amanieu: Agreed
Josh: Leaving it unstable and asking for usecases before considering for stabilisation seems fine.
Nia: Agreed. If we have use cases, that can drive our decisions.
The 8472: It already seems like an edge case to get a `Range` back out of an iterator and then doing the same for a non-canonical range seems even less likely.
Nia: This seems like a case of someone thought about a possible thing and decided Libs should take a look. I'd keep it unstable but if we're stabilising it, I'd say do the `Option` thing.
Nia: I'll reply to say that if there are no objections.
The 8472: I'd like to see it turn in to a canonicalised way, but I'm fine waiting
### (waiting on team) rust.tf/153261 *Partially stabilize \`ptr\_alignment\_type\` as \`alignment\_type\`*
Amanieu: It's waiting on FCP. I thought I started one on the tracking issue, but I did not.
Josh: We discussed on zulip the possibility of making it public that it's `repr(transparent)`.
Amanieu: We rejected that in the meeting
Nia: We did, but then we discussed that a lot of internal stuff relies on this.
The 8472: But that's internal
Josh: But as we're relying it, do we want to let e.g. FFI cases too
Nia: I don't see a motivating reason to commit to doing that. We can wait for someone to have a reason for it to be transparent and then do it then.
Nia: Does anyone want to raise an issue on that?
Josh: I think it would be a good idea, but I'm not going to push if folks feel strongly against it.
Nia: I feel weakly against it
The 8472: My main concern is we're using some weird enum that's structured to work aronud a weird limitation of the compiler and if we make that official we'd have to keep that
Josh: Sounds like a veto on account of "meh". :+1:
Amanieu: Do we want to stabilize the layout methods along with it? We said: "either we accept them as they are" or we wait on edition-dependent name resolution to make the change over an edition.
Nia: Which of those proposals are people in favour of? I don't feel strongly on either, maybe leaning towards "accept as is"
The 8427: So Amanieu, you're objecting on stabilising this without the layout methods.
Amanieu: Yes. Either we stabilise the layout methods or change the signature of the layout methods over an edition.
The 8472: Layout is not everyday code
Amanieu: It's pretty widely used though.
The 8472: Does it make sense to optimise the names that we have? Or is having both fine?
Amanieu: Having both is fine, it's just awkward for methods like `align_to`. The alternative is `adjust_alignment_to`
The 8472: Can we optimise the names a bit so they're not awkward and have them existing side by side. If not, the edition think makes sense if we can't come up with good alternatives.
Amanieu: That woudl be ideal. I'm not going to block the stabilisation on these.
Nia: Is everyone okay with this?
Amanieu: Yes.
### (waiting on team) rust.tf/154287 *Add \`PartialEq\` and \`Eq\` impls to the character case iterators*
Amanieu: You can compare a string with a `ToUppercase` iterator
Nia: Oh no.
The 8472: It kind of makes sense because you don't need to materialise the string and prevent an allocation.
??: Someone proposed just `is`: https://github.com/rust-lang/rust/pull/154287#issuecomment-4145335526
> Isn't this done with .is_ methods on str? It feels a little confusing to compare an iterator (which might be halfway through the result or empty) with &str. Do we have precedent for Iterator / slice comparisons anywhere?
Josh: If we try to do a comparison, we have equals_ignoring_case
Josh: They're proposing `PartialEq` for `ToUppercase` and similar. ??
The 8472: There are edge cases where there are not the same operations due to case folding differences.
Josh: There are which is why you want EqIgnoreCase. And if you that's not for you ??.
Josh: The stated motivation is whether a string is in a particular case. And for that we should just add add `is_` on `str`
Nia:
Josh: The PR autohr made the point that these three iterators are already donig more than an iterator as they already implement `Display`. *That much* makes sense that we support that.
Amanieu: Becaues they support `Display` they support `to_string`
Josh: Do we also then want `PartialOrd` etc.?
Nia: I tend to agree. If you really care about a crazy fast string zero allocation case-insentivive comparison, you'd better writing your own implementation.
Josh: Yes. I'm in favour of rejecting these and asking to add the `to_` methods on `str`.
The 8472: Iterator has an `eq` method so you can call `.eq` on the iterator.
Josh: We could suggest they do that.
The 8472: We should ask why not those. Ask for motivation.
Josh: We currently have `eq_ignore_case` on `char` and we should add it to str
Nia: Yes. I think it's fine to reject the PR in that case.
Nia: In general, I'm not a fan of having unicode operations like this in the standard library. People should use a crate for that.
The 8472: We should use the unicode tables we already have efficiently so people don't load another tables to load into their application. I don't know if we have the case folding tables.
Nia: I don't think so, since we don't have the methods.
Nia: What's everyone leaning owards?
Josh: Reject this PR as written and open to:
* is_lowercase/is_uppercase for `str`
* potentially ading `eq_ignore_case` methods (if they don't add too much unicode overhead and they're compiled out for people not using them)
* ask about the `eq` method on iterator
Nia: I'll type it out.
Josh: Should we also consider something like `assert_eq_iter`? It could walk aloung and show left/rigth
Amanieu: `itertools::assert_equal`
### (new change proposal) rust.tf/libs699 *Bring \`hashbrown::Equivalent\` into std*
Amanieu: The question is: do we want to add the `Equivalent` and by extension `Comparable` trait to the standard library?
The 8472: Should we generalise further and put `Comparable` in the collections?
Amanieu: Yes, the more intruive thing is add a `Comparator` trait that you supply when `HashMap` is created
Josh Stone: There's also being able to do reverse comparison
Amanieu: We wanted to know your thoughts on that
Josh Stone: It makes it significantly more complicated. IS anyone asking for that?
Amanieu: People are asking for that.
Josh Stone: That's just asking for `Equivalent`
Amanieu: But if we're asking `Equivalent` we're also adding `Comparable`. And as a counter proposal we came up with rejecting this and having a full comparator instead.
Amanieu: The main usecase for `Equivalent` is to have with tuples of things that can be borrowed
Josh Stone: Or any kind of custom comparison. I fear doing a full comparator because that gives you an explosion of parameters on hashmap (comparator, allocator, hasher)
The 8472: But you usually don't use them at the same time
Josh Stone: But you'd need to specify them in the right order and put placeholders for the others
The 8472: If one of them is unstable and the others aren,t that would be annoying
Amanieu: We have two unstable generics now
Nia: In that case I'd say we commit to `Equivalen` / `Comparable` and not coparator
The 8472: People asked for it before. Java has it. `Equivalent` lets you do this for a particular type. You can use the comparator at runtime that gives you ad-hoc sorting without having to do newtypes. That's a significant benefit
Amanieu: It's probably possible to have a blanket ipml ofr equivalent for ??
https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=bd65b8c41c183e3da1b1a227fc0a143c
The 8472: We could keep `Equivalent` unstable and keep this for the tuples
Josh Stone: What did you change here?
Amanieu: The `Equivalent` is the same but we could do this as a blanket impl
Josh Stone: I think we should try that in practice. Worth trying in HashBrown and see how that plays out
Amanieu: I think it's a breaking change
Josh Stone: Don't merge it, just try the change with some usecases around it. Making it work for tuples would be nice
Nia: Might as well try it.
Amanieu: The PR stalled due to lack of interest. The author found a different way to do it and the PR is a bit of a mess.
Nia: So someone else should do it but it's worth replying to the ACP saying it's worth trying
Josh Stone: The PR also has the `K` and `Q` flipped from what's in the crate. I think that's nice but we'd need to try it.
Amanieu: I'll double check that. Is there any preference?
Josh Stone: It did help some type inference to have it flippde from the current way.
Amanieu: It can avoid annoying turbofish sometimes. I'll have a look and reply saying we're accepting this for both `Equivalent` and `Comparable`
Josh Stone: This may be annoying to coordinate between the standard library and HashBrown to get it implemented.
Josh Stone: It's convenient to try it with BTreeMap because we don't have the same conflicting crate issue there.
Amanieu: Once you start having tuple impls it starts having impact on stable.
The 8472: Would this be incompatbile with a future comparator impl?
Nia: I think this would be fine. They're differen things.
Amanieu: The default comparator would use the Comparable trait so they'd be compatible.
### (new change proposal) rust.tf/libs766 *Export the \`derive\` macro at \`core::derive\` and \`std::derive\`.*
Nia: Because it cannot be named other than through the prelude.
Amanieu: This touches an edge case of how we distinguish between a built-in attribute and a built-in macro. Are we committing to derive always being a macro and not a built-in attribute? I think at this point it's too late for that because it has to be in the prelude.
The 8472: You can already explicitly name it this way. We would have to put it on the exactly same namespace as the compiler
Nia: Right now because it's in a weird spot, probably nobody's naming it that way. And you could name it and it is th ebreaking change.
Josh: The person proposing it to us was broken.
Amanieu: Theres' currretly three attribute macros that are stable
Josh: If we came up with a built-in attribute derive we'd still find a way to export it in an ??. We're already providing this in `core::prelude::v1` so I'd argue we should provide it.
Nia: Yes.
Josh: The proposal is `core::derive` and `std::derive`. If we use that as a name of the macro, we can't use that as a name for a module.
Amanieu: macro namespace and module namespaces are technically separate and you can import both.
Nia: No.
Amanieu: We already haveth this with the `vec!` macro. It's a module and the macro. If you import `std::vec` it imports both the module and the macro.
Josh: At least that argument is I withdraw the concern because we could use the namespace.
Nia: `std::attrs::*`
Josh: That would be my preference.
Amanieu: Having talked with Jana, we might get built-in attributes with a separate syntax separate from built-in macros. So they can be explicitly imported.
Josh: Shall we approve this and move on?
Nia: Yes.
Amanieu: And for `global_allocator` and `test` too?
The 8472: We could shuffle each into an appropriate module?
Josh: Why don't we approve `derive` at `core::derive` and `std::derive` and ask to propose a separate ACP for `global_allocator` and `test` where e.g. it coudl be `alloc::alloc::global_allocator`
The 8472: So this is just for `core::derive`
Josh: and by extension `alloc::derive` and `std::derive`.
Josh: It requires an update to the Reference. I'll write it up.
### (new change proposal) rust.tf/libs765 *ACP: Saturating conversions between signed and unsigned integers*
Amanieu: I suggested this in a meeting, didn't get to it and then this person proposed precisely what I had in mind. But I also want the checked version.
Nia: I think it's a good proposal.
Amanieu: I think Josh wanted to object on the `checked` ones
Josh: In general, the saturating version makes perfect sense. We don't have that operation anywhere else. The `checked` operation here is effectively thesa me as `try_into` and you can always just call that.
Amanieu: I'd prefer the operation be explicit. It has a fixed return value. `try_into` might need a turbofish or a type annotation.
Josh: That's reasonable.
Nia: And this would make generics annoying. Okay, that makes sense.
Nia: In that case are we okay adding the checked verison and signing off on the ACP?
The 8472: What would be signature for the checked version?
Nia: Option?
Amanieu: Yes, checked returns an `Option`.
The 8472: What's the name: `checked_cast`?
Amanieu: Yes
The 8472: Sounds okay.
Amanieu: Do we want a strict one as well? I.e. checked+unwrap
Nia: Isn't that the default one?
Amanieu: Wrapping cast.
Nia: In that case, strict as well. We usually add all three.
The 8472: "usually", we do it when someone asks
Nia: This would have made all the miri code I wrote recently so much easier.
Amanieu: I'll reply.
### (new change proposal) rust.tf/libs762 *Simple \`bool\` Implementation for \`keepalive\`, \`set\_keepalive\` on \`TcpStream\`*
Amanieu: We discussed it and said ok. Someone should have replied but no reply happened.
Nia: I'll take a look at the notes and reply based on them.
Josh: We had some back-and-forth over the bool vs. Duration question. But I think we settled it.
Josh: If you call the `bool` version, that will potentially override the version from the extension trait. Let's do it.
### (new change proposal) rust.tf/libs761 *Add constructor of \`std::fs::Metadata\` from \`struct statx\`*
The 8472: We wanted to hear form Rust for Linux
Josh: The feedback we got was: this is not likely to change in incompatible ways. It is theoretically possible someone might need a statx2, but that shouldn't break. It would be fine for us to say "you need to have gotten this from the kernel". We also got feedback that if we wanted to specify flaxs to get from statx, we could get a const flag that they'd add anything they want to add to.
The 8472: That makes sense. If we want to add something like birth time, we should say we want it.
Josh: That sounds reasonable. We should explicitly say "please ask for this" and we'll need to cope with what the kernel gives us. And our statx method should be cautious in terms of defaults. And we should not read fields we didn't ask for.
Josh: And the last piece the RfL team provided was that once we've added this to the Rust API, we can argue to the kernel team that they broke userspace if they do.
Josh: So we should add this method, we shoudl document that you only pass in what you got from the kernel rather than building it yourself. We'll give you the flags you ask for. And we should check what we got.
The 8472: The kernel devs didn't explicitly mention if there's a size extension mechanism.
Josh: They didn't think so but they suggested we could ask in the fs mailing list. But they said that if a bigger size would be done, an older version of the kernel wouldn't know about them so it couldn't zero them out.
The 8472: Sounds good.
Nia: Sure.
The 8472: Alice propose struct `statx` with a lowercase. That's not our standard.
Josh: There are different proposals. This one is adding a statx struct from the kernel. I propose adding a MetadataExt method that takes a void pointer. Here we're depending on a libc type and people can expect to be able to cast this to a libc type.
Amanieu: Void pointer's fine.
The 8472: It's going to end up as transmute anyway. But then we have to make it unsafe.
the room: That's fine.
Josh: And rustix can make a safe version if they want.
Amanieu: I'd accept it with just the void pointer
Nia: Yes
The 8427: And the const with the flags we want to be able to construct `std::Metadata`.
Josh: We should say "you're allowed to request less, but as an advisory for if you want to ask for everything we can do something with, here's the bits"
The 8472: Yes.
Josh: I'll reply. We want the API that was originally proposed, plus the flags plus documenting our expectations.
### (new change proposal) rust.tf/libs743 *ACP: Opt\-in to calling GlobalAlloc in std's internals*
### (new change proposal) rust.tf/libs691 *\`std::io::Read\` provides byte\-order reading trait*
Josh: The original proposal asked for `read_le_order` etc. and we asked for `read_u32_le`. None of them will be in the trait vtable so it's fine to add them.
The 8472: They'd return `Result` on each read?
Amanieu: Yes, they must always return an `io::Error`. That's fine. The endiannness needs to be specified in the function name.
Amanieu: Should we just have "le", "be", "ne"?
The 8472: I was thinking about having infallible reads like in `Vec`
Amanieu: What if the integer type was inferred?
Josh: We'd still need the endiannness. I'm all for it but I don't think that's mutually exclusive. This seems like something that would be fiddly so I'd have the named ones and provide those too.
The 8472: It's a lot of names.
Amanieu: I like the idea of only providing the type-inferred functions. Explicit names let you explicit about the bytes but the generic names are nicer to write.
Josh: Presumably we'd have a sealed trait for integer here? ... Strictly speaking you could do it for anything `Sized`, right?
Amanieu: You couldn't do it for `bool` for example. And we probably want to do the same thing for the `Write` trait.
Josh: That's fair.
Josh: What about float types?
The 8472: That sounds suspicious. But they have `from_be_bytes`, fine.
Amanieu: What API do we want?
Josh: We add the type-generic three methods (`read_le`, `read_be`, `read_ne`) for the types in the stdlib that provide `from_le_bytes`. For integers and floats.
Amanieu: Do we want it for a Writer too?
Nia: Let's have that as a separate ACP.
Josh: Positive vibe but let's ask for ACP.
Nia: I'll do it.
### (new change proposal) rust.tf/libs688 *Initial state once cell value*
### (new change proposal) rust.tf/libs659 *Generalize ExactSizeIterator to QuantifiedIterator*
### (stalled change proposal) rust.tf/libs457 *APC: split\_pattern on slices*
### (stalled change proposal) rust.tf/libs334 *Customizing \`#\[derive(Debug)\]\`*
### (stalled change proposal) rust.tf/libs347 *Context reactor hook*
### (stalled change proposal) rust.tf/libs111 *Restructure ptr\_metadata to minimal support*
### (stalled change proposal) rust.tf/libs552 *Provider\-style API for \`Context\`*
### (stalled change proposal) rust.tf/libs131 *Add \`std::fs::rename\_noreplace\`*
### (stalled change proposal) rust.tf/libs207 *\`parse\_line\` method for \`Stdin\`*
### (stalled change proposal) rust.tf/libs246 *ACP: replace use of \`Pointee\` trait with a \`ptr::Metadata\` type*
### (stalled change proposal) rust.tf/libs520 *Add out of the box support for mapping custom error types that implement \`std::error::Error\` to \`Box\<dyn Error\>\`*
### (stalled change proposal) rust.tf/libs314 *Add security\_attributes() to windows::OpenOptionsExt*
_Generated by [fully-automatic-rust-libs-team-triage-meeting-agenda-generator](https://github.com/rust-lang/libs-team/tree/main/tools/agenda-generator)_