fix: free variable in do bind when continuation type depends on bvar (#13396)
This PR fixes #12768, where the new `do` elaborator produced a "declaration has free variables" kernel error when the bind continuation's result type was definitionally but not syntactically independent of the bound variable. The fix moves creation of the result type metavariable before `withLocalDecl`, so the unifier must reduce away the dependency. For example, given `def Quoted (x : Nat) := Nat`, the expression `do let val ← pure 3; withStuff val do return 3` would fail because `β` was assigned `Quoted val` rather than `Nat`.
This commit is contained in:
parent
4dced0287e
commit
cbda692e7e
4 changed files with 18 additions and 5 deletions
|
|
@ -384,6 +384,7 @@ def DoElemCont.mkBindUnlessPure (dec : DoElemCont) (e : Expr) : DoElabM Expr :=
|
|||
let k := dec.k
|
||||
-- The .ofBinderName below is mainly to interpret `__do_lift` binders as implementation details.
|
||||
let declKind := .ofBinderName x
|
||||
let kResultTy ← mkFreshResultType `kResultTy
|
||||
withLocalDecl x .default eResultTy (kind := declKind) fun xFVar => do
|
||||
let body ← k
|
||||
let body' := body.consumeMData
|
||||
|
|
@ -411,7 +412,6 @@ def DoElemCont.mkBindUnlessPure (dec : DoElemCont) (e : Expr) : DoElabM Expr :=
|
|||
-- else -- would be too aggressive
|
||||
-- return ← mapLetDecl (nondep := true) (kind := declKind) x eResultTy eRes fun _ => k ref
|
||||
|
||||
let kResultTy ← mkFreshResultType `kResultTy
|
||||
let body ← Term.ensureHasType (← mkMonadicType kResultTy) body
|
||||
let k ← mkLambdaFVars #[xFVar] body
|
||||
mkBindApp eResultTy kResultTy e k
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ would also work here.
|
|||
error: Application type mismatch: The argument
|
||||
isDigitEven? n
|
||||
has type
|
||||
?m.2 Bool
|
||||
?m.3 Bool
|
||||
but is expected to have type
|
||||
Prop
|
||||
in the application
|
||||
|
|
|
|||
13
tests/elab/issue12768.lean
Normal file
13
tests/elab/issue12768.lean
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
module
|
||||
|
||||
set_option backward.do.legacy false
|
||||
|
||||
set_option linter.unusedVariables.funArgs false in
|
||||
def Quoted (x : Nat) := Nat
|
||||
|
||||
def withStuff (x : Nat) (f : IO (Quoted x)) : IO (Quoted x) := f
|
||||
|
||||
def myFunc : IO Nat := do
|
||||
let val : Nat ← pure 3
|
||||
withStuff val do
|
||||
return (3 : Nat)
|
||||
|
|
@ -108,7 +108,7 @@ Hint: Adding type annotations and supplying implicit arguments to functions can
|
|||
example := do return 42
|
||||
/--
|
||||
error: typeclass instance problem is stuck
|
||||
Bind ?m.23
|
||||
Bind ?m.22
|
||||
|
||||
Note: Lean will not try to resolve this typeclass instance problem because the type argument to `Bind` is a metavariable. This argument must be fully determined before Lean will try to resolve the typeclass.
|
||||
|
||||
|
|
@ -211,8 +211,8 @@ trace: [Elab.do] let x := 42;
|
|||
else
|
||||
let x := x + i;
|
||||
pure (ForInStep.yield (none, x))
|
||||
let __r : Option ?m.182 := __s.fst
|
||||
let x : ?m.182 := __s.snd
|
||||
let __r : Option ?m.185 := __s.fst
|
||||
let x : ?m.185 := __s.snd
|
||||
match __r with
|
||||
| some r => pure r
|
||||
| none =>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue