Skip to content

Unhelpful error messages for trait with unbound lifetime #72106

Closed
@willir

Description

@willir

I was trying to implement FromSql of rusqlite for my reference type (with lifetime). And I faced an unclear error message, later I was explained that the trait does not allow the return type to borrow from the value argument since it doesn't specify lifetime parameter explicitly.

However, I thought that it worth filing a bug report about unhelpful error message anyway.

Here is a simplified code:

use std::error::Error;
use std::fmt;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
    Null,
    Integer(i64),
    Real(f64),
    Text(&'a [u8]),
    Blob(&'a [u8]),
}

impl<'a> ValueRef<'a> {
    pub fn as_str(&self) -> FromSqlResult<&'a str> {
        match *self {
            ValueRef::Text(t) => {
                std::str::from_utf8(t).map_err(|_| FromSqlError::InvalidType)
            }
            _ => Err(FromSqlError::InvalidType),
        }
    }
}

#[derive(Debug)]
#[non_exhaustive]
pub enum FromSqlError {
    InvalidType
}

impl fmt::Display for FromSqlError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "InvalidType")
    }
}

impl Error for FromSqlError {}

pub type FromSqlResult<T> = Result<T, FromSqlError>;

pub trait FromSql: Sized {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self>;
}

impl FromSql for &str {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str> {
        value.as_str()
    }
}

pub fn main() {
    println!("{}", "Hello World");
}

The error message I'm getting is:

error: `impl` item signature doesn't match `trait` item signature
  --> src/main.rs:45:5
   |
41 |     fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self>;
   |     ------------------------------------------------------------- expected fn(ValueRef<'_>) -> std::result::Result<&str, FromSqlError>
...
45 |     fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str> {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(ValueRef<'_>) -> std::result::Result<&str, FromSqlError>
   |
   = note: expected `fn(ValueRef<'_>) -> std::result::Result<&str, FromSqlError>`
              found `fn(ValueRef<'_>) -> std::result::Result<&str, FromSqlError>`

error: aborting due to previous error

error: could not compile `playground`.

To learn more, run the command again with --verbose.

So basically it says that I have a wrong signature, even though the expected and found signatures are the same.

I'm not sure what would be the right error message to raise here since I don't know lifetime rules quite well.

Here is, just in case, a link to playground

The rust version I'm using is: 1.44.0-nightly, but it also reproduces on 1.43.1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsC-enhancementCategory: An issue proposing an enhancement or a PR with one.D-confusingDiagnostics: Confusing error or lint that should be reworked.D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.T-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