Unstable features used by the 100 most popular crates

Here’s a list of the unstable features used by the 100 most popular crates on crates.io (by reverse deps). Perhaps this query and others like it can help drive stabilization decisions.

30 crates report using some unstable feature. A number are just using the test feature, presumably only in the test suite, mostly for benchmarking it seems. Some also seem to be cfgd to optionally support nightly features.

work/ex/unstable/res/stable/reg/bincode-0.6.0/log.txt
2:boom! unstable-feature: custom_attribute
3:boom! unstable-feature: custom_derive
4:boom! unstable-feature: plugin

work/ex/unstable/res/stable/reg/nom-2.0.1/log.txt
2:boom! unstable-feature: trace_macros

work/ex/unstable/res/stable/reg/pkg-config-0.3.8/log.txt
2:boom! unstable-feature: static_mutex

work/ex/unstable/res/stable/reg/bit-vec-0.4.3/log.txt
2:boom! unstable-feature: bit_vec_append_split_off
3:boom! unstable-feature: collections
4:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/tokio-core-0.1.2/log.txt
2:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/rand-0.3.15/log.txt
2:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/serde_derive-0.8.21/log.txt
2:boom! unstable-feature: proc_macro
3:boom! unstable-feature: proc_macro_lib

work/ex/unstable/res/stable/reg/image-0.10.4/log.txt
2:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/csv-0.14.7/log.txt
2:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/rustc-serialize-0.3.22/log.txt
2:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/cgmath-0.12.0/log.txt
2:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/quickcheck_macros-0.4.0/log.txt
2:boom! unstable-feature: custom_attribute
3:boom! unstable-feature: plugin
4:boom! unstable-feature: plugin_registrar
5:boom! unstable-feature: rustc_private

work/ex/unstable/res/stable/reg/clippy-0.0.104/log.txt
2:boom! unstable-feature: associated_consts
3:boom! unstable-feature: associated_type_defaults
4:boom! unstable-feature: attr_literals
5:boom! unstable-feature: borrow_state
6:boom! unstable-feature: box_syntax
7:boom! unstable-feature: collections
8:boom! unstable-feature: const_fn
9:boom! unstable-feature: custom_attribute
10:boom! unstable-feature: inclusive_range_syntax
11:boom! unstable-feature: never_type
12:boom! unstable-feature: non_ascii_idents
13:boom! unstable-feature: plugin
14:boom! unstable-feature: plugin_registrar
15:boom! unstable-feature: rustc_private
16:boom! unstable-feature: static_in_const
17:boom! unstable-feature: step_by
18:boom! unstable-feature: test
19:boom! unstable-feature: untagged_unions

work/ex/unstable/res/stable/reg/regex_macros-0.1.38/log.txt
2:boom! unstable-feature: plugin_registrar
3:boom! unstable-feature: quote
4:boom! unstable-feature: rustc_private

work/ex/unstable/res/stable/reg/byteorder-0.5.3/log.txt
2:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/time-0.1.35/log.txt
2:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/json-tools-0.3.0/log.txt
2:boom! unstable-feature: collections
3:boom! unstable-feature: core
4:boom! unstable-feature: io
5:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/lazy_static-0.2.2/log.txt
2:boom! unstable-feature: const_fn

work/ex/unstable/res/stable/reg/num-0.1.36/log.txt
2:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/itertools-0.5.8/log.txt
2:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/serde_macros-0.8.9/log.txt
2:boom! unstable-feature: plugin_registrar
3:boom! unstable-feature: rustc_private

work/ex/unstable/res/stable/reg/glium-0.15.0/log.txt
2:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/error-chain-0.7.2/log.txt
2:boom! unstable-feature: trace_macros

work/ex/unstable/res/stable/reg/regex-0.1.80/log.txt
2:boom! unstable-feature: plugin
3:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/docopt-0.6.86/log.txt
2:boom! unstable-feature: plugin

work/ex/unstable/res/stable/reg/nalgebra-0.10.1/log.txt
2:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/compiletest_rs-0.2.5/log.txt
2:boom! unstable-feature: rustc_private
3:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/uuid-0.3.1/log.txt
2:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/hyper-0.9.14/log.txt
2:boom! unstable-feature: test

work/ex/unstable/res/stable/reg/syntex_syntax-0.52.0/log.txt
2:boom! unstable-feature: ...
3:boom! unstable-feature: prelude_import
4:boom! unstable-feature: {}

(Clearly my parser needs some work)

1 Like

How did you determine this?

The list should be taken with a grain of salt.

