---
date: 2025-12-16
url: https://hackmd.io/l7HOM9sVRJG-yFR2l0iDCA
---
# Libs-API Meeting 2025-12-16
###### tags: `Libs Meetings` `Minutes`
**Meeting Link**: https://meet.jit.si/rust-libs-meeting-crxoz2at8hiccp7b3ixf89qgxfymlbwr
**Attendees**: Amanieu, David, The 8472, Josh, Chris Denton, TC
## Agenda
- Triage
- Anything else?
Tomas: You can propose 2026 goals now:
https://rust-lang.github.io/rust-project-goals/how_to/propose_a_goal.html
(deadline: end of January 2026)
Roughly the same process. Template has been simplified a little. Clarified the team asks (t-shirt sizes based on the level of support required from the team).
https://rust-lang.zulipchat.com/#narrow/channel/546987-project-goals.2F2026-workshop
Amanieu: We should start working towards language support towards edition dependent name resolution.
Josh: We need to pick what design we want. We've been aligning towards renaming a symbol to the symbol we want.
Tomas: Nothing's official, but we're looking at trying to get the next Edition in 2026 (plan and hopefully even ship).
## Triage
### FCPs
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/139087 *Fallback \`{float}\` to \`f32\` when \`f32: From\<{float}\>\` and add \`impl From\<f16\> for f32\`* - (4 checkboxes left)
- close rust.tf/136638 *warn on empty precision* - (3 checkboxes left)
- merge rust.tf/98407 *Tracking Issue for \`Exclusive\`* - (1 checkboxes left)
- merge rust.tf/145948 *Stabilize 29 RISC\-V target features (\`riscv\_ratified\_v2\`)* - (3 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/125687 *Tracking Issue for \`new\_range\_api\` (part of RFC 3550)* - (3 checkboxes left)
- merge rust.tf/149408 *refactor: remove Ord bound from BinaryHeap::new etc* - (3 checkboxes left)
- merge rust.tf/149482 *thread::scope: document how join interacts with TLS destructors* - (3 checkboxes left)
- merge rust.tf/139493 *Explicitly export core and std macros* - (8 checkboxes left)
- merge rust.tf/122034 *Tracking Issue for raw\-pointer\-to\-reference conversion methods* - (3 checkboxes left)
- merge rust.tf/99301 *Tracking Issue for \`error\_generic\_member\_access\`* - (4 checkboxes left)
[joshtriplett (6)](https://rfcbot.rs/fcp/joshtriplett), [scottmcm (3)](https://rfcbot.rs/fcp/scottmcm), [jackh726 (1)](https://rfcbot.rs/fcp/jackh726), [Amanieu (5)](https://rfcbot.rs/fcp/Amanieu), [nikomatsakis (3)](https://rfcbot.rs/fcp/nikomatsakis), [dtolnay (3)](https://rfcbot.rs/fcp/dtolnay), [the8472 (9)](https://rfcbot.rs/fcp/the8472), [tmandry (1)](https://rfcbot.rs/fcp/tmandry), [BurntSushi (11)](https://rfcbot.rs/fcp/BurntSushi)
### (nominated) rust.tf/148941 *stabilize \`Peekable::next\_if\_map\` (\`#!\[feature(peekable\_next\_if\_map)\]\`)*
Amanieu: we added `next_if_map_mut` and that's on nightly
Josh: We said let's let it percolate it for a while. And it's been two weeks.
Amanieu: I'm happy to start an FCP.
Amanieu: Do we want to stabilize the mut one separately or both at the same time?
Josh: Same time seems fine.
The 8472: The API outline wasn't updated, was it?
Amanieu: It wasn't. I'll update it and start FCP.
### (nominated) rust.tf/149069 *Tracking Issue for \`uint\_gather\_scatter\_bits\`*
Amanieu: We asked for rename to deposit/extract. It hasn't happened yet.
Amanieu: And we're not stabilizing this without LLVM support for this as an intrinsic.
### (nominated) rust.tf/149359 *Edition 2027: Consider replacing \`std::sync::Mutex\` and other locks with \`std::sync::nonpoison\` versions*
Josh: This is what we were talking about doing and we should make an official reason. People started raising the question of whether poison or nonpoison was the correct default. People who want the default be changed are louder than people who want it to stay the same. So now that's been raised, people who wanted the default raised their voice. We should be aware there are people who want it.
Amanieu: Yes. I personally still think we should do this and people would appreciate doing this (not having to do `.unwrap()`)
Josh: I think people very much want to not do `.unwrap()`. Some people said they wanted it to be internally poisoning and then panicking.
Amanieu: It seems to me those people should be using is `panic=abort`.
Josh: It seems for those people doing panic unwind is better.
The 8472: We have webservers where the mutexes that get poisoned are background tasks for jobs that are submitted by the user. And only specific tasks get poisoned.
Josh: I see. But if you have a mutex that covers a critical process then if that gets poisoned you might as well abort.
Amanieu: I don't think it needs to be nominated right now. Theres' nothing actionable there.
The 8472: Are people aware of the idea of pulling out the poison wrapper? I think you should bring taht up in discussion.
Amanieu: It's been brought up, but it'll be clearer once I've got it in the standard library.
The 8472: We should also make it ergonomic so this can be done in one step.
Amanieu: I don't think that's possible.
The 8472: You could have a separate method, like `lock_poison()` that tries to lock and panics on poison.
Josh: The people replied to the Poison wrapper why is that not the default when it's safer.
Amanieu: It's not safer.
Josh: Agreed but that's what people think.
Amanieu: I have flashbacks ot panicking drop.
Amanieu: Do we have anythnig to respond to here?
Josh: I don't think we need an immediate response but we should reply within the month or so.
Amanieu: We have the `A-maybe-future-edition` label set
### (nominated) rust.tf/149537 *f\*::min/max do not behave as documented for signaling NaN on aarch64, or with optimizations*
The 8472: This was also discussed on Zulip.
Amanieu: The question was: do we want to do a breaking change and the answer is: maybe?
The 8472: We can do the implementation work to get fast min/max on all platforms. And a separate question is how to expose this (a new method) or do a breaking change and make the existing one fast and provide the guaranteed behaviour in separate methods.
Amanieu: It feels bad for min/max not do the right thing. Especially for SIMD. I think x86 and old PowerPC are the only architectures that have copmare-and-select based min/max as opposed to the proper IEEE version.
The 8472: In principle SIMD could do something different than the scalar version.
Amanieu: It will feel wrong though.
Amanieu: I'll ask Jubilee for some feedback since Jubilee is involved in the portable SIMD work.
The 8472: It depends whether people rely on the NaN behaviour or not
Amanieu: I think that's unlikely but possible.
The 8472: And how do we find out. I'd be sceptical that crater run would rely on this behaviour.
Amanieu: It'd be strange for someone to rely on this for optimization if it's slower on x86.
The 8472: That seems odd, yeah.
The 8472: You could use it as a "ignore all NaN values". So if someone has noisy data
Amanieu: I don't think we need to discuss this in a meeting. I need to write up a PR to change the documentation guarantee and start an FCP on it.
The 8472: It would be a preliminary change for now -- only in the docs. But if people see it, they'll come out.
Amanieu: Nobody's going to notice until it's in the nightly.
The 8472: We could announce it, ask for feedback.
Amanieu: Separately, do we want to stabilize the f32 minimum/maximum? http://github.com/rust-lang/rust/issues/91079
The 8472: We need to.
Amanieu: And we also want minimum_number/maximum_number
The 8472: Do people need both?
Amanieu: There's three defined by IEEE. Minimum/maximum which does NaN propagation. minimum_number has changed. https://github.com/rust-lang/rust/issues/149537#issuecomment-3604776087
Amanieu: I'll fire up a PR for that.
### (nominated) rust.tf/149615 *implement error multi provider*
*side discussion*
Amanieu: we've dropped the provide method. Someone asked if we could add it back using external implementable items
David: I'm not in favor of that. One thing that differentiates backtrace. If someone advocated for replacing source ref. That would be difficult for the Error trait but for Backtrate that would be captured by the type.
The 8472: What are we going to do for discoverability? Do we ask people to put what they provide on the top level of the error type?
Amanieu: If its' a concrete error type, it'll always have a backtrace.
David: I think documentation is appropriate.
Amanieu: David, you're still a maintainer of Anyhow that will rely on this?
David: that's right
Amanieu: Is the current API suitable for this.
David: The open question is on the provide methods.
Amanieu: Can you raise a concern on the FCP?
Amanieu: I'd tend to say we should not provide stuff from the source errors?
The 8472: Agreed. You can always enumerate the chain, but if it happens automatically, you can't opt-out.
David: I agree. That's the right answer but we should agree on that as a team.
***
Amanieu: Back to this. Are we happy to merge it?
Josh: Last time we discussed that we'd merge this if someone needed it for a performance reason. The original person who posted it did it as a proof of concept.
Amanieu: I just talked with ariel earlier today. They had the expectation that the PR will be merged.
Josh: I'm happy to merge contingent on showing that it's actually being used before stabilization.
Amanieu: This is assigned to The 8472. Might be worth asking the author whether it's ready to merge.
The 8472: I chatted with ariel. I want to review it and it's on my queue.
### (nominated) rust.tf/149780 *core::intrinsics::abort: Terminate with \_\_fastfail on Windows*
Chris: The Libs API question is whether we're happy with the interupts in the call
Amanieu: Is it ok for Core to do os-specific stuff. E.g. on Linux abort could raise the abort syscall
The 8472: That's not the same as doing syscalls in general. Abort is a bit of a special case
Josh: I'd agree. Without making a general call about what syscall core is allowed to make on a system without an os, in this case it's fine, it'd be a few bytes.
Amanieu: It would be a function call. It's not a big deal.
Amanieu: I'm personally happy with that.
Josh: Yes. I do think we need to make a more general decision on doing syscalls in core. In particular for SIMD feature detection. But I think we should approve this and do something similar on Linux.
The 8472: Would LLVM also change? It inserts ud2 at the end of the function calls. Would that change?
Amanieu: I think we no longer need it. LLVM used to insert that for when not optimizing loops properly. But people mentioned it's important for UB cases.
The 8472: For UB detection it's good but should all ud2 be changed for this instruction change.
Josh: No.
Amanieu: This is for the undefined intrinsic.
The 8472: If someone's code-golfing and wants to have a branch and a loop, would that be possible? Some function you want to keep small in assembly but has unreachable.
Amanieu: I think we should just turn the LLVM option off. If you want a trap, use the abort intrinsic.
Chris: Follow-up: should we have `core::panic::abort`
Amanieu: Should it take a message (format_args)?
Amanieu: We have non-unwindable panics that are guaranteed to abort. But they're not publicly exposed. We only use them for panicking inside a drop when there's another panic triggered.
Amanieu: Perhaps the right thing is to stop using the abort intrinsic everywhere and replace its uses with call to panic_no_unwind
The 8472: Should we make that not internal?
Amanieu: It should probably be hidden, but do we want to expose this?
Amanieu: I feel this is something we sholud be publicly exposing.
The 8472: Has anyone asked for it?
Amanieu: Anyone who wants to use intrinsics abort. Anyone in core who's writing code that's not unwind-safe. But maybe a better solution would be to expose a function attribute that turns any unwind into abort if a panic is called within it.
Amaniu: Back to this specific issue. If it's only for intrinsic use, I'm ok with it.
The 8472: Are there no environments on Windows where you'd use this target but syscalls are unavaliable?
Amanieu: It's not a syscall, it's a trap instruction
The 8472: And it's also a stable interface?
Amanieu: I believe so. ... Yes.
The 8472: In that case I'm fine with it.
Amanieu: So we're happy to do this for Windows.
The 8472: Yes. I don't think this is a general policy, just a windows-specific behaviour.
Amanieu: I can reply to this one.
### (nominated) rust.tf/rfc3892 *Complex numbers*
Chris: What is this nominated for?
Josh: This came up in the last couple of meetings and we didn't have time to go throguh it. The RFC proposes having a common vocabulary type for complex numbers in the standard library. We asked to make it as simple as possible so what we're approving is just the type and and essential operators.
Josh: The only open question is what the type restrictions on the operators should be. Things like the Add/Mul/Sub/Div operators will need to declare some trait bounds. The original proposal was to have a trait that defines what operators do we need for thing like floating points. Question is: do we need that sealed. That's what we need settling.
Josh: Otherwise from libs perspective we're ready to evaluate and merge. It's only the question of which bounds we need.
...
Josh: Looks like they rewrote it in a much simple way. Mul and Dive are now written in `f32`. That solves the bounds problem completely. I think they've removed the trait.
Amanieu: It's still in the Reference level explanation, but I don't think it's used anywhere.
..
Amanieu: No, it's used in the modulus operation and the `i` associated constant. Ah, that's a future possibility.
Josh: Future possibilities are fine.
Amanieu: So it's still used on modulus.
Josh: That should be fixed.
Amanieu: Given the trait's just gone, we allow creating `Complex<T>` for any `T`
Amanieu: Is there a reason for not having this a struct in public fields
The 8472: Has the FFI question been resolved? If it requires a special ABI, does the compiler treat is as a general struct most of the time but special-cases it for `Complex<f32>`? That might need special code in the layout to match on the item.
The 8472: If we have a mix of user implementations and standard library implementations that need special handling, the compiler might not be happy.
(the first meeting ended here)
(the second meeting started here)
Amanieu: On x86 and PowerPC the ABI for complex numbers is different. We have the concept of FFI-safe types.
The 8472: But we should still ask if it causes the compiler a pain.
Amanieu: I think the difference is going to be miner
The 8472: I'll post the comment on the RFC
Josh: Then it makes sense to keep the fields of the struct private for now. We can revisit during FCP.
Josh: I'd be almost tempted to have some way of getting a mutable reference to modify one of the fields directly. But if you have a mutable reference to a Complex, it's a simple copy type.
Amanieu: This is the complex type from num-complex
```rust
#[repr(C)]
pub struct Complex<T> {
pub re: T,
pub im: T,
}
```
Amanieu: do we want to expose the fields publicly?
Josh: yes, if we can do so by meeting the calling convention. If we can do that by having a lang item to make sure it's handled correcly.
Amanieu: I think that's the best way, having it marked as lang item that's handled properly for certain types
The 8472: so it's just a struct, the only different thing is the calling convention
The 8472: If we set a repr(C) on it, that would conflict with the special layout
Amanieu: The memory layout is defined in C. The only thing is different is the calling convention
Josh: I see. In that case we should just make this a `repr(C)` with public fields
Amanieu: I'm trying to think of a transition trait for crates like num-complex
The 8472: They could just use it if it's public, right?
Amanieu: They'd have to wrap it. Maybe a `Deref` would suffice?
The 8472: I see, they implement standard library traits too, I see. So they need a wrapper.
Amanieu: It would work for complex bignums.
Josh: Yes. I think that's where we want to land eventually. This is blocked on "do we want to have standard num traits". But as a stopgap let's have a common type people can use.
Amanieu: If we want num-complex to be able to use this type, we can't put restrictions on the `T` itself, just on the operations.
Josh: Before making this stable: if we don't put a restriction on T and only define mul and div on specific types, then someone would be able to do an implementation of Complex on their own type T and that would block our ability to introduce a trait in the future.
Josh: Would we want to provide an empty trait solely for the purpose of ensuring people can't do exactly that until we're ready to define a general trait?
The problem:
```rust
// core
pub struct Complex<T> { ... }
impl Mul for Complex<f32> { ... }
impl Mul for Complex<f64> { ... }
// Third-party crate
pub struct MyBignum { ... }
impl Mul for Complex<MyBignum> { ... }
// Future core
impl<T: FinallyAWorkingNumericTrait> Mul for Complex<T> { ... }
// Now the third-party crate breaks.
```
Amanieu: Is the `impl Mul for Complex<MyBignum>` even allowed?
Josh: It's definitely allowed for certain types in the standard library. Let me go check.
...
Josh: You can't e.g. implement std::ops::Add for `Option<MyType>`. I got thrown off by the fact that there are many types in the standard library that are fundamental. But it's not the default. So as long as `Complex` isn't fundamental, this isn't a problem.
The 8472: What about the generic on Mul on the right-hand side. You could imlement it in the other direction.
Josh: I see, when you do impl mul for the RHS type.
Amanieu: That should work.
Josh: That seems less concerning. We can mention this in the documentation, that you might encounter coherence breakage in the RHS case.
Amanieu: That sounds reasonable. I'd like to cc Josh Stone to double-check the API as the author of num-complex.
Josh: Yes, we should definitely pull him into this. I can post the comment saying this should have public fields and `repr(C)` saying we can do the FFI despite that.
Josh: Assuming we make the fields public, we don't need the accessor methods anymore, right?
### (picking up checkboxes) Explicitly export core and std macros #139493
https://github.com/rust-lang/rust/pull/139493
TC: This is a dual lang/libs-api FCP. The lang side are the changes to name resolution and the change to not bring std macros into the `macro_use` prelude. The libs-api side are the compensatory additions to the standard library prelude.
TC: There was some back and forth as we were trying to undertand exactly what the changes to the name resolution were. We've got that undertood and documented now. So I proposed FCP merge. There's an interesting nuance with `no_implicit_prelude`; it's worth reading the comments about that.
Amanieu: This is necessary for us to be able to move forward with `assert_matches!`
TC: Exactly.
Josh: Also, it seems that now we can treat macros even more like other items rather than something that happens magically. Especially with [the other proposal to allow exporting macros that don't get exposed with `macro_export`](https://github.com/rust-lang/rust/issues/148610), I'm hopeful.
Amanieu: Ok, I've checked my box.
Josh: I've checked mine.
The 8472: Is this related some RFC?
TC: No, that's just our lang stabilization template.
The 8472: So this is basically no change, but we had some small changes in practice that we checked with crater, right?
TC: Exactly.
The 8472: Ticking my box.
TC: Then I will un-nominate for libs-api.
### (waiting-on-team) rust.tf/147781 Tracking Issue for `clamp_min` and `clamp_max`
Amanieu: People aren't happy with our decision.
Josh: I see Chris's comment from October 22: "Using range types was discussed In the libs-api meeting but team members weren't generally favourable.". IS that true?
Amanieu: Here's the comment I posted summarising the meeting: https://github.com/rust-lang/libs-team/issues/665#issuecomment-3378377615
> We preferred the name clamp_range over limit: it's better to explicitly call out the difference between this function and clamp rather than using 2 synonyms.
>
> ...
> Finally, an alternative example was also proposed which adds 2 methods clamp_max and clamp_min as aliases for min and max respectively. These methods would have the intuitive behavior of clamping the input value to the given minimum/maximum.
Amanieu: I don't think we decided on the alternative.
Josh: Yeah, I don't recall us deciding on the alternative.
The 8472: https://github.com/rust-lang/libs-team/issues/665#issuecomment-3403099491
TC: There's not a lot of discussion on the Oct-14 meeting
Josh: Regardless. These are not yet stable. What do we actually want here?
Amanieu: Switch back to `clamp_range`? That would only allow inclusive ranges.
0x||x0: So it wouldn't look like what's suggested in the danielhenrymantilla's comment: https://github.com/rust-lang/rust/issues/147781#issuecomment-3660617839
Amanieu: `clamp_to`. Sounds good, ship it. I think we should just band exclusive ranges.
TC: Why?
Amanieu: It's very complex to make them work. The way min/max works is through inclusive ranges.
Amanieu: How would that work for floats?
The 8472: You'd do `next_down`
TC: I think that's the correct behaviour.
Amanieu: I don't think that makes sense.
Josh: If it's not what you meant, it could be confusing. But sometimes it is what you meant. If I have an array of size 10 and I do `clamp(0, 10)` I do exactly what I intended.
TC: Exactly.
The 8472: Can we allow exclusive ranges for integers and not floats?
Amanieu: We could allow it on anything that implements `Step`
Josh: I don't see float being the largest problem. My issues would be people writing inclusive bounds for maximums on integers.
TC: On floats, the behaviour The 8472: is exactly what I'd expect and it's a pain having to do that manually.
Amanieu: Is this on Ord or PartialOrd? It's on Ord so not implemented for floats.
The 8472: It would basically be a special implementation for float types.
Josh: We could just add `float::clap_range`
Amanieu: `clamp_to`.
TC: `clamp_to` seems fine to me
Josh: Yes.
Josh: Any names we'll pick will be unfortunate because ideally we'd only have one of those.
Amanieu: We need to go back to the original proposal, we need the NaN semantics for the float version of this. Note that the current PR description doesn't implement this for float. But it has an explicit implementation for floats.
Josh: That's because it's currently not implemented for exclusive ranges?
Amanieu: Yes. The PR is `clamp_min` and `clamp_max` -- the two methods people aren't happy about.
The 8472: Not sure if having a type `..=` maximum is better than writing min.
Josh: I've had cases where it would be much clearer.
The 8472: It's not about the name and more about `..=`. That's harder to type.
The 8472: It's more about having one method that takes ranges vs. having two methods as alternatives with better names for `min` and `max`
Josh: With the new names, I'd still stop and stare to get a sense of them. I wouldn't do that with looking at the range.
The 8472: I like the at_least/at_most in the tracking issue
Josh: Those are clever, but I'd still stop and stare.
Amanieu: We could have overloading based on arity.
TC: File the issue for lang; we'll take the nomination. I was thinking of how we could have an edition-dependent name resolution and recover the name `clamp` in a future edition.
Amanieu: We need a list of all the things we want to do with the edition-dependent name resolution.
Josh: We probably need to systematically go through anything that's deprecated in the standard library, anything that's not consistent. We need a comprehensive review of the API.
Josh: Once we get the features we need for safe trait migration and similar, we'll want to systematically go through all of those.
Amanieu: Safe trait migration?
Josh: Splitting traits and creating parents.
TC: E.g.:
https://github.com/rust-lang/rfcs/pull/3851
Josh: clamp_to and a range, allow both inclusive and exclusive
Amanieu: I'm vetoing exclusive
Josh: For floats or across the board?
Amanieu: across the board
Josh: That's genuinely useful for integers
TC: If we have a lang feature that you don't want to use because it's confusing, we should bring that back to Lang
TC: This is similar to us having a similar case in matches. You have a stack of matches (1..9, 10..19) we made a decision to allow for exclusive matches. It feels more coherent that as a language we accept this here too.
Amanieu: So you'd implement it for Ord + Step?
TC: I'd need to look into it. But kind of like in the float case it should calculate what the range endpoint is and use that
Amanieu: Sure.
The 8472: Then we'd need to define the behaviour for the edge case for things like bounds negative zero etc.
TC: Can we rely on next_down?
Amanieu: I think it treats `-0 < +0`
TC: That makes sense. The behaviour I'd expect is it'd be defined in the terms of next_down
Josh: Agreed
The 8472: (0.next_down returns 0 - eps)
TC: Even better.
Amanieu: I still think we should only accept inclusive ranges.
The 8472: `clamp_to(..=5-1)`
??: Doesn't that require parentheses?
Amanieu: It doesn't
The 8472: That looks terrible, please no.
TC: I always write half-open ranges. If we don't support those, I'd nearly always then have to calculate the end point of the closed range manually.
Amanieu: working on integers or floats?
TC: Both. Mostly I'm working on unsigned integers.
Josh: If we were writing a lint, we wouldn't be able to write it without false positives. That's what's arguing to me that we should allow it.
Amanieu: That's arguing to me we shouldn't allow it.
Josh: To verify, is your contern primarly with the implementation needing `Step`? Or is it about the confusion with using ..
Amanieu: Right now we have clamp on floats. And I suspect that using clamp on floats is the vast majority of the usecases. And for that, it would be very strange to support exclusive ranges on floats. Especially since next_up and next_down is very slow
The 8472: I do resource control (VMs, memory) and I clamp to integers quite a bit.
Josh: I did a quick grep for all my projects and it's an even mix for float and integers.
0xllx0: wouldn't users concerned with performance just use the inclusive range anyway?
Amanieu: I'm uncomfortable to providing something that's slow
TC: For what it's worth, the code example in `next_down` is demonstrating clamping:
https://doc.rust-lang.org/std/primitive.f64.html#method.next_down
```rust
let x = 1.0f64;
// Clamp value into range [0, 1).
let clamped = x.clamp(0.0, 1.0f64.next_down());
assert!(clamped < 1.0);
assert_eq!(clamped.next_up(), 1.0);
```
Josh: If we did this for exclusive ranges, the exclusive range impl would have to be for types that implement step. And if we wanted to do it for floats, we'd have to provide it separately for floats.
The 8472: we do this anyway.
Josh: So, we can potentially make this decision independently for float vs. integer. We could choose to do this for floats inclusive only and for integers inclusive or exclusive.
Josh: I'd propose we migrate to the `clamp_to` version on nightly and specificaly state we're feeling some uncertainty for exclusive ranges for floats for these reasons. And have the option to stabilize those separrately using trait bounds. We don't have to make the call today.
Amanieu: I'm happy to support switching to clamp_to with inclusive ranges. It's just the exclusive ranges. On floats next_up/next_down is quite slow. On other types we have to rely on Step. Which it would only work for integers and not user-defined types. Step is unstable.
Josh: Could we verify we'd be able to support clamp on inclusive ranges without step and support clamp on exclusive ranges only with Step without using specialization?
Amanieu: No problem. We'd define a trait for the types of ranges we accept for this function. And we'd impl this for any inclusive ranges.
Amanieu but we can't stabilize those two separately.
Josh: Traits can have stability bounds on them now.
TC: Are you sure? I remember we talked about it; I hadn't heard we did it.
Josh: You can definitely declare such bounds. I've been informed by the types folks that they work but I've not tested them myself.
Josh: If we can do that, then that would remove the strictness on this for things that don't implement Step. I'd want that because I'd like clamp to be implemented on PartialOrd types.
The 8472: `foo.at_least(5).at_most(10)`
The 8472: You'd say this ^ would be a head-scratcher, you'd need to double-check it.
Josh: At first look, `at_least` I'd expect to return bool.
TC: Yes, if it doesn't have `clamp` in the name, it's not clear that it's clamping.
Amanieu: It would make sense if we'd do `clamp_min`/`clamp_max`
Amanieu: Do we have a consensus to go with range-based clamp_to?
The 8472: Do we also accept range bounds with inclusive/exclusive enum?
Amanieu: If we're accepting exclusive ranges, we might as well accept range bounds.
Josh: I'd advocate we need to support all of range bounds.
TC: Does that mean we have to decide this upfront?
Josh: We could accept a trait "ClampableBounds", if `T: Step` then implement `ClampableBounds` for all of range bounds. If `T` is not `Step` and it's `PartialOrd` we could implement it specifically for inclusive bounds
Amanieu: Implementing ClampableBounds, we could implement it with RangeBounds later.
The 8472: They're all in core, even if there were cohernce issues, we'd be fine in core
Amanieu: We can't. If you have ClampedBounds, it has a trait method in there, you have the clamp implementation and the public function just calls that. Kind of how SliceIndex works.
Amanieu: The Index trait doesn't do the actual indexing.
```rust
// Private, sealed
trait ClampBounds<T> {
fn clamp_to(self, x: T) -> T;
}
impl ClampBounds<T> for Range<T> where T: Ord + Step {}
impl ClampBounds<f32> for Range<f32> {}
impl ClampBounds<T> for RangeInclusive<T> where T: Ord {}
// and so on for all the range types + tuples of `Bound<T>`
trait Ord {
fn clamp_to(self, range: impl ClampBounds<Self>) -> Self;
}
impl f32 {
fn clamp_to(self, range: impl ClampBounds<Self>) -> Self;
}
```
The 8472: Even if we can't use the trait, we could cover a few more things by implementing them directly.
Josh: Presumable for the exclusive range types you'd have to write `Step` instead of `Ord`?
Amanieu: You'd have to write `Step + Ord`
Josh: `ClampBounds<T>` should its method be written as `clamp_to` as well?
Amanieu: Doesn't matter, it's a private trait.
Josh: Can we post this is the thing we want. With the caveat that we're still debating the exclusive ranges. And get nightly converted to this?
TC: Sounds right to me.
Amanieu: Sure
Amanieu: Presumaly if we have support for stability attributes for impls, we'd only stabilize them separately
Josh: +1 of kicking the inclusive/exclusive discussion down a road a bit.
Amanieu: I'll go ahead and create a hackmd
TC: Such docs are always great. Maybe as well it'd be worth creating issues and label them with `maybe-next-edition`.
Josh: hackmd is right for brainstorming, but the idea is always for them to end up in github issues
Amanieu: Here's the list: https://hackmd.io/56KVIwnUTBKpo5f5cTRb_g
### (new change proposal) rust.tf/libs711 *Add \`mem::needs\_clone\`*
Amanieu: I'm not sure this works. It's mini-specialization kind of like needs_drop. But with
Amanieu: It's the same issue as specialization. I presume this is checknig for copy. I think codegen can't produce correct true/false answer for this. If you have a lifetime-dependent Copy impl.
Josh: I assume they're thinking that this is `Copy` if it's `'static`
Amanieu: I don't think we can have this for the same reason as we can't have specialization
TC: That's correct, in Rust trait selection does not depend on lifetimes ("lifetimes do not participate in trait selection"). E.g.:
```rust!
// This demonstrates statically how lifetimes don't participate in
// trait selection.
struct _True; struct _False;
struct W<T>(T);
impl<T> W<T> { fn f(&self) -> _False { _False } }
trait Assert { fn f(&self) -> _True { _True } }
impl<'a, 'b> Assert for &W<(&'a (), &'b ())> where 'a: 'b {}
fn f<'a, 'b>(x: &&W<(&'a (), &'b ())>) -> _True {
x.f()
}
```
Josh: If that's the case, shouldn't we be detecting that we have a lifetime-dependent type bound?
Amanieu: Your impl may not be lifetime-dependent. But it depends on another impl of `T` that can be lifetime dependent.
The 8472: It could also be an associated type that happens to be lifetime-dependent.
The 8472: The argument in this ACP would be that it's the best effort
Josh: If you think something's trivial clone and it isn't, that would be bad.
Amanieu: You could do a very conservative analysis, but this would always return true.
The 8472: It could look inside the type
Amanieu: We could check with a specialization expetr. Would that be lcnr?
Josh: Proposal: we punt and let t-types know, "can you look at the possible solutions"
Amanieu: The current implementation work and is sound. It doesn't use the Copy trait, it uses the TrivialClone trait. Which is an unsafe trait.
Josh: And you can't manually implement it.
Amanieu: The trivial clone doesn't do anythnig on its own. It just indicates that clone on this type is identical to a copy.
Josh: And I think if you make it a public stable unsafe trait, you can just say that "if you unsafe impl this trait, then you must not do any form of lifetime-dependent implementation"
Amanieu: I don't know what the requiremens are
The 8472: Wasn't there an issue with derive macros being unsafe due to ordering issues? Couldn't this also have the same issue?
Amanieu: You'd only get this with proc macros that would be handling that code and in that case you're processing unsafe. You have to be careful.
The 8472: There's no unsafe in the code you're writing.
The 8472: https://github.com/rust-lang/rust/issues/148423
The 8472: The proc macro might look harmless
Amanieu: But you have a proc macro that's messing with unsafe code
The 8472: We're dealing with a derive that's messing with an unsafe trait. If we accept this in the standard library, we'd have to have some mechanism to flag that kind of implementation that this can be copied. If it always returned true, the method would be useless. So we need to have something in the compiler to analyze uses and at least sometimes.
Amanieu: You can already do that with TrivialClone.
The 8472: You can only use that in the standard library. You'd need something else to be usable from the userspace.
The 8472: Whether TrivialClone is implemented it gives us the information. But that's in the typesystem. But to get that out of the type system to a boolean we still need some mechanism and a commitment from the compiler team or types. I think oli is working on some intrinsic that does a type query or something?
Amanieu: I think the conclusion here is to cc Types.
The 8472 + Josh: Yes.
Amanieu: This is sound only when it's relying on TrivialClone, it's unstable
The 8472: I'd say the trait alone is not sufficion. We need some compiler magic to go from the trait to the bool and that's currently specialization.
Amanieu: We don't need to commit to anything, because it could always just returns true.
The 8472: We would never add such a method because we'd never add a method that always returns true.
Amanieu: Does `NeedsDrop` counts as specialization? Technically it does, but it doesn't have this lifetime issue.
### (new change proposal) rust.tf/libs710 *\`BinaryHeap::from\_raw\_vec\`*
Josh: Assuming it's an unsafe function this seems fine.
Amanieu: Does it give you
Josh: There's an into sorted vec and there's also into vec which means arbitrary order (but in practice heap order)
The 8472: would the ordedr need to be specified to be useful?
Josh: Heap order
Josh: I think we should accept this and add a comment to `into_vec` saying that it's heap order
Amanieu: We also have an `Into` trait that
Amanieu: We can convert from an arbitrary vec. And convert to an arbitrary vec and leave it in heap order
The 8472: If we only say round-tripping works, that's easy. If someone manually arranges it into a heap order, how precise do we want to be?
Amanieu: What's the use-case? ... multi-threaded heap build.
The 8472: I guess we can make a debug_assert to make sure it's in the right order.
Amanieu: Scott says this should be unsafe.
Amanieu: shall we just drop it for the next time
### (new change proposal) rust.tf/libs709 *Add \`str::copy\_from\_str\` and other mutating \`str\` methods*
### (new change proposal) rust.tf/libs706 *More arithmetic functions for Duration*
### (new change proposal) rust.tf/libs705 *\`File::close\`*
### (new change proposal) rust.tf/libs700 *Mapped Arc and UniqueArc*
### (new change proposal) rust.tf/libs699 *Bring \`hashbrown::Equivalent\` into std*
### (new change proposal) rust.tf/libs698 *Stabilize trait \`ZeroablePrimitive\`*
### (new change proposal) rust.tf/libs691 *\`std::io::Read\` provides byte\-order reading trait*
### (new change proposal) rust.tf/libs688 *Initial state once cell value*
### (stalled change proposal) rust.tf/libs540 *Add Unicode XID related functionalities to \`proc\_macro\` crate*
### (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/libs544 *\`Arc\<impl !Sized\>\` constructors*
### (stalled change proposal) rust.tf/libs525 *Vec::try\_remove*
### (stalled change proposal) rust.tf/libs262 *Add infallible variant of RangeFrom::next()*
### (stalled change proposal) rust.tf/libs501 *ACP: Add floating point representation conversions*
### (stalled change proposal) rust.tf/libs395 *\`impl core::str::Pattern for \[&str; N\]\`*
### (stalled change proposal) rust.tf/libs246 *ACP: replace use of \`Pointee\` trait with a \`ptr::Metadata\` type*
### (stalled change proposal) rust.tf/libs523 *Add a deterministic constructor for \`RandomState\`*
### (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)_