This is a tracking issue for Seek::{stream_len, stream_position}. Proposed and implemented in https://github.com/rust-lang/rust/pull/58422.
Unresolved questions:
As the issue calls for a bikeshed... tell seems to be an established name for what is called stream_position here. I don't see an analogous alternative name for stream_length, though, and the two methods having similar names might be advantageous. Besides, stream_position is more descriptive.
From the API user perspective, stream_position should probably borrow immutably.
I opened a stabilization PR here: #70904
From the API user perspective,
stream_positionshould probably borrow immutably.
@marmistrz Yes, that would be nice. But it's not possible as the method is just a small helper around seek. And seek requires &mut self.
Yes, therefore this should be implemented separately, on the low level, just as it's done in yanix:
https://github.com/bytecodealliance/wasmtime/blob/c4e90f729ca5e17a29a778ace7971aeda7c22391/crates/wasi-common/yanix/src/file.rs#L251-L258
@marmistrz Unfortunately, I don't quite understand what you are suggesting. And in particular: are you opposing stabilization of the features as they currently are?
In my opinion, instead of the cross-platform implementation present in
https://github.com/rust-lang/rust/pull/58422/files#diff-668f8f358d4a93474b396dcb3727399eR1407-R1410, platform-specific implementations should be used (lseek on Unix/something else on Windows/etc), so that a mutable borrow is not required.
I think that the API should not be stabilized, because it's semantically incorrect to require mutable borrows for immutable queries. If the API user only has an immutable reference, they'll still have to use platform-specific unsafe code. (casting & to &mut is UB)
A few things:
You are mainly talking about files, but Seek is implemented for many more things which potentially do not have a way to get the length otherwise. So "it's semantically incorrect to require mutable borrows for immutable queries." is only true for files and the like where mutability is indeed not required. But for some of Seeks implementors, a mutable borrow is indeed correct.
For files, there is already an API that safely gets you the length with only an immutable borrow (file.metadata().len()).
Even if we want to add another API for tell-like behavior (e.g. because metadata().len() is not the same), this would not conflict with Seek::stream_len. The only reason I see for not stabilizing this API is if you think that it is "a bad influence on users". I.e. "users should only very rarely use three seeks to get the length and instead prefer other ways to obtain the length, so having a method that does this easily accessible is harmful". Is that what you were implying? However, again remember that Seek is not just about files.
@LukasKalbertodt "Seek is not just about files" I'm curious, on which other "I/O objects" is this intended to be implemented on (just to make clear what we're talking about)? Are there existing I/O objects on which stream_len can only be implemented with a mutable borrow?
- For files, there is already an API that safely gets you the length with only an immutable borrow (
file.metadata().len()).
file.metadata().len() returns the total file length, not the current offset in the file and doesn't change after seeking. It's not a replacement for ftell() or stream_position.
I think for files there could be a specialized File::position() method that takes an immutable &self, similar to the existing Cursor::position(). As the Seek trait is more general (and due to API stability) the Seek::stream_len() and Seek::stream_position() convenience / optimization functions unfortunately require a mutable borrow. They are still useful, in my opinion.
@marmistrz As with most io-traits there is the impl<'_> Seek for &'_ File and the &mut &File signature for its stream_position is for all functional means equivalent to taking a &File as self. This wouldn't require any changes to the current design. It does mean, however, that any specialization to File should be done to &File as well as the implementation of the latter does not dispatch to the former.
Most helpful comment
A few things:
You are mainly talking about files, but
Seekis implemented for many more things which potentially do not have a way to get the length otherwise. So "it's semantically incorrect to require mutable borrows for immutable queries." is only true for files and the like where mutability is indeed not required. But for some ofSeeks implementors, a mutable borrow is indeed correct.For files, there is already an API that safely gets you the length with only an immutable borrow (
file.metadata().len()).Even if we want to add another API for
tell-like behavior (e.g. becausemetadata().len()is not the same), this would not conflict withSeek::stream_len. The only reason I see for not stabilizing this API is if you think that it is "a bad influence on users". I.e. "users should only very rarely use three seeks to get the length and instead prefer other ways to obtain the length, so having a method that does this easily accessible is harmful". Is that what you were implying? However, again remember thatSeekis not just about files.