Skip to content

Unhelpful error messages for trait with unbound lifetime #72106

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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