These crates are popular because they work on stable, and maybe they don’t use some features that they would like to use because these features are unstable.

Not every crate writer has the motivation to add an unstable Cargo feature that enables more things.

3 Likes

The popularity is determined by the number of reverse dependencies each crate has, which can be calculated from the crates.io index.

More specifically, I first get the set of dependencies for every crate, discarding version numbers. So for every crate I have a map of its dependencies, from crate name to crate name. Then I do a simple sum of the direct reverse dependencies of every crate by walking over every crates dependencies.

Absolutely. Take it anyway it pleases you.

What I'm looking for is a simple metric that can be used to track the amount of nightly dependency, and also tools to help us decide what features to prioritize.

This seems like a good start to me. If we could e.g. make all these crates "green", that's better than today, where 30% are "red".

I'd love to hear suggestions for other techniques to track progress toward stabilization.

Note that some crates would like to use certain features that are presently unstable, but cannot because they must work on stable, nor can they provide a nightly cfg for it because it would be too major of an API change.

Like for winapi, I’d really like to use the new untagged unions, but I can’t yet. Making unions use that new feature would significantly change their API relative to the current hack, so a nightly cfg is out of the question.

5 Likes

Unstable features should be well tested before making them stable. So if the community don’t care enough to provide nightly builds for a crate using a specific feature, maybe that is a sign that this feature is not well tested yet, it is not mature enough to be stabilized.

Creating a separate version of your library that uses an unstable feature makes the code considerably more complex.

If you take features like the ? operator or break/continue being able to return a value for example, which are features that only affect the internals of your crate, it’s not worth making the code considerably more difficult to read just to use a feature that’s supposed to make the code slightly easier to read.

If you take features like -> impl Trait or ! being a proper type for example, which have an impact on a crate’s API, it’s too cumbersome to distribute two different versions of the crate with two different APIs and two different documentations. Nobody is going to use the unstable version anyway unless the gains are very substantial (which is the case for only very few features like plugins for example).

7 Likes

Interesting that try_from didn’t show up in this list. I use that in several of Ruma’s crates, and I feel like I’ve seen it a lot in other crates, though I can’t recall which offhand.

1 Like

It's limited to the 100 most popular crates, so misses a lot. I'd rather see an aggregation of unstable features used across all crates, sorted by frequency of use.

Here's the list of features ordered by the number of times its used by a crate on crates.io, counting all crates, reproduced below.

