Skip to content

Wip repair

Sewen Thy edited this page Oct 31, 2022 · 5 revisions

Rustc errors related to lifetime:

  • E0010 value of statics and constants must be known at compile time; initialize the value.
  • E0106 missing lifetime annotation; needs explicit annotations.
  • E0195 lifetime annotations on implemented methods are different from trait; need to make it the same.
  • E0226 more than 1 explicit lifetime on a trait; need to reduce to 1 lifetime.
  • E0227 unable to determine unique region; needs additional constraint.
  • E0228 lifetime bounds for trait object cannot be deduced from context; needs explicit annotation(s) or bounds.
  • E0261 undeclared lifetime used; declare lifetime.
  • E0262 declared illegal lifetime name; rename declared lifetime.
  • E0309 missing lifetime bounds and may not live long enough; needs explicit bounds.
  • E0310 parameter type (i.e. trait) have a lifetime that does not live long enough or missing constraint; add constraint to type definition.
  • E0316 nested where constraint clause; rewrite to un-nest.
  • E0392 unused declared lifetime; delete it.
  • E0478 lifetime bounds not satisfied; add additional bounds.
  • E0491 reference's lifetime is longer than its data reference; add additional bounds.
  • E0496 named lifetime is overshadowed; rename new lifetime name.
  • E0515 return reference of value owned by function; use non-owned value as return.
  • E0521 borrowed data escaped out of closure; drop type definition of argument into closure.
  • E0581 a lifetime appears only in the return type in a fn type and not in the arguments types; use the lifetime in argument or use 'static.
  • E0582 same as E0581 but for traits.
  • E0621 mismatch between the lifetimes appearing in the function signature and actual return variable; make the lifetime the same in signatures.
  • E0623 mismatch between the expected lifetime (e.g. in trait) and actual return variable; make the lifetime the same/add bounds.
  • E0637 illegally using reference without lifetime (e.g. &T) or illegally using '_ lifetimes; use valid lifetime.
  • E0657 lifetime bound on a trait implementation was captured at an incorrect place; add lifetime annotation at function.
  • E0700 trait returns lifetime not defined in trait; add lifetime bounds.
  • E0712 borrow of thread-local variable was made inside a function which outlived the lifetime of the function; no repair available.
  • E0713 borrow of trait type implementing Drop after dropped; add lifetime annotation to the value.
  • E0716 value dropped while borrow is active; use references.
  • E0726 elided lifetime in async function; add '_ lifetimes.
  • E0726 generic arguments were not provided in the same order as the corresponding generic parameters are declared; change to match order.
  • E0771 A non-'static lifetime was used in a const generic; use 'static lifetime for const.

Lifetime errors related to extract method refactoring

There are a few errors above that needs to be repaired when extracting--for now we will not consider extracting to trait yet and we excludes teh error we cannot repair. Here are a few that are prominent:

  • E0106 we will need to add explicit lifetime annotations.
  • E0261 if we extract any lines that has declared lifetime, then we need to take it as input.
  • E0262 and E0496 if we repair using illegal lifetime name, then we need to rename declared lifetime.
  • E0309 missing lifetime bounds and may not live long enough; needs explicit bounds.
  • E0392 if during the repair we add unused declared lifetime then we need to delete it.
  • E0478 when extracting lines with references usages having different lifetimes, then we need to add bounds.
  • E0491 when extracting data reference that already have lifetime we need additional bounds to say it does not outlive its data lifetime.
  • E0581 if the return value of the extracted function has a lifetime we need to include that in the argument.
  • E0621 sometimes like this toy example the extracted block can have multiple lifetime depends on the control flow, so we need to perform an analysis to get the correct lifetime (widest correct bound) or make sure the signature says that it must have the same lifetime (tightest possible bound).
  • E0637 when extracting functions that have multiple references as input, we need to add the correct lifetime annotations.
  • E0713 when borrowing of trait type implementing Drop into our function we need to add lifetime annotation to the value so that it is not dropped within our function.
  • E0716 this error can be solved by our approach to borrowing values.

However, in any of the errors above, to add these lifetimes we need to perform static analysis so we know the correct annotations to add and get the function to compiles. To do that we need to understand how lifetime works in rustc.

Non-lexical lifetimes (NLL)

Lifetimes in rustc is calculated using non-lexical lifetime and it is used by the borrow checker to ensure that each reference (or borrow) is legal i.e. it cannot have unsoundness or define behaviour by violating the term of its borrow. You can read in more details here.

So scope refers to the lifetime of a value, corresponding to the span of time before that value gets freed (or, put another way, before the destructor for the value runs). This describes how long a value is valid. Lifetime refers to the lifetime of a reference, corresponding to the span of time in which that reference is used.

NLL in Rustc

Starting from this RFC, rustc uses NLL to analyze for some lifetime errors in the borrow checker, which includes the following error codes:

  1. E0521
  2. E0713
  3. E0716

Since these errors occur in the borrow checker which runs on rustc's MIR, we can use those information to perform our analysis and fix the errors. However, there are errors like E0106 which is caught at name resolution so no MIR is generated (as it is done before that) and it needs explicit annotations to fix but we can't get the intermediate representation(i.e. MIR) to run analysis on. Notice that while the error generated by this toy example is actually E0106 because there is no lifetime annotation but if we try to annotate it we might run into E0621 as described above and we have no MIR to run the static analysis on.

To account for errors like this we have 2 approaches:

  1. Tightest bounds first: we try to annotate all the borrow lifetimes the same and we repair the lifetime errors using rustc as an oracle.
  2. Loosest bounds first: we try to annotate all the borrow lifetimes differently and we repair the lifetime errors using rustc as an oracle.

Both these approaches should handle the cases that we mentioned above as it would have to reach the borrow checker to know whether the annotated lifetime is correct then we can look at the MIR to do more static analysis if we need to.

Slight change of scope:

Generate better suggestion from rustc and just apply rustfix from the suggestion.

References:

I owe a lot of my understanding to the rustc documentations and the rustc MIR working group chat on Zulip.