Modifies how the declaration command elaborator reports when there are unassigned metavariables. The visible effects are that (1) now errors like "don't know how to synthesize implicit argument" and "failed to infer 'let' declaration type" take precedence over universe level issues, (2) universe level metavariables are reported as metavariables (rather than as `u_1`, `u_2`, etc.), and (3) if the universe level metavariables appear in `let` binding types or `fun` binder types, the error is localized there. Motivation: Reporting unsolved expression metavariables is more important than universe level issues (typically universe issues are from unsolved expression metavariables). Furthermore, `let` and `fun` binders can't introduce universe polymorphism, so we can "blame" such bindings for universe metavariables, if possible. Example 1: Now the errors are on `x` and `none` (reporting expression metavariables) rather than on `example` (which reported universe level metavariables). ```lean example : IO Unit := do let x := none pure () ``` Example 2: Now there is a "failed to infer universe levels in 'let' declaration type" error on `PUnit`. ```lean def foo : IO Unit := do let x : PUnit := PUnit.unit pure () ``` In more detail: * `elabMutualDef` used to turn all level mvars into fresh level parameters before doing an analysis for "hidden levels". This analysis turns out to be exactly the same as instead creating fresh parameters for level mvars in only pre-definitions' types and then looking for level metavariables in their bodies. With this PR, error messages refer to the same level metavariables in the Infoview, rather than obscure generated `u_1`, `u_2`, ... level parameters. * This PR made it possible to push the "hidden levels" check into `addPreDefinitions`, after the checks for unassigned expression mvars. It used to be that if the "hidden levels" check produced an "invalid occurrence of universe level" error it would suppress errors for unassigned expression mvars, and now it is the other way around. * There is now a list of `LevelMVarErrorInfo` objects in the `TermElabM` state. These record expressions that should receive a localized error if they still contain level metavariables. Currently `let` expressions and binder types in general register such info. Error messages make use of a new `exposeLevelMVars` function that adds pretty printer annotations that try to expose all universe level metavariables. * When there are universe level metavariables, for error recovery the definition is still added to the environment after assigning each metavariable to level 0. * There's a new `Lean.Util.CollectLevelMVars` module for collecting level metavariables from expressions. Closes #2058
31 lines
648 B
Text
31 lines
648 B
Text
/-!
|
|
# Localized error messages with unassigned metavariables
|
|
-/
|
|
|
|
set_option pp.mvars false
|
|
|
|
|
|
/-!
|
|
Test: now reports that the universe levels are not assigned at the 'let' rather than an error on the `example` command.
|
|
-/
|
|
|
|
def foo : IO Unit := do
|
|
let x : PUnit := PUnit.unit
|
|
--^ collectDiagnostics
|
|
pure ()
|
|
|
|
|
|
/-!
|
|
Test: Works for `fun` binders too.
|
|
-/
|
|
|
|
example : Nat := (fun x : PUnit => 2) PUnit.unit
|
|
--^ collectDiagnostics
|
|
|
|
|
|
/-!
|
|
Test: A failure not in a binder, right now reports an error on `example` since there's no other location information.
|
|
-/
|
|
|
|
example : Nat := Function.const _ 2 @id
|
|
--^ collectDiagnostics
|