feat: better error message when constructor parameter universe level is too big
This commit is contained in:
parent
ef8fecff79
commit
3ee8ceafb4
4 changed files with 64 additions and 7 deletions
|
|
@ -1,6 +1,8 @@
|
|||
Unreleased
|
||||
---------
|
||||
|
||||
* Improve error message when constructor parameter universe level is too big.
|
||||
|
||||
* Add support for `for h : i in [start:stop] do .. ` where `h : i ∈ [start:stop]`. This feature is useful for proving
|
||||
termination of functions such as:
|
||||
```lean
|
||||
|
|
|
|||
|
|
@ -392,17 +392,37 @@ def checkResultingUniverse (u : Level) : TermElabM Unit := do
|
|||
if !u.isZero && !u.isNeverZero then
|
||||
throwError "invalid universe polymorphic type, the resultant universe is not Prop (i.e., 0), but it may be Prop for some parameter values (solution: use 'u+1' or 'max 1 u'{indentD u}"
|
||||
|
||||
private def checkResultingUniverses (numParams : Nat) (indTypes : List InductiveType) : TermElabM Unit := do
|
||||
let u ← getResultingUniverse indTypes
|
||||
/--
|
||||
Execute `k` using the `Syntax` reference associated with constructor `ctorName`.
|
||||
-/
|
||||
def withCtorRef (views : Array InductiveView) (ctorName : Name) (k : TermElabM α) : TermElabM α := do
|
||||
for view in views do
|
||||
for ctorView in view.ctors do
|
||||
if ctorView.declName == ctorName then
|
||||
return (← withRef ctorView.ref k)
|
||||
k
|
||||
|
||||
private def checkResultingUniverses (views : Array InductiveView) (numParams : Nat) (indTypes : List InductiveType) : TermElabM Unit := do
|
||||
let u ← instantiateLevelMVars (← getResultingUniverse indTypes)
|
||||
checkResultingUniverse u
|
||||
unless u.isZero do
|
||||
indTypes.forM fun indType => indType.ctors.forM fun ctor =>
|
||||
forallTelescopeReducing ctor.type fun ctorArgs type =>
|
||||
for ctorArg in ctorArgs[numParams:] do
|
||||
let v ← getLevel (← inferType ctorArg)
|
||||
-- TODO
|
||||
trace[Meta.debug] "checkCtorArgLevel, {v} <= {u}"
|
||||
return ()
|
||||
let type ← inferType ctorArg
|
||||
let v ← instantiateLevelMVars (← getLevel type)
|
||||
if v.hasMVar then
|
||||
-- TODO
|
||||
trace[Meta.debug] "checkCtorArgLevel, {v} <= {u}"
|
||||
else unless u.geq v do
|
||||
let mut msg := m!"invalid universe level in constructor '{ctor.name}', parameter"
|
||||
let localDecl ← getFVarLocalDecl ctorArg
|
||||
unless localDecl.userName.hasMacroScopes do
|
||||
msg := msg ++ m!" '{ctorArg}'"
|
||||
msg := msg ++ m!" has type{indentExpr type}"
|
||||
msg := msg ++ m!"\nat universe level{indentD v}"
|
||||
msg := msg ++ m!"\nit must be smaller than or equal to the inductive datatype universe level{indentD u}"
|
||||
withCtorRef views ctor.name <| throwError msg
|
||||
|
||||
private def collectUsed (indTypes : List InductiveType) : StateRefT CollectFVars.State MetaM Unit := do
|
||||
indTypes.forM fun indType => do
|
||||
|
|
@ -602,7 +622,7 @@ private def mkInductiveDecl (vars : Array Expr) (views : Array InductiveView) :
|
|||
if inferLevel then
|
||||
updateResultingUniverse numParams (← levelMVarToParam indTypes)
|
||||
else
|
||||
checkResultingUniverses numParams indTypes
|
||||
checkResultingUniverses views numParams indTypes
|
||||
levelMVarToParam indTypes
|
||||
let usedLevelNames := collectLevelParamsInInductive indTypes
|
||||
match sortDeclLevelParams scopeLevelNames allUserLevelNames usedLevelNames with
|
||||
|
|
|
|||
17
tests/lean/ctorUnivTooBig.lean
Normal file
17
tests/lean/ctorUnivTooBig.lean
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
inductive Bla : Type u where
|
||||
| nil : Bla
|
||||
| cons : (α : Type u) → (a : α) → Bla → Bla
|
||||
|
||||
inductive Foo : Type where
|
||||
| leaf
|
||||
| mk (α : Type) (a : α)
|
||||
| mk₂
|
||||
|
||||
inductive Foo' : Type u where
|
||||
| leaf
|
||||
| mk : Sort (max u v) → a → Foo'
|
||||
| mk₂
|
||||
|
||||
inductive Boo : Type u where
|
||||
| nil : Boo
|
||||
| cons : (α : Sort u) → (a : α) → Boo → Boo
|
||||
18
tests/lean/ctorUnivTooBig.lean.expected.out
Normal file
18
tests/lean/ctorUnivTooBig.lean.expected.out
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
ctorUnivTooBig.lean:3:2-3:45: error: invalid universe level in constructor 'Bla.cons', parameter 'α' has type
|
||||
Type u
|
||||
at universe level
|
||||
u+2
|
||||
it must be smaller than or equal to the inductive datatype universe level
|
||||
u+1
|
||||
ctorUnivTooBig.lean:7:2-7:25: error: invalid universe level in constructor 'Foo.mk', parameter 'α' has type
|
||||
Type
|
||||
at universe level
|
||||
2
|
||||
it must be smaller than or equal to the inductive datatype universe level
|
||||
1
|
||||
ctorUnivTooBig.lean:12:2-12:34: error: invalid universe level in constructor 'Foo'.mk', parameter has type
|
||||
Sort (max u v)
|
||||
at universe level
|
||||
(max u v)+1
|
||||
it must be smaller than or equal to the inductive datatype universe level
|
||||
u+1
|
||||
Loading…
Add table
Reference in a new issue