This is consistent with traits being as optimistic as plausible. There are all sorts of somewhat-related cases, and every time as long as the types match and it _could_ work, the compiler happily assumes that it does. Here are some others:
// Class can fill in for trait
class Salmon { def foo = "foo" }
trait Foo { def foo: String }
val fish = new Salmon with Foo {}
// Trait can fill in for trait
trait Bippy { def bip: String; def ppy: Int }
trait Biplane { def bip = "bip" }
trait Happy { def ppy = 7 }
val wish = new Bippy with Biplane with Happy {}
// Trait can fill in for class
abstract class Sparrow { def tweet: String }
trait Twitterer { def tweet: String = "@all #roflForLife" }
val gamish = new Sparrow with Twitterer {}
The override is taken to mean "it's all cool here, I found something that satisfies all the constraints", and at that point it's consistent with the optimistic principle.
class Bowl { def food = true }
trait Carrot { def food = true }
val a_ok = new Bowl with Carrot { override def food = false }
And if you don't override it tells you (if you do it this blatantly) how to make it work:
scala> val nogo = new Bowl with Carrot {}
<console>:12: error: <$anon: Bowl with Carrot>
inherits conflicting members:
method food in class Bowl of type => Boolean and
method food in trait Carrot of type => Boolean
(Note: this can be resolved by declaring an override in
<$anon: Bowl with Carrot>.)
So, yes, I agree that the semantics might have changed, but the (optimistic) interpretation of override written explicitly at the point of unification is "I made sure it worked". Maybe this is too optimistic.
--Rex