-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[NLL] Record more infomation on free region constraints in typeck #54262
Conversation
☔ The latest upstream changes (presumably #53900) made this pull request unmergeable. Please resolve the merge conflicts. |
a: Ty<'tcx>, | ||
b: Ty<'tcx>, | ||
locations: Locations, | ||
category: ConstraintCategory, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, I did not want to do it this way — but I'm trying to remember why and coming up empty. Seems ok.
I'm wondering if it makes sense to keep both locations and category as distinct things. Perhaps so: in particular, locations (once we transition to polonius) will be relevant to whether or not this is an error, whereas category
is not.
| ^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` | ||
... | ||
LL | (a, b) //[krisskross]~ ERROR 55:5: 55:6: lifetime mismatch [E0623] | ||
| ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting example. I feel like this is a good case where I'd prefer to see more than one highlight.
Or, even better, if we could highlight a
and not the entire tuple. I think this would be possible: we could probably detect if we are returning an aggregate and see if we can trace back to one of the inputs into the aggregate. This is particularly easy in tuples.
That said, another route that might be better (or just complementary) is to highlight more than one location. In this case, I think it'd be nice to highlight the bar(foo, y)
point as well, basically saying "data gets the lifetime 'a
from here". Anyway, I'm noting this down for further iteration.
| | ||
LL | x | ||
| ^ | ||
LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this feels like a regression, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess actually it's another case of "it'd be nice to highlight more spots"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The highlighted span is the span of the first statement, it just happens to be the right span in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lol ok
| | ||
LL | x | ||
| ^ | ||
LL | fn foo<T>(x: T) -> impl Any + 'static { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
another case where highlight the return type feels not quite right
the core problem here is that, with impl Trait
in particular, it's useful to highlight the return type.
I wonder if we could add a note like this:
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/type_parameters_captured.rs:17:20
|
LL | fn foo<T>(x: T) -> impl Any + 'static {
| ^^^^^^^^^^^^^^^^^^
LL | x
| - the `impl Trait` is inferred to have the type `T`
LL | }
|
= help: consider adding an explicit lifetime bound `T: 'static`...
The idea would be to find the span(s) of where the return slot is assigned and use those, and just show the underlying type.
| _________________________________________________________________^ | ||
LL | | x //~ ERROR E0312 | ||
LL | | })); | ||
| |_____^ closure body requires that `'x` must outlive `'static` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this case would be addressed by @davidtwco's PR -- anyway, feels like an improvement in this PR, if not optimal.
@@ -6,7 +6,7 @@ LL | fn foo(mut x: Ref, y: &u32) { | |||
| | | |||
| has type `Ref<'_, '2>` | |||
LL | x.b = y; //~ ERROR lifetime mismatch | |||
| ^^^^^^^ requires that `'1` must outlive `'2` | |||
| ^^^^^^^ assignment requires that `'1` must outlive `'2` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: is this an improvement? It seems like it's sort of obvious that it's an assignment, not sure if it helps for us to say so?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe if we said something better, like "data with lifetime '1
is stored into a location with lifetime '2
here"? that doesn't quite sound right either.
... | ||
LL | let _x = *s; //~ ERROR | ||
| ^^ `s` escapes the function body here | ||
| ^^ proving this value is `Sized` requires that `'a` must outlive `'static` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`... | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, pulling out the constraint category into typeck might mean that we can package it up with the ClosureRegionRequirements
, as well. Have to think a bit about that. This might enable us to give finer-grained reports here.
LL | fn i<'a, T, U>(v: Box<A<U>+'a>) -> Box<X+'static> { | ||
| -- lifetime `'a` defined here | ||
LL | box B(&*v) as Box<X> //~ ERROR cannot infer | ||
| ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in these cases, it'd be really nice if we could tie this a bit harder to the return type. good follow-up.
r=me post rebase |
The MIR/NLL type checker is in a much better position to classify constraints and already has to classify into boring and interesting. Adds spans to Locations::All for error reporting Adds more constraint categories
33c9188
to
bd0895d
Compare
@bors r+ |
📌 Commit bd0895d has been approved by |
[NLL] Record more infomation on free region constraints in typeck Changes: * Makes the span of the MIR return place point to the return type * Don't try to use a path to a type alias as a path to the adt it aliases (fixes an ICE) * Don't claim that `self` is declared outside of the function. [see this test](f2995d5#diff-0c9e6b1b204f42129b481df9ce459d44) * Remove boring/interesting distinction and instead add a `ConstraintCategory` to the constraint. * Add categories for implicit `Sized` and `Copy` requirements, for closure bounds, for user type annotations and `impl Trait`. * Don't use the span of the first statement for Locations::All bounds (even if it happens to work on the tests we have) Future work: * Fine tuning the heuristic used to choose the place the report the error. * Reporting multiple places (behind a flag) * Better closure bounds reporting. This probably requires some discussion. r? @nikomatsakis
☀️ Test successful - status-appveyor, status-travis |
Changes:
self
is declared outside of the function. see this testConstraintCategory
to the constraint.Sized
andCopy
requirements, for closure bounds, for user type annotations andimpl Trait
.Future work:
r? @nikomatsakis