Description
How often have you seen a message like:
error: mismatched types: expected
()
but foundint
(expected () but found int)
when writing an impl, and responded (with some head-scratching): "Nonsense! This trait's method definitely returns an int, not unit!" ... only to then read further down the compiler output and see:
error: method
foo
has an incompatible type for trait: expected int but found ()
I know it happens to me a lot.
Sample code to illustrate this:
#![crate_type="lib"]
trait A {
fn foo(self) -> int;
}
struct B;
impl A for B {
fn foo(self) {
if 0i == 1i {
return 3i;
}
*4i; // (insert an arbitary number of ill-typed expressions here.)
3i
}
}
which yields the transcript:
% DYLD_LIBRARY_PATH=./objdir-dbgopt/x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib ./objdir-dbgopt/x86_64-apple-darwin/stage2/bin/rustc /tmp/g.rs
/tmp/g.rs:9:20: 9:22 error: mismatched types: expected `()` but found `int` (expected () but found int)
/tmp/g.rs:9 return 3i;
^~
/tmp/g.rs:11:9: 11:12 error: type `int` cannot be dereferenced
/tmp/g.rs:11 *4i; // (insert an arbitary number of ill-typed expressions here.)
^~~
/tmp/g.rs:12:9: 12:11 error: mismatched types: expected `()` but found `int` (expected () but found int)
/tmp/g.rs:12 3i
^~
/tmp/g.rs:7:5: 13:6 error: method `foo` has an incompatible type for trait: expected int but found ()
/tmp/g.rs:7 fn foo(self) {
/tmp/g.rs:8 if 0i == 1i {
/tmp/g.rs:9 return 3i;
/tmp/g.rs:10 }
/tmp/g.rs:11 *4i; // (insert an arbitary number of ill-typed expressions here.)
/tmp/g.rs:12 3i
...
error: aborting due to 4 previous errors
As noted in the program comment, there can be an arbitrary number of type errors before one sees the report of the signature mismatch between the trait and its impl.
In principle there is no "100% right" ordering here between these messages, because there are scenarios where the right response to this message is to revise the trait definition (so that its method signature is changed to match the one in the impl you are writing).
But I believe that in most cases, the trait definition has been worked out long ahead of time (and is often fixed/unchangeable), while the impl itself is under active development, and therefore it would be more helpful to the user if in the final error report, the mismatches between the trait and its impl(s) are reported before the error when attempting to type-check the body of the impl itself.
(I am not super familiar with the code that drives these checks; it could be that fixing this is as simple as reordering a few statements.)