So, one of the big topics in NLL is how to handle lifetime errors – specifically, I am taking aim at that class of errors that currently show up as “unable to infer lifetime for foo”. I want to see if, with NLL, we can do a better job of presenting that information. We’ve been working on a template for such errors and I’d like to get some feedback.
Here is an example test:
fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
Box::new(items.iter())
}
Here is the current error message that you get when you try to compile this test:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> underscore-lifetime/dyn-trait-underscore.rs:18:20
|
17 | Box::new(items.iter())
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 16:1...
--> underscore-lifetime/dyn-trait-underscore.rs:16:1
|
16 | / fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
17 | | Box::new(items.iter())
17 | | }
| |_^
note: ...so that reference does not outlive borrowed content
--> underscore-lifetime/dyn-trait-underscore.rs:18:14
|
17 | Box::new(items.iter())
| ^^^^^
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected std::boxed::Box<(dyn std::iter::Iterator<Item=&T> + 'static)>
found std::boxed::Box<dyn std::iter::Iterator<Item=&T>>
My experience has been that most people just have their eyes glaze over when confronted with all this stuff.
General plan
In general, my plan for region errors is two-fold:
- First, we should identify as many special cases as we can and give highly tailored messages.
- But we also need a general fallback plan.
It’s the latter point I want to talk about here: a kind of general fallback for region errors when we don’t have a specific error message at hand. I think this “general plan” probably can also have a number of smaller helpful notes that we add from time to time (in fact, my example below has one).
A new template for general errors
Before I explain how my new template for “general errors” works, let me show you how it might look on the error above. I want to give you this first so as not to bias you:
error: unsatisfied lifetime constraints
--> underscore-lifetime/dyn-trait-underscore.rs:18:5
|
16 | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
| ----- -------------------------- defaults to: `Box<dyn Iterator<Item = &T> + 'static>`
| |
| the fully elaborated type of `items` is `&'1 [T]`
17 | Box::new(items.iter())
| ^^^^^^^^^^^^^^^^^^^^^^ casting this value to `Box<dyn Iterator<Item = &T>>` requires `'1` to be `'static`
The basic plan here:
- first, to first give names to anonymous lifetimes via “fully elaborated types”. So here the lifetime of the
items
argument is “elaborated” and named'1
– this is intentionally not valid syntax, for a variety of reasons. - second, to identify key points within the function and talk about the constraints they introduce. In this case, the point we identify is the cast to
Box<dyn Iterator<Item = &T>>
, but in general there may be more than one such case - third, try to add add’l helpful tips for defaults and things that may not be obvious, such as the fact that
Box<dyn Iterator>
defaults toBox<dyn Iterator + 'static>
This error message feels much better than the original, but still ungreat. It feels like a system that one could learn to understand as you become more experienced, but is probably not very good for newbies. That’s progress – and I’ll take it – but it’d be nice if we could do better.
Anyway, I wanted to open up this thread to chat with folks (cc @davidtwco, @ekuber) and try to brainstorm how we might do better here.
Implementation plan
In terms of implementation, I am hoping to land https://github.com/rust-lang/rust/pull/52021 ASAP, which lays some of the foundation here. Then I thought I would open up some issues and try to keep things moving towards the error I gave above. In the meantime, maybe we can discuss come up with a better overall system for talking about these sorts of errors, and we can adjust things to match.