--- date: 2026-02-03 url: https://hackmd.io/ES9x36msQsOrKlWZ4naHFA --- # Libs-API Meeting 2026-02-03 ###### tags: `Libs Meetings` `Minutes` **Meeting Link**: https://meet.jit.si/rust-libs-meeting-crxoz2at8hiccp7b3ixf89qgxfymlbwr **Attendees**: Amanieu, David, Josh, Nurzhan Saken, Tomas Sedovic, The 8472, TC ## Agenda - Triage - Anything else? ### Tomas: Nurzhan Saken, our new Program manager joined us! He'll be joining the meetings this week to get to know y'all. I'll take the minutes this week and Nurzhan will do it the next one. After a few weeks, we'll likely alternate the calls. So you can get familiar with both of our faces, get to know us and know to reach out to us. And so we both remain plugged into the Project. ### Tomas: 2026 goals First look at 2026 goals post: https://blog.rust-lang.org/inside-rust/2026/02/03/first-look-at-2026-project-goals/ Please take a look, think about asks on your team. It has some examples for the sizes that team asks can be. ### Team asks on Libs Team https://rust-lang.github.io/rust-project-goals/2026/goals.html#libs-team Amanieu: https://rust-lang.github.io/rust-project-goals/2026/library-api-evolution.html Edition-dependent name resolution. The goal covers the specific mechanism Amanieu: List of ideas for things we might like to do over an edition: https://hackmd.io/56KVIwnUTBKpo5f5cTRb_g *** Amanieu: Reflection and comptime has a medium ask: https://rust-lang.github.io/rust-project-goals/2026/reflection-and-comptime.html Josh: oli is driving this. The libs ask is similar to the way `proc-macro` is a crate maintained as part of the standard library. The reflection API will be exposed by the compiler but have a stable API surface area eventually. This seems like a reasonable level of ask for the scope of the goal. If they were to ship the full and complete API for the entirety of the language, this would be a much larger ask. But right now it seems like the correct sizing to me Amanieu: Sounds like a small ask because it doesn't need a dedicated reviewer (??) The 8472: Is this about reviewing unstable APIs or is it about stabiliing initial reflection API too? Josh: Unclear whether there's any expectation of stabilizing a one-off API. Doesn't sound like it to me The 8472: Is this just experimental? Amanieu: I think this will stay experimental for at least the next year The 8472: So it should be easier to let it go Josh: The reason I think this is at least medium is that the example given for small is basically "review one pull request". Medium is looking at it regularly, give feedback on design as we're gearing towards an RFC. If it were beyond the experiment scope, it would be large Josh: It might also make sense to have a Lang design meeting and have a couple of our folks show up Amanieu: This seems fine to me *** Amanieu: for everything small we don't need a champion? Tomas: That's correct Josh: We don't need a champion for small or vibes, but we still need to approve the scope. *** Amanieu: Normative documentation for sound `unsafe` Rust. The ask is small The 8472: Josh: There'd also be "is this a format we're prepared to work with going forward". We'd want to have someone on the team looking at the format and making sure we're okay with it. Amanieu: Do you think it's worth assigning a champion? Josh: I think there is Amanieu: Then we'll want to raise this to medium. We also have a lot of unsafe functions in the standard library Josh: Agreed Amanieu: How do we handle changes we want to see in goals? Tomas: for a discussion about a topic, go here: https://rust-lang.zulipchat.com/#narrow/channel/546987-project-goals.2F2026-workshop Tomas: You can also open an issue on [rust-project-goals](https://github.com/rust-lang/rust-project-goals) or even a PR if you have concrete changes Josh: safety comments: two kinds: comments in code and safety comments on in docstrings Amanieu: The two should link: the docstring should talk about things that would affect the safety of the code inside the function The 8472: Is the tooling part of this goal? I'm not sure Amanieu: Sorry, I think that was probably mentioned elsewhere. I think Predrag was suggesting that. Amanieu: Do we have a dedicated champion for this? Any volunteers? Josh: I'm not intending to volunteer myself as a champion. *** Amanieu: redesigning super let. This has libs impact because of how it affects the `pin!` macro and `format_args` Josh: True but given this is more about implementation details, I think this is small -- handful of PRs *** Amanieu: C++/Rust Interop Problem Space Mapping. This already has David as a champion David: That's right Amanieu: What's the ask? David: Iterating with the C++ standards committee, they'll bring things that affect Rust. E.g. types in FFI, mapping and so on Tomas: There's probably going to be additional focus ont the Rust side of things this year too *** Amanieu: Ergonomic ref-counting Josh: For libs, this would be mainly about the `Share` trait and the implementation of it for specific type in the standard library. Amanieu: Is it an implicit clone? Josh: It's not an implicit clone. But it's a marker that this clone doesn't do substantial work and shares the same underlying data. E.g. `Arc<T>`, `&T`, but not `Vec<T>` Amanieu: So you still call `.share()` Josh: The syntax is up in the air, but at the moment the proposal is explicit not implicit Amanieu: Sure, that seems acceptable. *** Amanieu: Rust for Linux in stable, language features. Libs asks for `Deref`/`Receiver` and `derive(CoercePointee)`. Makes sense, we'll get to them as they're proposed. *** Amanieu: Size hierarchy and scalable vectors: intrinsics -- I'd bump that to medium. Josh: I'd concur on that being medium. That's a non-trivial libs api surface. In addition to the intrinsics, it's the magic mechanism of dealing with sizing Amanieu: the compiler work is in Josh: Yes, but this will have libs API so I propose bumping to medium *** Amanieu: libc 1.0 release readiness The 8472: That's more crate maintainers than API? Amanieu: The major owners are the libc maintainers. Small is fine Josh: Agreed Amanieu: We have a libc team Josh: We do, libc-maintainers *** Amanieu: field projections. Libs involvement is making sure projections are implemented for some library types. PR review and stabilization process. I don't think this needs a champion. Josh: Given most is an experiment, explore design space and draft RFC that seems reasonable *** Amanieu: build-std Josh: This just came up in the Cargo meeting. I raised a thread on the 2026-workshop that if this is just "do an implementation but don't stabilize" then it's accurate it's small for libs. If they propose any further in 2026 and plan to stabilize, it'd rise to medium. *** Amanieu: WASM components: libs ask is threading support (implementation of `std::thread`) needs a review Josh: That sounds like small. Target-specific PRs so I'd expcet they'd even be reviewed by target-specific reviewers *** Amanieu: open enums: I assume these are nonexhaustive enums that are C compatible Josh: Exactly, "this enum is u32, I expect to accept all the values not just the ones listed". Small *** Amanieu: Nightly support for function overloading in FFI bindings Amanieu: The ask is vibes Josh: The answer historically is "we don't want it". The ask is "how do we make this interop with other languages that expect this being the same function". I expect there are variants for how this would work where this could be small or medium for libs. The most obvious to do this would be to stabilize `Fn` traits Amanieu: That would break in all sorts of interesting ways Josh: Absolutely. But that sounds like a compiler/types problem. Making the surface API sounds like a medium area for Libs Amanieu: I think Lang is the one who should see if this should be rejected Josh: This will be a lang experiment Amanieu: I don't see the need to block this The 8472: It talks only about FFI but in the team asks, if we have use cases in standard rust -- that's going beyond that. Amanieu: Yes. They're asking whether it makes sense beyond FFI. Which we probably don't want The 8472: Is that the case? The concerns are about breaking interference etc. Amanieu: We may want overloading over the number of arguments, but probably not types-based overloading The 8472: We should discuss that Amanieu: Yes, but we shouldn't block the experiment *** Amanieu: We've been delegating this to the testing-devex team ## Triage ### FCPs 2 rust-lang/rfcs T-libs-api FCPs - merge rust.tf/rfc3874 *build\-std: always* - (14 checkboxes left) - merge rust.tf/rfc3892 *Complex numbers* - (5 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/149218 *Make PinCoerceUnsized require Deref* - (3 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/139087 *Fallback \`{float}\` to \`f32\` when \`f32: From\<{float}\>\` and add \`impl From\<f16\> for f32\`* - (3 checkboxes left) - merge rust.tf/99301 *Tracking Issue for \`error\_generic\_member\_access\`* - (2 checkboxes left) - close rust.tf/136638 *warn on empty precision* - (3 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/149926 *Do not deduplicate captured args while expanding \`format\_args!\`* - (3 checkboxes left) - merge rust.tf/111688 *Tracking Issue for ExitCodeExt on Windows* - (4 checkboxes left) - merge rust.tf/140266 *Tracking Issue for \`#!\[feature(control\_flow\_ok)\]\`* - (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) [epage (1)](https://rfcbot.rs/fcp/epage), [dtolnay (1)](https://rfcbot.rs/fcp/dtolnay), [the8472 (11)](https://rfcbot.rs/fcp/the8472), [Mark-Simulacrum (1)](https://rfcbot.rs/fcp/Mark-Simulacrum), [BurntSushi (7)](https://rfcbot.rs/fcp/BurntSushi), [Amanieu (7)](https://rfcbot.rs/fcp/Amanieu), [nikomatsakis (4)](https://rfcbot.rs/fcp/nikomatsakis), [matthewjasper (1)](https://rfcbot.rs/fcp/matthewjasper), [jackh726 (1)](https://rfcbot.rs/fcp/jackh726), [estebank (1)](https://rfcbot.rs/fcp/estebank), [tmandry (1)](https://rfcbot.rs/fcp/tmandry), [davidtwco (1)](https://rfcbot.rs/fcp/davidtwco), [spastorino (1)](https://rfcbot.rs/fcp/spastorino), [cjgillot (1)](https://rfcbot.rs/fcp/cjgillot), [weihanglo (1)](https://rfcbot.rs/fcp/weihanglo), [Muscraft (1)](https://rfcbot.rs/fcp/Muscraft), [0xPoe (1)](https://rfcbot.rs/fcp/0xPoe), [joshtriplett (6)](https://rfcbot.rs/fcp/joshtriplett), [oli-obk (1)](https://rfcbot.rs/fcp/oli-obk), [scottmcm (3)](https://rfcbot.rs/fcp/scottmcm), [traviscross (1)](https://rfcbot.rs/fcp/traviscross) ### (nominated) rust.tf/libs548 *ACP: Add \`NonZero::\<T\>::from\_str\_radix\`* Amanieu: This is an old ACP that we should review. Someone made a PR for this. Amanieu: We already have `from_str`, this adds `from_str_radix` The 8472: `from_str` is coming from a trait impl. the `_radix` one isn't from a trait, right? Amanieu: Yes, it's an inherent method. We'd be adding it to `NonZero<u8>`. The 8472: Is it worth it adding a convenience here Amanieu: Is there any reason not to? The 8472: Maintenance, API bloat Amanieu: The line in the problem statement says it will never produce `IntErrorKind::Zero` The 8472: You get an `Option` for the `NonZero` conversion. Amanieu: But then you'd have to manually shuffle it around. And it can't be used in const context, but that's because `const trait` is not stable yet The 8472: Do we have `TryFrom<NonZero>`? If people want error, they could use `TryFrom` Amanieu: The errors are different type. This is a `FromUtf8Error`. The 8472: But if you use something like `anyhow`, that'll be handled Amanieu: Yes The 8472: Feels niche, and if the only reason is to have a common error type for a composite operation, I'm not convinced Amanieu: Same argument is "why do we have `FromStr`".. The 8472: We're not replicating all the integer API on `NonZero`. E.g. the `is_ascii` method. Amanieu: What's more interesting is constructor methods The 8472: If your argument is chaining two methods, it's the same argument here Amanieu: Fair, but we already have `FromStr` The 8472: The `FromStr` is a trait method so it only bloats up the list of the implemented method traits. Not the inherent methods list. Amanieu: Currently you have `IntErrorKind::Zero`. I feel it `IntErrorKind` shouldn't exist and we should make it an alias to `IntError`. TC: Why wouldn't we do this? We already have this method on all the integer types. We have `NonZero` and `NonZero` should be a clean wrapper on integer types. The 8472: Then we have a lot more methods to add. TC: Maybe, but we can start where it's useful, as it seems to be here. The 8472: We should be more principled. TC: Agreed; I think methods such as this should be on a trait that's then implemented on all appropriate types. But that's a bigger shift. Amanieu: That's possible with [inherent_trait_impls](https://github.com/rust-lang/rfcs/pull/2375). TC: From the lang side, we should indeed move inherent_trait_impls forward. The 8472: Looking at other methods, `from_ascii` is on u32. It produces `Result<u32>`. Amanieu: And there's `from_ascii_radix`. And I'd expect those to be on `NonZero` as well. The 8472: Do we have things like `overflowing_rem`? Amanieu: Yes but not on `NonZero` The 8472: Looking at all the arithmethic methods on all flavors, that would increase the API surface a lot and some might produce weird edge cases. The 8472: But I'm not objecting. Amanieu: I'll mark as accepted and say to add the from_ascii impls too. ### (nominated) rust.tf/libs705 *\`File::close\`* The 8472: There's been thread on the LKML about the manpage for the `close` syscall. And during that discussion I asked questions relevant to this. I've posted the summary last week with the discussion link. One of the maintainers said the only useful error from close is E_BADF and anything else is unreliable due to the reasons I've listed it. The 8472: That's a strong argument on not making error checking of close standard or expect the user code to do this. If someone knows what they're doing, they can do this with the libc crate or rustix and similar Josh: Agreed Amanieu: The conclusion: reject any error handling on close? The 8472: This ACP proposes a public API for close. There's also a PR from the author that handles this internally in stdlib Amanieu: I can see that it doesn't hurt to check for errors on close in stdlib. But I don't want to encourage people to do this because we check for errors. So I'm of the opinion that the general policy for an assert for E_BADF The 8472: We do that today: we check E_BADF in debug mode. We do it via an extra syscall due to issues with fuse or network error. Josh: Why do we care? The 8472: We don't panic, we abort the process. Josh: That's fair if you run it on a FS that lies about what the file handle is Amanieu: If it's debug-mode only, it doesn't matter. No one runs debug builds of stdlib Josh: It's reasonable in debug build if we care about doing the extra syscall. But in all builds, it makes sense to always abort when the file descriptor is invalid when you thought it was valid The 8472: Josh: +1 we swallow other errors with close. The 8472: So reject both this ACP and the PR that does this internally? Josh: Yes The 8472: I'll write the response? Amanieu: Shall we do fcp close so this shows the support from the entire team? The 8472: sure Josh: Yes. Thank you for going the distance and getting authoritative answer from Linux ### (nominated) rust.tf/99301 *Tracking Issue for \`error\_generic\_member\_access\`* FCP finished. Should be merged? Amanieu: I didn't reply last week, I'll do that ### (nominated) rust.tf/109737 *Tracking Issue for \`once\_cell\_try\`* Amanieu: It wants to change API signatures. David, you proposed to merge this not using `Residual` from the `Try` trait David: The function is useful that people land on it and understand how to get the job done. Signature involving `Residual` you won't understand. A signature involving `Result` is a better outcome. Amanieu: I disagree. You could make that argument for everything using `Residual` David: The point of `Residual` is to be on all the signature. It's to support `try` blocks. For signatures I want to use `Residual` as little as possible. BurntSushi shares that Amanieu: `Residual` here is only needed because we're changing the success type in the `Result`. David: We need to change it from `T` to `&T` and in the `Result` signature that's clear The 8472: Can we fake something for rustdoc Amanieu: I still disagree. When we stabilize this ?? Josh: Broadly, I agree that most things that take a function from the user and return what the function returs should be expected to use `try` and deal with what the user dealt with. But we have 50 functions in the stdlib that's variations on `map`. We shouldn't do that here now as we'll end up having to do an edition change The 8472: We have `try_map` on array that does the same thing, but is not stabilized, probably for the same reason. TC: What APIs you're thinking about Josh? Josh: A lot of different variations an `map` that take a closure and return something based on the closure and a lot of them don't handle things other than `Result` TC: I thought we'd avoided that in most cases. I agree the simpler signature is simpler. But as we move the language to embrace this hierarchy, that'll create a rough edge as our API will embrace `Result` as the language will embrace `Try`. Josh: TC, you're right that we *don't* seem to hardcode Result anywhere. We have a lot of things taking a function and using Try, all of them unstable. David: Has there been anything done on the language side to help here? Josh: You're talking about effects or something like that. David: No. In C++ it'd be either "template template" vs overload sets. Both values and types have the same issue. I think there's something like `std::overload` that captures this for values. On our side we don't have something like that. - https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1170r0.html TC: Similar to Josh, the first thing I think about are the conversations we had on various manners of effect systems. Regarding how you see this different from effect systems, I'd like to see any write-ups or references. David: ```rust fn get_or_try_init<F, R<T>>(...) -> R<&T> where F: FnOnce() -> R<T> ``` https://github.com/rust-lang/rust/issues/109737#issuecomment-3821238360 Josh: All the cases residual in the `Try` trait is about ?? Amanieu: I'll categorize anything with `Residual` and `try_map`. If it's forward compatible with using `Option`/`Result`. The issue is with the inconsistency with the other function using the `Try` trait which support `Option` as well as `Result`. Josh: It's not forward-compatible to change from hardcoding `Result` to change to `try` with `Residual`. It might be considered a breakage where people haven't specified the fn type would be affected. I don't think that would be rare. Anyone using `?` and not specifying the type anywhere would not get resolution properly. We would find ourselves doing edition-dependent resolution. Josh: I agree with TC that in most cases we don't hardcode the `Result`. TC: Josh's analysis of the breakage that would occur is correct. In the past, we've removed hardcoded `Result` types ahead of stabilization. It'd seem strange to hardcode this now when it seems likely the language will go in the other direction. Josh: It is a problem with the `Try` trait that the signatures become less readable. That is something we should do. But we also had other cases like that. The 8472: I think all the methods are unstable because there are open questions around `Try`. Amanieu: Anything using the bare `Try` trait can be stable, anything using `Residual` can't be The 8472: Maybe do use `Residual` but block stabilization until the `Try` story is resolved Josh: I don't think we should block this on the basis of stabilizing `Try`. A lot of people are waiting on that to move from the ecosystem `OnceCell` to the standard library Amanieu: I'm not sure I'm comfortable with that reasoning. ... Josh: I'd like to not block this; we can stabilize this with the `Try`-based signature and handle making it interpretable to the user through documentation and examples. TC: I'd second what Josh is saying here. Rust has an advanced type system. Sometimes we have to rely on that. We can then help the user through focused effort on documentation. E.g., the signatures of macros in our standard library are often difficult to read as well. We similarly handle those cases with documentation and examples. David: TC, how often would you expect people to use this with something else? Amanieu: I'd expect people to use this with `Option`. David: `Option` is easier, you can use `Result<T, ()>`. TC: Looking to the future, on the lang side, as we add features that encode state machines such as coroutines, we may want to add new special-purpose `Result`-like types (e.g. as we did with `Poll`). In doing this, we'd be leaning on the theory that we could add these and they'd work seemlessly because they are `Try`-shaped. If we start to hardcode `Result`, that will constrain us. We might instead then end up in the uncomfortable position of needing to make all these return types `Result`-shaped rather than `Try`-shaped. The 8472: The real try signatures look even more complicated due to const stuff. https://doc.rust-lang.org/nightly/src/core/array/mod.rs.html#595-601 TC: Another case where we simplified what we presented to the user was the change we made regarding `PinCoerceUnsized`; we shouldn't do exactly that here, but it goes to the point that we can be careful in the documentation about what we show to the user. Amanieu: We're not reaching any consensus. Josh: I propose we pick this up as the first item next week and try to prioritize it. Amanieu: Sure. I'm still inclined to block it until we get a response from Scott Josh: No objection to hearing back from the status of the stabilization. But I don't want to block a long time given how desired this is Amanieu: I wouldn't expect to block for more than a few weeks Josh: A few weeks would be fine, a few months would be a problem. --- *Post-meeting thought:* TC: Thinking about it after the meeting, it occurs to me that, for my part, the problem with making `get_or_try_init` `Result`-shaped is that it's stepping on the appropriate name for the `Try`-shaped one. One possibility, then, could be to add a `Result`-shaped one with a `Result`-shaped name such as `get_or_try_init_result` (we could similarly have `get_or_try_init_option`, etc.). That's not a proposal, exactly, but I mention it as one option. I.e., if we want to manually degenericize, we should add the filled-in type to the name. ### (nominated) rust.tf/149537 *f\*::min/max do not behave as documented for signaling NaN on aarch64, or with optimizations* ### (nominated) rust.tf/149926 `P-lang-drag-1` *Do not deduplicate captured args while expanding \`format\_args!\`* The 8472: I don't like that one. TC: There are no concerns outstanding. In my view, this is a lang matter. We're driving for a language consistency on it. The 8472: To me this is API surface. It's a macro from the user perspective. TC: This is a built-in macro; that makes it part of the language. From the lang point of view the difference whether something is a macro or special syntax is minimal. We almost went with having a `await!` as a macro rather than a keyword. There's no difference between `addr_of!` and `&raw const`. This is a language built-in. The 8742: This could be written as library macro Amanieu: nearly, `format_args!` relies on `super let`. But interpolation is tricky. The 8472: Is this in the compiler for efficiency reasons? TC: Even if this could be entirely library code, I'd personally assert lang jurisdiction on the flavor of the macros that are in the standard library. Macros are special: they do syntactic transformation and that's the bread-and-butter of lang. The 8472: From a user perspective, a macro is a magic that could do anything. I'm not expecting consistency with macros. Amanieu: If you look at the attached issue https://github.com/rust-lang/rust/issues/145739 Amanieu: it's expected that each argument gets a separate zero The 8472: macros shouldn't have expectations Amanieu: The main argument is forward compatibility The 8472: If you add future extensions to `format_args` with new behavior, they should be different. It's a different feature that behaves differently TC: In practical concerns, if we can't fix this, I'll file a concern on Josh's field access RFC. The 8472, if we don't do this, how do you want to desugar field access? The 8472: I don't think it's different than the zero/zero case. I'd just deduplicate Amanieu: The interpretation that each is evaluate separately is easier to reason about The 8472: These should not have side-effects TC: You want them to be pure functions. I do too, but that's not the case in the language. The 8472: If you have a pre-set opinion, I don't know why libs is on the FCP TC: Tyler thought it should be lang only, I leaned to that too. I reached to Amanieu as a courtesy. Jack felt it should have libs api because of the point Mara raised and Josh made a formal request for the libs api. Amanieu: I just operate on the principle of minimal drama The 8472: Mara's main concern is that it's less efficient. Which is why I'd always deduplicate. Amanieu: It's resolvable in terms of a clippy lint that tells you to deduplicate. Or optimization. The 8472: To that, the response was also "god, no" Amanieu: I disagree with that, that's an easy optimization to make The 8472: I think something should be done about the performance. Mara spent a lot of time to get `format_args` efficient. Amanieu: You'd block on having the optimization implemented? I think having the duplication is not a big deal. The 8472: It apparently increases code size Amanieu: Is this measurable? Do we have numbers? The 8472: Mara pointed at godbolt that added more instructions. People are complaining about format machinery in embedded. How do we measure it? Amanieu: It's very rare in practice that we'll have duplicate variables. I expect the effect will be barely noticable. The 8472: Is anyone working on this optimization? Amanieu: Not at the moment. TC: Dianne thought really carefully about it. And she's a very clever implementor Amanieu: If you raise the blocking concern, someone will write the optimization The 8472: Then I'll think I'll do that. TC: Please don't do that. That will force me to raise a blocking concern on Josh's RFC and there's an entire fallout to do this Amanieu: We have a perf run. It came back even. Code size changes: basicaly none. The 8472: But perf likely doesn't measure this because benchmarks don't contain duplicates Amanieu: This is such an edge case that the impact in practice is going to be tiny and we should just merge this. The perf results kind of support it The 8472: The perf resoults don't have the cases of interest Amanieu: Add this to nightly and then people might complain The 8472: Then someone files a regression and then we'll ignore it? Amanieu: I believe we should focus on sane semantics first. And that's that they're each evaluated separately. The 8472: The current semantics were sane for now Amanieu: Yes, until we want to add future changes (field access) The 8472: But the deref with side-effects are also weird TC: We want to specify the language and we want to have sane operational semantics. The less of these edge cases can make the semantics clearer The 8472: Then I'll just ignore this. ### (new change proposal) rust.tf/libs740 *ACP: add \`str::version\_cmp\`* Amanieu: Which version spec are you using? The 8472: They mention it's the sorting defined in the Style guide TC: We also have the `cfg_version` RFC Amanieu: Would this be consistent? TC: That's why I bring it up. It probably should be Amanieu: Does this only work with Rust versions? TC: The new RFC is generic over many things beyond the Rust version The 8472: Shouldn't this to be a rust version sort or something? Amanieu: I'd expect people to rely on proc macros over tools The 8472: It doesn't have to be in the standard library. TC: I like this API, but I don't like that it doesn't specify the version sorting. I'd say to defer it and if/when we do cfg_version to reconsider this and match the semantics then. At that point it would be useful to have something in the library side that matches the language. Amanieu: Could we call this `rust_version_cmp`? The 8472: If we have the Rust specification then maybe. If you can do at runtime what you can do at compiler time, it makes sense in the standard library TC: Doing that would create a stability guarantee of how we do our versioning in the future Amanieu: We can add this on nightly only now and block stabilization on the `cfg_version` The 8472: Even then I'd change the name. Now it just quotes the Style guide, that's not very normative. Amanieu: I belive the Style guide is consistent with cargo versions TC: I wouldn't call it 'rust_version_sort' unless you're sorting rust versions The 8472: What is an ?? sorting Amanieu: It's a sorting that says 0.10 is higher than 0.2 TC: There are different sort options. But this is closest to the version sorts: it breaks them into decimals and sort each part individually Amanieu: Accept this, block on stabilization cfg_version and on consistency for cargo versioning and cfg_version The 8472: I think we should still clarify in the name that this is sorting according to the Rust convention Amanieu: You'd assume that the version compare from the Rust standard library would use the Rust version convention The 8472: Maybe documentation is enough TC: agreed with Amanieu. We also want a complete specification regarding the version. TC: When you say "consistent with cargo", what do you mean? Amanieu: Cargo should agree on ordering, right? How one version is more than another The 8472: Don't the alpha versions etc. not participate in the ordering? TC: Yes. I don't think cargo has different total orders, but there are partial order considerations Amanieu: Cargo has comparison constraints. ... Ah, but "version requirements exclude prerelease versions" The 8472: Does rustup have similar issues? TC: I'm still okay with accepting the general idea but it'll need a lot of work in nightly Amanieu: We should refer this to cfg_version RFC and have them talk to each other. ### (new change proposal) rust.tf/libs739 *ACP: Add \`BTreeMap::append\_with\`* The 8472: That's more of a "merge"? Amanieu: > If a key from other is already present in self, the respective value from self will be overwritten with the respective value from other. Amanieu: So it's with but with config resolution present. I'd call it "merge" The 8472: I'd cal it "merge" Amanieu: It creates iterators from both of them, constructs a new tree from the sorted iterator. The 8472: Which means it's not "appending" it's "merging" Amanieu: "append" will always prefer the later value if there's a conflict The 8472: I'm just saying the name isn't great. Should we continue with that or use a better name for the new stuff? Having the method is fine. ~~I think Java has something like that too? ... Pretty much this exists in Java under the name "merge":~~ https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#merge-K-V-java.util.function.BiFunction- Amanieu: I'm in favor of this but I'd call it "merge". I'm inclined to accept The 8472: Yes, sounds fine. Amanieu: "merge" The 8472: I'd normally expect "merge" to be what `append` currently does so that's confusing. Amanieu: But `merge` has a conflict resolution strategy when there's conflict TC: I'd call it "merge" too. Feels like a merge than an append. Amanieu: "append" is a merge that always takes the second value all the time. TC: Does this mutate? The 8472: It takes `&mut self`, `&mut other` and it leaves the `other` tree empty. Amanieu: I'd rather take it by value The 8472: We do have that on other collections too Amanieu: And I don't want it there too TC: It's never too late to start doing the right thing. Amanieu, would you take `other` by value? Amanieu: I'd absolutely take it by value. The 8472: What's the advantage of taking `other` by value? Amanieu: It's more consistent API. It's awkward for it to leave an empty btree afterwards. It doesn't have any underlying allocation that's preserved. The 8472: I'm convinced. TC: Why not to take `self` by value for the same reason? The 8472: The dance gets more complicated. For `other` you can just call `.take()`. If you do it for `self`, you first have to take `self` out, then append, then put it back. And you often have a tree inside some data structure. TC: You're taking about the case when you're not returning the btree and you're modifying it Amanieu: I prefer `&mut self` and no return value in the end TC: Is there a case for having both? I think we've done that in one case. And e.g. Python has `sort` and `sorted` The 8472: We don't tend to take collections by value except with `IntoIter` TC: I wanted it before though. The 8472: Anything named `into` on a collection takes `self` by value but the rest doesn't TC: So we call it "merge", we take `other` by value and `&mut self`. Amanieu: There's a lot of discussion on what the signature for the `conflict` should be. I'm inclined to take what's proposed The 8472: So we move the value out. Can that cause spurious resizing? Amanieu: That's irrelevant. We call `.into_iter` on both trees and then creates a new tree from scratch. The 8472: That can be inefficient if one of the trees is tiny Amanieu: We have a fast path for when one of the trees is empty but not tiny. The 8472: The difference is when you have a huge btree map and you're inserting like five values Amanieu: Right, but I don't know what the threshold should be. Amanieu: I'm inclined to keep `conflict` as proposed in the ACP TC: The algorithm is removing the value out of both threes. Amanieu: Removing key and value out of both trees. We're only giving you read-only access to the key. These need to be sorted. The 8742: If we want to optimize inserting the smaller map into the bigger one, we'd have to swap them TC: If the signature were you'd be consuming both trees and making a new one, it'd make sense to me to returning both values out. But if you're merging into the left-hand-side does it make sense to only have a reference to the value? The 8472: as an implementation detail you could swap them. Amanieu: I just want to accepted as proposed with the name change and other by value The 8472: We could have a special travel approach where it doesn't resize with by value because the closure will return it. If we want to optimize it further in the future. So by value should be ok. TC: Imagine the LHS is huge and RHS is small. The 8472: Right now the proposed implementation would be inefficient. It deconstructs both maps, iterates over them and reconstructs into the LHS TC: I'd probably be doing this with the immutable reference on the LHS The 8472: For the case where LHS is much bigger than the LHS, we'd iterate on the RHS which is smaller, find the buckets where it fits and put the values on directly and put them back on without resizing. The function is only called when there is a conflict, so we take the value out, call the function and put it back in here. The 8472: It makes the implementation more tricky -- you need a `DropGuard` in case it panics Amanieu: It's equivalent but I prefer by value. It makes it easier if your value doesnn't implemnet `Default`. The 8472: You can implement a custom merge function on your value type. But it sounds ok. TC: I worried about the cases where the values are really large. I was wondering whether we'd be able to optimize these cases for cases where the values are large enough so you would'n moving them The 8472: The proposed implementation would not only move them but also delallocate so it would be fairly inefficient Amanieu: I'd say if this is a problem, the users should box their values The 8472: The function is called only when there's conflict. An optimized implementation wouldn't have to move the value in the first place. TC: I'm looking at when you want to do a trivial merge and if there's a conflict, you'd want to keep the thing in the left-hand-side in the first place. Amanieu: Reading it out and returning it back, I think LLVM could optimize it. TC: If I were writing it by hand, I wouldn't be sure it'd optimize it so I'd use a mutable reference The 8472: I think we discussed a similar case in `Peekable` whether some helper method is by value or reference. `next_if_map_mut` TC: And we ended up doing both The 8472: The proposed implementation is going to be far from optimal anyway. It'll only becomes a concern once we approach something being more optimal. TC: Our natural inclination towards zero-cost implementation is what I'm worrying. When using something from the standard library you should beconfident it's as good as if you wrote it by hand ### (new change proposal) rust.tf/libs738 *ACP: Add carryless product for unsigned integers* Amanieu: That's XOR multiplication. While normal multiplication is equilavalent for one operand being shift and accumulate by the other operand. Carryless multiply is the same thing except instead of doing ADD you're doing an XOR. Some instruction sets have an instruction for this. Amanieu: We accepted compressed bits so I'm inclined to accept this too The 8472: Most of these are vector though. Does that only make sense if you call it in a loop of chunks? Amanieu: CLMUL is in x86 processors since 2010 The 8472: Do you nede to write code that vectorizes this? Amanieu: I'd expect this in portable SIMD The 8472: It makes sense there, but on the primitives? It's not in V1, it's in V2? TC: Is the hardware fast for this? Amanieu: It's much faster than the software fallback. The 8472: Some people implemented the CRC32 algorithm using the x86 CLMUL and it was faster than the dedicated CRC function The 8472: Is there a point in having this in the scalar instructions if we're not getting any benefits out of it? Shouldn't it only go into portable SIMD? TC: If this gets you the codegen you want The 8472: There is no scalar instruction for this, only for vector instructions TC: Was that the case for compressed bits too? The 8472: It takes a mask so you could load a scalar into the vector register and apply a mask to do this on a single value. But on scalar values, what did we implement Amanieu: extract and deposit? The 8472: So if you do it on u128 or on chunks and you set the target_cpu level high enough, it'd probably be the same situation here. You'd get no optimization for just scalars or the CPU baseline TC: But if you do it in the loop, doesn't the LLVM have the option to fuse this? The 8472: It could if you shape your code exactly so LLVM is happy. I guess if we have the bit deposit stuff on scalar, this makes sense too Amanieu: I'm inclined. Only concern is the signature about `widening` TC: Scott's comment: https://github.com/rust-lang/libs-team/issues/738#issuecomment-3830559513 Amanieu: As a general solution to the `widening_mul` problem, I'd have `widening_mul` to return an integer of the larger size. We just don't have it on 128 The 8472: If anyone uses it... But normally people want consistency across values. Does LLVM have problems with that? Amanieu: No, it'll work. It'll generate terrible code. The 8427: I guess we can keep it. TC: I don't think it'll affecct the ACP. We have `widening_mul` on nightly. We can add a note that we should not stabilize it until we resolve the `widening_mul` naming/signature Amanieu: Stabilize carrying mul but only on unsigned integers, not signed integer The 8472: Does carrying exist for XOR? Amanieu: `widening_mul` is pointing to a closed tracking issue. The 8472: So maybe we should just remove it if it's been supreceded..? Amanieu: It has a new tracking issue now: https://github.com/rust-lang/rust/issues/152016 Amanieu: My inclination is `widening_mul` return the next size integer and not have it for 128 The 8472: Do we need `widening_mul` at all? TC+Amanieu: It's very useful. TC: It is useful to have a method that returns a tuple of integers of the same width; I just don't want it to be called `widening`. Amanieu: We do have that, it's called `carrying` Tomas: TODO update the tracking issues in the top of the issue: https://github.com/rust-lang/libs-team/issues/738 Amanieu: There are other naming options: `carrying_carryless_mul` TC: Is it just about the name being bad? A carryless multiplication can end up touching bits moving into the higher limb, right? Amanieu: Yes it can. TC: Then for consistency, we should have a carrying carryless multiplication. It's consistent; we'll just document it. Amanieu: It work in that you can combine these arbitrary long multiplications. TC: I agree the name sounds silly. But it logically makes sense. Sometimes that's the natural consequence of composition. Amanieu: `widening_carryless_mul` is equivalent to zero-extendent values and doing caryless multiplication on the two values. Technically we don't even need `widening`. I'd just not have the carrying one. TC: It's useful though. When you're writing these algorithms, you often structure them where everything is the same width. Amanieu: propose we accept this and change widening to return the next highest integer type. The 8472: Can we do that separately? TC: I'd propose to accepting this modulo adding carrying carryless. If it's going to have `widening_carryless_mul` it should have `carrying_carryless_mul`. TC: What's the differentce between the widenings and carryings we have in stdlib? The 8472: carrying has an extra argument to add an extra bit (for the add) or limb (for the multiplications) TC: Is there a need for that here or is that irrelevant for carryless multiplication? All: We'd need to look into that. TC: We should accept this in a way that it's consistent with what's in nightly. And note we're not happy with what's in nightly and change that. ### (new change proposal) rust.tf/libs735 *ACP: Document how escape\_debug escapes characters.* The 8472: Josh commented: https://github.com/rust-lang/libs-team/issues/735#issuecomment-3806851387 The 8472: I don't think there's anything we need to do Amanieu: Is the ACP accepted? The 8472: No. I think the author was asking for guarantees for how things are escaped. And we settled on being willing to guarantee on the general structure of escaping but not on the exact set of what's escaped. It's not exactly what the author asked for, but we've ended up with a decision that could result in a PR. Amanieu: I didn't have strong opinions. The 8472: We said we accepted a subset as sort. We can mark it as sort of accepted. Amanieu: Based on Josh's comment this should have been accepted. The 8472: We've arrived a subset that the author might not be happy with ### (new change proposal) rust.tf/libs733 *allow specifying whether \`Instant\` should be suspend\-aware* Amanieu: This is a very difficult issue we don't have a good answer to. We skipped it last week. The 8472: If you're using the other clock that does account for suspend and you have a large timeout and it might sleep a long after the wake up where you might want the time-out trigger immediately Amanieu: Both use cases are valid. I don't know which one sleep uses The 8472: It is mathematically valid if it sleeps longer. But it's still not what you'd expect Amanieu: I don't think CLOCK_BOOTTIME is the one that makes sense The 8472: You don't want all your ticks to bunch up right after resume. And there's the FreeBSD problem. Amanieu: I think FreeBSD has proper clocks now. The 8472: It's been a while since I've checked. Amanieu: On Linux CLOCK_MONOTONIC doesn't count suspended time. On OpenBSD and MacOS it does count suspended time. FreeBSD does not have CLOCK_MONOTONIC that counts suspended time. TC: Obviously we'll have to allow both somehow. There are use cases for both. The 8472: And we can't privilege one over the other. FreeBSD doesn't support the one that doesn't count while suspended. Oh, CLOCK_UPTIME. Amanieu: It's an alias to CLOCK_MONOTONIC. The 8472: That's not what the manpage is saying. Let's look at what's in libc: they're different constants in libc. Amanieu: But I think internally it's the same. The 8472: They have a different clock that Linux doesn't have: CLOCK_UPTIME. Amanieu: CLOCK_BOOTTIME is an alias for CLOCK_MONOTONIC which counts the suspend time. The 8472: But there's a separate CLOCK_UPTIME. TC: What's the behavior on Linux today? Amanieu: CLOCK_MONOTONIC is uptime and CLOCK_BOOTTIME is realtime. BOOTTIME is time elapsed when the system is booted. CLOCK_MONOTONIC doesn't count when the system is suspended. TC: That's a footgun. The 8472: They're different usecases and you want both behaviours. Having the "wrong" is the footgun. Amanieu: They do the same thing on FreeBSD: https://github.com/freebsd/freebsd-src/blob/2d0564b9daf49c46e0e4ef6c7d162c73fc8b35d7/lib/libsys/__vdso_gettimeofday.c#L176 The 8472: Then the manpage is wrong. Amanieu: Yes! The 8472: This might have changed from version to version. I've looked at another manpage and it was different Amanieu: This should be master. TC: What can we ask form the contributor. Ask for what every system does, ask for proposals? The 8472: Having a table for what every system does, which cases we can support? TC: To make this consistent, we may need a breaking change. The 8472: I propose having an "os default clock" and have additional platform-specific clocks on top. TC: That would be an unfortunate default. We try to not make platform-dependent defaults. The 8472: This can be dependent on hardware. It must be monotonic. Having a clock that counts wall time can be adjusted and it's not monotonic. For that you need a CPU counter that only increments. TC: Can we implement this? The 8472: It has really bad performance. TC: That would only happen on certain hardware. Amanieu: We had this on hypervisor-specific hardware. Amanieu: There's no way we can make any guarantees about what the underlying OS support. Some only support monotonic, some only support boottime. Some embedded OS only has boot time and no system time. The 8472: That's why I propose having a "system clock". What TC said re asking for survey makes sense. But we already know some weird behavior exists. Amanieu: FreeBSD declares clock-monotonic is supposed to increment during suspend, but it doesnt't yet. The 8472: But that's been open for years. Amanieu: Then don't use FreeBSD. The 8472: FreeBSD is the visible example there's more in embedded probably. Not a good starting point for API design. TC: At the end of the day, Linux etc. support both cases. The 8472: I'm in favor of supporting both but as something you need to request and the OS being able to say "not supported". Which means we still do default. TC: Then you'd want to document that you don't want this. The 8472: This is what we have with Instant already. Most people are fine with it except for Android TC: I think for the vast majority of usecases you want boot time, since the vast majority of things are going to involve network services. Amanieu: I agree boot time is what we should do. But sleep doesn't work with boot time. The 8472: So we already have two issues. ### (new change proposal) rust.tf/libs732 *ACP: \`impl TryFrom\<{OsString, &OsStr}\> for String\`* ### (new change proposal) rust.tf/libs728 *Adding fallible shrinking to vec using \`try\_shrink\_to\` and \`try\_shrink\_to\_fit\`* ### (new change proposal) rust.tf/libs713 *ACP: Add float constants for min/max limits of consecutive integers that convert to unique floats* ### (new change proposal) rust.tf/libs711 *Add \`mem::needs\_clone\`* ### (new change proposal) rust.tf/libs710 *\`BinaryHeap::from\_raw\_vec\`* ### (stalled change proposal) rust.tf/libs131 *Add \`std::fs::rename\_noreplace\`* ### (stalled change proposal) rust.tf/libs457 *APC: split\_pattern on slices* ### (stalled change proposal) rust.tf/libs552 *Provider\-style API for \`Context\`* ### (stalled change proposal) rust.tf/libs347 *Context reactor hook* ### (stalled change proposal) rust.tf/libs549 *Add \`uNN::checked\_sub\_nonzero\`* ### (stalled change proposal) rust.tf/libs314 *Add security\_attributes() to windows::OpenOptionsExt* ### (stalled change proposal) rust.tf/libs525 *Vec::try\_remove* ### (stalled change proposal) rust.tf/libs192 *Report allocation errors through the panic handler* ### (stalled change proposal) rust.tf/libs204 *Integer Manipulation API* ### (stalled change proposal) rust.tf/libs287 *ACP: Add \`FromByteStr\` trait with blanket impl \`FromStr\`* _Generated by [fully-automatic-rust-libs-team-triage-meeting-agenda-generator](https://github.com/rust-lang/libs-team/tree/main/tools/agenda-generator)_