I’ve read through most of the 2018 features, and one thing I found lacking, which is essential for trying them out, is how to “enable” them and how to “lint” for opportunities to apply them. (For some there is information on how to enable, but for most there isn’t.)
For example one of my favorite additions, the dyn Trait one is enabled by default, but you have to also #[warn(bare_trait_objects)] in order to get pointed to where it should be applied.
Regarding the module system changes, I have two “minor issues” with the path clarity feature, namely:
- I found it to be extremely useful to always use
extern cate something, as it provides a nice overview from the source code of what libraries are used;
- using just
crate struct Something (instead of pub(crate) struct Something) has two drawbacks:
- for once it overloads the “semantic” of the keyword
crate; (you can use it (although optionally) in extern crate something, as a “root” for module paths as in use crate::something, then as a visibility modifier crate struct Something, and I’m sure there are other options I don’t know of;)
- having only
pub and pub(<something>) as the only visibility specifier made things easier to search for (for example via regular expressions), and it was also more “intuitive” for people not accustomed with all of Rust’s “specificities”;
Regarding the new ownership and lifetimes features:
-
the anonymous lifetime – I tried to enable
#[warn(elided_lifetimes_in_paths)] to see where it might be applied and I think it’ll take me an entire day to correct my code… moreover I don’t see exactly what advantages does it bring? (I mean if a function returns a structure which contains borrowed values, then the compiler will complain, thus it will be even more clearer than looking into the definition of that function; moreover it will make refactoring code even more involved when one introduces a new lifetime in an internal structure;)
-
in-band lifetimes and lifetime elision in
impl – I love these feature as it will make my life easier (and my signatures more sane);
-
default match bindings – i.e. no more random sequences of
&, ref and * in my match statements – love this!
Just wanted to say I also love these three additions, especially the impl Trait which makes it even more easier to create generic functions (and thus hopefully improve performance).
For example I had a lot of functions like pub fn some_functionality <FirstValueRef : AsRef<Value>, SecondValueRef<AsRef<Value>> (first : &FirstValueRef, second : &SecondValueRef) { ... } which I now can write as simple as pub some_functionality (first : &impl AsRef<Value>, second : &impl AsRef<Value>) {...}. Moreover I also have some functions that use plain &Value as arguments, which I can now transform into generics by just “find-and-replace” &Value with &impl AsRef<Value>.
Moreover the addition of &dyn Trait allows me to visually find places in my code where I could use &impl Trait in order to convert them to generics.
All in all great work on getting Rust more “production friendly”!
I welcome any change that reduces the random “character soup” (which as said involves &, *, ref and similar) especially in match statements and working with simple wrappers such as Option<&T> or references.