These don't seem like insurmountable challenges though. Unnamed impl blocks could work entirely within requirements. There could also be a lint to warn about any fields that are below trait definitions.
struct Example {
number: i32,
}
impl Example {
fn boo() {
println!("boo! Example::boo() was called!");
}
}
trait Thingy {
fn do_thingy(&self);
}
impl Thingy for Example {
fn do_thingy(&self) {
println!("doing a thing! also, number is {}!", self.number);
}
}
This could be expressed as: struct Example {
number: i32,
impl {
fn boo() {
println!("boo! Example::boo() was called!");
}
}
impl Thingy {
fn do_thingy(&self) {
println!("doing a thing! also, number is {}!", self.number);
}
}
}
trait Thingy {
fn do_thingy(&self);
}
Keeping related things together is just infinitely more readable, in my opinion. In fact, the confusing nature of "impl <struct>" becoming "impl <trait> for <struct>" is obviated by internal impl blocks. Keeping them separate just seems so artificial, if not downright dogmatic.
I mean, these are in the same file almost all the time anyway, and in that case all it gives you is an extra level of indentation. I don't think it's nicer at all.
It's comments like this that remind me of the conciseness-at-all-costs dogma: that people genuinely treat indentation as some kind of eldritch horror; that they would genuinely prefer "impl X" becoming "impl Y for X" (thus making it difficult to parse at a glance because the target keeps shifting places) over it. It's bewildering.