Skip to content

Confusing lifetime inference error / error messages #30387

Closed
@jld

Description

@jld

I'm not sure whether this is code that ought to be valid but the lifetime inference isn't clever enough for, or if it's invalid but subtyping makes it hard to give a good error message about why. This part is reduced from code in the regex crate (specifically Captures):

use std::ops::Index;
struct StrHolder<'a>(&'a str);
impl<'a> Index<&'a str> for StrHolder<'a> {
    type Output = str;
    fn index<'b>(&'b self, _name: &str) -> &'b str { self.0 }
}

And this tries to use it:

pub fn problem(s: &str) -> usize {
    let sh = StrHolder(s);
    sh["whatever"].len()
}

Which leads to this:

bounds_thing.rs:10:24: 10:25 error: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements [E0495]
bounds_thing.rs:10     let sh = StrHolder(s);
                                          ^
bounds_thing.rs:10:14: 10:23 note: first, the lifetime cannot outlive the expression at 10:13...
bounds_thing.rs:10     let sh = StrHolder(s);
                                ^~~~~~~~~
bounds_thing.rs:10:14: 10:23 note: ...so that a type/lifetime parameter is in scope here
bounds_thing.rs:10     let sh = StrHolder(s);
                                ^~~~~~~~~
bounds_thing.rs:10:24: 10:25 note: but, the lifetime must be valid for the expression at 10:23...
bounds_thing.rs:10     let sh = StrHolder(s);
                                          ^
bounds_thing.rs:10:24: 10:25 note: ...so that auto-reference is valid at the time of borrow
bounds_thing.rs:10     let sh = StrHolder(s);
                                          ^

If the impl started like this (which is the PR I'm going to send to regex) then it would work, because there wouldn't be a constraint between the index string and the region parameter on problem (in addition to Index requiring the returned str to have the same lifetime as the StrHolder):

impl<'a, 'i> Index<&'i str> for StrHolder<'a>

The weird part is that making this change, to explicitly coerce the &'static str literal to an unspecified maybe-shorter lifetime, also fixes it:

    sh["whatever" as &str].len()

And this is why I'm wondering if it's more than just a quality-of-error-message issue.

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