Using unstable APIs? Tell us about it!

I started to use std::path and std::ffi in rust-fuse a few days ago. When it comes to ffi, I found it inconvenient to convert between Path / OSStr and CStr. There's no easy way to get a CStr from an OsStr or vice versa. Workarounds involve extra copying and str (utf-8 enforced).

OsStr probably intentionally hides the byte representation because you can't be sure about it on different OSes. But this also makes it hard to use ffi with paths. (Workarounds in rust-fuse can be seen in channels.rs, just search for the FIXME comments).

Isn't std::os::unix::OsStrExt supposed to help with that?

Oops, I totally missed that. Thanks! :slight_smile:

From core, str::Utf8Error, because I'm reading in external data that has to be converted. From std_misc, a bunch of stuff relating to FFI and C libraries: ffi::CString::new(), ffi::CStr::from_ptr(), CString as_ptr(), CStr to_bytes(), and of course, libc.

Features that I used

Related to integer conventions (probably will be fixed soon):

  • core:
  • SignedInt::abs() used like (x-y).abs() != 1 to check a certain special case
  • Int::trailing_zeros() for bit-fiddling
  • Int::count_ones() for bit-fiddling
  • unicode:
  • CharExt::to_digit() used in parsing

Others (probably more important):

  • core:
  • IteratorExt::cloned() seems to be required to satisfy borrowck and typeck. not sure why this is unstable
  • collections:
  • Vec::drain() using into_iter() caused borrowing errors with new destructor rules
  • StrExt::char_at() used in parsing (my program deals with an ascii-only protocol)
  • str_words:
  • StrExt::words() used in parsing
  • std_misc:
  • select! {} used in an "event loop"
  • time::Duration required in old_io::timer

As an update, we've got basically all of the large API areas stable today that are going to be stable for 1.0. The largest fruit to pluck next are the methods in std::num which should happen shortly this week. Otherwise, however, if there are still APIs that need stabilization, please continue to let us know!

I encourage you to try to move off unstable APIs wherever possible in your crates, I've found that while we still have little pieces here and there that are unstable, they're fairly easy (and idiomatic) to avoid. For example all usage of char_at and char_range_at I was able to replace with either the chars or char_indices iterators.

Taken all together, we currently have 6/12 of the top crates running on 100% stable Rust, and I'm sure there are many more candidates for earning this so soon as well!

The last pieces that seem to be missing for me is std::old_io::timer::sleep and Duration.

1 Like

sleep has a PR: https://github.com/rust-lang/rust/pull/23330

If we're (as it seems) opening up this thread beyond (collections, core, std_misc):

I'm still using std::old_io::process::InheritFd to daemonize, and std::old_io::Command to set stdout(), stderr() on the child, which then requires using std:old_path::Path.

This is all one issue, IMHO, and already known and accounted for in Expand the scope of std::process ยท Issue #941 ยท rust-lang/rfcs ยท GitHub. So :+1: for work in that direction eventually, hopefully before ripping those old crates out (at least make the old ones available on cargo so I don't have to drop existing features). Cheers :beers:

The only reason I'm still using std::old_io::net::udp::UdpSocket in my ยตTP implementation is because of set_timeout.

I'm aware of Tracking issue for RFC 517: IO reform ยท Issue #21070 ยท rust-lang/rust ยท GitHub, and I've been waiting for the dust to settle a bit, but I don't know whether set_timeout will be definitively removed or coming back.

I can use mio instead, it's not a big deal.

