Skip to content

[E0308] one type is more general than the other: expected and found are reported as same #114849

Closed as not planned
@loganmzz

Description

Code

use std::{
    fmt::Debug,
};

#[derive(Clone,Debug)]
struct Data {
    name: String,
}

impl Data {
    fn new(name: &'static str) -> Self {
        Self {
            name: name.to_owned(),
        }
    }
    fn name(&self) -> &String {
        &self.name
    }
}


fn assert_all<FN, A, E>(
    producer: Vec<Data>,
    f: FN,
    expecteds: Vec<E>,
)
where
    FN: FnMut(&Data) -> A,
    A: Debug + std::cmp::PartialEq<E>,
    E: Debug,
{
    let data = producer.clone();
    let actuals: Vec<_> = data.iter().map(f).collect();
    assert_eq!(actuals, expecteds);
}

fn main() {
    let producer = vec![
        Data::new("first"),
        Data::new("second"),
    ];
    assert_all(producer, Data::name, vec!["first", "second"]);
}

Current output

error[E0308]: mismatched types
  --> src/main.rs:42:5
   |
42 |     assert_all(producer, Data::name, vec!["first", "second"]);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
   |
   = note: expected reference `&String`
              found reference `&String`
note: the lifetime requirement is introduced here
  --> src/main.rs:28:25
   |
28 |     FN: FnMut(&Data) -> A,
   |                         ^

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` (bin "playground") due to previous error

Desired output

  1. Underline (^^^^) code doesn't point to faulty types.
  2. Lifetime is "noted", but not represented in output.
  3. Don't know as I can't really understand issue with current output. I suspect issue comes from lifetime not "just types" (I suppose lifetime are part of type signature).

Rationale and extra context

No response

Other cases

I tried to add explicit lifetime 'inner to method generic signature, and bound to both f arg and A (https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=b1ae4d1f31e235183b0bc164d8c777bf):

fn assert_all<'inner, FN, A, E>(...) where 
  FN: FnMut(&'inner Data) -> A,
  A: 'inner + Debug + std::cmp::PartialEq<E>,
{ ... }

But got another issue about data needed to outlive assert_all function. Sounds like it's interpreted as a requirement that data must outlive f:

error[E0597]: `data` does not live long enough
  --> src/main.rs:33:27
   |
22 | fn assert_all<'inner, FN, A, E>(
   |               ------ lifetime `'inner` defined here
...
32 |     let data = producer.clone();
   |         ---- binding `data` declared here
33 |     let actuals: Vec<_> = data.iter().map(f).collect();
   |                           ^^^^^^^^^^^-------
   |                           |
   |                           borrowed value does not live long enough
   |                           argument requires that `data` is borrowed for `'inner`
34 |     assert_eq!(actuals, expecteds);
35 | }
   | - `data` dropped here while still borrowed

For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground` (bin "playground") due to previous error

Anything else?

No response

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions