The following gates: plugin, box_syntax, custom_derive, custom_attribute
were ignored for this analysis because these are features we don't plan on moving off unless absolutely necessary. Nevertheless, they're not strictly necessary for Servo to work; they just make some code nicer.
The main point of this exercise was to find what unstable APIs Servo uses/needs a lot, which might probably be needed by others too. Most of these have workarounds, and most of these are blocked on trivial things like naming (and could be easily stabilized). While I did remove some unstable usage in Servo, I didn't fix the majority of these even though it was easy to fix because we use nightly anyway (plugins, etc) and it would be nice to end up with the final, polished, performant APIs instead of a slightly more verbose workaround that we'll forget about.
collections
almost everywhere is just blocked on Vec.push_all()
. We can immediately use extend()
here if we want, or a for loop, but if this API is going to be replaced with
something performant, I'd prefer to keep the existing code till it breaks and tells us the
better API to use.
alloc
needs Rc.make_unique()
/Arc.make_unique()
(which is unstable for some unknown reason), and from_raw
/into_raw
for Box
(which are unstable for naming reasons). FnBox
is also needed.
Other APIs which got used in more than one crate:
[T].tail()
(naming)slice::bytes::copy_memory
(needs review)NonZero
DefaultState
(and the other custom hasher stuff to a lesser degree)step_by
(recently added)CharRange
(we could replace this easily)Handle
from the select API
Except for NonZero
, DefaultState
, and Handle
I think our API usage for these would be relatively easy to convert to stable APIs. I'm not sure if DefaultState
is necessary to be stable either.
Weak<T>
is something that we don't use much but probably deserves to be stabilized.
Stuff in parentheses is the reason given by the stability tag for its instability. Stuff in brackets is a note on how necessary it is for us and if it could be replaced easily.
collections
:
Vec.push_all()
(May be replaced) [We could replace this with a for loop]
core
:
copy_memory
(needs review) [Can be replaced with other calls eg copy_nonoverlapping]
NonZero
[Not necessary but slight optimization]
core
:
copy_memory
[Can be replaced]
collections
:
push_all
[Can be replaced with a for loop orextend()
]
core
:
Reflect
/Any
stuff [I think the API could be moved to enum-based dynamic dispatch if necessary]
alloc
:
- weak pointers (may not belong) [Using
Rc
here would lead to a slight perf drop, but doable] boxed::into_raw
andfrom_raw
(naming) [Transmutes and other things would work]
collections
:
Vec.push_all()
(May be replaced) [Can be fixed with a loop orextend()
]
core
:
min_by
(#15311) [Could just use a loop]PI_2
(naming) [Can just use a hardcoded constant]
rustc_private
:
FnvHasher
[I think we can just use rust-fnv here]
std_misc
:
- Hash state stuff [I think this isn't necessayr, but
DefaultState
would be nice to have stable]
str_char
:
CharRange
usage [Can be replaced by regular iterators (char_indices
)]
We do lots of crazy pointer-fu and optimizations here. Perhaps this section should be ignored.
alloc
:
make_unique()
- direct calls into
heap::allocate()
, etc boxed::into_raw()
(naming)
collections
:
slice_chars()
(needs to prove its worth)
core
:
- lots and lots of pointer manip
raw
stuff
std_misc
:
Handle
stuff- hasher stuff
str_char
:
CharRange
[Can be replaced with an iterator]
unsafe_no_drop_flag
- For pointer-fu
std_misc
:
Handle
usage (API will be replaced and is perhaps broken) [No replacement without restructuring the code, which isn't too hard]
path_ext
:
- Checking if a file exists. [This is doable from the File directly, but needs some method chaining]
core
:
FnBox
alloc:
boxed::into_raw()
(naming)
collections
:
push_all
again [ for loop orextend()
]
step_by
: step_by
[Could easily be replaced by a loop]
Ahahahaha nope.
collections
:
[T].tail()
(naming) [use iterators]
alloc
:
Rc.make_unique()
into_raw
/from_raw
(naming). All over the bindings code.
collections
:
Vec.push_all()
from_str
- can be replaced by
.to_owned()
- can be replaced by
from_raw_buf
- could be done directly
core
:
nonzero
[ just a perf improvement]UnsafeCell
(as_unsafe_cell
) [For our own interior mutability structs with DOM integration.]Zeroable
[Not really necessary]Peekable.is_empty
[Not really necessary]
std_misc
:
Handle
stuff
alloc
:
Arc.make_unique()
everywhere
core
:
intrinsics::discriminant_value
for a small optimization. Not sure what's happening here
hash
:
Hasher.write_u16
(recently redesigned)
alloc
/ OIBIT : For deque (which was just copied from rust's source). Probably could be cleaned up to not use these.
collections
:
[T].tail()
to_lowercase()
core
:
FnBox
intrinsics::breakpoint()
[only used for debugging[
exit_status
: for setting exit status [Could be done in other ways]
path_ext: for is_dir
and exists()
[can be done in other ways]
step_by
/step_trait
: [use regular loops]
std_misc
:
Thunk
(same asFnBox
)DefaultState
and other hasher stuff
zero_one
: num::One
[Not really necessary]
ip_addr
: for SocketAddr
(new)