I don't have a good handle on what's expected to be stabilized or not (or what's in progress), so I'll just list them. I didn't realize there would be this much, so my apologies if some of these are slated to be fixed very soon.

Not everything here is a major blocker, many of them can be worked around (some are trivial to work around). But I've resisted working around them because I don't know whether they will become stable or not. Some advice here would be much appreciated. i.e., Which will become stable? Which will I have to work around?

  • collections - std::vec::Drain
  • collections - std::collections::BinaryHeap::{into_vec, into_sorted_vec}
  • core - std::error::Error is used in almost all my crates.
  • core - The start and end members on the various std::ops::Range structs. These seem necessary for useful impls of std::ops::Index.
  • core - std::num::cast, std::num::Int::{zero, one}, std::num::SignedInt::abs
  • core - std::marker::MarkerTrait (Although I suppose I could just use PhantomFn.)
  • core - std::iter::Cloned
  • core - std::iter::AdditiveIterator
  • core - std::num::from_str_radix
  • core - std::str::Searcher, std::str::Pattern and std::str::SearchStep
  • core - std::num::ToPrimitive
  • core - std::iter::order
  • core - std::str::CharRange (used with char_range_at and char_range_at_reverse. I can get by with char_indices, but it's slower). Similarly, std::str::StrExt::char_at.
  • core - std::ptr::PtrExt::as_ref and std::ptr::PtrExt::as_mut
  • core - std::iter::range_step
  • exit_status - std::env::set_exit_status essential for any CLI app.
  • file_path - std::fs::File::path
  • fs_time - std::fs::Metadata::modified
  • io - io::Seek, io::SeekFrom, io::Write::flush
  • io - io::Error and io::ErrorKind
  • std_misc - The entry API. It's very useful.
  • std_misc - std::path::AsPath
  • std_misc - The str::f32::to_str_digits and std::f64::to_str_digits functions.
  • test - I think test::Bencher is the culprit here.
  • unicode - std::char::CharExt::encode_utf8
  • unicode - std::char::CharExt::width

The Str trait as in <S: Str, I: IntoIterator<Item = S>>
Vec::from_raw_buf

I'm using FromPrimitive to convert enums to strings and back in a one-to-one and unto fashion in a macro.

1 Like

std::os::num_cpus() Seems to have been deprecated this week (with std::os). Not sure sure if this api was meant to be moved into a different module or not.

Thanks everyone for all the suggestions! I've tried to respond to some big ones below:

Good point! I think we should be at least able to expose some platform-specific constructors if necessary, they shouldn't be too hard to at least get unstable!

The only holdout for timeouts right now is stabilizing a Duration type, once we've got that we've got a pretty concrete plan of how to add back timeouts to UDP/TCP sockets. For now though I might recommend mio for more flavorful needs!

I would recommend replace + into_iter for now as the conventions around this method may not be quite in place for 1.0 to be stable.

We hope to do a large num stabilization PR before the end of the week. It may not hit all the points you've listed here, but it should definitely knock out a big chunk.

Both of these are pretty trivial to implement with other adaptors, but I think that Cloned may become stable. I'm less sure about AdditiveIterator becoming stable though (it's been awhile since we looked at it.

I think we're still working through whether we want this precise API to be stable for 1.0. Usage will be stable but custom implementations may not be. I'll have to check up with Kimundi.

I've found char_at + len_utf8 to be a good replacement for CharRange, but I haven't personally taken much time to benchmark it yet. I do think we will likely end up stabilizing char_at.

I'd recommend .is_null :smile:

Now it's stable! Deprecate range, range_step, count, distributions by aturon ยท Pull Request #23347 ยท rust-lang/rust ยท GitHub

We definitely want a method to set the exit status stable for 1.0, we're still thinking about the precise method we'd like to do this though.

I would recommend storing the path elsewhere for now, we're likely to remove this.

Unfortunately this probably won't be stable due to the lack of an abstraction for a moment in time. We're considering exposing the raw representations in a stable fashion though so this could be calculated for comparisons at least.

Coming soon!

I believe @Gankra would know more on this, but I think the intention was for it to be stable for 1.0.

We're hoping that generic conversion traits will obsolete this trait.

It's likely that benchmarking will not be stable for 1.0. The good news is you only need it for tests though!

We could plausibly stabilize encode_utf8, but width will likely remain unstable for now.

We're hoping the generic conversion traits will obsolete Str, and I'm not sure that Vec::from_raw_buf will be stabilized. The implicit copy performed here isn't really idiomatic with the rest of Vec's API. I would recommend using slice::from_raw_parts and going from there.

We will likely not stabilize this function as there are a number of questions around its semantics. The current implementation, however, has been published on crates.io

Edit: added more things

  • std_misc for collections::hash_map::Entry
  • io for:
  • io::ErrorKind
  • io::Write::flush
  • net for:
  • net::TcpStream

Knowing the number of cores/cpu's is pretty fundamental when creating a scalable server-side multi-threaded service. I am new to Rust and had expected to see this in the threading library. Most of my work involves back-end large volume data processing across many machines. In this scenario the normal mode of operation is to have multiple thread "contexts" (one per core), who divide and conquer, stealing from each others work queues to reduce context switches and keep cache-lines hot. I was hoping to build this concept using Rust for comparison, but I'd be expecting to see this in the standard.

@alexcrichton Thank you so much for responding. That is very helpful. I'll start updating my crates soon with your advice in mind. :smile:

The core entry API should be stabilized, but the convenience on the enum itself is very volatile atm. Basically you can get the perf; not the convenience.

I agree! Your sentiment seems to be shared by many others, so I've written an RFC to help include this functionality back into the standard library.