Using unstable APIs? Tell us about it!

UPDATE

Stabilization is now being tracked within github, and we'll be publishing dashboards as part of subteam reports.

Very soon, when you use a gated feature, the compiler will hand you an issue number you can use to discuss and track it. For now, you can see the libs list here -- I'd encourage you to leave comments on the features you care about!


As the beta release draws closer, we're going to be pushing to stabilize a lot of the remaining APIs, as described in an earlier post:

While some big modules need to be stabilized wholesale (like io), others are mostly stable but have some gaps.

We want as many libraries/apps as possible to work on stable Rust 1.0, so this thread is a way to record the gaps that people are running into.

If you're using APIs that are part of the collections, core or std_misc feature set (that means NOT io, os, path, hash or rand), please leave a comment here about what APIs you're using and why!

2 Likes

r2d2 depends on Condvar::wait_timeout. It also uses Condvar::wait_timeout_with, though I can live without it.

log depends on rt::at_exit to cleanup/flush the logger.

Beyond the common ones (such as Thread, transmute and the entry API), rduperemove needs:

  • File::as_raw_fd(), to be able to call the btrfs ioctls. Without this, I would need to drop to the C apis for opening files.
  • ptr::zero_memory(), on the process of allocating the flexarray that the ioctls expect. Not exactly required, bu definitely convenient.

https://github.com/renato-zannon/rduperemove/blob/5c2ed5ae5a00901dc7111d1890814af93e79aa73/lib/btrfs/src/bindings.rs#L74

1 Like

Here are the APIs that I would like to be able to use:

alloc::heap::{
	allocate,
	deallocate,
	reallocate,
	reallocate_inplace,
	usable_size
}

ptr::{
	copy_memory,
	copy_nonoverlapping_memory,
	set_memory
}

raw::{
	Slice,
	TraitObject,
}

I have used the heap & ptr APIs to implement low level structures, for example my byte buffer abstraction:

https://github.com/carllerche/mio/blob/master/src/buf/ring.rs

or my slab:

https://github.com/carllerche/mio/blob/master/src/util/slab.rs

In these cases, I want to do away with any bounds checking and any extra overhead.

