Open aturon opened 7 years ago
@le-jzr I'd love to have automatic implementations like that - it'd also be possible to implement Read
automatically for BufRead
types. We may need to wait until after specialization stabilizes to be able to add them, though, since I believe you need to enable the feature to specialize an implementation.
I think this RFC ("Allow comparisons between integers of different types") is also relevant here. Much like default binding modes for match
, it takes a case where the compiler today issues errors and forces people to manually write boilerplate and makes it just do the obviously right thing instead. (Except in this case, the manual boilerplate is also highly error-prone.)
use
inside trait
definitions.
Local use
statements are an extremely cool rust feature. But unfortunately, there're some places where you can't use them. One of such places are trait definitions.
Long story short, I want to be able to write something like this:
trait Foo {
use std::iter::IntoIterator;
// ...
}
@suhr: That's https://github.com/rust-lang/rfcs/pull/1976, and it's about to get postponed.
It turned out trickier than folks thought. I think you can mostly work around it using submodules judiciously.
mod UseNo1 {
use std::iter::IntoIterator;
pub(super) trait Foo { ... }
} // UseNo1
pub use UseNo1::*;
it's about to get postponed
Well, that's unfortunate.
I think you can mostly work around it using submodules judiciously.
It's an ugly and awkward kludge that is not worth it.
I wonder if this would get a different reaction in the context of this thread.
RFC: https://github.com/rust-lang/rfcs/pull/2063
link to text:
https://github.com/dobkeratops/rfcs/blob/infer-function-signatures-from-trait-declaration-into-'impl's/text/infer%20function%20signatures%20from%20trait%20declaration%20into%20impls.md
alternating between languages, I continue to find the need to micromanage traits to be irritating (i.e. the single function trait case), but strangely in haskell the typeclasses don't feel as bad. It's because the there, defining and referring to the 'type class' saves you writing details out again. Initially I found it odd, but their function signatures being split are actually clearer.
Hence this PR.
People are complaining 'you read it more than you write it' but it's the repetition that is annoying: if I'm specifying the types , I would rather it figures out the trait from them. If I've specified the trait, it makes sense to use that to infer the types. Users are going to read the trait declaration itself more surely, which has all the types, and you need to refer back to that to implement anyway, surely. Aren't you just taking up more screenspace in a useless way displaying it again. The trait defs are very easy to grep for ( i have that all working nicely in emacs), and there's rustdoc too.
Something else to mention is this mental flip of arguments in the single-function-trait case (e.g. used for overloading)..
I wish you could write the impl the other way round so that it's impl Type:Trait<..>
, so the types appear in the same order as the function definition
e.g.
// "I want to implement LHS.add(RHS)->Output"
impl LHS:Add<RHS> { type Output=..; // trait: "LHS,add, RHS, Output.."
// | | |
fn add(&self,rhs){... } //function: "add LHS,RHS,Output"
}
wouldn't that be so much bettter? the mental flip between the intent "LHS,add,RHS" and expressing the trait makes the trait so much more annoying.
Again the 'multi-parameter-typeclass' case in haskell is more pleasant, possibly because you get to choose the order, so in the case of 'a single function class' you can write the class-types in the same order as the function types. (there's extra symmetry from the fact they have no 'self', but with better ordering I don't think special-Self would be a pain)
Combined with eliding the signature types, that might be enough for me to achieve peace with this system.
I believe mutability, references, lifetimes, etc. change that calculation somewhat from Haskell, so maybe wait until folks become more comfortable with lifetime elision for impls
https://github.com/rust-lang/rust/issues/15872 ?
At least one can then deduce if type elision ever confuses the reader familiar with lifetime elision. If so, type elision could be restricted to cases where lifetime elision works. And maybe it should be restricted to not doing mut
s anyways.
most of the time operators are just reference inputs, and the lifetime elision kicks in; Thinking in C++, I'm used to 2 main cases which are both quite simple:
So basically the times you actually need to write lifetimes, you're doing something rarer (IMO).
Eliding information in the obvious cases will give you more 'cognitive budget' to spend on the unusual.
Also the information is still there and will surface if you hit compile.
I argue people reading code are more likely to be reading the trait, which does have the full types.
also I argue haskell's split is actually helping readability, regardless of how much type information there is
Conversely if I must write out the types then I'd prefer it to do the opposite: figure out the trait from the types.
This reminds me of years of people in C++ claiming "writing out the iterator types is good for you..", delaying the deployment of 'range based for', 'auto' ..
Point of contact
@nikomatsakis @aturon @withoutboats
Overview
As part of the effort to lower Rust's learning curve, we are interested in pursuing a number of language improvements that will make Rust both nicer to use and easier to learn. The goal is to enhance productivity without sacrificing Rust's other core values. See the README for more details.
A kind of manifesto for this work was written up on the main blog.
Status
There are a lot of ideas in flight! The lang team has been focused on writing RFCs for the biggest changes; there are lots of opportunities to help either there, or with more narrow RFCs. If you are interested in the ideas listed below, please contact @aturon or others on the team to hook you up with a mentor for RFC writing!
The potential improvements are organized by broad areas of Rust:
Ownership/borrowing
RFCs
Sketches
AsRef
coercions) (@aturon)Copy
types (@aturon)Traits
RFCs
impl Trait
stabilization and expansion (@aturon)impl Trait
work, e.g.impl Trait
in traits (@aturon, @cramertj, @eddyb, @withoutboats)T: SomeTrait
Sketches
dyn Trait
syntax for trait objects (@nikomatsakis, @aturon)Module and privacy system
Landed
pub(restricted)
is stable!RFCs
extern crate
to take a list (@withoutboats)Sketches
Error handling
RFCs
?
to work with more types (@nikomatsakis)?
inmain
(@nikomatsakis)Result
when leaving a block (@scottmcm, @nikomatsakis, @aturon)Try<Ok=()>
: https://github.com/rust-lang/rfcs/pull/2120Primitive types/core traits
Sketches
String
(@aturon)PartialEq
/PartialOrd
(@aturon)#[derive(Data)]
Type annotations/verbosity
RFCs
const
/static
declarations (@schuster)Sketches
match
arms::
infoo::<u32>(blah)
, in at least the single-argument caseFFI
Landed
Other
RFCs
async
/await
notation built on top; we are considering landing that experimentally in the compiler.More ideas
return
and closuresIdeas that didn't make it
else match