--- date: 2024-04-16 url: https://hackmd.io/yAMv6TOdTk6YZXZDJGonyg --- # Libs-API Meeting 2024-04-16 ###### tags: `Libs Meetings` `Minutes` **Meeting Link**: https://meet.jit.si/rust-libs-meeting-crxoz2at8hiccp7b3ixf89qgxfymlbwr **Attendees**: Amanieu, Mara, David, Josh, The 8472, Chris Denton, TC, Eric Holk ## Agenda - Triage - Anything else? ## Triage ### FCPs 1 rust-lang/rfcs T-libs-api FCPs - merge rust.tf/rfc3550 *RFC: New range types for Edition 2024* - (4 checkboxes left) 20 rust-lang/rust T-libs-api FCPs - merge rust.tf/80437 *Tracking Issue for \`box\_into\_inner\`* - (1 checkboxes left) - merge rust.tf/82901 *Tracking Issue for \`Option::get\_or\_insert\_default\`* - (2 checkboxes left) - merge rust.tf/83871 *Tracking Issue for CharIndices::offset function* - (3 checkboxes left) - merge rust.tf/98934 *Add \`Option::take\_if\`* - (3 checkboxes left) - merge rust.tf/102012 *Tracking Issue for \`const\_waker\`* - (3 checkboxes left) - merge rust.tf/106943 *Implement DoubleEnded and ExactSize for Take\<Repeat\> and Take\<RepeatWith\>* - (3 checkboxes left) - merge rust.tf/113744 *Tracking Issue for \`IpvNAddr::{BITS, to\_bits, from\_bits}\` (\`ip\_bits\`)* - (3 checkboxes left) - merge rust.tf/62726 *Tracking issue for io\_slice\_advance* - (3 checkboxes left) - merge rust.tf/109402 *Implement owned ops for \`HashSet\` and \`BTreeSet\`* - (3 checkboxes left) - merge rust.tf/116113 * Generalize \`{Rc,Arc}::make\_mut()\` to unsized types.* - (4 checkboxes left) - merge rust.tf/115974 *Split core's PanicInfo and std's PanicInfo* - (2 checkboxes left) - merge rust.tf/117468 *Stabilize Wasm relaxed SIMD* - (4 checkboxes left) - merge rust.tf/101196 *Tracking Issue for \`Ready::into\_inner()\`* - (1 checkboxes left) - merge rust.tf/119131 *Tracking Issue for \`hint::assert\_unchecked\`* - (2 checkboxes left) - merge rust.tf/106418 *Implement \`PartialOrd\` and \`Ord\` for \`Discriminant\`* - (2 checkboxes left) - close rust.tf/56167 *Tracking issue for HashMap::raw\_entry* - (3 checkboxes left) - merge rust.tf/113219 *Tracking Issue for \`const\_cstr\_from\_ptr\`* - (5 checkboxes left) - merge rust.tf/123168 *Add \`size\_of\` and \`size\_of\_val\` and \`align\_of\` and \`align\_of\_val\` to the prelude* - (2 checkboxes left) - merge rust.tf/55132 *Tracking issue for thread::Builder::spawn\_unchecked* - (4 checkboxes left) - merge rust.tf/98485 *Tracking Issue for \`AtomicBool::fetch\_not\`* - (4 checkboxes left) [Amanieu (7)](https://rfcbot.rs/fcp/Amanieu), [BurntSushi (12)](https://rfcbot.rs/fcp/BurntSushi), [m-ou-se (14)](https://rfcbot.rs/fcp/m-ou-se), [dtolnay (1)](https://rfcbot.rs/fcp/dtolnay), [joshtriplett (15)](https://rfcbot.rs/fcp/joshtriplett) ### (nominated) rust.tf/rfc3550 *RFC: New range types for Edition 2024* Mara: See https://github.com/rust-lang/rfcs/pull/3550#issuecomment-2059068023 Mara: Effectively, accept the 'ACP' for adding new range types as unstable. Amanieu: Sounds good. David: Sounds good to me as well. ### rust.tf/123759 Tracking Issue for Rust 2024: `Box<[T]>` (and `Box<[T; N]>`): IntoIter TC: This is looking for an owner for Edition 2024. Mara: This is the same as what we did in 2021 for into_iter on arrays. But now in a box. Amanieu: How about Arc and others? The 8472: IntoIter is only for owned types. ACP: https://github.com/rust-lang/libs-team/issues/263 Draft PR: https://github.com/rust-lang/rust/pull/116607 Mara: How likely is it that this will pass stabliization FCP? Seems very likely. Owner: clarfonthey, 330161-Clar-Fon on zulip Mara: Looks like they need some guidance: https://github.com/rust-lang/rust/pull/116607#issuecomment-2050592046 Mara: Specifically, if it should be done for only box-of-slice or also box-of-array, and then if the iter type should be separate from Vec's IntoIter type. The 8472: Knowing the upper bound is useful in some cases. Amanieu: putting the size in the type can result in a lot of extra monomorphization David: I'd prefer of all of these have the same iter (Vec, Box of slice, Box of array) The 8472: What's the benefit of that? Amanieu: compilation time Mara: If you use .map or w/e, you get lots of monomorphization anyway. David: I like having fewer types when there's no need to have more types. Mara: Useful for collect_array or w/e David: Some elements might have already been consumed, so you only have an upper bound Mara: Right! Convinced then. David: Would make sense for smallvec, as you only need an upper bound Mara: Yeah, but then i don't think it's worth it. Consensus: same type Mara left a comment ### (nominated) rust.tf/121377 *Partially stabilize \`LazyCell\` and \`LazyLock\`* Mara: We didn't satbilize `LazyLock<T, F>` before, because the default F used in statics would be `fn() -> T` which is not a ZST, resulting in unnecessarily storing a function pointer in the static. Mara: If we had type inferrence for statics, it could store the ZST type of the closure. Mara: This is a hack to stabilize it without waiting for that lang feature, accepting the unnecessary function pointer for now. Question is whether we think this leaves enough space for improvements in the future. Amanieu: What would the syntax be for the inferrence? Josh: That's an open question. Amanieu: People will likely use `LazyLock<T>`, just omit the second type. TC: As background, the more near term path here is likely using `impl Trait`. E.g., someone could use ATPIT or TAIT to opaquely specify some `Fn*` type here. It's possible we may later extend `impl Trait` to this position directly. Amanieu: Example with map containing `LazyLock<T>`, Mara: Depending on use case, you might want that map to store function pointers for each item or not. Amanieu: Prefer having the `F` explicit and pushing lang team for this lang feature. Josh: What is the path forward from `LazyLock` with `fn()` to the ZST situation? The 8472: `LazyLock<T, ZstClosureTypeHere>` Amanieu: I want to avoid the situation where `HashMap<K, LazyLock>` is more performant than `HashMap<K, LazyLock<T>>`. Mara: But that might be different behaviour: the latter will store a function pointer per element, so it can be a different function for each element. David: Spelling out TC's suggestion here: ```rust #![feature(lazy_cell)] #![feature(type_alias_impl_trait)] use std::collections::HashMap; use std::sync::LazyLock; pub static LAZY_MAP: LazyLock<HashMap<i32, i32>, imp::LazyFn> = LazyLock::new(imp::get_lazy_fn()); mod imp { use std::collections::HashMap; pub type LazyFn = impl FnOnce() -> HashMap<i32, i32>; pub const fn get_lazy_fn() -> LazyFn { || { let mut map = HashMap::new(); map.insert(0, 0); map } } } ``` Mara: So, this works today (unstably). Seems like the remaining work on the lang feature we need is 'just syntax' then. Josh: fair Amanieu: There's also some issue about variance.. Mara: Basically, do we want the (co)variance to be fixed now or can it be stabilized as invariant for now and maybe fix it later? TC: The conceivable extension of `impl Trait` to this position would look like this: ```rust #![feature(lazy_cell)] #![feature(type_alias_impl_trait)] use std::collections::HashMap; use std::sync::LazyLock; pub static LAZY_MAP: LazyLock<HashMap<i32, i32>, impl FnOnce() -> HashMap<i32, i32>> = LazyLock::new(|| { let mut map = HashMap::new(); map.insert(0, 0); map }); // David: Or perhaps: // but somehow Freeze makes this problematic. https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=2d6c6d0691a2d1743132e5d89da83cfe pub static LAZY_MAP: impl Deref<Target = HashMap<i32, i32>> = LazyLock::new(|| { let mut map = HashMap::new(); map.insert(0, 0); map }); pub static LAZY_MAP: impl Lazy<HashMap<i32, i32>> = LazyLock::new(|| { let mut map = HashMap::new(); map.insert(0, 0); map }); ``` TC: How might that affect the thinking on this issue? Mara: Still very verbose ^^' Josh: TC, do you see a reason why we couldn't just omit the second argument? E.g. make it default to `impl FnOnce() -> ..` Amanieu: That's what `, _` would be for. The bound is already part of the type. The 8472: The bound is now only on the impl, not on the struct. That'd be a backwards incompatible change, so we need to do that now if we want to do that. Mara: If we want to continue with this proposal, we'll stabilize the default of `fn() -> T`. Replacing it later with `impl FnOnce() -> T` or something doesn't seem fully backwards compatible, so then we'll have a difference between `LazyLock<T>` and `LazyLock<T, _>`, which seems bad. Mara: Should we send this to lang to get an estimate on how big the problem is there? TC: Concrete type inference in items was discussed recently and some lang members definitely have concerns about this. There would be a significant hill to climb. Opaque types are the identified solution here. Mara: I can see that with `_` it's unclear whether the resulting type is part of your public API or not. With `impl ..` it's clear that you only guarantee that property. Josh: Yeah that's exactly the issue. Similar case: there were proposals to infer array lengths `[T; _]`, to avoid having to count the array elements, and there was pushback (in part) because the inferred type parameter. Mara: About rust.tf/121377 , do we think that would work? Amanieu: I think it can work. Mara: I'm afraid we'll not be able to 'fix' it later. That we'll always have function pointers. Maybe with some edition change at some point. The 8472: And stabilizing both parameters and no default? Josh: If it's not ergonomic, people will just prefer a macro. David: It'd be useful to know how many people use LazyLock as a static vs using it as a field. David: For statics, the extra function pointer is not going to matter to anyone.. Mara: True.. I would really like it if we could 'fix' it later, but you're right that it's very unlikely to matter. Josh: There is value in being able to fix it later. But not doing anything now because we might be able to do it better at some point doesn't seem like the right thing. We *can* make it better at some point, but that might need an ugly migration. David: We can also decide to never fix it, to just accept the function pointer. Mara: If we accept that, then we can go for a full stabilization rather than a partial one. Josh: We could have a type and an alias later with different defaults. Amanieu: I'm in favour of a full stabilization. Keeping the default argument for the second argument. With the knowledge that if in the future we get some form of type inferrence, we can suggest using that with a lint. Mara: So then there will be a difference between `LazyLock<T>` and `LazyLock<T, _>`? Amanieu: Yes. Mara: But with a lint. David: Agree with full stabilization. David: Still need to figure out the variance story. Whether fixing variance later is a breaking change. Amanieu: I'm looking at the code, and I think i see how to make it covariant. (It's a bit ugly.) Amanieu: I don't think it's a breaking change to make it covariant later. David: +1 Mara: Wouldn't it break for people who have a LazyLock as a field in their struct, and rely on their struct being invariant? (someone): That would mean that someone hadn't bounded their own type correctly. TC: Unfortunately, people do use types in `std` for their implicit properties. So if we were to stabilize with invariance, we should at least document specifically that people should't rely on this. Mara: People might not realize it. If we can fix it before stabilization, let's just do that. Consensus: full stabilization, not partial. keep default for `F`. fix covariance first. ### (nominated) rust.tf/121920 *downgrade ptr.is\_aligned\_to crate\-private* Removed label. ### (nominated) rust.tf/122661 *Assert that the first \`assert!\` expression is \`bool\`* Mara: Forgot to discuss `&bool` last time. David: In the new edition, require `*`? Amanieu: crater run? I'd like to avoid a special case. David: The vast majority of Rust code is still to be written, in the new edition. Amanieu: I mean that hopefully nobody depends on this. Mara: E.g. `assert!(vec_of_bool.get(0))` or we. David: Or in pattern matching. Amanieu: then just make it an edition change. David: sgtm. Consensus: not support `&bool` in the new edition. Amanieu: and if possible remove it from existing editions, if it doesn't break things. Mara: Seems unlikely, but sure. ### (nominated) rust.tf/123110 *Rename iter::Iterator::intersperse() to ::separate()* Josh: Do we have a better way of dealing with conflicts with itertools other than just picking a new name? Amanieu: need to talk to petrochenkov Mara: Independently from itertools, `separate` could be a better name. Josh: cfg(accessible) in itertools would allow for a good migration David: Build script that checks compiler version? Amanieu: Itertools should be compatible with future versions of rust/std. So you need cfg(accessible) on every single item. Mara: Then itertools would be assuming that every single overlapping feature to std in the future would have the exact same interface as theirs. That is not something we can commit to. David: Seems fine to expect people to upgrade both their rustc and dependencies at the same time. Amanieu: itertools releases major versions. So you'd need to release many new versions. Amanieu: last time there were 59 root regressions. 59 crates that need updating. Amanieu: afraid we'll have to go through a lot of pain every time Mara: and we can't deviate from itertool's interfaces. The 8472: +1 Mara: Fwiw, niko had an idea for a name resolution solution very recently. TC: There's perhaps some downside to adding a second name for this operation into Rust. People will have to learn that these are synonymous. Mara: That's fairly common, that we use a new name when adding something from the ecosystem to std. Josh: If we can choose a *better* name, that's a good thing to do. It's unfortunate if we have to choose a worse name due to what's in the ecosystem. TC: Agreed. In this case, it seems at least plausible that `intersperse` is the best name. `separate` has many possible semantics; `interperse` is much more precise. While "separate" is perhaps more common, "intersperse" is also a common English word well-known to non-technical speakers. TC (later): Looking at Google's ngram tool, it seems that "separated by" is only a bit over twice as common in print in 2019 as "interspersed", and they've fluctuated against each other over time: https://books.google.com/ngrams/graph?content=interspersed%2Cseparated+by&year_start=1800&year_end=2019&corpus=en-2019&smoothing=3 TC (later): As another sanity check, there are many thousands of hits in the NYT for the word "interspersed": https://www.google.com/search?q=site%3Anytimes.com+interspersed Mara: As a non-native speaker, I have no clue what that means. `separated_by` would be very obvious to me. Amanieu: Why can't we just have people use itertools? Josh: intersperse is probably in the top 3 things that people use itertools for, and there's one obvious way to do it. TC: As a policy matter, aren't maybe people who use extension traits on `std` traits expecting some breakage? I certainly am when I write or use such an extension trait. The 8472: Sure, we can break it, but we are extra careful to not break a lot of users. Josh: (Aside: it would be useful if we could use method syntax while disambiguating the trait the method comes from.) (multiple people): This came up recently in lang discussions. Amanieu: unlikely we'll reach a useful conclusion in this meeting. Let's move on. ### (nominated) rust.tf/123168 *Add \`size\_of\` and \`size\_of\_val\` and \`align\_of\` and \`align\_of\_val\` to the prelude* Amaineu: lint should ignore the prelude Mara: makes sense Josh: +1 ### (nominated) rust.tf/123728 *Windows: Consider disallowing \`.bat\` and \`.cmd\` files in \`Command::new\`* It's basically impossible to escape arguments to batch files correctly. Chris: Would need some terrible terrible hack with a magic environment variable expanding to nothing. Josh: Hard to know if code will break. Mara: We know of build scripts with `Command::new("thing.bat")` that will break. Amanieu: example: https://github.com/DioxusLabs/dioxus/blob/c9ab09b3480ba2ad3b77d16c5e86382a62258194/packages/cli/src/tools.rs#L293 Josh: What if it finds a .bat file during search for a name? Chris: No, we only react to `.bat` and `.cmd` specifically, explicitly. We don't implement PATHEXT. The 8472: How do people invoke powershell scripts? Just invoke the powershell exe? Chris: Yeah. Chris: It's an undocumented feature of the CreateProcess windows api to handle .bat and .cmd, and we replicated that in Command::new. Josh: Do we expect microsoft to fix something in the future? Mara: The problem is not a bug or something, the problem is that windows does not have the concept of argv, it has a single argument string. Amanieu: I don't think we can remove batch support. Things will break. The 8472: It was never guaranteed. Josh: It works though. We shouldn't pretend it didn't work before. Mara: It also works on python and many other languages. Josh: Do we expect microsoft to fix cmd argument parsing in the future? Chris: It's... possible, but it's been decades.. Mara: So back to the question: can we rip out batch file support? Amanieu and I have concerns, but so I think no. but we could deny more things, to simplify the escaping code. Josh: We could simplify. E.g. only without args or something. Mara: As part of the wg-security discussion, we already looked for usage in the wild and found places where people use arguments, even with spaces and quotes and `=`. That's what informed the current implementation. Anything less will result in breakage. Mara: Does everyone agree that we cannot rip out batch support entirely? Amanieu: yeah Josh: Agreed. The 8472: The docs only mention exe files. It's a bug that we support batch files. Amanieu: we should fix the docs to say that .bat/.cmd files will work. The 8472: The alternative is linting against it. Options: 1. Rip batch support out 2. Promise batch support 3. Don't promise it, but still keep it working for compatibility. (Possibly with a lint.) Mara: our Command impl is now more robust in escaping than basically any bat file. something like `"$@"` doens't exist in windows batch files. No consensus for removing batch file support. (The meeting ended here.) --- ### (waiting on team) rust.tf/119550 *Rename \`AsyncIterator\` back to \`Stream\`, introduce an AFIT\-based \`AsyncIterator\` trait* TC: This is not waiting on libs-api. ### (new change proposal) rust.tf/libs364 *ACP: Add {Box, Rc, Arc}::map and {Box, Rc, Arc}::try\_map* ### (new change proposal) rust.tf/libs365 *ACP: \`TwoSidedRange\` trait* ### (new change proposal) rust.tf/libs366 *Implementing UnixSocketExt traits for solaris/illumos ; starting with the unix\_socket\_exclbind feature* ### (new change proposal) rust.tf/libs367 *Enable accessing written data in a \`BorrowedCursor\`* ### (new change proposal) rust.tf/libs368 *impl PathBuf::add\_extension and Path::with\_extra\_extension* ### (stalled change proposal) rust.tf/libs67 *Replace \`feature(layout\_for\_ptr)\` with \`feature(layout\_for\_meta)\`* ### (stalled change proposal) rust.tf/libs150 *\`Option::as\_\`(\`mut\_\`)\`slice\` and \`::into\_slice\`* ### (stalled change proposal) rust.tf/libs183 *Add uN::to\_signed and iN::to\_unsigned* ### (stalled change proposal) rust.tf/libs124 *Integrate \`Error\` trait with panic interfaces* ### (stalled change proposal) rust.tf/libs148 *Expose raw std{in,out,err}* _Generated by [fully-automatic-rust-libs-team-triage-meeting-agenda-generator](https://github.com/rust-lang/libs-team/tree/main/tools/agenda-generator)_