# Libs-API Meeting 2025-10-28 ###### tags: `Libs Meetings` `Minutes` **Meeting Link**: https://meet.jit.si/rust-libs-meeting-crxoz2at8hiccp7b3ixf89qgxfymlbwr **Attendees**: Amanieu, Tomas Sedovic, Chris Denton, The 8472, David, Josh ## Agenda - Triage - Anything else? ## Potential breakage needing a revert https://rust-lang.zulipchat.com/#narrow/channel/144729-t-types/topic/Can.20this.20change.20break.20code.20in.201.2E91.3F/with/547514063 The 8472: Wasn't it reverted it? Amanieu: That revert has landed and been backport accepted. Did that fix this? Josh: It sounds like the revert they attempted to apply was not a straight revert and it deleted the entire bound. They were trying to figure out if this is going to break anything. I responded that whether or not it will, we don't want to do a revert that isn't a straight revert. Jack Huey seems to be aligned. Amanieu: Anything we need to do? Josh: Weighing in as T-libs-api saying that we don't want to accept the risk of accepting a revert that's not a straight revert. ## Triage ### FCPs 13 rust-lang/rust T-libs-api FCPs - merge rust.tf/80437 *Tracking Issue for \`box\_into\_inner\`* - (1 checkboxes left) - merge rust.tf/146792 *Implement \`TryFrom\<char\>\` for \`usize\`.* - (3 checkboxes left) - merge rust.tf/106418 *Implement \`PartialOrd\` and \`Ord\` for \`Discriminant\`* - (2 checkboxes left) - merge rust.tf/146560 *Add the \`cpuid\` target feature* - (5 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/146660 *Tracking issue for release notes of #146410: Iterator repeat: no infinite loop for \`last\` and \`count\`* - (0 checkboxes left) - merge rust.tf/140808 *Implement Default for &Option* - (2 checkboxes left) - merge rust.tf/65816 *Tracking issue for \`vec\_into\_raw\_parts\`* - (3 checkboxes left) - merge rust.tf/146724 *Tracking Issue for \`const\_mul\_add\`* - (4 checkboxes left) 1 rust-lang/stdarch T-libs-api FCPs - merge github.com/rust-lang/stdarch/issues/1935 *Make \`cpuid\` safe and update docs* - (4 checkboxes left) [jackh726 (1)](https://rfcbot.rs/fcp/jackh726), [joshtriplett (4)](https://rfcbot.rs/fcp/joshtriplett), [the8472 (8)](https://rfcbot.rs/fcp/the8472), [dtolnay (1)](https://rfcbot.rs/fcp/dtolnay), [tmandry (1)](https://rfcbot.rs/fcp/tmandry), [Amanieu (4)](https://rfcbot.rs/fcp/Amanieu), [traviscross (1)](https://rfcbot.rs/fcp/traviscross), [nikomatsakis (3)](https://rfcbot.rs/fcp/nikomatsakis), [scottmcm (4)](https://rfcbot.rs/fcp/scottmcm), [BurntSushi (9)](https://rfcbot.rs/fcp/BurntSushi) ### (nominated) rust.tf/79995 *Tracking Issue for maybe\_uninit\_write\_slice* Amanieu: There is a concern that seems to have been resolved. Some people are bikeshedding the name. `write_copied`, `write_cloned`, `write_slice_copied`, ... The 8472: The functions on `MaybeUninit` are still unstable so we can rename them and not have consistency issues. https://doc.rust-lang.org/nightly/std/primitive.slice.html#impl-%5BMaybeUninit%3CT%3E%5D Amanieu: Are we happy with the name? The 8472: What other alternatives are people proposing? https://github.com/rust-lang/rust/issues/79995#issuecomment-3446956283 > Either > write_slice_copied > write_slice_cloned > Or, seeing that the "slice" is somewhat redundant (as there's no conflict with the existing write now), > write_copied > write_cloned David: slice has a method called `clone_from_slice`. That's a bit of a clash with (write_)clone_of_slice. Amanieu: I don't have strong thoughts. David: I think the existing names are good. Josh: The existing names being: `write_copy_of_slice` / `write_clone_of_slice`? Amanieu: Yes. Josh: Those sound good. Josh: I'll write a reply. The 8472: Regarding the method name, I have a slight preference for the alternatives because they're shorter. Amanieu: I don't feel too strong about this. David: They're long because they're four words, but the words carry meaning. Josh: I don't think it makes it clearer to say `write_slice_copy/clone`. The copy/clone distinction seems relevant. It doesn't feel excessively verbose. The 8472: I guess they aren't used that frequently. Ok. ### (nominated) rust.tf/145457 *Experiment: Add \`where T: Default\` to \`Default for \[T; 0\]\` impl.* Amanieu: We've discussed this before. Chris: WaffleLapkin has done the analysis with breakage. I tihnk we could break this if we wanted. https://github.com/rust-lang/rust/pull/145457#issuecomment-3456697758 Amanieu: In one case this reports a breaking change to a public API. The 8472: Of a user crate? But if they've accepted the breaking change. The 8472: Are they sending PRs before we've agreed we want that? Amanieu: I was always in favour of not hacking the type system. Josh: On the one hand I do think we should have a `Default` for empty arrays that doesn't require you to implement `Default`. But if we can make this shift without making a substantial amount of pain, I'm inclined to try to make it. Right now, this is getting in our way of providing a default impl for abitrarily big arrays. If we decided to have a Default impl arbitrarily-long arrays, that's better than not having Amanieu: Absolutely. The current situation is terrible. The question is whether we're keeping the type system hack for an array length of zero. Josh: Long-term, I'd hope that rather than having a special type system hack we'd instead end up with general type system improvements of "[T; N] if N > 0 then Default". Josh: If people are willing to deal with the breakage over this, Amanieu: They've accepted that it's in their public API but no-one is using that API. David: There was a comment from lcnr that supporting generic-sized array arguments is not a huge issue. - https://github.com/rust-lang/rust/issues/61415#issuecomment-3291334606 Josh: If they feel they can do this in the near future, I'm all for putting this off and not trying to make this change. Because we can support this going forward that's better-integrated with the type system. If it's a few months off, let's not go through the breakage. previous discussion: https://github.com/rust-lang/rust/issues/61415#issuecomment-3299319159 David: If you say "switch to something better", Josh: If there's something capable of dealing with `if N > 0`, that's great. David: My understanding was that as of just a few weeks ago this seems possible. Amanieu: I think we should just get Waffle and lcnr in the same room. Amanieu: We get lcnr reply to Waffle and see what comes out of it. The 8472: Sounds good. Chris: Theer's also a zulip thread where Boxy responded: https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/topic/removing.20special.20.60.5BT.3B.200.5D.3A.20Default.60.20impl/near/547253217 Amanieu: let's defer this until we get a reply and move on. ### (nominated) rust.tf/146553 *add trait impls to proc\_macro::Ident* Amanieu: Seems to have been discussed last week? https://github.com/rust-lang/rust/pull/146553#issuecomment-3427366374 David: I missed the last week, but I don't think the `PartialEq` impl outcome the team settled on is correct. Josh: The last paragraph of your comment sounds exactly what we were thinking about last week. David: We're talking about the proc-macro library. Nobody's ever going to write a proc macro who's bottleneck is going to be string performance of fancy intern type. Josh: At least in the compiler ??. Are people likely to have ident types on their own that are potentially interned in this fashion and don't want them to be David: Proc-macro-ident doesn't expose its integer quantity so how else would you compare it other than checking its string data? Josh: I see, Ident itself doesn't have an `AsRef<str>`. I was imagining a newtype wrapeer around Ident. But the only way they can implement `AsRef<str>` would be if they had a cached string they ?? David: I think the downside is really small and the benefit is worthwhile. Josh: The tradeoff is: if we didn't have `PartialEq` with `AsRef<str>` then we'd have `PartialEq` with the types in the standard library where it makes sense (`Box<str>`, etc.). So it doesn't seem it would be that much of a trade-off. The only difference would be you wouldn't get it for free with your own downstream string type. David: I'm happy with either way. Josh: If it had any limitation in functionality, I'd say it's not worth it. But given we can easily implement this via a macro for the half-dozen types we need. The 8472: Wouldn such a PartialEq had affinity issues with ??. If they had different spans, would they compare equally? Josh: I'm not aware if Ident takes that into account. But that would apply to either implementation here. The 8472: As a general PartialEq, we have some transitivity rules here. Josh: The current proposed impl would do that too in the same situation. The 8472: Yeah, so maybe we shouldn't do that. Josh: Effectively, only allow you to do `.to_string().equal()`? The 8472: I have no idea about proc macro David: For ident comparison the span is irrelevant. The 8472: But the new constructor says something about hygiene that the span makes a difference there? David: There are two ways proc-macro is used: parsing an input and writing output. For parsing, macro input containing a struct with fields, you want to commpare ident to a string. It doesn't even come up to a question tehre. Josh: There are things where it would make sense to do a hygiene-based macro identifier, but that's not relevant here. It wouldn't be span-based but seeing whether there's an underlying object The 8472: I think if there's one usecase where the difference is semantically meaningful that it would violate transitivity. So I should not make this change. Josh: There is a link from 2018: https://github.com/rust-lang/rust/issues/51074 Josh: At the time it was rejected because it wasn't clear whether we care about spans. We should have a clearer picture now and be consistent here. David: Josh is correct, there are ways to add PartialEq that would never violate transitivity by always ignoring Spans. The 8472: That is in conflict with the constructor that says spans have semantic meanings. Josh: That's about how they're resolved not compared. The 8472: If they're resolved differnetly they should not be equal. Josh: The right comparison would not be "are the spans equal?". The correct comparison was "if you want to do hygiene, look up the object in the span and look at the underlying object". And taht's not what's happening in the macro. The way the macro would work is you emit the idents with the accompanying spans and the compiler will look at them. But the macro is not resolving them. The 8472: But you would still have effectively two different idents that do resolve differently. Josh: Two idents with the same string and same span will always be the same. Two idents with the same string or different spans may or may not be the same ident based on the resolver which doesn't have. The 8472: It's PartialEq so we could return None if we'er not sure. Josh: That would not be useful. There's no value in providing a PartialEq that forces identical ??. It would be better to add a `.to_string` method and comparing those. The 8742: That would be useful. David: You could have two idents that have the same span, hygiene, location and still compare to different things. There's no way to know whether they're the same. ``` let x = Ident::new("X", Span::call_site()); quote! { { const X: u8 = 1; print($x); } { const X: u8 = 2; print($x); } } ``` Josh: so this is just a problem of `const` not following scoping the way you'd expect? If I declare a local `let` that would not be the same problem. David: Even for a local you would have the same problem. Even without shadowing you'd have the same issue. David: Broadly my point is that Span cannot ever be useful for comparison. So I'm in favour of writing a comparison that compares the string values. In contrast there's a lots of proc macro code that compares strings to idents. That's a 100% usecase that I want to support better. The 8472: You cannot distinguish either whether that's from a micro context. If you have two incoming tokens form differnt spans, how do you pick the right one? The 8472: How can you have spans that affect resolution but at the same time they're irrelevant for comparison? Josh: I think the issue is there's nothing you can usefully do with a span at macro invocation that would give you information that would help you with comparison. The only two options is: you compare strings or you can't do anything here. The 8472: Okay. Since you have more proc macro experience I'll defer to your experties. Josh: Might be worth adding a paragraph or two at the documentation of proc macro Ident. To make people aware of this. We should optimise for the usable common usecase here, but we should also tell people that these impls are pointedly ignoring spans and that's ok. Josh: IF we're adding these, we should presumably also add an Equal for Ident. David: I agree and I'm in favour of that. Josh: If we ever get to the point of having a mechanism that's smarter than string comparison, it will probably use a different mechanism. I don't think it would ever be something we'd do on a comparison for Idents. Amanieu: Seems we've reached a consensus. Josh: Sounds like the consensus is: Add the impls, add more documentation. Amanieu: Yeah. David: I'll do this. David: We talked about PartialEq but not Hash. It seems we can add both. Amanieu: We'd be adding Eq for Hash. But anything that has Eq should have Hash. Josh: If you were throwing idents into a HashMap/HashSet, you'd be throwing the Span for all but the first but again it seems fine. ### (nominated) rust.tf/147068 `P-lang-drag-1` *Move CoercePointee to core::ops* Josh: This is pretty much been delegated from Lang saying: "figure out where these things should go and make a consistent story". There are traits in `ops` that should go to `marker`, `ops`, other places. We should have a consistency story. Amanieu: I don't have a strong opinion on this. I was happy to delegate itto Tyler who seems to have an opinion. I don't think it really matters as long as all the traits are there. Josh: We should be consistent for things going forward. This would be setting a pattern for where we'd put things. The 8472: And in the future more stuff would accumulate. Josh: Exactly. Amanieu: I'm happy to support anyone who has a vague plan. Josh: There are two consistent strategies here: `ops` is for overloaded operators and ??. For everyting else we put it elsewhere. Josh: The other strategy is `ops` is for any other trait that's specific to the language regardless of theyr name. And then we'd have to update documentation and figure out what goes into `marker`. Josh: `CoercePointee` doesn't have a specific operation, it's an empty trait. In `markers` traits have an empty value. I would advocate "this is an empty trait, it goes in `marker`". The 8472: Is it even a trait? Isn't it a macro? Amanieu: `CoercePointe` is only a macro, not a trait. Josh: I see, we didn't even end up export this as a trait. Amanieu: There is no `CoercePointee` trait, just a bunch of traits the derive macro implements. The 8472: Usually traits form families -- there is a trait with an associated type, that associated type also needs to implement something, that may be a marker trait etc. Josh: Sure, if something is very closely related to ranges, maybe it belongs to `range`. But in this case you could argue it might go into `std::pointer` but people pushed back arguing it isn't quite related to that. Amanieu: Either `marker` or `ops` makes sense. Josh: I'd advocate for `marker` and in practice it won't matter much because it'll probably end up in the prelude and people will just derive it. Amanieu: If you write that, I'll support you. ### (new change proposal) rust.tf/libs684 *\[ACP\] Implement \`Into\<Option\<U\>\> for Option\<T\> where T: Into\<U\>\`* Amanieu: Just from the title: it's not possible because we have a blanket impl for `Into` already. The 8472: But we can still implement `From`. Amanieu: Yes. Amanieu: Sure if you can get it to work, but it's probably going to fail even building the standard library or compiler due to inference failure. Josh: Seconding: "if you can actually make it work, sure" Amanieu: Would this conflict with `From<T> for Option<T>`? Josh: Probably? You'd have to test it. Amanieu: Is our reply that yes if you can make it but it'll probably break the universe? Josh: Yes. ### (new change proposal) rust.tf/libs683 *Expose \`FloatErrorKind\` from private \`core::num::dec2flt\` to public \`core::num::FloatErrorKind\`* Amanieu: `ParseIntError` exposes a `kind` but `ParseFloatError` doesn't Josh: They want to expose the different reasons why the parsing failed. That seems fine if it's not exhaustive. Amanieu: Unclear why this wasn't done for float. The 8472: Isn't it currently just empty and invalid? Much less detail than the int error? Amanieu: Yes. That's not very helpful. The 8472: Exactly. They don't say why they need the `kind` in their motivation. It seems incomplete. Do they need some kind of error message? Recovery? Amanieu: Yeah, I don't think it's useful as is. I'd say "repropose this with saying which error kinds you want to handle"? The 8472: Even more basic: the motivation is incomplete. It doesn't explain how is the personal project handling the errors. Josh: Empty is one of the cases does sound like something that I could imagine being empty. E.g. "you didn't fill in the optional field" or similar. But it would be helpful to have more information on whether they'd be able to do something more valuable here. The 8472: If you just want to print the error, you can just display the error without accessing the underlying kind. And if it is just about error messages then we could improve the messages without exposing kind. The 8472: I can reply. ### (new change proposal) rust.tf/libs682 *Add \`std::ops::range::Bound::map\_all\`* Amanieu: It's a pretty terrible API that takes takes two closures for all the cases. And in that case you're pretty much writing the match cases. That's what it the `match` keyword is for. It's shorter if all your matches all fit in a single line. As soon as that's not the case it's no longer a benefit. Josh: I also think it seems very specialised in readability. You have to look up the cases it covers and in which order it's doing. It's optimising for writability (or readability for someone who's very familiar with bounds). Amanieu: I can reject this one. ### (new change proposal) rust.tf/libs679 *ACP: Freezable Mutex Guards* Amanieu: I believe this was discussed last week? Josh: We did. There's been a bunch of discussion since the comment. Amanieu: I'm sympathetic to this. I specifically added this to parking_lot witout the complexity of poisoning. Josh: The only complaint someone has here is: if the mutex is poisoned, if you're doing a convar that takes a mutable reference to the MutexGuard, you have to propagate the poison out. I don't think that's a problem, you just have to do that. I think it makes sense to add the `&mut` operation on the condvar. Amanieu: There are other usecases beyond condvar. I want to have a general usecase. The 8472: The author's motivation was for condvar. I think the condvar idea could just call `condvar.wait()` and then drop the guard. It might not be clear to someone not deeply familiar with lock primitives. Josh: I think if you're not aware that dropping MutexGuard you'll have a hard time with anything we'll give you here. We already provide these APIs and they are documented as such. Josh: What I'm suggesting is that we can have a wait_ref that takes a `&mut`. Josh: Given we're talking about having a whole new non-poisoning set of APIs, we might just want to change the API to take a mutable reference. Amanieu: Yes. But the usecase in the ACP was notify not wait. Which is why I was suggesting the more general API for temporarily releasing the mutex. Josh: Are you suggesting something closer to the API they recommended? Or something that just returns the thing? Amanieu: look at: https://docs.rs/lock_api/latest/lock_api/struct.MutexGuard.html#method.unlocked Amanieu: It's what they're suggesting witohut the heal closure. Because it's non-posioned. Josh: I agree the general API is gnarly for the poisoned case and pretty straightforward for the non-poisoned case. Amanieu: Do we have nonpoison mutexes? Josh: Unstably. Amanieu: We need to fix the API to take the mutable reference. Josh: Agreed. The 8472: The ACP author says the nonpoison variant would not be useful for them. Amanieu: But that's because it's not stable. The 8472: No, in the second-last comment at the bottom: https://github.com/rust-lang/libs-team/issues/679#issuecomment-3444660312 Amanieu: The idea of non-poisoning locks is we can still provide poisoning as a wrapper around mutable data. If you want a poisoned mutex, wrap the T around a poisoned T. That's more general to unwinding. The 8472: But we don't have yet. Josh: true, but that's part of a larger tihng we should try to implement. Josh: I think we should say that for the non poisoning case we should provide the unlock method like in parking_lot, and we should add the `&mut` reference for unlock. And we should add ??. The 8472: I suspect these changes won't help the author. Amanieu: They don't care about `wait` they want `notify`. And then sleep without holding the `CondVar`. Josh: Is there ever any scenario where someone's going to write a `heal` closure other than poison panic. Amanieu: Or ignore panic. Josh: Should we provide this version of the API that's just documented as panicking on poison. Amanieu: We already have a guard. You already handle poisoning. What if the closure panics? If it panics, you can't poison your guard. Josh: The other scenario is: you unlock the mutex, the mutex gets poisoned when you try to lock it, you notice it's poisoned. Amanieu: When your closure returns, there's a drop impl that will ?? the mutex guard. That will fail if it's poisoned. The 8472: You can also have a drop guard but you could do a pre-check outside the drop. Amanieu: It's the same as mutex_with. It's a nice API if you don't have to deal with poisoning. But with poisoning it's such a pain that it's not worth to have it. And I think it's the same here. Josh: So your argument is it's so unusable with poison that we shouldn't even bother adding something. Amanieu: Yes. The 8472: It sounds like the author is handling poison somehow and actually prefers it. Amanieu: I don't think anyone actually relies on poisoning. They're under the impression that poisoning hepls with panic safety but it's not true at all. Amanieu: I feel the proper way forward is full decoupling from mutexes. If you want to opt-into poisoning, you can do it but it's completely dufferent from mutex. Josh: So we'd have a public `Poison<T>` and poisoned mutexes are just unpoisoned mutexes wrapped around `Poison` and then stop adding new poison API to mutexes. Amanieu: Is everyone happy with this approach? The 8472: I'd have to see the `Poison` API surface. Amanieu: You would have to `.unwrap()` it to get into the thing inside. I don't think we'd want to implemnt `Deref`. Josh: The proposal here is we respond this would be sufficiently awkward to work with poisoned mutexes that we'd only support this for non-poisoned mutexes? Amanieu: Yes. Josh: No fundamental issue with that. Amanieu: I'll write this one up. ### (new change proposal) rust.tf/libs676 *\`only\` on iterators* Amanieu: Previously, we said we'd be happy with `collect_array`. There was some pushback saying that `collect_array` is nice but it's still better to have `exactly_one` or `single` in addition to `collect_array`. I'd prefer to just have `collect_array`. Josh: So `collect_array` returns an Option of the array. And requires a match on length. The 8472: But if you have an Option, you need to write let to handle Josh: There would be an annoyance to write `Some([item])` rather than `Some(item)`. Josh: I think collect_array is great and we should have it. But there's a degree of self-documentingnsess. If I'm writing `.collect_array`, then match it and check if it's a `Some([item])` that's less readable than asking to have a single item. The 8472: If you want to be explicit, you can put the `1` in there. Amanieu: itertools takes an item and returns a result. Josh: Ah, itertools takes `collect_array::<1>()` to take 1 item. That's slightly less horrible. Amanieu: Itertools has `exactly_one` and `at_most_one`. Josh: Interesting that `exactly_one` returns an "ExactlyOneError" rather than just returning `None`. Josh: Looks like it only exists so it can put back the element if you had a problem. Josh: I feel like I'd want to add these methods. It seems clearer to me. Amanieu: I slightly prefer returning the `Option` but I see the error being useful. Josh: I think the main argument is that you have the ability to get the iterator back. Amanieu: It breaks `.unwrap` if the item doesn't implement `Debug`. `ExactlyOneError` has a conditional Debug. Josh: If you unwrap, it will print the entire contenst of the iterator? Amanieu: Yes. The 8472: But for the Display iterator it only prints either zero or two elements. Josh: We could debate that if we add it to the standard library. Josh: I'm all for us copying to from itertools. Amanieu: I'm inclined to just making it an option. Josh: I wouldn't object. Though in that particular case we might consider calling it something other than `exactly_one`. If we're not supporting the same API it will be more annoying breakage. Josh: Have we finished subtrait item shadowing? Amanieu: They have not. https://github.com/rust-lang/rust/issues/89151 Josh: Let's go with `exactly_one` and `collect_array`. If you want `at_most_one` we will come up with the right API. Josh: If we go the `ExactlyOneError` route I'd want it to unconditionally implement Debug. It shouldn't try to print the elements that it got out. Josh: If you have an error case that holds onto the iterator, the iterator may hold on some data with an lifetime it can't outlive and you wouldn't be able to question mark it. Amanieu: Let's just make it Option, then. The 8472: From an implementation perspective, would it make sense to look at the size hint before working on the iterator? Amanieu: It seems it's just cheaper to just do `.next`. The 8472: It depends on how expensive your `map` operation is. Amanieu: I think we should optimise for the common case where this is successful because there's no other element. Josh: `size_hint` is plastered with warnings about how it's not correct. The 8472: The warnings are there for safety, not correctness. ### (new change proposal) rust.tf/libs674 *Vec::recycle* Tomas: Lots of comments since we last looked: https://github.com/rust-lang/libs-team/issues/674#issuecomment-3402960814 The 8472: There was some discussion of maybe not supporting generic T over U. But that suffers from the problem that we don't have a way to Amanieu: Are we just trying to transmute the lifetimes? For recycle we only care about a layout. The 8472: There was a blog post to recycle a new `Vec` in a loop with a new lifetime every iteration of the loop. Josh: I'm not entirely certain that's writable. Josh: Is this actually a safe transmute? Amanieu: It's a transmute of `MaybeUninit<T>` to `MaybeUninit<U>`. Josh: We're trying to avoid turning `T` into `U`. Amanieu: Recycle cleares the vector, only the size is preserved. Josh: I think this is probably okay as is. Chris: The objection is about semver hazard. Amanieu: But that's the same with transmute. The 8472: But that one is unsafe. Amanieu: Because of the transmute bounds, this can't depend on any user types. It can only constraint your own types. Josh: Alternative possibility: we could say if the layout is the same, recycle this. IF the layout isn't the same, allocate a new one. Amanieu: That changse it from a semver hazard to a hidden performance footgun. The 8472: matthieu-m mentioned the option 3 weeks ago. Josh: And Scottmcm mentioned we could add a separate `recycle_or_new` that would always work. The 8472; I was thinking about "same type except lifetimes" and I did something like that ina previous PR. It had a struct with two generic arguments (A and B) and a marker impl that's only implemented if A and B is the same T. Josh: I don't think we should go that. You're going down the path of reimplementing the safe transmute. Checking this is safe via the type system route. Josh: I'm happy with the current method. Sizeof and alignof have always been potential semver hazards. This doesn't change that, it only gives you one more thing that potentially has that. The 8472: Are we talking about compile time? Josh: Compile-time. The 8472: That gives you hard to opt-out compile errors. Amanieu: I'm inclined to ad this as unstable with the safe transmute bound. And see how it gets used. The 8472: That's good for dogfooding. Less good for users because it will be a while. Amanieu: We could stabilize this before safe transmute just like we did for ??. The 8472: I guess we could remove the bound later and replace with a const assert that would allow more uses which would just get a post-mono error. The 8472: I think the safe transmute approach is at least a good experiment. If it turns out to be a problem, we can still reconsider. Chris: Sounds good to me. Josh: No objection to trying as unstable. It just seems harder to work with. The 8472: We did ask in a thread and they planned to make some progress by the end of the year. Amanieu: Accept with safe transmute as experiment and have people try it out and see. Josh: I'd say "if safe transmute doesn't make the expected progress in expected timeline we might change the approach to not rely on it and do the originally-proposed compile-time panic instead". ### (new change proposal) rust.tf/libs661 *ACP: More float constants* Josh: This is asking for sqrt of 5, its reciprocal and a ln(3). The 8472: There is an FCP going. Is this different? Ah yes, the FCP is for frac_1_sqrt_3 and this one is for frac_1_sqrt_5. The 8472: On the tracking issue, someone asked for `sqrt(5)` and it got a bunch of thumbs up. Amanieu: I don't feel too strongly about this but I'm happy to accept. I have no objections. Josh: None either. It seems perfectly fine. We have enough constants that adding a few more doesn't cause issues. Chris: At what point do we stop? Josh: The argument of this being used in several common approximations makes sense. They don'ttake up space if you don't use them. The 8472: They make rustdoc bigger. Josh: With the amount we have already, that ship has sailed. Josh: Someone mentioned we might not need ln(3) after all. Let's just add the square roots of 5. The 8472: Should we create a new tracking issue or add it to the other ones? The other one is already in FCP. Josh: Yeah I'd expect so (creating a new tracking issue). ### (new change proposal) rust.tf/libs660 *ACP: std::rc::RcUninit for deferred initialization and await\-safe cyclic construction* Amanieu: This seems like a special case of in-place initialization. Josh: It does. And there's progress on in-place initialization. MaybeUninit already handles some aspect for this. Maybe it makes more sense for the author to work with the in-place init people. Amanieu: It seems they want a UniqueRc that allows writing to MaybeUninit. Josh: You can get a Weak from UniqueRc so you should be able to do that. Josh: If you have a `UniqueRc<T>` you can get a `Weak<T>` and you can initialize that. But if you have a `UniqueRc<MaybeUninit<T>>` you can't get a `Weak<T>`. Amanieu: If you don't initialize it, it's unsound. Josh: I'm trying to see if there's a way to do this. Amanieu: I don't think there is. Josh: You can use unsafe, of course. But that's unsafe. Josh: I'm seeing their usecase now. Just trying to figure out if there's a way of meeting that usecase without a dedicated type. Josh: The API they're describing is `Rc<Uninit<T>>`. The main benefit of their idea is you're not allowed to get to something you can reference until it's been initialised. And `Rc<Unitit<T>>` doesn't prevent that. Amanieu: Yes. The 8472: What is the issue with `UniqueRc`? Josh: If you have a `UniqueRc<MaybeUninit<T>>` you get a `Weak<MaybeUninit<T>>` and what they want is a `Weak<T>`. The 8472: Should we bring that to the in-place init discussion? Josh: There is a way that we could do this stragihtformardly. Add a method you pass a closure to that initializes the type and that gives you a `Weak<T>`. The 8472: But that's less flexible. Amanieu: It's definitely interesting. But I don't like introducing a new type for this. Josh: I don't either, but I don't see how to get there without. Josh: They mentioned wanting to do this for something like a graph. If you're doing that, where do you put all the `Rc<Uninit<T>>`'s while you're putting the graph together. Presumably you stuff them in an array or something that's local. And then you reference them to the node in a graph. Josh: Proposal: we agree new_cyclic doesn't suffice. And we agree `UniqeRC<MaybeUninit<T>>` doesn't quite suffice. They mentioned `UniqueRc` plus setters. Amanieu: For that you'd need an unsafe code. Josh: Is there a way to track that this is what we were doing and make it so that you can make a safe call to initialize all the `Weak`s once the base has been initialized. ANd you can, but there would be the overhead of tracking the initialization. Amanieu: I don't think we can do better than what was proposed. Josh: I don't think so either. Josh: Presumably `RcUninit` is just a wrapper over `UniqueRc<MaybeUninit<T>>` that Josh: If we had an unsafe function that would allow you to go to `Weak<T>` from `Weak<MaybeUninit<T>>` you could do this. This will then becomes a wrapper over that, providing a safe interface. Amanieu: Yeah. I'm inclined to accept because I don't see another option. Amanieu: The `weak` method should be called `downgrade` to match the Rc method. And instead of `init`, the method should be called `write`. Josh: Agreed. It should mirror the API of `UniqueRc`. The 8472: Should we bring that up in the lang discussions about in-place init? To make sure there's no way to make this better using those? Amanieu: Makes sense. Josh: I'll add that note. ### (new change proposal) rust.tf/libs659 *Generalize ExactSizeIterator to QuantifiedIterator* The 8472: Marked as blocked on evolving trait hierarchies. We can skip it. Josh: Not clear if we want to do this even if we *had* that feature, but can defer for now. ### (new change proposal) rust.tf/libs656 *implement Default for more iterators* The 8472: programmerjake proposes more default impls on iterators. Josh: Presumably to allow `derive(Default)`. Josh: For any obvious value that is empty. The 8472: We could ask which ones are actually need and implement those. Josh: Sure, but given there's a specific principle proposed and we agree with the principle. The 8472: The idea that it *can* be empty doesn't necessarily mean that empty is the right default. E.g. for OptionIterator if `T: Default` it might make sense to default to `Some(::default())` Josh: The concrete usecase is they want to do this for `Chars`. Generally: "I have a wrapper around this that I want to derive Default on". The 8472: They could also handroll the Default implementation. Josh: Sure, it's mostly trivial to do this by hand. It means you don't get to use `derive(Default)`. The 8472: It doesn't need std default, it's just nice to have. Josh: You need to work around the fact that std doesn't have them. The 8472: Some of them seem questionable. How are you going to implement `Default` for `Map`? Josh: Are we arguing we shouldn't implement the Default iterator where it makes sense or The 8472: For some of them I'd agree but I disagree about the overall list of what should implement Default. Josh: I agree this is not the right list. But we should come up with the rigth list and implement Default for them. Amanieu: Generally, most of the ones on slice seem okay to add (for empty slices). Josh: Agreed. Most of the ones on str likewise. Amanieu: Yes as long as they don't take a closuse. Matches and Split. The 8472: The Match indicises take a `P: Pattern`. Josh: Why don't we skim the list, see ones we think should be filtered out (taking a pattern, taking a closure), and give us a new list. The 8472: The other one is the OptionIter. Josh: The default of `Option` is `None`. So the default of OptionIter should also implement None. The 8472: But the implementation isn't as obvious. Josh: That same argument would apply to `Option` as well. The 8472: default for Cloned. If the inner iterator has a Default is non-empty, than the Cloned iterator is also non-copy. Josh: The argument here is implement only for iterators, where the iterator is constructed from types where the default value is empty. Amanieu: The default implementation for a generic impl should never call the default implementation for a generic type. The 8472: What about `Chain`. It's internally implemented by two options. It creates the default for both arms. Josh: That sounds right. The 8472: If our rule is that they should be empty, then we'd just create an iterator of empty chain. Josh: I see, so we could have had the default for Chain be `None, None`. The 8472: I guess we can change the rule and say: whenever we can, we create the empty iterator, but there are types where we don't quite match the rule. Josh: I can write it up. We've discussed this, there are some cases we had concerns about. Please adjust and we'll discuss later. The 8472: Sure. Amanieu: Yes, that seems reasonable for now. ### (stalled change proposal) rust.tf/libs360 *make FromResidual #\[fundamental\]* ### (stalled change proposal) rust.tf/libs395 *\`impl core::str::Pattern for \[&str; N\]\`* ### (stalled change proposal) rust.tf/libs501 *ACP: Add floating point representation conversions* ### (stalled change proposal) rust.tf/libs287 *ACP: Add \`FromByteStr\` trait with blanket impl \`FromStr\`* ### (stalled change proposal) rust.tf/libs195 *OS\-level \`thread::Builder\` priority and affinity extensions* ### (stalled change proposal) rust.tf/libs133 *Add fmt::Write to io::Write adapter* ### (stalled change proposal) rust.tf/libs295 *Create iterator function in std libs: split\_item\_mut()* ### (stalled change proposal) rust.tf/libs336 *Add \`or\_try\_\*\` variants for HashMap and BTreeMap Entry APIs* ### (stalled change proposal) rust.tf/libs462 *impl fmt::Write for BufWriter* ### (stalled change proposal) rust.tf/libs304 *ACP: Avoid the common mistake of \`for x in 0u8..\`* _Generated by [fully-automatic-rust-libs-team-triage-meeting-agenda-generator](https://github.com/rust-lang/libs-team/tree/main/tools/agenda-generator)_