---
title: Libs-API Meeting 2025-08-13
tags: ["T-libs-api", "Libs Meetings", "triage-meeting", "minutes"]
date: 2025-08-13
discussion: https://rust-lang.zulipchat.com/#narrow/channel/259402-t-libs.2Fmeetings/topic/Meeting.202025-08-12
url: https://hackmd.io/W0FNHuKzQqGvPOOQchyAdA
---
# Libs-API Meeting 2025-08-12
###### tags: `Libs Meetings` `Minutes`
**Meeting Link**: https://meet.jit.si/rust-libs-meeting-crxoz2at8hiccp7b3ixf89qgxfymlbwr
**Attendees**: Amanieu, The 8472, Josh, David, Tomas Sedovic, Chris Denton, TC
## Agenda
- Triage
- Anything else?
## Triage
### FCPs
15 rust-lang/rust T-libs-api FCPs
- merge rust.tf/80437 *Tracking Issue for \`box\_into\_inner\`* - (1 checkboxes left)
- merge rust.tf/140808 *Implement Default for &Option* - (3 checkboxes left)
- merge rust.tf/143191 *Stabilize \`rwlock\_downgrade\` library feature* - (3 checkboxes left)
- merge rust.tf/106418 *Implement \`PartialOrd\` and \`Ord\` for \`Discriminant\`* - (2 checkboxes left)
- merge rust.tf/65816 *Tracking issue for \`vec\_into\_raw\_parts\`* - (3 checkboxes left)
- merge rust.tf/132968 *Tracking Issue for \`NonZero\<u\*\>::div\_ceil\`* - (3 checkboxes left)
- merge rust.tf/116258 *Tracking Issue for explicit\-endian String::from\_utf16* - (3 checkboxes left)
- merge rust.tf/139087 *Fallback \`{float}\` to \`f32\` when \`f32: From\<{float}\>\` and add \`impl From\<f16\> for f32\`* - (5 checkboxes left)
- merge rust.tf/129333 *Tracking Issue for \`lazy\_get\`* - (3 checkboxes left)
- merge rust.tf/127213 *Tracking Issue for AVX512\_FP16 intrinsics* - (3 checkboxes left)
- merge rust.tf/136306 *Tracking Issue for NEON fp16 intrinsics* - (3 checkboxes left)
- merge rust.tf/141994 *add Iterator::contains* - (3 checkboxes left)
- merge rust.tf/144494 *Partial\-stabilize the basics from \`bigint\_helper\_methods\`* - (3 checkboxes left)
- merge rust.tf/144091 *Stabilize \`new\_zeroed\_alloc\`* - (3 checkboxes left)
- merge rust.tf/63569 * Tracking issue for \`#!\[feature(maybe\_uninit\_slice)\]\`* - (3 checkboxes left)
[scottmcm (1)](https://rfcbot.rs/fcp/scottmcm), [joshtriplett (10)](https://rfcbot.rs/fcp/joshtriplett), [jackh726 (1)](https://rfcbot.rs/fcp/jackh726), [BurntSushi (13)](https://rfcbot.rs/fcp/BurntSushi), [nikomatsakis (2)](https://rfcbot.rs/fcp/nikomatsakis), [m-ou-se (13)](https://rfcbot.rs/fcp/m-ou-se), [dtolnay (1)](https://rfcbot.rs/fcp/dtolnay), [Amanieu (3)](https://rfcbot.rs/fcp/Amanieu)
### (nominated) rust.tf/116258 *Tracking Issue for explicit\-endian String::from\_utf16*
Amanieu: We've nominated this last week, forgot to remove the label. Should be in FCP now
### (nominated) rust.tf/132087 *Fix overly restrictive lifetime in \`core::panic::Location::file\` return type*
Amanieu: This is not a breaking change..
Josh: The call to `caller` will create a location with a lifetime of `'static`. Location has a `'a` in it. I think in practice this is not observable. I don't think there's a way to get a `Location` with a lifetime other than `'static`. So I think we could clasify this as not a breaking change.
Josh: Technically, it changes the type of the function so if someone's doing type crimes they may be affected. But I don't think it even warrants an extra crater run. Just the regular one during release. Ship it.
Amanieu: October last year we discussed this during libs and the question was why does `Location` had a lifetime at all. We didn't have an answer.
Josh: Hold on. There is a actually a way to get a hold of a `Location` that's not guaranteed `'static`. If you call `panic_info`, it will return `'_`. Is panic info always static?
Amanieu: Yes, it will always have a static lifetime.
The 8472: But that's an implementation detail.
Josh: That's not the lifetime in panic info though. The location will always be static. But there's also the lifetime to format_arguments. Can that one be sometimes not static?
Amanieu: That one can be not static.
Josh: That means `Location` in `panic_info` returns `'a` for whatever `panic_info` is. I don't think it's an issue in practice though.
Amanieu: This seems fine. Happy to do FCP merge.
### (nominated) rust.tf/144870 *Stabilize \`path\_file\_prefix\` feature*
Amanieu: FCP completed, there's a conrern raised. The 8472?
The 8472: I think I withdrew my concern last time. It can be merged now.
Amanieu: Soeone asked whether this should be closed or removed from nightly?
The 8472: Someone got confused by something I said?
Amanieu: Does path_prefix strip out multiple extensions?
The 8472: It only returns the basename regardless of how many extensions the file has.
Amanieu: I think this is good to go.
### (nominated) rust.tf/145233 `P-lang-drag-1` *cfg\_select: Support unbraced expressions*
Josh: It was made into a built-in macro. The fix I did is it will now accept expressions without braces. Now that this is a built-in, it's unclear to me whether this is a libs or lang concern. So I've nominated it to both.
Amanieu: Sounds good to me. Was the original motivation to making it a builtin macro this?
Josh: The original motivation was the double expr parsing. But they left the braces in for the single expression.
The 8472: Does this factor into our discussions for the `hashmap!` macro?
Amanieu: That was about using a colon.
Amanieu: I'll reply.
### (nominated) rust.tf/145269 *Deprecate RUST\_TEST\_\* env variables*
Amanieu: I use `RUST_TEST_THREADS` a lot. What's the alternative to that?
Josh: I think the main motivation is not saying they want to rip this out. But that it's not guaranteed to be implemented by custom test runners. It's an implementation specific to the compiler.
Amanieu: I'm generally happy to give full authority to the devex team on issues related to test. Should we formalyl delegate this responsibilty in general?
Josh: Seems fine to me.
Josh: If we want to do that, we should file an issue that specificly tracks the decision. Do an FCP on it and when FCP passes, consider it done.
Amanieu: Do we have RFC bot on the libs repo?
Amanieu: But for this PR, are we happy about it?
Josh: Seems fine.
The 8472: Doesn't it inherit the `-j` from `cargo`? As that also affects compilation so maybe that's not wanted.
Amanieu: We do have labels for RFC bot.
Amanieu: I'll reply to this one and raise new issue to delegate it to the testing devex team.
### (nominated) rust.tf/libs587 *ACP: \`try\_exact\_div\` method on \`NonZero\<{integer}\>\`*
Tomas: We'd asked the author to provide a table showing the combination of types and their results when calling `try_exact_div_or_rem`. They've done that now so this is nominated again.
Amanieu: (looking at the table) one thing seems incorrect: Non-zero divided by integer can be zero when rounded down. I guess that could be a `Result`?
The 8472: Is Result the best thing here? In division there's the division and remainder. Could we have a more readable type?
Amanieu: Yeah I'm not a fan of using `Result` when the "error" type is not an error.
The 8472: Though considering the name ("exact div") it makes sense that anything that's not an exact div could be an error. But from readability point of view a dedicated enum would be nice.
Amanieu: Yeah, dedicated enum could be nice but `Result` also makes sense.
TC: Ship it. We talked about it before, they did what we asked.
The 8472: Which variant exactly? Only for `NonZero`? IIRC they only asked for `NonZero` divided by `NonZero`.
Amanieu: Yeah.
TC: Sounds like a good place to start.
Amanieu: Except that the signed ones can still panic on overflow.
The 8472: They're only asking for unsigned.
Josh: Yes, they say that explicitly at the top.
Amanieu: I never liked this one but if people feel we should have it, go ahead.
David: Is the only justification for this being the error value?
Amanieu: The motivating example is decimal formatting.
David: Is there an example of what that code would look like? I'm having a hard time picturing what it would look like compared to doing the mod yourself.
Amanieu: The idea is you divide by ten in a loop. As long as the division is exactly by ten, you keep the loop.
David: I'd expect that to be written to `while a.mod(10) != 0 { ... }`
TC: It'd be reasonable to ask the author to post examples on the playground with and without this feature.
The 8472: I think the main motivation here is avoiding `unsafe new_unchecked`.
TC: Also we do have exact_div so this is a "try"-ification of an existing method.
Amanieu: Except it isn't because the signature is very different. Because of the Result returning a remainder.
Josh: Yes, we have `exact_div` elsewhere that panics.
TC: I still consider it a "try"-ification because it has the same semantics.
David: Does anyone get the impression that `NonZero` is shoehorn in here? You can implement decial counting without nonzero.
TC: Isn't that argument against `NonZero` in general?
David: There are costs against `NonZero` usecases here as well. And I think the costs here outweigh the benefits. The algorithm is maybe 20 lines of code that can be easily understood. NonZero complicates it.
The 8472: That's what I meant earlier with an enum that would clarify what the value is (quotient or a remainder).
Josh: I think the usecase for Result would be if you wanted to use a `?` on it. There's no usecase here for doing anything with the error that depends on the Result. So this is a good reason to use an enum.
David: For cases like this, I'd like to compare what the code would look like with the feature vs. without it.
TC: Do we want to ask them for that?
David: Do we want to ask this now or part of the stabilization?
Josh: If we're going to go to the trouble of adding something, going through stabilization, we should ask the question so we can get an idea of improvement this does or doesn't make.
The 8472: A step back is asking why they're using NonZero in the first place.
Josh: I wouldn't necessarily ask them to justify their NonZero use. But asking them to show the before-and-after of their code with this method seems reasonable.
David: That's what I do when I get PRs on my repos where it's not clear to me.
TC: I'll leave a comment.
### (waiting on team) rust.tf/116258 *Tracking Issue for explicit\-endian String::from\_utf16*
### (waiting on team) rust.tf/139087 *Fallback \`{float}\` to \`f32\` when \`f32: From\<{float}\>\` and add \`impl From\<f16\> for f32\`*
### (new change proposal) rust.tf/libs621 *ACP: Add Waker::with\_arc\_wake*
Amanieu: async-wg said they'd prefer a general approach of `WakerRef` last time.
TC: Do we want to close this FCP and ask them to repropose with a `WakerRef` style?
Amanieu: I have no context here, happy to defer to your decision.
TC: That'd probably the cleanest. We'd go with a clean proposal.
### (new change proposal) rust.tf/libs619 *slice::get\_clamped*
Amanieu: I like the counterproposal of a `Clamp` wrapper type.
Josh: The counter proposal seems intriguing. There's already a lot of implementations of `SliceIndex` so it couldn't cause inference issues.
Amanieu: Also: what if we had a unit struct called `Last` and implemented `SliceIndex` on it? For the last element.
The 8472: Why not reverse zero?
Amanieu: Yes, it'd be equivalent to Clamp(reverse zero).
The 8472: Would it panic on empty?
Josh: Would this work with ranges so you could do `3..Last` if you wanted to?
Amanieu: That's just `3..`
David: `3..Last` wouldn't work because `Range` requres both start and end to be the same type.
David: I think The 8472 would use the `std::comp::Reverse` wrapper type for ordering.
Josh: We don't implement `SliceIdex` but it'd be interesting if we did. You could also do `Reverse(3)` similar to Pyton's `-3` for index. I kind of still want `Last` even if it's just `Reverse(0)`, but the idea of implementing this via `Reverse` is fun.
Amanieu: Reply: we'd like to see more exploration around wrappers around ranges that implement `SliceIndex`. Clamp, Last, Reverse.
The 8472: This also works: `Reverse(3..)`
Josh: That's not what I'd expect people to write though. Also not clear it's perfectly equivalent depend on how you interpret the `3`.
Amanieu: `Reverse` sounds interesting but I'm not sure how it would work because of the issues around range types.
Josh: We don't have to bring up `Reverse` in the context of asking for the index types. We can just ask for `Clamp` and `Last`.
### (new change proposal) rust.tf/libs618 *ACP: Implement fmt::Binary for \[u8\] and friends*
Amanieu: was this an "accept" last time we discussed this?
Amanieu: An alternative: say to make a wrapper type that implements `Display` that shows the format in binary
Josh: We could but AFAICT we already support this in hex. ANd we should support binary anywhere we support hex.
Amanieu: What about octal?
Josh: We should support that as well, probably?
Amanieu: It feels this should probably be orthogonal rather than hacked-up? What if I want debug but my floats be formatted in a particular way?
Josh: I'd argue we made a mistake when we first allowed this recursively. We passed this through so e.g. hex could modify what numbers are going to be displayed through the formatter. And given that, we should support it even for binary given hex works.
Amanieu: We don't have a spare flag bit to encode this though. We could encode this because the lower and upper hex flags are feature exclusive. But that'd only give us four possible options: decimal, binary, lower hex, upper hex.
Josh: That probably sounds sufficient. If anyone wants to implement octal later, they can do the work trying to find another flag bit.
Amanieu: I guess we're inclined to accepted? I messaged Mara just in case she has any objections. If she doesn't we should just accept this.
### (new change proposal) rust.tf/libs616 *API Proposal: Slice iterator helpers for taking chunks of data*
Amanieu: Last comment from the last month: ask for specific examples where this matters. It's a fundemental design issues for pointer slices whether we use (pointer, length) or (pointer, pointer). (pointer, pointer) is faster for iteration.
Amanieu: given the discussion, we probably want to close this.
The 8472: We would have to replicate the entire slice API just for the case that one is better than the other.
Amanieu: yeah.
Amanieu: the conclusion is to just close.
### (new change proposal) rust.tf/libs603 *A \`Static\` receiver type for dyn\-trait methods that do not take values*
Amanieu: It's a zero-sized type that can be used as a receiver type. Useful for dyn traits where the dyn trait only becomes a vtable for a pointer. I like the design. I don't like the use of the keyword static. That's replicating the mistake of C of having a ton of meaning of the keyword `static`.
Re: Alice's comment: https://github.com/rust-lang/libs-team/issues/603#issuecomment-3045568983
Amanieu: Would this actually work with the right CoercePointee?
Josh: That is a proposal for building smart pointers outside of the standard library without requiring any special privileges.
Amanieu: This woludn't work here because this is a zero-sized type, not a wrapper type.
Josh: I see, because you'd only need this for things that don't need `Self`.
Amanieu: so that wouldn't work.
The 8472: Can you conjure up a pointer to a zst?
Amanieu: You'd need a pointer of a static.
The 8472: Can we use something similar here? Doesn't smart pointer go through Deref?
Amanieu: It doesn't implemnt deref but it can be implemented as a self type.
Josh: This is basically `Receiver`.
Amanieu: Should this be nominated for lang to see if we can make it work with the existing proposal?
Josh: I do think it's worth bringing it to the attention of the folks working on CoercePointee.
Amanieu: This actually creates a raw pointer that's dangling rather than a zero sized type.
Josh: Why? Are they doing that because they want DeriveCoerce pointee? Ah, yes, they implement Receiver.
Amanieu: That's bad because it still uses an argument in the function call. Why can't this be PhantomData? Oh, PhantomData dyn trait doesn't have a vtable pointer.
Josh: One of the things we've talked about with dyn trait was it'd be nice if you could have ewerything be sort of dyn safe. You could have a version of the trait that doesn't have anything that's not dyn safe and have those methods in a vtable. This is similar: you don't want any of the methods that take a self and only want methods that are associated.
Josh: If so, that sounds similar to that except it's adding another layer. T-types and santiago pastorino who's working on dyn safety and dynasour and similar.
Amanieu: It does have a pointer field, we just never use it. But yes, if we want to support this, it has to be a zero sized type.
Josh: I will write something up as well as fixing that comment.
### (new change proposal) rust.tf/libs587 *ACP: \`try\_exact\_div\` method on \`NonZero\<{integer}\>\`*
(we've just talked about this an hour ago)
### (new change proposal) rust.tf/libs574 *ACP: str::advance\_char*
Amanieu: Some people suggest using the Iterator? An alternative is something like split_off_first. On the other hand this is basically the opposite of what we decided.
Josh: Yes, we just told to people to do things on the slice not the iterator. And now we'd say to do this on the slice rather than the iterator.
The 8472: Our string indexing is byte-based but you want to advance by utf-8 units so this is not trivial. Opposed to general slice indexing.
Josh: I can see the value of doing this with an Iterator. You can get the iterator advance by one and ask for the remaining string. But that seems inconvenient if you're actually trying to advance character by character and you rstate is a string. That's a convenient method for that, but maybe not for other thnigs. Sounds like if we had seal_char_boundery but above rather below.
Amanieu: For both slice iterators and string iterators we have `.as_str` and `as_slice` that returns the rest. Here this is literally just asking for `Iterator::next`.
Josh: So you're saying you could turn it unto `Chars`, call `next` and then ask to return the rest?
Amanieu: Yes.
Josh: I'm not sure the borrow durations work out here. If you call `Chars` you may not be able to mutate the original string anymore. `Chars::as_str` gives you a `&str`.
The 8472: It has the lifetime of the iterator.
Amanieu: But the iterator itself takes an immutable borrow.
Josh: I haven't realised this was only implemented on `&mut &str` and not `&mut &mut str`.
The 8472: Does `&mut str` even does anything?
Amanieu: ascii_uppercase / ascii_lowercase. And mutate bytes. But it doesn't do much.
Josh: I can appreciate you might want to have an iterator instead. On the other hand, it sure is convenient sometimes to ask it to "give me the next" method rather than complicated conversions.
Amanieu: Someone mentioned the unscanny crate (https://crates.io/crates/unscanny). Sems to be similar to what the Rust project is doing?
The 8472: That's one possible answer: use a crate.
Josh: I do think it would be worth noting this could be written in a few lines of code as a wrapper. And at the moment we're not seeing necessary motivation to making it jump straight into the standard library rather than happening in an external crate.
Amanieu: Is our conclusion here: we're not going to accept it. Either use an iterator or a crate.
Josh: I'd say we think this could be done with an external crate and we'd like to see it and adopted before we add it in the standard library.
Amanieu: The counterargument is that this is such a simple thing that no one would publish such a crate.
Josh: I'd like to see at least an example of private methods in codebases taht do this. Maybe it's not something anyone would publish as a standalone crate but surely they'we written this code.
The 8472: Isn't that basically what the unscanny crate is? But it has a lot of other things.
Amanieu: Yes and if you want to write a parser, you basically want to use this.
The 8472: The majority of its uses come from PyO3.
Amanieu: If we do add this, we should call it `.split_off` like we do for slice. I don't feel too strongly either way.
The 8472: Are we going to add a whole bunch of other helpers to the string too? If you look at slice, it didn't stop at `split_off`. And then we have the split / split_off variants which multiply the surface again.
The 8472: What about the ceil_char_boundary? Was it not considered?
Amanieu: That's a different ACP that I think we've accepted.
The 8472: So maybe it was new and wasn't considered?
Amanieu: That's still less nice than the iterator solution. I'm inclined to close this and say you should be using the iterator here.
The 8472: The FCP (for the ceil_char_boundary) finished four days ago.
Josh: It seems like we're reacting to this with a mixture of ambivalence and "maybe there's a better way to do this". Not with "yeah this is a great idea and we should do it". Maybe that's a signal. I'd suggest we respond to something to the effect of: "we didn't have enough support or consensus with adding this to the standard library right now."
### (new change proposal) rust.tf/libs573 *ACP: \[perf\] \`proc\-macro\` \`Ident\` should have method \`as\_str\`*
Amanieu: Is there any reason we don't? We have Display which provides to_tring. We don't have as_str. It's trickier than it seems because of raw identifiers.
Josh: I agree with the comment saying that we could implement `PartialEq` and similar other things between ident and str. They want to call as_str with the primary goal of not making a copy before comparing to the identifier.
Amanieu: They want to match on it.
The 8472: We could return a `Cow` or `Option`. I think we have that on `fmt::Arguments`.
Josh: `Cow` is a sensible thing to use here but it wouldn't solve the `match` problem.
The 8472: You could match on the `Borrowed`. You need as_ref and match on that.
Amanieu: Im' inclined to approve the comparison traits.
Josh: +1 on approving the comparison traits. And say we're not opposed to having as_str, but we need
The 8472: Checked, fmt::Arguments does have a `as_str() -> Option<&str>`
Josh: If we didn't call this as_str and gave it more descriptive name. Then we could not do anything with raw identifiers. The rationalle for the Display impl is if you print it it should roundtrip. If we added e.g. ident_str that made it clear it's not reproducing the whole thing and e.g. explicitly just return `fn` for `fn`, wouldn't that solve the problem? If someone wanted to just compare, they could compare those and know they just have the raw identifier rather than the whole string.
Amanieu: I'd rather just implement this as extender traits like proc_macro_2 does.
Josh: I'd be in favor of us implementing all these traits. I just say in addition we can provide this extra method that returns the name and not require the r-hash.
Amanieu: That's a more complex idea. In the meantime, should we just approve the traits and accept the ACP?
The 8472: Did they ask for the traits?
Amanieu: The traits were proposed in April.
The 8472: Not by the ACP author.
Amanieu: The ACP author has not responded. The specific request was for comparison.
### (new change proposal) rust.tf/libs572 *Add \`Cell::get\` for \`Rc\`\-like shallow\-copying types*
Josh: I get what they're trying to do but baffled by the terminology -- "borrow sign"?
...
Josh: The concept here makes sense. The signature under Alternative seems vaguely sensible. It's weird they don't list the concrete proposal in the Solution sketch. The actual solution is listed under Alternatives. But it seems fine? Gives you a wrapper trait aroung Cell that gives you a method iff the type is valid here.
Amanieu: I proposed an alternative: Cell::get_cloned
```rust
impl Cell<T> {
fn get_cloned(&self) -> T where T: Default + Clone ;
}
```
Amanieu: the `Clone` implementation can recursively access the cell itself.
Josh: I see. If you borrow the type, you potentially leave the Cell in the borrowed state which could cause the Cell to be in a subsequent state where it's Freeze. But if you take the thing out of the cell and put it back when you're done, wouldn't you get some odd result when it's recursive?
Amanieu: It would leave default in place.
The 8472: If you had recursive data structure (e.g. json with ??).
Amanieu: Are we adding new auto traits? Ah, no it's a market trait, not auto trait.
Amanieu: If a type is Freeze, then we can make a copy, copy the value out, clone that.. no that doesn't work, nevermind.
Amanieu: You just need a clone impl that's guaranteed not to recursively access the thing it's cloning.
Amanieu: You can memcpy the Rc, do a clone on that copy and then memfree the copy. I believe our sort implementation exploits that.
Amanieu: Also Freeze got renamed. It's `NoCell`.
Amanieu: The clone implementation must not recursively access. And while we're cloning we need to make sure no one accesses the original value.
The 8472: For Rc you have the refcount. You don't need to Freeze. If you want to make this less unsafe you can implement the ref count.
Amanieu: at that point it's sort of equivalent of taking the thing out of the cell, clone it and put it back.
The 8472: Except you're never in an intermediate state where the thing is out.
Amanieu: The optimizer should handle that.
The 8472: My point is you can just increment/decrement it.
Josh: What's the advantage of doing it via copy out / copy in vs. having a safe list of types we can do this on?
The 8472: User types? You just need a Default, you don't need to be on the whitelist.
Josh: So just trying to make Rc less special? Then I think "can clone from copy" seems reasobable? But if we're going to have an unsafe trait anyway, the trait can access teh internals directly rather than doing a copy?
Josh: Could we have something simal to can_clone from Copy that doesn't use the copy? We can alerady define the unsafe trait to have any pre semantics we want. For Rc/Arc you don't have to make the copy you can just access the internals.
The 8472: You need to increment the ref count I think.
Josh: That's what clone does, right?
The 8472: Right, it doesn't invoke any user code.
Josh: I'm unclear why you'd need to copy out the type rather than just doing `clone(&*self.ptr)`
The 8472: Yeah, that could work.
Josh: The original Cell::get proponal. There's nothing stopping you from implementing that for your own types. We'er not proposing to seal that trait.
The 8472: yeah it does seem more general since it deosn't limit you to `Default` bounds.
Josh: And it doesn't rely on optimization or specialization.
The 8472: For the users, you need to add the trait, you don't get this automatically.
Josh: Yes, but most of the time you'd only hit this if you were implementing your own smart pointer type. In which case you're already implementing a host of other traits.
Josh: It would be the Cell::get trait in the alternative section. Another option would be something similar to CanCloneFromCopy except it'd be CanCloneInPlace and not make a copy.
Josh: Going back to their original proposal they don't find that ideal. They want this to automatically work whether it's from. Copy or not.
Josh: The only specific rationalle for CanCloneFromCopy is that making it that general makes it suitable for implementing Clone for Cell. If we don't make it about Clone and just make it a get method or similar... I'm now reading https://github.com/rust-lang/libs-team/issues/572#issuecomment-2806961051:
> I think you'd have to copy Self and call clone() on the copy otherwise you can get UB
Josh: But this is an unsafe trait so don't implement clone in a naughty way.
Amanieu: Think of it as the cell being in a thread-local storage. And taking the tthing out of the cell while cloning it.
The 8472: Which is why I said earlier that one option is tho increment the ref count for Rc.
Josh: I think it's not an issue for Rc. It's an isuse for other types. If you're trying to generalize this far. It looks like the previous one has.
Josh: If you only implemented this for Rc and Arc and similar, that's fine. Just stop trying ot implement Clone for `Cell<T>` and just implemnt it for this narrow case.
Amanieu: Oh I see the problem. Even if the type implements the Copy trait, its Clone impl may be malicious and access the same `Cell` from the local storage.
Josh: Right.
..
Josh: Two concrete porposals:
Proposal 1. use the relatively simpler `CellGet` trait proposed in the top post and implement it for Rc and Arc and similar.
Proposal 2. have an unsafe trait for things where it's safe to write `Clone::clone(unsafe {&*self.as_ptr()})`. And then implement that and implement the get method for this exact body.
I think either of those is a workable alternative.
The 8472: To get the blanket for T: Copy wed' need specialization.
Josh: That's explicitly not the proposal.
Amanieu: I don't want it to be called `get` method.
Josh: Could be called `get_cloned` or similar.
Josh: If we actually feel there's need for doing this for all sorts of things including `T: Copy` we'd need a new proposal.
Amanieu: I prefer proposal 2 because it's simpler. The marker trait implementations are just empty. I don't think these need a separate body for each and just require a generic implementation.
Josh: We don't have to decide to stabilize both at the same time. We can stabilize get_cloned independent of the stabilization of the unsafe trait.
Amanieu: We wouldn't implement get_cloned on the Cell itselrf. We'd implement it on the CellGet trait.
The 8472: What if someone want to write a macro on a mix of Copy and cloneable types.
Josh: If you want to have something that works on Copy, you need the more complicated thing.
Amanieu: This proposal works https://github.com/rust-lang/libs-team/issues/572#issuecomment-2807026558
Josh: That has an implementation of Rc, Arc, Weak etc. It has to recurse.
Amanieu: We would have to recurse anyway. The CellGet type has the same impls except it manually lists them out.
Josh: I see, you're suggesting we'd want to implement CellGet for more of these things as well?
Amanieu: Yeah.
The 8472: Then the unsafe trait makes more sense because we can cover both copy and self impls.
Josh: If we go down that road, is there any path we can simplify this by using NoCell?
Amanieu: We couldn't. You could make NoCell a dependency of this trait because I believe Copy implies NoCell.
Josh: Has the rename not happened yet?
Josh: Look at the implemntations of Freeze and scroll thorugh the implementers. I don't think we want to manually write even a tenth of these.
Amanieu: No. But it's unsound to implement CanCloneFromCopy for types that are not Freeze.
Josh: Is there something we can implement for things that are Freeze.
Amanieu: No, this is stricter than Freeze -- you must only use things that are guaranteed to not recursively clone.
Josh: Can the compiler help us?
Amanieu: No. If you have a Cell that's in a thread-local storage, a clone impl could reach in and do unsound things.
Josh: So we'd have to implement this for every thing in the standard library (recursions: Option, Result, Vec, slice, etc.)
Amanieu: Vec calls into the global allocator.
The 8472: With the Copy blanket we do get a bunch of types.
Josh: I would want to see the `...` in this proposal expanded to the list of the actual things proposed. If the list is another 5 after that, sure. But if it's 500, maybe not.
Amanieu: We don't have to be exhaustive. I'd be happy with just having it on `Option`, not deal with `Result` or anything.
Josh: Sure, but then I wouldn't want to see a trickle of 200 implementations from CanCloneFromCopy.
Amanieu: Realistically, I don't think there are any other usecases.
Josh: If that's the case let's remove the `...` and ship it.
Amanieu: And we'll need tuples.
Josh: And so it beigns.
TC: Yes it's hard to set out in advance that we'll never implement this trait for other things.
Amanieu: That's why I liked my original get_cloned proposal.
Josh: But then it doesn't work for Rc or Arc and I think that's an important usecase.
Amanieu: I think both options are reasonable.
Josh: I'm not objecting to this. Just that it's unfortunate that we're proposing another thing that will be implemented for "everything".
TC: I'd call it `CloneFromCopy` rather than `CanCloneFromCopy` -- can is already implied (traits already represent capabilities).
Amanieu: CloneFromCopy implies Freeze. This is more.
The 8472: TrustedClone?
TC: It needs a better name than CanCloneFromCopy. That sounds like a misnamed trait.
Josh:
The 8472: Would String be one of the types that could implement this?
Amanieu: No, it allocates.
Amanieu: If you have a `Cell<String>` and have a malicious global allocator you may end up with a dangling pointer.
Josh: To what extend is doing things like that just getting what you asked for by doing stupid things with the global allocator?
TC: Is the comment that programmerjake wrote here correct?
> Safety: can call `Self::clone(&*ManuallyDrop::new(ptr::read(ptr_to_self)))`
TC: If that safety comment is correct, I think `CloneFromCopy` is right. We're saying not just that we literally can clone from the manual copy here, but that it doesn't cause any problems to do so (which is why the trait is unsafe, to represent the user's responsibility to satisfy that).
The 8472: I'm not yet convinced we can't implement this for String.
Josh: If you go look at it first and allocate enough memory to clone afterwards. Then the memory allocator haven't had access to the cell.
Amanieu: You've made a
The 8427: You can get the pointer after teh allocator has been called.
Amanieu: In which case you have a dangling pointer.
Josh: In which case you panic.
Once you've finished allocating, go access the Cell again. If the link is different, panic. Otherwise call CloneInto.
The downside is the same downside as having to copy out in the first place. Seems unlikely the allocator is going to throw all this away rather than just increment the refcount and copy the whole thing.
The 8472: Josh was asking earlier how many types we'd implement this for. String seems like a good example.
Amanieu: Going back to the motivating example. You start with an left and right child that's an option if a ref cell of an Rc. Do we want a trusted Deref which means you can only deref this with a copy of this?
.. nevermind
Josh: I'd be inclined to say this is fine to try as an experiment in nightly. And we reserve the right to get rid of it if it results in shock and horror.
Amanieu: We want programmer jake's latest proposal except without the clone trait.
Josh: I thougt we did want the clone trait.
Amanieu: Which makes it instantly stable. We could make it a separate trait and then turn it into clone during stabilization.
The 8472: Wouldn't this overlap with the existing clone implementation?
Amanieu: It would replace the existing implementation.
Josh: Ok, then exactly what programmer jake suggested. Possibly with the clone supertrait bound that kennytm suggested. And with a revised name and a method instead of clone so we can make it unstable for now.
TC: As a general matter, many of our marker traits should have ended up with a method rather than just being markers, e.g. `size_of` and `Sized`.
Amanieu: In this case there's only really one implementation function. So it's redundant having separate implementations.
Josh: The other issue is this is not a method on a marker trait. It's a method on Cell if T implements the marker trait.
The 8472: Can we still do this with String? Or any other owning type?
Josh: It would only work for the owning type if you're actually cloning the owning type.
Amanieu: I'm writing this up.
(the meeting ended here)
### (new change proposal) rust.tf/libs568 *Implement \`Read\` and \`Write\` traits for \`BorrowedFd\` and \`OwnedFd\`*
### (stalled change proposal) rust.tf/libs131 *Add \`std::fs::rename\_noreplace\`*
### (stalled change proposal) rust.tf/libs347 *Context reactor hook*
### (stalled change proposal) rust.tf/libs483 *\`Box::new\_from\_ref\` for making a \`Box\<T\>\` from a \`&T\` where \`T: CloneToUninit + ?Sized\` (and \`Rc\` and \`Arc\`)*
### (stalled change proposal) rust.tf/libs457 *APC: split\_pattern on slices*
### (stalled change proposal) rust.tf/libs191 *Add LocalWaker support*
### (stalled change proposal) rust.tf/libs459 *ACP: Expose rustc\_lexer::unescape Functionality in the proc\_macro Crate for Standardized Literal Parsing*
### (stalled change proposal) rust.tf/libs262 *Add infallible variant of RangeFrom::next()*
### (stalled change proposal) rust.tf/libs287 *ACP: Add \`FromByteStr\` trait with blanket impl \`FromStr\`*
### (stalled change proposal) rust.tf/libs462 *impl fmt::Write for BufWriter*
### (stalled change proposal) rust.tf/libs348 *std::os::unix::env::{argc, argv}*
_Generated by [fully-automatic-rust-libs-team-triage-meeting-agenda-generator](https://github.com/rust-lang/libs-team/tree/main/tools/agenda-generator)_