Here's the raw data.

    498 test
    268 plugin
    164 rustc_private
    156 plugin_registrar
    131 core
     97 collections
     85 custom_derive
     84 quote
     84 box_syntax
     65 libc
     64 alloc
     63 phase
     59 std_misc
     53 proc_macro
     50 const_fn
     49 unboxed_closures
     48 io
     44 custom_attribute
     42 macro_rules
     41 asm
     40 slice_patterns
     36 core_intrinsics
     36 convert
     33 heap_api
     31 unsafe_destructor
     31 globs
     29 question_mark
     26 unique
     26 box_patterns
     24 step_by
     24 old_io
     23 unicode
     23 associated_type_defaults
     22 associated_consts
     21 slicing_syntax
     19 zero_one
     19 proc_macro_lib
     18 path
     18 no_std
     15 trace_macros
     15 stmt_expr_attributes
     15 specialization
     15 optin_builtin_traits
     15 fs
     14 path_ext
     14 filling_drop
     13 unsafe_no_drop_flag
     13 type_ascription
     13 fnbox
     13 conservative_impl_trait
     13 alloc_system
     12 oom
     12 collections_bound
     11 env
     10 rand
     10 if_let
     10 hash
     10 allocator
      9 try_from
      9 raw
      9 os
      9 lang_items
      9 concat_idents
      8 old_path
      8 iter_arith
      8 inclusive_range_syntax
      8 hashmap_hasher
      8 core_slice_ext
      8 btree_range
      7 type_macros
      7 str_char
      7 prelude_import
      7 non_ascii_idents
      7 fn_traits
      7 coerce_unsized
      6 unsize
      6 start
      6 staged_api
      6 simd
      6 reflect_marker
      6 placement_in_syntax
      6 linkage
      6 drain
      6 associated_types
      5 vec_push_all
      5 scoped
      5 repr_simd
      5 old_orphan_check
      5 nonzero
      5 macro_reexport
      5 get_type_id
      5 dropck_parametricity
      5 default_type_params
      5 cfg_target_feature
      5 catch_panic
      5 box_raw
      5 augmented_assignments
      5 append
      5 {}
      4 untagged_unions
      4 tuple_indexing
      4 simd_ffi
      4 shared
      4 rt
      4 platform_intrinsics
      4 op_assign_traits
      4 mpsc_select
      4 main
      4 link_llvm_intrinsics
      4 ip_addr
      4 int_uint
      4 fs_walk
      4 fixed_size_array
      4 exit_status
      4 core_prelude
      4 ...
      3 thread_local
      3 tempdir
      3 tcp
      3 str_escape
      3 std_panic
      3 static_in_const
      3 slice_bytes
      3 scheme
      3 rustc_macro
      3 result_expect
      3 recover
      3 read_exact
      3 rc_weak
      3 pub_restricted
      3 ptr_as_ref
      3 process_exec
      3 process
      3 placement_new_protocol
      3 pattern
      3 path_relative_from
      3 num_bits_bytes
      3 net
      3 naked_functions
      3 lookup_host
      3 link_args
      3 ip
      3 intrinsics
      3 into_cow
      3 integer_atomics
      3 fs_time
      3 enumset
      3 duration
      3 drop_types_in_const
      3 core_float
      3 compile
      3 collections_range
      3 arc_counts
      3 
      2 unmarked_api
      2 time2
      2 step_trait
      2 static_mutex
      2 slice_concat_ext
      2 sip_hash_13
      2 set_stdio
      2 set_recovery
      2 rustdoc
      2 rustc_attrs
      2 page_size
      2 on_unimplemented
      2 no_core
      2 never_type
      2 iter_order
      2 iter_cmp
      2 forktable
      2 float_extras
      2 field_init_shorthand
      2 clone_from_slice
      2 braced_empty_structs
      2 bit_vec_append_split_off
      2 advanced_slice_patterns
      1 wrapping
      1 while_let
      1 wait_timeout
      1 vecmap
      1 unwind_attributes
      1 unboxed_closure_sugar
      1 types]
      1 thread_sleep
      1 str_words
      1 structural_match
      1 string_split_off
      1 split_off
      1 slice_splits
      1 scoped_tls
      1 rustc_macro_lib
      1 rustc_builtins
      1 repeat_str
      1 read_and_zero
      1 rc_unique
      1 rc_counts
      1 range_inclusive
      1 panic_propagate
      1 ordering_chaining
      1 negate_unsigned
      1 map_values_mut
      1 map_in_place
      1 map_entry_recover_keys
      1 managed_boxes
      1 log_syntax
      1 list
      1 linked_list_extras
      1 iter_idx
      1 iter_arith_traits
      1 io_take_into_inner
      1 inclusive_range
      1 import_shadowing
      1 hasher_write
      1 hash_default
      1 fused
      1 fs_ext
      1 fs_canonicalize
      1 float_from_str_radix
      1 drop_in_place
      1 dir_entry_ext
      1 dir_builder
      1 deque_extras
      1 deprecated
      1 debug_builders
      1 cstr_to_str
      1 cstr_memory
      1 copy_from_slice
      1 collections_drain
      1 cfg_target_vendor
      1 cell_extras
      1 btree_append
      1 borrow_state
      1 binary_heap_extras
      1 attr_literals
      1 as_unsafe_cell
2 Likes

I don’t think this is a good way to prioritize features. Basically it punishes people who put in extraordinary effort to make their crate work with the existing Stable Rust limitations (e.g. using C to implement things that can’t be done in Rust, or implementing other nasty workarounds). For example, I’d love to see const_fn in Stable Rust. Is the best way to do that to drop support for Stable in my crates and use const_fn now? That’s what this thread is encouraging, and it would make my code prettier (fewer macros in my code simulating const_fn).

Besides counting the crates that use a particular feature, we must also count the crates that don’t use a particular feature. 498 crates using the test feature seems like a lot until you consider there’s over 7,000 crates on crates.io, so 498 is less than 7%. This is the upper bound on the utility of such counting, and that bound is pretty low.

In the case of the test and bench stuff, IMO the fact that rustc-test crate exists means there’s really no work important to do right now, except for encouraging people to use rustc-test instead of the unstable built-in version. In other words, the most important-looking feature in the list isn’t really urgent, considering there’s a simple workaround.

Also keep in mind that people can only use feature flags for features that are already at least partially implemented. There’s no feature flag for #[repr(align)] or for guaranteed-constant-time integer operations, so those features aren’t counted at all. But there are really important features that haven’t even been started yet, which are (IMO) much more important than any of the ones listed.

4 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.