Description
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.