Skip to content

Better error messages for &T == T #40660

Closed

Description

@iqualfragile

Something along the lines of "you are trying to compare a refference to to Type, try dereferencing first" would be nice, right now it just has the usual PartialEq not implemented.

Activity

  1. added
    A-frontendArea: Compiler frontend (errors, parsing and HIR)
    A-docsArea: Documentation for any part of the project, including the compiler, standard library, and tools
    on Mar 20, 2017
  2. estebank commented on Mar 21, 2017

    @estebank
    Contributor

    Would the following output (as proposed in #40565) be enough to make the situation a bit more clear?

    error[E0277]: the trait bound `&T: std::cmp::PartialEq<T>>` is not satisfied
      --> $DIR/file.rs:14:5
       |
    14 |     &t == t;
       |     ^^^^^^^ can't compare `&T` with `T`
  3. iqualfragile commented on Mar 21, 2017

    @iqualfragile
    Author

    that would certainly improve things, but in this case the error message could be even more specific and thereby helpful by providing the information about deref-ing, so i would keep it as a separate issue, i think

  4. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    and removed
    A-docsArea: Documentation for any part of the project, including the compiler, standard library, and tools
    on Apr 25, 2017
  5. added
    A-diagnosticsArea: Messages for errors, warnings, and lints
    and removed
    A-frontendArea: Compiler frontend (errors, parsing and HIR)
    on May 7, 2017
  6. added a commit that references this issue on May 23, 2017
  7. estebank commented on Dec 6, 2017

    @estebank
    Contributor

    Current output for:

    fn main() {
        let x: usize = 3;
        let y: &usize = &3;
        if x == y {
            println!("asdf");
        }
        if y == x {
            println!("asdf");
        }
        if 3 == &3 {
            println!("asdf");
        }
        if &3 == 3 {
            println!("asdf");
        }
    }
    error[E0308]: mismatched types
     --> src/main.rs:4:13
      |
    4 |     if x == y {
      |             ^
      |             |
      |             expected usize, found &usize
      |             help: consider dereferencing the borrow: `*y`
      |
      = note: expected type `usize`
                 found type `&usize`
    
    error[E0277]: the trait bound `&usize: std::cmp::PartialEq<usize>` is not satisfied
     --> src/main.rs:7:10
      |
    7 |     if y == x {
      |          ^^ can't compare `&usize` with `usize`
      |
      = help: the trait `std::cmp::PartialEq<usize>` is not implemented for `&usize`
    
    error[E0277]: the trait bound `{integer}: std::cmp::PartialEq<&{integer}>` is not satisfied
      --> src/main.rs:10:10
       |
    10 |     if 3 == &3 {
       |          ^^ can't compare `{integer}` with `&{integer}`
       |
       = help: the trait `std::cmp::PartialEq<&{integer}>` is not implemented for `{integer}`
    
    error[E0277]: the trait bound `&{integer}: std::cmp::PartialEq<{integer}>` is not satisfied
      --> src/main.rs:13:11
       |
    13 |     if &3 == 3 {
       |           ^^ can't compare `&{integer}` with `{integer}`
       |
       = help: the trait `std::cmp::PartialEq<{integer}>` is not implemented for `&{integer}`
    

    There's room for improvement.

  8. estebank commented on Mar 8, 2019

    @estebank
    Contributor

    Current output

    error[E0308]: mismatched types
     --> src/main.rs:4:13
      |
    4 |     if x == y {
      |             ^
      |             |
      |             expected usize, found &usize
      |             help: consider dereferencing the borrow: `*y`
      |
      = note: expected type `usize`
                 found type `&usize`
    
    error[E0277]: can't compare `&usize` with `usize`
     --> src/main.rs:7:10
      |
    7 |     if y == x {
      |          ^^ no implementation for `&usize == usize`
      |
      = help: the trait `std::cmp::PartialEq<usize>` is not implemented for `&usize`
    
    error[E0277]: can't compare `{integer}` with `&{integer}`
      --> src/main.rs:10:10
       |
    10 |     if 3 == &3 {
       |          ^^ no implementation for `{integer} == &{integer}`
       |
       = help: the trait `std::cmp::PartialEq<&{integer}>` is not implemented for `{integer}`
    
    error[E0277]: can't compare `&{integer}` with `{integer}`
      --> src/main.rs:13:11
       |
    13 |     if &3 == 3 {
       |           ^^ no implementation for `&{integer} == {integer}`
       |
       = help: the trait `std::cmp::PartialEq<{integer}>` is not implemented for `&{integer}`
    
  9. estebank commented on Sep 26, 2019

    @estebank
    Contributor
  10. 1 remaining item

  11. rylev commented on Dec 9, 2020

    @rylev
    Contributor

    Triage: current output is only slightly improved over previous output.

    error[E0308]: mismatched types
     --> src/main.rs:4:13
      |
    4 |     if x == y {
      |             ^
      |             |
      |             expected `usize`, found `&usize`
      |             help: consider dereferencing the borrow: `*y`
    
    error[E0277]: can't compare `&usize` with `usize`
     --> src/main.rs:7:10
      |
    7 |     if y == x {
      |          ^^ no implementation for `&usize == usize`
      |
      = help: the trait `PartialEq<usize>` is not implemented for `&usize`
    
    error[E0277]: can't compare `{integer}` with `&{integer}`
      --> src/main.rs:10:10
       |
    10 |     if 3 == &3 {
       |          ^^ no implementation for `{integer} == &{integer}`
       |
       = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}`
    
    error[E0277]: can't compare `&{integer}` with `{integer}`
      --> src/main.rs:13:11
       |
    13 |     if &3 == 3 {
       |           ^^ no implementation for `&{integer} == {integer}`
       |
       = help: the trait `PartialEq<{integer}>` is not implemented for `&{integer}`
    

    It's not clear what should improve to make this better. Should we try to detect if T implements the trait and if so, suggest dereferencing &T?

  12. estebank commented on Jan 12, 2021

    @estebank
    Contributor

    Should we try to detect if T implements the trait and if so, suggest dereferencing &T?

    Yes, I think we should do exactly that. I think that #57621, #52544 and #44695 cover that requirement as well (but lets keep them open and close in one sweep once we fix this).

  13. estebank commented on Oct 18, 2021

    @estebank
    Contributor

    Output with #90006:

    error[E0308]: mismatched types
      --> f16.rs:18:13
       |
    18 |     if x == y {
       |             ^ expected `usize`, found `&usize`
       |
    help: consider dereferencing the borrow
       |
    18 |     if x == *y {
       |             +
    
    error[E0369]: can't compare `&usize` with `usize`
      --> f16.rs:21:10
       |
    21 |     if y == x {
       |        - ^^ - usize
       |        |
       |        &usize
       |
    help: `==` can be applied on `&usize`
       |
    21 |     if y == &x {
       |             +
    help: `==` can be used on `usize`, you can dereference `y`
       |
    21 |     if *y == x {
       |        +
    
    error[E0277]: can't compare `{integer}` with `&{integer}`
      --> f16.rs:24:10
       |
    24 |     if 3 == &3 {
       |          ^^ no implementation for `{integer} == &{integer}`
       |
       = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}`
    
    error[E0277]: can't compare `&{integer}` with `{integer}`
      --> f16.rs:27:11
       |
    27 |     if &3 == 3 {
       |           ^^ no implementation for `&{integer} == {integer}`
       |
       = help: the trait `PartialEq<{integer}>` is not implemented for `&{integer}`
    
  14. added
    D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.
    on Jan 5, 2023
  15. estebank commented on Nov 17, 2023

    @estebank
    Contributor

    Another case that should be accounted for (from #67571):

    struct MyType<T>
        where T: PartialEq,
    {
        data: T,
    }
    
    impl<T> MyType<T>
        where T: PartialEq,
    {
        fn write(&mut self, data: T) {
            self.data = data;
        }
    
        fn matches(&self, data: &T) -> bool {
            data == self.data
        }
    }
    
    fn main() {
        let foo: MyType<String> = MyType { data: String::from("ABC") };
        let bar = String::from("XYZ");
    
        if foo.matches(&bar) {
             println!("{:?}", bar);
        }    
    }
  16. estebank commented on Nov 17, 2023

    @estebank
    Contributor

    Triage, few changes:

    error[E0308]: mismatched types
     --> src/main.rs:4:13
      |
    4 |     if x == y {
      |        -    ^ expected `usize`, found `&usize`
      |        |
      |        expected because this is `usize`
      |
    help: consider dereferencing the borrow
      |
    4 |     if x == *y {
      |             +
    
    error[E0277]: can't compare `&usize` with `usize`
     --> src/main.rs:7:10
      |
    7 |     if y == x {
      |          ^^ no implementation for `&usize == usize`
      |
      = help: the trait `PartialEq<usize>` is not implemented for `&usize`
      = help: the trait `PartialEq` is implemented for `usize`
      = help: for that trait implementation, expected `usize`, found `&usize`
    
    error[E0277]: can't compare `{integer}` with `&{integer}`
      --> src/main.rs:10:10
       |
    10 |     if 3 == &3 {
       |          ^^ no implementation for `{integer} == &{integer}`
       |
       = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}`
       = help: the following other types implement trait `PartialEq<Rhs>`:
                 isize
                 i8
                 i16
                 i32
                 i64
                 i128
                 usize
                 u8
               and 6 others
    
    error[E0277]: can't compare `&{integer}` with `{integer}`
      --> src/main.rs:13:11
       |
    13 |     if &3 == 3 {
       |           ^^ no implementation for `&{integer} == {integer}`
       |
       = help: the trait `PartialEq<{integer}>` is not implemented for `&{integer}`
       = help: the following other types implement trait `PartialEq<Rhs>`:
                 isize
                 i8
                 i16
                 i32
                 i64
                 i128
                 usize
                 u8
               and 6 others
    
  17. sjwang05 commented on Nov 28, 2023

    @sjwang05
    Contributor

    I've gotten the output to look like this:

    fn main() {
        let x: usize = 3;
        let y: &usize = &3;
        _ = y == x;
        _ = &y == x;
        _ = &&y == x;
        _ = 3 == &3;
        _ = &3 == 3;
    }
    error[E0277]: can't compare `&usize` with `usize`
     --> foo.rs:6:11
      |
    6 |     _ = y == x;
      |           ^^ no implementation for `&usize == usize`
      |
      = help: the trait `PartialEq<usize>` is not implemented for `&usize`
    help: consider dereferencing here
      |
    6 |     _ = *y == x;
      |         +
    
    error[E0277]: can't compare `&&usize` with `usize`        
     --> foo.rs:7:12
      |
    7 |     _ = &y == x;
      |            ^^ no implementation for `&&usize == usize`
      |
      = help: the trait `PartialEq<usize>` is not implemented for `&&usize`
    help: consider removing the borrow and dereferencing instead
      |
    7 -     _ = &y == x;
    7 +     _ = *y == x;
      |
    
    error[E0277]: can't compare `&&&usize` with `usize`
     --> foo.rs:8:13
      |
    8 |     _ = &&y == x;
      |             ^^ no implementation for `&&&usize == usize`
      |
      = help: the trait `PartialEq<usize>` is not implemented for `&&&usize`
    help: consider removing the borrows and dereferencing instead
      |
    8 -     _ = &&y == x;
    8 +     _ = *y == x;
      |
    
    error[E0277]: can't compare `{integer}` with `&{integer}`
     --> foo.rs:9:11
      |
    9 |     _ = 3 == &3;
      |           ^^ no implementation for `{integer} == &{integer}`
      |
      = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}`
      = help: the following other types implement trait `PartialEq<Rhs>`:
                isize
                i8
                i16
                i32
                i64
                i128
                usize
                u8
              and 6 others
    
    error[E0277]: can't compare `&{integer}` with `{integer}`
      --> foo.rs:10:12
       |
    10 |     _ = &3 == 3;
       |            ^^ no implementation for `&{integer} == {integer}`
       |
       = help: the trait `PartialEq<{integer}>` is not implemented for `&{integer}`
    help: consider removing the borrow
       |
    10 -     _ = &3 == 3;
    10 +     _ = 3 == 3;
       |
    
    error: aborting due to 5 previous errors
    
    For more information about this error, try `rustc --explain E0277`.
    

    I'll see if I can get Rhs suggestions working.

    @rustbot claim

  18. estebank commented on Nov 28, 2023

    @estebank
    Contributor

    @sjwang05 if you make a new ObligationCauseCode you should be able to keep both lhs and rhs in it to do this.

  19. sjwang05 commented on Nov 29, 2023

    @sjwang05
    Contributor

    Storing the lhs and rhs HirIds in ObligationCauseCode::BinOp did the trick. Thanks!

  20. added a commit that references this issue on Dec 26, 2023
    2df6406
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsC-enhancementCategory: An issue proposing an enhancement or a PR with one.D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.D-papercutDiagnostics: An error or lint that needs small tweaks.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.WG-diagnosticsWorking group: Diagnostics

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions