--- date: 2025-12-02 url: https://hackmd.io/Q5LZhMY4SFuILnB1nt3wAw --- # Libs-API Meeting 2025-12-02 ###### tags: `Libs Meetings` `Minutes` **Meeting Link**: https://meet.jit.si/rust-libs-meeting-crxoz2at8hiccp7b3ixf89qgxfymlbwr **Attendees**: Amanieu, David, Chris Denton, TC ## Agenda - Triage - Anything else? ## Triage ### FCPs 1 rust-lang/rfcs T-libs-api FCPs - merge rust.tf/rfc3873 *build\-std: context* - (13 checkboxes left) 12 rust-lang/rust T-libs-api FCPs - merge rust.tf/80437 *Tracking Issue for \`box\_into\_inner\`* - (1 checkboxes left) - merge rust.tf/106418 *Implement \`PartialOrd\` and \`Ord\` for \`Discriminant\`* - (2 checkboxes left) - merge rust.tf/116258 *Tracking Issue for explicit\-endian String::from\_utf16* - (1 checkboxes left) - merge rust.tf/139087 *Fallback \`{float}\` to \`f32\` when \`f32: From\<{float}\>\` and add \`impl From\<f16\> for f32\`* - (4 checkboxes left) - close rust.tf/136638 *warn on empty precision* - (3 checkboxes left) - merge rust.tf/98407 *Tracking Issue for \`Exclusive\`* - (1 checkboxes left) - merge rust.tf/145948 *Stabilize 29 RISC\-V target features (\`riscv\_ratified\_v2\`)* - (3 checkboxes left) - merge rust.tf/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* - (1 checkboxes left) - merge rust.tf/141994 *add Iterator::contains* - (1 checkboxes left) - merge rust.tf/135894 *Tracking Issue for \`atomic\_try\_update\`* - (3 checkboxes left) - merge rust.tf/76314 *Tracking Issue for atomic\_from\_mut* - (2 checkboxes left) [joshtriplett (3)](https://rfcbot.rs/fcp/joshtriplett), [the8472 (5)](https://rfcbot.rs/fcp/the8472), [nagisa (1)](https://rfcbot.rs/fcp/nagisa), [0xPoe (1)](https://rfcbot.rs/fcp/0xPoe), [nikomatsakis (2)](https://rfcbot.rs/fcp/nikomatsakis), [estebank (1)](https://rfcbot.rs/fcp/estebank), [matthewjasper (1)](https://rfcbot.rs/fcp/matthewjasper), [mdtro (1)](https://rfcbot.rs/fcp/mdtro), [SparrowLii (1)](https://rfcbot.rs/fcp/SparrowLii), [scottmcm (2)](https://rfcbot.rs/fcp/scottmcm), [LawnGnome (1)](https://rfcbot.rs/fcp/LawnGnome), [eth3lbert (1)](https://rfcbot.rs/fcp/eth3lbert), [dtolnay (3)](https://rfcbot.rs/fcp/dtolnay), [BurntSushi (6)](https://rfcbot.rs/fcp/BurntSushi), [jackh726 (1)](https://rfcbot.rs/fcp/jackh726), [cjgillot (1)](https://rfcbot.rs/fcp/cjgillot), [Amanieu (3)](https://rfcbot.rs/fcp/Amanieu), [jtgeibel (1)](https://rfcbot.rs/fcp/jtgeibel) ### (nominated) rust.tf/125687 *Tracking Issue for \`new\_range\_api\` (part of RFC 3550)* Amanieu: There's a PR proposing a name change. It renames `IterRange*` to `Range*Iter` Josh: The argument for consistency feels correct. David: This seems fine. An alternative is `std::range::Iter<RangeFrom>` with a generic over what kind of range they iterate over Amanieu: These would have to be separate modules for each range type David: it would be a simple type with the generic. We went this direction with the `NonZero` types Amanieu: The state would be different David: We could use an associated type for that. Amanieu: Would they want to name the iterator or just the range type directly? Josh: The main usecase for naming the iterator is sticking an iterate in a struct. In practice there are still usecases where people want it. Amanieu: If you put it in a struct you should just use a Range not the Iterator Josh: I've seen cases where people want to store the iterator in a structure and then walk it The 8472: You'd run into issues with chaining iterators (e.g. Filter) Josh: But people still want it The 8472: Doesn't the type alias impl trait let you do this? Have it stored in the struct? Amanieu: You could. The 8472: So you could just return an `impl Iterator` Amanieu: I'd like to merge the PR as proposed and fix the names. I think this is fine to stabilize. David: That's fine with me too. Amanieu: The next question is actually stabilizing the range API The 8472: there was something on the zulip discussion Amanieu: I think is_empty was a problem. ... But that's tracked as a separate issue. And it's on RangeBounds not ranges. Amanieu: "Figure out a way to have IterRangeFrom overflow panic only after yielding the maximum value, without impacting release mode" I think we have that Amanieu: "How can we / should we optimize IterRangeInclusive now that it is not bound by the API constraints of legacy RangeInclusive?" ... Josh: how simple is the conditional that the compiler generates? If you can check a simple boolean "is the iterator exhausted" that would be better than what we have now Amanieu: Okay. But I don't think we should block the stabilisation on this. Josh: Given the iterators are opaque, we can fix this later. Amanieu: Do we want to block this on the language feature that allows for edition-dependent name resolution? If that turns out to not be possible, will we regret stabilising this? Josh: I don't think we need edition-dependent name resolution for *this*. I think we change what ranges change into over an edition. The 8472: Methods that take Ranges might need that. Amanieu: That's going to be a breaking changes for crates. Josh: That's a breaking change for crates that put `Range` rather than `RangeBounds` or similar into their APIs, yes. Amanieu: Seems fine to me. Josh: And I'd expect we'd put the new types into the prelude in the new edition. Amanieu: So we already have the new language features we need. The 8472: Would the edition-dependend name resolution be also for methods? Or just for types? Josh: It'd be for both. The 8472: If we have a method that takes a range, we could have e.g. `ectrat_if_2021` vs. `extract_if_2027` Amanieu: `extract_if` takes range bounds. `slice_to_ptr_range` is the only method that take `Range` Josh: The `as_ptr_range` and `as_mut_ptr_range` could benefit from edition-dependent name resolution Amanieu: And any range-based slice indexing would work Josh: Yes. The 8472: I thikn people have been asking to stabilise this before the edition so they can start using them in crates. Josh: That seems like a good idea for that. Let's do an FCP for stabilisation and nominate the issue for lang, where the nomination is to say "we intend to stabilise this, we expect that the new edition will change what the range syntax desugars to, if there's any expected change to that plan please let us know" Amanieu: Sounds good. Josh: Should we start the FCP for stabilisation? Amanieu: Yes. And approve the name change as part of the FCPing. Josh: I'll write it up and start the FCP. ### (nominated) rust.tf/148941 *stabilize \`Peekable::next\_if\_map\` (\`#!\[feature(peekable\_next\_if\_map)\]\`)* Amanieu: We've got next_if_map_mut. It allows you to mutate the peek slot Josh: They're adding the mut that we asked for Josh: Do we need a `ref` version in addition to this and the owned version? The 8472: We can add it later anyway Josh: Fair enough. The 8472: Wasn't there something about better pattern ergonomics that might it unnecessary? About closure arguments being able to just write `&` and it would work. The 8472: Anyway, I don't think we need the `ref` version at all. Amanieu: Okay. Do we want to stabilise it right away or wait a bit longer? Josh: Give we've just changed the APIs, it feels we should let it bake a bit longer? We might want to wait a week or two to make sure someone doesn't say there's a reason we should have done that. Josh: Let's wait for a couple of weeks and start the stabilisation then. Amanieu: I'll leave it nominated for a week or two then. Amanieu: Ok, so we're approving the `mut`, I'll reply to this one. ### (nominated) rust.tf/149359 *Edition 2027: Consider replacing \`std::sync::Mutex\` and other locks with \`std::sync::nonpoison\` versions* Amanieu: switching `Mutex` to nonpoison version. This has been quite controversial. Josh: Have we introduced the `Poison<T>` type yet? Amanieu: We don't have that yet. Josh: I think we want to introduce that before we do that switch over. Josh: This came up in 2 different context last week. (1) it came up on Hacker News, someone brought up an issue of mutex poisoning, discussion of ergonomic issue vs. reliability issue if we don't do this. (2) there was a similar discussion on the `r/rust` subreddit. Some peole think this is a great change for ergonomics and others feel it's trading usability for correctness. I don't think either discussion introduced any new arguments. Josh: One person did say how they're using mutex poisoning and showed us how. They're using it to spawn up GPUs to work and they use poisoning and actually do cleanup rather than just panic: to shut down what's going on the GPUs before they exit. Amanieu: Seems like a usecase for a Drop guard and not poisoning. Josh: The impression I had was mutex was guarding the use of GPU and the poison was saying that we need to do cleanup before the GPU can be reused. To me it sounds like a good example to definitely add the `Poison<T>` type for these usecases. Amanieu: This was nominated last week. It will have to be discussed by the team at some point. The 8472: Should we stabilise the non-poison mutexes first and let people use them before making that the default? The 8472: They'll co-exist anyway so having a shorter path doesn't seem that important? Amanieu: Are we happy having nonpoinosing mutexes even without no edition-dependent name resolution? The 8472: Yep. Every time I write application code I need to decide between std mutex and tokio mutex. This is no different. Josh: Yes. Amanieu: Does tokio have a poisoning mutex? Josh: It doesn't poison the mutex. Amanieu: If we do have edition-dependent name resolution, this is something we'd want to do? Josh: Yes, we'd have std::sync::nonpoison::Mutex, `std::sync::poison::Mutex` and `std::sync::Mutex` aliased to one nonpoisoning The 8472: The defaults matter, poisoning might be better. Amanieu: I've been pretty vocal about not having the poisoning mutex The 8472: Amanieu: You should be using explicit poisoning -- that's the answer to all of these concerns. The 8472: If we have that, that would be great, but we don't have that. Amanieu: Before we engage in any of these discussions, we should add `Posion<T>`. I can write up an implementation of that probably under the `std::panic` module (it uses thread storage). The 8472: Would that need two guards? Amanieu: Yes, you'd need two guards. The 8472: I'm interested to see what it looks like. Amanieu: as a sketch you'd do `mutex.lock().borrow_mut().unwrap()`. `lock` gives you a `Result<PoisonGuard>` The 8472: We could add a `poison_check()` method that would combine `borrow_mut().unwrap()`. Then you'd get the current approach Amanieu: You'd still have two drop guards but yes, I could see that. Amanieu: I'll write up a PR for `Poison` and submit it and link back to the discussion. And say the team consensus is to switch to these new mutexes over an edition. Josh: +1 ### (nominated) rust.tf/149400 *unstable proc\_macro tracked::\* rename/restructure* Amanieu: Does anyone have context here? David: The first 2 bullet points make sense to me. The third one we talked about `AsRef<str> + AsRef<Path>`. Due to utf-8 issues. Amanieu: This is a compile time macro. It's okay if we panic here. It's just a compiler error. David: Then I'm fine with all of there. Josh: We should document this that this could panic on non-UTF-8. Amanieu: Fundamentally, the dep-info format is unstable, if we decide proper path in the future David: I think dep-info is not something we control, it comes from make etc. Amanieu: Isn't this tracked in cargo? David: Cargo and other build systems. Amanieu: This was part of a larger PR (https://github.com/rust-lang/rust/pull/87173). ... I think this is reasonable. Amanieu: I think it's just approve? David: Let's also talk about what's next for stabilizing these? Amanieu: Can we just stabilise these? David: I hope so. Amanieu: On the tracking issue about what does tracked_path return. It doesn't return anything, it just track path. Would it make sense for it to return that so we can chain it. David: I'd prefer the current signature. Amanieu: we can start FCP on the tracking issue once this lands. I can review the PR. Amanieu: One concern from 5 days ago: relative paths might not be intuitive. The relative paths in `track_path` vs. `file::Open` work differently: https://github.com/rust-lang/rust/issues/99515#issuecomment-3587126287 David: Do we need two method for tracking paths? One relative to the current file the other relative to the proc macro Amanieu: The doc comments don't add anything about relative paths Amanieu: Are the paths in dep-info usually absolute paths? David: yes Amanieu: So it'd make sense for the path to work the same as `File::Open` relative to the current directory. We should David: bjorn3 says Amanieu: If you're tracking the file inside proc macro it means proc macro is reading that file David: I think you're right Amanieu: Should we explicitly add this as the team agreement on handling relative paths? David: We'd need to provide a guidance on how to write a macro that resolves path the same way as `include!` does. Amanieu: There's comment on clarfonthey's comment that says: `span.local_file() gives you the path to the relevant source file.` https://github.com/rust-lang/rust/issues/99515#issuecomment-3587413205 David: That sounds correct and good to me. As long as that shows up in the docs, I'm happy to stabilise the proposed behaviour. David: Should we do FCP for track_env right away? Amanieu: No because that's unstable. I'm going to approve the PR now. ### (nominated) rust.tf/149408 *refactor: remove Ord bound from BinaryHeap::new etc* Josh: Seems where we don't put the bound on creation but on operation. Sounds fine to me. Amanieu: This seems fine but we'll need to have an FCP. I'll set one up. ### (nominated) rust.tf/149482 *thread::scope: document how join interacts with TLS destructors* Chris: The API ask is: if you want to guarantee that calling join will wait on TLS descructors. Amanieu: The answer is: it depends. There's another PR that creates a future join handle can wait on. And that works on executing a TLS destructor on Amanieu: I think that might work becaues TLS destructors are executed in reverse order than they're created in. Not sure that works on all platforms though. The 8472: What about initialising the variable. Does it change the order? Amanieu: IT doesn't Chris: What about threads spawned outside of Rust Amanieu: That's fine, you can't get a join handle for them. The 8472: Unless we add something that transfer ownership to Rust Amanieu: Please no? Amanieu: scoped threads only wait for the main function to exit. Unless you explicitly join with the join handle. Chris: That was decided on a previous FCP. Amanieu: Yes, when we stabilised scoped threads. Josh: Regardless, one way or another we should be consistent whether you join on this or drop it. Chris: But it already does. Josh: I agree it does, we should change taht. Amanieu: Should we use the TLS destruction ordering trick? If you register TLS destructor before any user code could execute, that will execute after any user-defined TLS destructors. However, that's truly a join. The thread-id is still live. Chris: We did previously FCP close this as not a bug. So saying it is would be reversing that decision a bit. https://github.com/rust-lang/rust/issues/116237#issuecomment-2217974226 Chris: well, not a bug but "needs documentation" Amanieu: Which this fixes by adding the necessary documentation. Amanieu: I'm happy with this. The 8472: What about Josh's idea for making it consistent? Amanieu: It would be nice for it to be consistent. But I don't think it's necessary. The 8472: It's similar to how we close files. If you don't care what happens, we'll clean it up. Amanieu: I think it's fine to document the current behaviour and then see if we can improve this with the TLS destructors trick. The 8472: It does add a new guarantee to the join that it does fully wait. Amanieu+Chris: Yes. Chris: I don't see a problem with that. If we add something ne that will be a new API The 8472: join is on the handle but the join future would be a separate method. Yeah, that should be fine. Or would the join handle implement Future directly? Amanieu: No, it would be `Into<JoinFuture>` The 8472: I think the new guarantees mean it needs an FCP. Amanieu: I think it has fewer guarantees than before The 8472: It guarantees that we won't return until all the destructors are run. Amanieu: I started the FCP. ### (new change proposal) rust.tf/libs708 *Freeze file times on Windows* Chris: I'm in favour Josh: This started as a rust internals thread. Someone observed there were calls on Windows freezing the file time. You have to do that immediately after creating the file handle before using the handle. When using `truncate(true)` we do make a call right after creating a file handle. So adding a method to OpenOptionsExt lets you do that Amanieu: That seems fine. The 8472: The problem is with truncate but you could do this manually by not calling `truncate` and doing that manually? Josh: That's what they listed but they're looking for a more ergonomic option. ### (new change proposal) rust.tf/libs707 *FFI\-compatible std complex numbers* Josh: Another long discussion on internals. The ecosystem have a few crates handling complex numbers. It would be helpful if there was a stable representation for complex numbers everyone could share. It's not asknig to add a lot of constants. It's about adding vocabulary types for complex floats so the ecosystem could over time shift to that. The 8472: The discussion has been steering the user to making an RFC? Josh: What would necessitate a full RFC? Amanieu: Are there ABI implications? The 8472: C FFI is there. Amanieu: Josh: We should check. Amanieu: C doesn't use structs, it has a dedicated complex type. Josh: I thought it used structs. The 8472: That doesn't help because it has to be in the C standard. Amanieu: I feel this kind of vocabulary should be in the num crate. Josh: I think half of the num crate should be in the standard library. Amanieu: that, too. Josh: One at a time. The 8472: If we use intrinsics, those will demand this ABI too. That has consequences and I think that's why the discussion goes towards the RFC. Josh: Yeah, that's fair. And I see they've already added the RFC: https://github.com/rust-lang/rfcs/pull/3892 Josh: If someone wants to make a sealed trait for the convenience, then fine. But they should be sealed traits not something people can implement. They should also be unstable so people don't count on the exact bounds in case we need to change that. Amanieu: I also don't think we should `c16` etc. names. Josh: I think any kind of alias should get moved into the "maybe future possibilities" section Amanieu: I was thinking `Complex<f32>` in the cffi module only, not as a global type. Josh: Sure. I suggested that rather than having a separate thing in cffi module is that the complex type is compatible with C Complex rather than float. Amanieu: I'd be against making this a primitive type. Josh: If we wanted to make syntax, that would make it a primitive type. Having a syntax to say `3 + 4i` is compelling, but we should leave that as a future possibility. Josh: The RFC also doesn't mention C 32 and C 64. I'll add it to future possibilities but I don't think it should be in the RFC. Amanieu: This is missing an API voerview. It's incomplete. Where's the `i()` method defined? Josh: I see, that should not be a thing. The 8472: Why not? Josh: We should not add a method until we decide on the native syntax. Amanieu: Could we have the `i` method as unstable and defer it to stabilisation? Josh: I'd leave the `i` entire for now. The 8472: That would probably be fairly cumbeersome to write. Josh: There are multiple ways of writing this. Method, macro, etc. The 8472: I'd like to see some math-heavy code that deals with complex numbers to see how much it should improve. Josh: Sure. I'm suggesting we don't do that right now. It should list the various potential syntax options. The 8472: The RFC should do more. E.g. FFI coverage. Josh: Agreed, this should be compatible with FFI in C Amanieu: This should work today because it's a `repr(C)` struct. Josh: We should state that before stabilisation we need to confirm it's ABI compatible on all targets and that we won't do anythnig preventing it from the future. Amanieu: I'm looking at Clang output. The libm functions take return it as a struct but they take it as a scalar pair like we do in Rust. E.g. `cpow` takes four doubles as arguments in the lowered version. But in the C syntax it takes two complex numbers. Amanieu: So there are ABI implications. It's not just a struct. It's going to need custom ABI lowering I think. Amanieu: I'm generally happy with this. I don't think it should be a primitive type but I'm happy to have a complex type. Josh: Yes, let's have a complex type, see how widely it's used and if it is, we could consider a language syntax. But we're not there yet. Josh: Should we give it some time and nominate for the next week? Amanieu: Sure. And close the ACP? Josh: Yes, I'm doing that. ### (new change proposal) rust.tf/libs706 *More arithmetic functions for Duration* Chris: `div_duration_floor/ceil` returns `u128`, shouldn't it return Duration? Josh: If you divide `Duration` by `Duration`, it should return a number. If you divide it by a number, it should use `Duration`. Amanieu: I wish `Duration` used u64 nanoseconds, that would make things so much easier. Josh: The usecase they brought up was dividing a Duration by a period to figure out how many cycles to count and you need the result as integer. Chris: Can we just have a function for that? Josh: I'm confused by how the function isn't just a `div_duration_floor/ceil` Chris: Ther's a lot of other functions such as strict_mul Josh: Yeah, I'm much less certain about those. Amanieu: There's the issue that `div_duration_floor/ceil` would panic with the right-hand side being zero Amanieu: This can't overflow. Josh: and no negative durations. Josh: I'd add `div_duration_floor/ceil`. Even `div_duration_exact` is questionable. I'd definitely not add `strict_mul/div` Amanieu: Looking at the examples, it's all just div_floor. As is the ACP example. Josh: I feel if we're adding `floor` we should add `ceil`. But I'd be inclined to push back on all of the rest. And for the strict ones, could we just add operators for those? The 8472: We don't have a Strict wrapper yet. Josh: We don't? The 8472: We only have `Wrapping` and `Saturating` Amanieu: Can we get a concensus of just `div_duration_floor/ceil` with panic on divide by zero? Amanieu: "strict" is redundant, we always do divide by zero check. Amanieu: For `div_ceil` we don't have a `check` variant of it Amanieu: and `div_floor` is still unstable. Josh: For `Duration` we appear to have a `checked_add` so it's trivial for someone to write `checked_add(..).expect()`. I think that's an easy justification for rejecting that. Amanieu: `Strict` wrapper? The 8472: similar to Wrapping and Saturating Amanieu: I'm not a fan but ok? The 8472: It helps us not having too many methods on the base type. Amanieu: I don't mind. The 8472 + Josh: I do. Josh: I'll respond that we want `div_duration_floor/ceil` ### (new change proposal) rust.tf/libs705 *\`File::close\`* The 8472: I'm not a fan of having this under the `close` name. Maybe something more obscure. It does nothing but decrementing the reference count to the file description. In some cases it does more than that, but it's very env/platform dependent. You can't build portable code. People may be tempted to say fsync is close, I'll do this. Amanieu: `File::close` is useless unless you've opened it with specifically with an option The 8472: The example is always the same: NFS on Linux under other conditions close behaves like fsync. It would support error reporting. Josh: I don't think telling people they should be using sync is the right answer here. I thikn we need to consider the impact on the wider ecosystem. We don't people think tehy're suddenly doing it wrong if they don't call close and not value. The 8472: I don't want people to think that they've called `close` and checked the errors and then believe that the data is consistent. Josh: I don't think it's a common thing. The 8472: You don't get an Josh: Close returning an error was a bad idea. System did it anyway. NFS is full of bad decisions. Its approach to reporting errors is to return them after calling close. I don't want the world where people feel they need to depend on close. For most people closing with errors should panic. Josh: But I like the suggestion of not returning error on close on file, but using it on `OwnedFd`. The 8472: My suggestion was calling it "decrement_reference_count" Josh: It's the operation that the OS calls close. The 8472: But what happens is it decrements the reference count and you don't know if anything else is happening. You closed the file descriptor but not the *file description* Josh: Yes, that's why it's called close. It closes the file descriptor. Amanieu: I think close has less value on File and more on WriteBuf. The 8472: On there, we have `flush` already. Amanieu: On BufWriter it flushes and then follows the flush of the inner thing Chris: I posted a related issue: https://github.com/rust-lang/rust/issues/148098 Chris: We used to flush but don't anymore The 8472: I think we should fix that. That's an implementation bug. The 8472: Chris, you also suggested returning an Option on Close? I kind of like it because you can't just question marking it. Amanieu: What's the issue with question marking it? The 8472: You might get None even if an error happens. It's not error reporting. Do you even need an error? The 8472: But if it's on OwnedFd, it's enough out of the way so people don't stumble on it by accident. Amanieu: In that case, I don't think it's much value in it. Josh: The idea of adding the trait is kind of appealing. There are other kinds of resources for which there are useful close operations. The 8472: Is it always an IO error or should we have an associate type? Josh: Based on previous experience I'd make it `type Error = ...` and then using `io::Error` for most types The 8472: If you put it on `OwnedFd` it's unix only. If you put it on File, it's more portable but there I don't want it under the `close` name. Josh: Chris, are you aware of any Windows filesystems calling close on file will produce an error? Chris: I've not encountered that but it's technically possible that some FS could. Josh: Would this be passed through the filesystem if the filesystem did it? The 8472: FUSE can return -ebadf Amanieu: In that case your filesystem is broken and we don't support it Josh: Agreed The 8472: I had to work around that when implementing the UB check. Amanieu: I have no strong opinion on `File::close` Amanieu: I don't mind adding it. It's useful for some people, the rest can ignore it. Josh: We should be careful of how to add it. Amanieu: Adding it to BufWriter? Josh: That and any other external place we would write to. Josh: close should take object by ownership, not reference. Josh: Rustix also has a `close` method that was subject to a bunch of debate. They make point of saying that their version of close does not return a result as it's the responsibility of the filesystem designers to not return errors on close. Amanieu: The usecases of this are so tiny! The 8472: That's my point -- should we have this in std or have something in the ecosystem? What's the point of adding the method? The 8472: The only possible usecase is if you want to debug every possible error. But if your concern is "I care about my data and I'm using NFS" then you're very much in the non-portable special needs. Josh: I think people who want this only thing it's a means of reoprting errors. Get error, report the error, done. TC: That's exactly how I'd use it, and I'd expect it to be there for that reason. The 8472: The motivating example is specifically NFS file reporting. Josh: NFS is the prime example because it behaves this way. Amanieu: Is NFS still used? Josh: There are major cloud providers that provide an implementation of NFS. The 8472: The NFS client on linux returns the error, it's not neressarily the FS issue Josh: I'm in favour of adding the `CloseTrait` and having an implementation of `OwnedFd` and I'd be hesitant on having on `File` without a long message explaining why people should not be coerced to using it. Amanieu: Something that flushes would work better than anything tahts' proposed here. The 8472: `into_inner` does flush Josh: Amanieu, you'd prefer not to have this be a trait? Or have a better behaviour if it is a trait? Amanieu: This doesn't need a trait. The point of traits is let user types implement this. Or are we thinking of this to be an extension type? The 8472: We have `Drop` dispose of this without error handling? This would do the same while returning an error. Josh: If we want to add this as a trait, we should add it to have an associated error type. I don't think it necessarily needs to be a trait. I'd also not object to just sticking a metnhod on OwnedFd Amanieu: What about adding `close` on the `Write` trait with the implementation calling close and flushing self? The 8472: Write doesn't seem like the right thing? Amanieu: It's important for BufWriting Josh: I don't think we should add it to Write. There are some writers where this wouldn't be the right behaviour. Amanieu: It flushes on drop already. This is equivalent to calling flush and reporting errors. Josh: Consider special methods similarly to how db transactions would have rollbacks. The 8472: Having a vocabulary type that says "all of the things you need to do when you get rid of this" Josh: Having linear types, I'd love that The 8472: I like the trait in the abstract case but specifically not on File. I don't want users to be misled about having to call close. Josh: I think we agree on it for different reasons. I don't want people thinking that that they need it to handle errors. Josh: I agree with Amanieu this would take design time. Josh: Proposal: add `close` to `OwnedFd` with a long comment explaining what it does and does not do. The 8472: Chris, have you ever used the Windows NFS client? I wonder whether it behaves the same way as the linux one? Chris: I haven't used it The 8472: And SMB? Chris: I've never seen an SMB error. It does buffering but I don't think it ever returns an error. The 8472: It might make sense to look into the windows-specific behaviour Chris: I don't think there's much downside on having a `close` function on `OwnedHandle` Josh: Why don't we explicitly say we don't want trait now (but maybe in future). We don't want it on File. And we're willing to entertaine a close method on `OwnedFd` and potentially `OwnedHandle` given a comment explaining that this is only for specialised needs. The 8472: I agree, but people might not like that they'll have to `cfg!` this out. They may want to have a portable version. And for the portable version I'd want a different name. Josh: I agree people may want it, but I don't really want to offer it now. Josh: Rustix had a long debate over this and they ended up having a conclusion they shouldn't add this. And it seems worth learning from. Why don't we defer this and pull sunfish into the conversation and ask about the rationalle of saying "no" or "yes" to this. Amanieu: Rustix seems to have added "try_close" Josh: It has a doc comment that the rustix developers don't think it should be used by anyone Josh: I'd agree with the rationale that if we return an error it should by `try_close` instead of `close`. And that comment makes me question us adding this to the standard library. Amanieu: For a lot of code, it is generic code that works on any FS. And it's the user who selects the filesystem. TC: Two thoughts. First, I wouldn't name this `try_close` -- I'd expect this to not necessarily close it based on that name. Amanieu: We'd call it close. The 8472: I don't want to call it `close` on `File`. TC: OK. Just not `try_close`; that'd mean something else. TC: Second, the reason the person writing the code knows she needs to use it does not depend on the filesystem being used; as you said, the user will be choosing that. The reason is because the author needs to log the error. For me, I know I want to emit a log, and that's why I'm going to use this. The 8472: That's not the motivation for the ACP author Amanieu: Consider a function "write config file". You writes, you get an error, if that happens the write_config_file should return an error The 8472: The flush may have been writen and error for another reason Josh: If you're checking for error, you can't assume that the on error the file was written out The 8472: If you care, you have to do the sync. Josh: But even if you use sync, there are still thnigs in the hardware etc. that could silently fail The 8472: Sure. But if you don't fsync, you're not even trying and all the error handling is just cargo-culting Josh: I agree with you that if you care about the durability, don't rely on close + errors The 8472: The person who wrote the Reddit thread thinks that this will give them kinda-sorta-durability without the full cost of fsync. And that doesn't exist. Josh: Agreed. Amanieu: I believe fsync actually blocks until the sync is complete. The 8472: There are other options (io_uring etc.). And I guess people don't just want fsync. Josh: Proposal on how to dela with that now: let's not. TC: In my view, a team should strong-man a proposal. If a person proposes it for an imperfect reason, we should think about the best possible reason instead. And here there is a real use case better than what the proposal mentioned. And designing around that use case should be feasible. If we rename it, as The 8472 wants to do, to "close_for_logging" or something, can we just accept that? That's one way to not have to deal with this again. Josh: Yes, in general we should be strong-manning a proposal. But even doing that it doesn't necessarily mean we should accept it. But it gives me pause to degree how rustix responded to this and I don't want to be more cavaleer than them. And on that note I don't think we should accept this now. Instead we should CC sunfish, have them respond, maybe have join a meeting and talk us through their experience. TC: Yes, tabling it and making sure that the concerns are heard and understood makes sense. Josh: And the next best thing is pointing people to the rustix try_close. Us adding a thing even with a comment has the risk that we'll start seeing PRs in the ecosystem on "call close and report on the potential error". TC: What's the concern exactly with having a function to return an error to log it? Josh: There's a difference of having a special purpose library where if there wasn't a thing, I'd call libc close. Vs. people thinking that everyone should call this all the time. We don't want people to think it's sloppy or incorrect to not do this every time someone's working on a file. TC: I see this less about how correct you want to be about file handling and more that if you want to be nitty with logging, it would be correct to call this. Josh: Yes, but what about someone's library that returns an io::Result and drops close. TC: I think that's on the ecosystem to figure out. Downstreams and upstreams will work out what makes sense. It's not for us to decide. Josh: We're not deciding on the ecosysetm. But we need to be conscious of the impact. The 8472: It goes back to the initial discussion. The close method basically does nothing. The OS devs say it should never return an error. The standard says it basiaclly does nothing. The only case you have is if you run it on NFS on linux with that particular mount option. And you get the same error reporting from fsync. So the only reason you want this is: you want error reporting, you don't want want to call fsync and you are on NFS. That's a pretty niche case. Josh: you mentioned a particular NFS option. What option is it? The 8472: CTO (close to open). And to disable is to set noCTO. CTO enables the consistency. If you close the file and reopen on a different machine, you'll see the data immediately. Josh: So it essentially makes close to do a fraction of the writeback. Amanieu: and CTO is on by default on linux. Josh: I propose adding cc to sunfish, invite them to chat to us about this. The 8472: Sunfish did comment on the Rust repository issue that's been open for a long time. And the opinion there was pretty similar: https://github.com/rust-lang/rust/issues/98338#issuecomment-1163296233 Josh: > Rust has ignored errors from close since 1.0, which is a precedent across the ecosystem. If we change that, it will create a new expectation for almost all Rust libraries and utilities that write files. It's tempting to say "you don't need to check if your use case doesn't need it", but libraries and utilities usually don't pick the filesystems they run on, or how data is used outside their scope. Josh: That captures it perfectly. Josh: And the discussion on the rustix repository is: https://github.com/bytecodealliance/rustix/issues/1084 The 8472: A part of the answer could be "go bother the operating systems, filesystems etc. to get your data secure without performance penalties". Josh: I'll try to write a short summary saynig we talked about it for a long time, retreaded all the previous discussions and didn't come to a good conclusion. TC: Are you going to request Sunfish to weigh in? Josh: That was before I saw Sunfish's replies. He might be tired of making the argument. TC: Clearly we shouldn't pull anyone into an argument. But I wonder whether he may have additional useful thoughts. The 8472: This is not the first time it came up even in kernel etc. And never really resolved itself. Chris: This is a few lines of code that you could implement outside of the standard library. The 8472: You'd have do more than that if you wanted it to be portable. ### (new change proposal) rust.tf/libs703 *Add #\[track\_caller\] to drop\_in\_place* The 8472: We expect this is too expensive. Josh: No semantic objection, but we expect this function to be far to hot to be annotated to consider it. If you think it could be done without a performance hit, come back with numbers backed by rust-perf. Amanieu: Sure. ### (new change proposal) rust.tf/libs702 *ACP: Add \`wake\_fn\` to \`alloc::task\`* The 8472: We pinged async-wg and they left comments. Amanieu: Seems like a nice convenience. Everyone seems to think this is ok. TC: What do we think about the auto-wrap in Arc? Amanieu: The agreement seems to be to return the Waker directly and wrapping in Arc. Amanieu: I think everyone's in agreement. I'd say ACP apprved? TC: This was proposed in `core` and we'd move it to `alloc`? And the author proposed if we're going to do that we should rename it `waker_fn` rather than `wake_fn` Amanieu: Do we need a separate local waker fn? TC: Intuitively, maybe. ### (new change proposal) rust.tf/libs700 *Mapped Arc and UniqueArc* ### (new change proposal) rust.tf/libs699 *Bring \`hashbrown::Equivalent\` into std* ### (new change proposal) rust.tf/libs698 *Stabilize trait \`ZeroablePrimitive\`* ### (new change proposal) rust.tf/libs691 *\`std::io::Read\` provides byte\-order reading trait* ### (stalled change proposal) rust.tf/libs395 *\`impl core::str::Pattern for \[&str; N\]\`* ### (stalled change proposal) rust.tf/libs523 *Add a deterministic constructor for \`RandomState\`* ### (stalled change proposal) rust.tf/libs525 *Vec::try\_remove* ### (stalled change proposal) rust.tf/libs133 *Add fmt::Write to io::Write adapter* ### (stalled change proposal) rust.tf/libs111 *Restructure ptr\_metadata to minimal support* ### (stalled change proposal) rust.tf/libs131 *Add \`std::fs::rename\_noreplace\`* ### (stalled change proposal) rust.tf/libs379 *Combine, an iterator adapter which statefully maps multiple input iterations to a single output iteration* ### (stalled change proposal) rust.tf/libs296 *ACP: Designing an alternative \`FromStr\`* ### (stalled change proposal) rust.tf/libs371 *ACP: primitive numeric traits* ### (stalled change proposal) rust.tf/libs543 *ACP: Slice to array version of \`split\_off\`* _Generated by [fully-automatic-rust-libs-team-triage-meeting-agenda-generator](https://github.com/rust-lang/libs-team/tree/main/tools/agenda-generator)_