@@ -377,6 +377,7 @@ partial def foldAndCollect (oldIH newIH : FVarId) (isRecCall : Expr → Option E
377377 mkForallFVars #[x] body'
378378
379379 | .letE n t v b nondep =>
380+ trace[Meta.FunInd] "Let-binding {n} with (nondep := {nondep})"
380381 let t' ← foldAndCollect oldIH newIH isRecCall t
381382 let v' ← foldAndCollect oldIH newIH isRecCall v
382383 withLetDecl n t' v' (nondep := nondep) fun x => do
@@ -520,7 +521,7 @@ def buildInductionCase (oldIH newIH : FVarId) (isRecCall : Expr → Option Expr)
520521Like `mkLambdaFVars (usedOnly := true)`, but
521522
522523 * silently skips expression in `xs` that are not `.isFVar`
523- * also skips let-bound variabls
524+ * also skips let-bound variables
524525 * returns a mask (same size as `xs`) indicating which variables have been abstracted
525526 (`true` means was abstracted).
526527
@@ -631,11 +632,17 @@ public def rwIfWith (hc : Expr) (e : Expr) : MetaM Simp.Result := do
631632 return { expr := e }
632633
633634def rwLetWith (h : Expr) (e : Expr) : MetaM Simp.Result := do
634- if e.isLet then
635- if (← isDefEq e.letValue! h) then
636- return { expr := e.letBody!.instantiate1 h }
637- trace[Meta.FunInd] "rwLetWith failed:{inlineExpr e}not a let expression or `{h}` is not definitionally equal to `{e.letValue!}`"
638- return { expr := e }
635+ match e with
636+ | .letE _ t v b nondep =>
637+ unless (← isDefEq t (← inferType h)) do
638+ trace[Meta.FunInd] "rwLetWith failed:The type of{inlineExpr h}is not definitionally equal to `{t}`"
639+ unless nondep do
640+ unless (← isDefEq v h) do
641+ trace[Meta.FunInd] "rwLetWith failed:{inlineExpr h}is not definitionally equal to{inlineExpr v}"
642+ return { expr := b.instantiate1 h }
643+ | _ =>
644+ trace[Meta.FunInd] "rwLetWith failed:{inlineExpr e}not a let expression"
645+ return { expr := e }
639646
640647def rwMData (e : Expr) : MetaM Simp.Result := do
641648 return { expr := e.consumeMData }
@@ -735,7 +742,7 @@ as `MVars` as it goes.
735742partial def buildInductionBody (toErase toClear : Array FVarId) (goal : Expr)
736743 (oldIH newIH : FVarId) (isRecCall : Expr → Option Expr) (e : Expr) : M2 Expr := do
737744 withTraceNode `Meta.FunInd
738- (pure m!"{exceptEmoji ·} buildInductionBody: {oldIH.name} → {newIH.name}\n goal: { goal}:{indentExpr e}" ) do
745+ (pure m!"{exceptEmoji ·} buildInductionBody: {oldIH.name} → {newIH.name}\n goal:{indentExpr goal}\n expr :{indentExpr e}" ) do
739746
740747 -- if-then-else cause case split:
741748 match_expr e with
@@ -863,13 +870,14 @@ partial def buildInductionBody (toErase toClear : Array FVarId) (goal : Expr)
863870 buildInductionBody toErase toClear goal' oldIH newIH isRecCall e.mdataExpr!
864871 return e.updateMData! b
865872
866- if let .letE n t v b _ := e then
873+ if let .letE n t v b nondep := e then
874+ trace[Meta.FunInd] "Let-binding {n} with (nondep := {nondep})"
867875 let t' ← foldAndCollect oldIH newIH isRecCall t
868876 let v' ← foldAndCollect oldIH newIH isRecCall v
869- return ← withLetDecl n t' v' fun x => M2.branch do
877+ return ← withLetDecl n t' v' (nondep := nondep) fun x => M2.branch do
870878 let b' ← withRewrittenMotiveArg goal (rwLetWith x) fun goal' =>
871879 buildInductionBody toErase toClear goal' oldIH newIH isRecCall (b.instantiate1 x)
872- mkLetFVars #[x] b'
880+ mkLetFVars (generalizeNondepLet := false ) #[x] b'
873881
874882 -- Special case for traversing the PProd’ed bodies in our encoding of structural mutual recursion
875883 if let .lam n t b bi := e then
@@ -903,19 +911,25 @@ do not handle delayed assignments correctly.
903911-/
904912def abstractIndependentMVars (mvars : Array MVarId) (index : Nat) (e : Expr) : MetaM Expr := do
905913 trace[Meta.FunInd] "abstractIndependentMVars, to revert after {index}, original mvars: {mvars}"
906- let mvars ← mvars.mapM fun mvar => do
907- let mvar ← cleanupAfter mvar index
908- mvar.withContext do
909- let fvarIds := (← getLCtx).foldl (init := #[]) (start := index+1 ) fun fvarIds decl => fvarIds.push decl.fvarId
910- let (_, mvar) ← mvar.revert fvarIds
911- pure mvar
912- trace[Meta.FunInd] "abstractIndependentMVars, reverted mvars: {mvars}"
914+ let mvars ← mvars.mapM (cleanupAfter · index)
913915 let names := Array.ofFn (n := mvars.size) fun ⟨i,_⟩ => .mkSimple s! "case{ i+1 } "
914- let types ← mvars.mapM MVarId.getType
916+ let types ← mvars.mapM fun mvar => do
917+ mvar.withContext do
918+ let goal ← mvar.getType
919+ let xs := (← getLCtx).foldl (init := #[]) (start := index+1 ) fun fvarIds decl =>
920+ fvarIds.push (mkFVar decl.fvarId)
921+ mkForallFVars (generalizeNondepLet := true ) xs goal
922+ trace[Meta.FunInd] "abstractIndependentMVars, reverted types: {types}"
915923 Meta.withLocalDeclsDND (names.zip types) fun xs => do
916- for mvar in mvars, x in xs do
917- mvar.assign x
918- mkLambdaFVars xs (← instantiateMVars e)
924+ for mvar in mvars, x in xs do
925+ mvar.withContext do
926+ let e := (← getLCtx).foldl (init := x) (start := index+1 ) fun e decl =>
927+ if decl.isLet (allowNondep := false ) then
928+ e
929+ else
930+ .app e (mkFVar decl.fvarId)
931+ mvar.assign e
932+ mkLambdaFVars xs (← instantiateMVars e)
919933
920934/--
921935Given a unary definition `foo` defined via `WellFounded.fixF`, derive a suitable induction principle
0 commit comments