Regarding the other APIs such as heap::reallocate_inplace() I plan to use them to make significant optimizations to my Future & Stream implementation (though it currently isn't done).

Specifically, when a Future is passed a completion callback, right now I always wrap the callback in a Box, however, I plan to use the various heap APIs to be able to conditionally store the callback in the future's allocated memory itself if it fits in order to reduce allocations.

Finally, I am unsure if this is the best place to post this, but I plan on using unwind::try as part of an actor scheduler that is still in spike mode, but I will get back to once the Future / Stream lib is more polished. I am hoping for this RFC to land for this Specify unwinding by Aatch · Pull Request #638 · rust-lang/rfcs · GitHub

I should also note that I would need AsRawFd to be able to use Rust's std::io types with mio

Hyper needs std::io and thread. Specifically, Reader, Writer, Buffer, tcp, ip, spawn, and TaskPool...

From collections:

  • StrExt::split_terminator
  • Vec::drain
  • String::from_str

I specifically use from_str because it isn't overloaded. I've been bitten by to_string accepting things that I thought were a &str, but turned out to be a Result or other type, but the compiler accepted it anyway since it also has a to_string impl.

From std_misc:

  • CString
  • c_str_to_bytes
  • AsciiExt::to_ascii_lowercase

The ASCII support is important for GLSL shaders, as they are defined to be ASCII text.

From core:

  • Debug/Display
  • Error
  • Send
  • FromStr
  • FromPrimitive
  • Int::zero
  • PtrExt::as_ref
  • RefCell::try_borrow_mut
  • ContravariantLifetime
  • full-slice syntax &foo[] No longer used given new Deref impls that allow &*foo

Error only used in so far as I try to be compatible with whatever the stdlib decides on its error handling story. I have my own error handling API that expands on it, providing stacktraces and kind information.

Int::zero is useful for a function I have that checks error codes by comparing a generic integer type against 0.

FromStr is good for types that have a simple, canonical text representation and don't require the full machinery of rustc-serialize.

PtrExt::as_ref: is convenient to gain autoderef behavior, and to assert that the pointer has been checked and assured safe.

ContravariantLifetime is used for structs that aren't technically borrowed, but are conceptually borrowed, or have ffi drop semantics that need to be guaranteed to happen within a certain scope.

I'm using AtomicUsize (specifically load and compare_and_swap) which is stable but has no stable member functions.

I'm also using thread pools but I'd have no problem farming that functionality out to a separate crate (actually, I think this would be preferable).

@stebalien I have a ThreadPool implementation here: https://github.com/carllerche/syncbox/blob/master/src/util/thread_pool.rs :smile:

1 Like

Oh of course. Hyper headers make a lot of use out of FromStr and fmt::Display.

std::thunk is currently the only way to use a Box<FnOnce> (because FnOnce is not object-safe). Not stabilizing it would hurt Glium and probably all libraries that have a queue of functions.

In a small lisp implementation I wrote, I use several unstable string-related APIs in the parser/lexer including:

  • collections::str::StrExt::{char_at, contains_char, escape_default, is_char_boundary}
  • collections::string::ToString

Evidently, for loops currently rely on or are part of core; those would be nice to be stable :wink:

The Entry API

core

std::borrow::BorrowFrom (3)
std::error::Error
std::fmt::{Debug,Display} (1)
std::iter::IteratorExt:partition
std::iter::AdditiveIterator
std::iter::Peekable::peek (1)
std::num::from_str_radix
std::ptr::copy_nonoverlapping_memory (4)
std::raw::Slice (2)
std::slice::from_raw_parts
  1. Stabilized
  2. Replaced with unstable std::slice::from_raw_parts
  3. Stabilized as std::borrow::Borrow
  4. Stabilized as std::ptr::copy_nonoverlapping

std_misc

std::ascii::AsciiExt::eq_ignore_ascii_case (1)
std::str::StrExt::find_str (2)
std::str::StrExt::slice_shift_char
std::num::Float::{is_nan,nan,infinity,neg_infinity,is_infinite,zero,neg_zero}
  1. Stabilized
  2. Stabilized as std::str::StrExt::find

collections

std::slice::SliceExt::tail
std::str::StrExt::slice_chars
std::string::String::from_str (1)
std::vec::Vec::drain
  1. Replaced by ToOwned::to_owned

rustc_private

arena::TypedArena

alloc

std::rt::heap::{allocate,deallocate} (1)
  1. Replaced by Vec<u8>.

test

test::Bencher

I haven't evaluated to see if each of these has comparable replacements in functionality and performance, this is just from the list of warnings I got when removing the feature attributes.

What about other APIs? I also am using alloc, box_syntax, rustc_private, and test.

drain still has some open design questions. In particular it could theoretically be replaced by a more robust remove_range method that allows draining of arbitrary subranges. It's not clear if drain needs an entire seperate method.

In general this list should largely just be for APIs in "std and below" libraries. For example features like alloc should definitely fall under this list (aka alloc::heap::* as @carllerche desired as well). The rustc_private feature is intended to be used for libraries above std (the compiler and its supporting libraries), and it is not planned that we will un-feature-gate these APIs for 1.0 (but all useful ones should be available on crates.io). The test feature is somewhat of a stickler in that we do not currently have plans to stabilize it, but we definitely understand that there is very much a desire to stabilize at least portions of it!

Language features like box_syntax will require further RFCs and we can save for other threads, We'll just stick to #[unstable] APIs here for now.

That's an interesting possibility, but at least for my part, I think draining the entire collection will be sufficiently common that having a function for it will pull its own weight by making more nuanced uses that require remove_range easier to spot. This is also consistent with the already stable clear, which could technically also be done by removing the full range of elements, but is sufficiently common as to warrant its own function.

In any case, as long as the functionality is available in some form or other that's what's really important.

1 Like

Thanks, @alexcrichton. I think I understood what you said, but I'll readily admit to not having a model of what is above/below std. I've updated my post with items I'd be up-the-creek without.

I use std::ascii::escape_default. I agree that it needs to be changed to return iterators. Perhaps a byteslice utility should be provided as well, because a big use case here is to escape byte slices.