Skip to content

in impl A for B, report trait/impl sig inconsistency before method/body inconsistency #15657

Closed
@pnkfelix

Description

@pnkfelix

How often have you seen a message like:

error: mismatched types: expected () but found int (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.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lints

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions