Skip to content

Restore "Proof Using Clear Unused"#22107

Draft
SkySkimmer wants to merge 6 commits into
rocq-prover:masterfrom
SkySkimmer:keep-using
Draft

Restore "Proof Using Clear Unused"#22107
SkySkimmer wants to merge 6 commits into
rocq-prover:masterfrom
SkySkimmer:keep-using

Conversation

@SkySkimmer

@SkySkimmer SkySkimmer commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

@SkySkimmer SkySkimmer added the request: full CI Use this label when you want your next push to trigger a full CI. label Jun 9, 2026
@coqbot-app coqbot-app Bot removed the request: full CI Use this label when you want your next push to trigger a full CI. label Jun 9, 2026
@SkySkimmer SkySkimmer added the needs: fixing The proposed code change is broken. label Jun 9, 2026
@SkySkimmer

Copy link
Copy Markdown
Contributor Author

The first commit breaks Derive somehow

@SkySkimmer SkySkimmer added request: full CI Use this label when you want your next push to trigger a full CI. and removed needs: fixing The proposed code change is broken. labels Jun 10, 2026
@coqbot-app coqbot-app Bot removed the request: full CI Use this label when you want your next push to trigger a full CI. label Jun 10, 2026
@SkySkimmer SkySkimmer added needs: overlay This is breaking external developments we track in CI. request: full CI Use this label when you want your next push to trigger a full CI. labels Jun 10, 2026
@coqbot-app coqbot-app Bot removed the request: full CI Use this label when you want your next push to trigger a full CI. label Jun 10, 2026
@SkySkimmer SkySkimmer added request: full CI Use this label when you want your next push to trigger a full CI. and removed needs: overlay This is breaking external developments we track in CI. labels Jun 10, 2026
@coqbot-app coqbot-app Bot removed the request: full CI Use this label when you want your next push to trigger a full CI. label Jun 10, 2026
@SkySkimmer

Copy link
Copy Markdown
Contributor Author

@coqbot ci minimize ci-metarocq ci-fiat_crypto
Using check_and_clear_in_constr to do the clearing may not end up working out as it needs to change clear semantics on shelved evars to work. If so then we will need to do separate clear and check.

@coqbot-app

coqbot-app Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

I am now running minimization at commit 78807c6 on requested target ci-metarocq. I'll come back to you with the results once it's done.

The requested target 'ci-fiat_crypto
Usi' could not be found among the jobs lint.

@SkySkimmer

Copy link
Copy Markdown
Contributor Author

@coqbot ci minimize ci-fiat_crypto

@coqbot-app

coqbot-app Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

I am now running minimization at commit 78807c6 on requested target ci-fiat_crypto. I'll come back to you with the results once it's done.

@coqbot-app

coqbot-app Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor
Minimization interrupted by timeout, being automatically continued. Partially Minimized File /home/runner/work/run-coq-bug-minimizer/run-coq-bug-minimizer/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories/PCUICInductiveInversion.v in 5h 15m 5s (from ci-metarocq) (interrupted by timeout, being automatically continued) (full log on GitHub Actions - verbose log)
⭐ ⏱️ Partially Minimized Coq File (timeout)
(* -*- mode: coq; coq-prog-args: ("-emacs" "-q" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/utils/theories" "MetaRocq.Utils" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/common/theories" "MetaRocq.Common" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories" "MetaRocq.PCUIC" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Equations" "Equations" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/ExtLib" "ExtLib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-top" "MetaRocq.PCUIC.PCUICInductiveInversion") -*- *)
(* File reduced by coq-bug-minimizer from original input, then from 4603 lines to 39 lines, then from 53 lines to 39 lines, then from 52 lines to 39 lines, then from 51 lines to 3774 lines, then from 3773 lines to 46 lines, then from 58 lines to 2403 lines, then from 2409 lines to 57 lines, then from 69 lines to 995 lines, then from 1000 lines to 81 lines, then from 93 lines to 2645 lines, then from 2646 lines to 213 lines *)
(* coqc version 9.3+alpha compiled with OCaml 4.14.2
   coqtop version 9.3+alpha
   Expected coqc runtime on this file: 1.390 sec
   Expected coqc peak memory usage on this file: 784396.0 kb *)









Require Corelib.Strings.PrimString.
Require Corelib.Setoids.Setoid.
Require Corelib.Init.Wf.
Require Corelib.BinNums.PosDef.
Require Corelib.Numbers.Cyclic.Int63.CarryType.
Require Corelib.Init.Ltac.
Require Corelib.ssr.ssreflect.
Require Corelib.Relations.Relation_Definitions.
Require Corelib.Floats.SpecFloat.
Require Corelib.Init.Byte.
Require Corelib.Program.Wf.
Require Corelib.Program.Tactics.
Require Corelib.extraction.Extraction.
Require Corelib.Program.Utils.
Require Corelib.Lists.ListDef.
Require Corelib.Classes.CRelationClasses.
Require Corelib.Classes.SetoidTactics.
Require Corelib.Numbers.Cyclic.Int63.Uint63Axioms.
Require Corelib.Init.Decimal.
Require Corelib.Floats.FloatAxioms.
Require Corelib.Classes.Morphisms_Prop.
Require Corelib.ssr.ssrbool.
Require Corelib.Init.Hexadecimal.
Require Corelib.Program.Basics.
Require Corelib.Strings.PrimStringAxioms.
Require Corelib.Floats.FloatOps.
Require Corelib.Numbers.Cyclic.Int63.Sint63Axioms.
Require Corelib.Classes.CMorphisms.
Require Corelib.Classes.RelationClasses.
Require Corelib.Classes.Morphisms.
Require Corelib.BinNums.IntDef.
Require Corelib.ssr.ssrfun.
Require Corelib.Numbers.BinNums.
Require Corelib.Floats.PrimFloat.
Require Corelib.Numbers.Cyclic.Int63.PrimInt63.
Require Corelib.Init.Sumbool.
Require Corelib.BinNums.NatDef.
Require Corelib.Init.Nat.
Require ExtLib.Core.Any.
Require ExtLib.Structures.BinOps.
Require MetaRocq.Utils.MREquality.
Require MetaRocq.Utils.MRSquash.
Require MetaRocq.Utils.MRTactics.DestructHyps.
Require MetaRocq.Utils.MRTactics.FindHyp.
Require MetaRocq.Utils.MRTactics.Head.
Require MetaRocq.Utils.MRTactics.SpecializeBy.
Require MetaRocq.Utils.MRTactics.SplitInContext.
Require MetaRocq.Utils.MRTactics.Zeta1.
Require Stdlib.Classes.DecidableClass.
Require Stdlib.Logic.Decidable.
Require Stdlib.Logic.EqdepFacts.
Require Stdlib.Logic.FunctionalExtensionality.
Require Stdlib.Logic.HLevelsBase.
Require Stdlib.Program.Syntax.
Require Stdlib.Sets.Relations_1.
Require Stdlib.Unicode.Utf8_core.
Require Stdlib.Wellfounded.Inverse_Image.
Require Stdlib.micromega.ZifyClasses.
Require Stdlib.setoid_ring.Algebra_syntax.
Require Equations.Init.
Require ExtLib.Structures.Functor.
Require ExtLib.Structures.Monoid.
Require Ltac2.Init.
Require MetaRocq.Utils.MRTactics.UniquePose.
Require Stdlib.BinNums.IntDef.
Require Stdlib.BinNums.NatDef.
Require Stdlib.BinNums.PosDef.
Require Stdlib.Classes.CMorphisms.
Require Stdlib.Classes.CRelationClasses.
Require Stdlib.Classes.Morphisms.
Require Stdlib.Classes.Morphisms_Prop.
Require Stdlib.Classes.RelationClasses.
Require Stdlib.Classes.SetoidTactics.
Require Stdlib.Floats.PrimFloat.
Require Stdlib.Floats.SpecFloat.
Require Stdlib.Floats.FloatAxioms.
Require Stdlib.Floats.FloatOps.
Require Stdlib.Init.Nat.
Require Stdlib.Init.Wf.
Require Stdlib.Init.Sumbool.
Require Stdlib.Init.Hexadecimal.
Require Stdlib.Init.Byte.
Require Stdlib.Init.Decimal.
Require Stdlib.Lists.ListDef.
Require Stdlib.Logic.Eqdep.
Require Stdlib.Logic.Eqdep_dec.
Require Stdlib.Logic.ProofIrrelevanceFacts.
Require Stdlib.Numbers.BinNums.
Require Stdlib.Numbers.Cyclic.Int63.CarryType.
Require Stdlib.Numbers.Cyclic.Int63.PrimInt63.
Require Stdlib.Numbers.Cyclic.Int63.Sint63Axioms.
Require Stdlib.Numbers.Cyclic.Int63.Uint63Axioms.
Require Stdlib.Program.Basics.
Require Stdlib.Program.Tactics.
Require Stdlib.Program.Utils.
Require Stdlib.Program.Wf.
Require Stdlib.Relations.Relation_Definitions.
Require Stdlib.Setoids.Setoid.
Require Stdlib.Strings.PrimString.
Require Stdlib.Strings.PrimStringAxioms.
Require Stdlib.Unicode.Utf8.
Require Stdlib.Wellfounded.Well_Ordering.
Require Stdlib.extraction.Extraction.
Require Stdlib.ssr.ssrbool.
Require Stdlib.ssr.ssrfun.
Require Stdlib.ssr.ssreflect.
Require Equations.Prop.SigmaNotations.
Require MetaRocq.PCUIC.PCUICContextSubst.
Require MetaRocq.PCUIC.PCUICWeakeningEnv.
Module Export PCUICUnivSubstitutionConv.
Import MetaRocq.Utils.utils.
Import MetaRocq.Common.config.
Import MetaRocq.PCUIC.PCUICAst.
Import MetaRocq.PCUIC.PCUICTyping.
Import MetaRocq.PCUIC.PCUICWeakeningEnv.

Definition wf_ext_wk {cf : checker_flags} (Σ : global_env_ext)
  := wf Σ.1 × on_udecl_prop Σ.1 Σ.2.

Definition wf_global_ext {cf : checker_flags} Σ ext := wf_ext_wk (Σ, ext).

Section SubstIdentity.

End SubstIdentity.

End PCUICUnivSubstitutionConv.

Import MetaRocq.Utils.utils.
Import MetaRocq.Common.config.
Import MetaRocq.PCUIC.PCUICAst.
Import MetaRocq.PCUIC.PCUICTyping.
Import MetaRocq.PCUIC.PCUICWeakeningEnv.

Lemma declared_inductive_inv `{checker_flags} {Σ P ind mdecl idecl} :
  weaken_env_strictly_decls_prop cumulSpec0 (lift_typing typing) P ->
  wf Σ -> on_global_env cumulSpec0 P Σ ->
  declared_inductive Σ ind mdecl idecl ->
  on_ind_body cumulSpec0 P (Σ, ind_universes mdecl) (inductive_mind ind) mdecl (inductive_ind ind) idecl.
Admitted.

Lemma weaken_env_prop_typing `{checker_flags} : weaken_env_prop cumulSpec0 (lift_typing typing) (lift_typing typing).
Admitted.

Lemma on_declared_constructor `{checker_flags} {Σ ref mdecl idecl cdecl}
  {wfΣ : wf Σ}
  (Hdecl : declared_constructor Σ ref mdecl idecl cdecl) :
  on_inductive cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
               (inductive_mind (fst ref)) mdecl *
  on_ind_body cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
              (inductive_mind (fst ref)) mdecl (inductive_ind (fst ref)) idecl *
  ∑ ind_ctor_sort,
    let onib := declared_inductive_inv weaken_env_prop_typing wfΣ wfΣ (let (x, _) := Hdecl in x) in
     nth_error (ind_cunivs onib) ref.2 = Some ind_ctor_sort
    ×  on_constructor cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
                 mdecl (inductive_ind (fst ref))
                 idecl idecl.(ind_indices) cdecl ind_ctor_sort.
Admitted.

Inductive subslet {cf:checker_flags} Σ (Γ : context) : list term -> context -> Type :=
| emptyslet : subslet Σ Γ [] []
| cons_let_ass Δ s na t T : subslet Σ Γ s Δ ->
              Σ ;;; Γ |- t : subst0 s T ->
             subslet Σ Γ (t :: s) (Δ ,, vass na T)
| cons_let_def Δ s na t T :
    subslet Σ Γ s Δ ->
    Σ ;;; Γ |- subst0 s t : subst0 s T ->
    subslet Σ Γ (subst0 s t :: s) (Δ ,, vdef na t T).
Import MetaRocq.PCUIC.PCUICContextSubst.

Record spine_subst {cf:checker_flags} Σ Γ inst s (Δ : context) := mkSpineSubst {
  spine_dom_wf : wf_local Σ Γ;
  spine_codom_wf : wf_local Σ (Γ ,,, Δ);
  inst_ctx_subst :> context_subst Δ inst s;
  inst_subslet :> subslet Σ Γ s Δ }.

Section OnConstructor.
  Context {cf:checker_flags} {Σ : global_env} {ind mdecl idecl cdecl}
    {wfΣ: wf Σ} (declc : declared_constructor Σ ind mdecl idecl cdecl).

  Lemma on_constructor_subst :
    wf_global_ext Σ (ind_universes mdecl) *
    wf_local (Σ, ind_universes mdecl)
    (arities_context (ind_bodies mdecl) ,,, ind_params mdecl ,,, cstr_args cdecl) *
    ∑ inst,
    spine_subst (Σ, ind_universes mdecl)
              (arities_context (ind_bodies mdecl) ,,, ind_params mdecl ,,,
                cstr_args cdecl)
              ((to_extended_list_k (ind_params mdecl) #|cstr_args cdecl|) ++
                (cstr_indices cdecl)) inst
            (ind_params mdecl ,,, ind_indices idecl).
  Proof using declc wfΣ.
    pose proof (on_declared_constructor declc) as [[onmind oib] [cunivs [hnth onc]]].
    pose proof (onc.(on_cargs)).
simpl in X.
    split.
split.
split.
    2:{
 eapply (weaken_lookup_on_global_env' _ _ (InductiveDecl mdecl)); tea.
        clear hnth.
unshelve eapply declared_constructor_to_gen in declc; eauto.
        exact (inductive_mind ind.1).
🛠️ Intermediate Coq File (useful for debugging if minimization did not go as far as you wanted) (truncated to 6.0KiB; full 147KiB file on GitHub Actions Artifacts under tmp.v)
(* -*- mode: coq; coq-prog-args: ("-emacs" "-q" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/utils/theories" "MetaRocq.Utils" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/common/theories" "MetaRocq.Common" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories" "MetaRocq.PCUIC" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Equations" "Equations" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/ExtLib" "ExtLib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-top" "MetaRocq.PCUIC.PCUICInductiveInversion") -*- *)
(* File reduced by coq-bug-minimizer from original input, then from 4603 lines to 39 lines, then from 53 lines to 3776 lines *)
(* coqc version 9.3+alpha compiled with OCaml 4.14.2
   coqtop version 9.3+alpha
   Expected coqc runtime on this file: 0.000 sec
   Expected coqc peak memory usage on this file: 0.0 kb *)
Require Coq.Init.Ltac.
Module Export AdmitTactic.
Module Import LocalFalse.
Inductive False : Prop := .
End LocalFalse.
Axiom proof_admitted : False.
Import Coq.Init.Ltac.
Tactic Notation "admit" := abstract case proof_admitted.
End AdmitTactic.
Require Corelib.BinNums.IntDef.
Require Corelib.BinNums.NatDef.
Require Corelib.BinNums.PosDef.
Require Corelib.Classes.CMorphisms.
Require Corelib.Classes.CRelationClasses.
Require Corelib.Classes.Morphisms.
Require Corelib.Classes.Morphisms_Prop.
Require Corelib.Classes.RelationClasses.
Require Corelib.Classes.SetoidTactics.
Require Corelib.Floats.FloatAxioms.
Require Corelib.Floats.FloatOps.
Require Corelib.Floats.PrimFloat.
Require Corelib.Floats.SpecFloat.
Require Corelib.Init.Byte.
Require Corelib.Init.Decimal.
Require Corelib.Init.Hexadecimal.
Require Corelib.Init.Ltac.
Require Corelib.Init.Nat.
Require Corelib.Init.Sumbool.
Require Corelib.Init.Wf.
Require Corelib.Lists.ListDef.
Require Corelib.Numbers.BinNums.
Require Corelib.Numbers.Cyclic.Int63.CarryType.
Require Corelib.Numbers.Cyclic.Int63.PrimInt63.
Require Corelib.Numbers.Cyclic.Int63.Sint63Axioms.
Require Corelib.Numbers.Cyclic.Int63.Uint63Axioms.
Require Corelib.Program.Basics.
Require Corelib.Program.Tactics.
Require Corelib.Program.Utils.
Require Corelib.Program.Wf.
Require Corelib.Relations.Relation_Definitions.
Require Corelib.Setoids.Setoid.
Require Corelib.Strings.PrimString.
Require Corelib.Strings.PrimStringAxioms.
Require Corelib.extraction.Extraction.
Require Corelib.ssr.ssrbool.
Require Corelib.ssr.ssreflect.
Require Corelib.ssr.ssrfun.
Require ExtLib.Core.Any.
Require ExtLib.Structures.BinOps.
Require MetaRocq.Utils.MREquality.
Require MetaRocq.Utils.MRSquash.
Require MetaRocq.Utils.MRTactics.DestructHyps.
Require MetaRocq.Utils.MRTactics.FindHyp.
Require MetaRocq.Utils.MRTactics.Head.
Require MetaRocq.Utils.MRTactics.SpecializeBy.
Require MetaRocq.Utils.MRTactics.SplitInContext.
Require MetaRocq.Utils.MRTactics.Zeta1.
Require Stdlib.Classes.DecidableClass.
Require Stdlib.Logic.Decidable.
Require Stdlib.Logic.EqdepFacts.
Require Stdlib.Logic.FunctionalExtensionality.
Require Stdlib.Logic.HLevelsBase.
Require Stdlib.Program.Syntax.
Require Stdlib.Sets.Relations_1.
Require Stdlib.Unicode.Utf8_core.
Require Stdlib.Wellfounded.Inverse_Image.
Require Stdlib.micromega.ZifyClasses.
Require Stdlib.setoid_ring.Algebra_syntax.
Require Equations.Init.
Require ExtLib.Structures.Functor.
Require ExtLib.Structures.Monoid.
Require Ltac2.Init.
Require MetaRocq.Utils.MRTactics.UniquePose.
Require Stdlib.BinNums.IntDef.
Require Stdlib.BinNums.NatDef.
Require Stdlib.BinNums.PosDef.
Require Stdlib.Classes.CMorphisms.
Require Stdlib.Classes.CRelationClasses.
Require Stdlib.Classes.Morphisms.
Require Stdlib.Classes.Morphisms_Prop.
Require Stdlib.Classes.RelationClasses.
Require Stdlib.Classes.SetoidTactics.
Require Stdlib.Floats.FloatAxioms.
Require Stdlib.Floats.FloatOps.
Require Stdlib.Floats.PrimFloat.
Require Stdlib.Floats.SpecFloat.
Require Stdlib.Init.Byte.
Require Stdlib.Init.Decimal.
Require Stdlib.Init.Hexadecimal.
Require Stdlib.Init.Nat.
Require Stdlib.Init.Sumbool.
Require Stdlib.Init.Wf.
Require Stdlib.Lists.ListDef.
Require Stdlib.Logic.Eqdep.
Require Stdlib.Logic.Eqdep_dec.
Require Stdlib.Logic.ProofIrrelevanceFacts.
Require Stdlib.Numbers.BinNums.
Require Stdlib.Numbers.Cyclic.Int63.CarryType.
Require Stdlib.Numbers.Cyclic.Int63.PrimInt63.
Require Stdlib.Numbers.Cyclic.Int63.Sint63Axioms.
Require Stdlib.Numbers.Cyclic.Int63.Uint63Axioms.
Require Stdlib.Program.Basics.
Require Stdlib.Program.Tactics.
Require Stdlib.Program.Utils.
Require Stdlib.Program.Wf.
Require Stdlib.Relations.Relation_Definitions.
Require Stdlib.Setoids.Setoid.
Require Stdlib.Strings.PrimString.
Require Stdlib.Strings.PrimStringAxioms.
Require Stdlib.Unicode.Utf8.
Require Stdlib.Wellfounded.Well_Ordering.
Require Stdlib.extraction.Extraction.
Require Stdlib.ssr.ssrbool.
Require Stdlib.ssr.ssreflect.
Require Stdlib.ssr.ssrfun.
Require Equations.Prop.SigmaNotations.
Require Equations.Signature.
Require ExtLib.Structures.Applicative.
Require Ltac2.Message.
Require Ltac2.Std.
Require MetaRocq.Utils.MRTactics.DestructHead.
Require MetaRocq.Utils.MRTactics.SpecializeAllWays.
Require Stdlib.Bool.Bool.
Require Stdlib.Logic.JMeq.
Require Stdlib.Logic.ProofIrrelevance.
Require Stdlib.Relations.Relation_Operators.
Require Stdlib.Wellfounded.Inclusion.
Require Equations.CoreTactics.
Require ExtLib.Structures.Monad.
Require Ltac2.Control.
Require MetaRocq.Utils.MRTactics.GeneralizeOverHoles.
Require Stdlib.Program.Combinators.
Require Stdlib.Relations.Operators_Properties.
Require Stdlib.Wellfounded.Disjoint_Union.
Require Stdlib.Wellfounded.Transitive_Closure.
Require ExtLib.Structures.MonadCont.
Require ExtLib.Structures.MonadExc.
Require ExtLib.Structures.MonadFix.
Require ExtLib.Str
🛠️ 📜 Intermediate Coq File log (useful for debugging if minimization did not go as far as you wanted) (truncated to last 2.0KiB; full 105KiB file on GitHub Actions Artifacts under tmp.log)
e-9.3,deprecated,default]
File "/tmp/tmpbyd3gz8a/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 2747, characters 6-13:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "/tmp/tmpbyd3gz8a/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 2749, characters 21-28:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "/tmp/tmpbyd3gz8a/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 2750, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "/tmp/tmpbyd3gz8a/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 2751, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "/tmp/tmpbyd3gz8a/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 2752, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "/tmp/tmpbyd3gz8a/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 2754, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "/tmp/tmpbyd3gz8a/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 2755, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "/tmp/tmpbyd3gz8a/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 2758, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "/tmp/tmpbyd3gz8a/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 2759, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "/tmp/tmpbyd3gz8a/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 2765, characters 12-19:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]

Timeout! (external)
📜 Build Log (contains the Coq error message) (truncated to last 8.0KiB; full 8.0MiB file on GitHub Actions Artifacts under build.log)
cated,default]Warning, feedback message received but no listener to handle it!
Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
Warning: Deprecated environment variable COQCORELIB,
use ROCQRUNTIMELIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 5, characters 0-758:
Warning:
New coercion path [weaken_env_prop_full_to_strictly_on_decls;
                   weaken_env_prop_full_strictly_on_decls_to_strictly_decls] : weaken_env_prop_full >-> weaken_env_strictly_decls_prop_full is ambiguous with existing 
[weaken_env_prop_full_to_decls; weaken_env_prop_full_decls_to_strictly_decls] : weaken_env_prop_full >-> weaken_env_strictly_decls_prop_full.
[ambiguous-paths,coercions,default]
File "./theories/PCUICInductiveInversion.v", line 5, characters 0-758:
Warning:
New coercion path [weaken_env_prop_to_strictly_on_decls;
                   weaken_env_prop_strictly_on_decls_to_strictly_decls] : weaken_env_prop >-> weaken_env_strictly_decls_prop is ambiguous with existing 
[weaken_env_prop_to_decls; weaken_env_prop_decls_to_strictly_decls] : weaken_env_prop >-> weaken_env_strictly_decls_prop.
[ambiguous-paths,coercions,default]
File "./theories/PCUICInductiveInversion.v", line 65, characters 23-30:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 79, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 80, characters 49-56:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 81, characters 56-63:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 82, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 84, characters 18-25:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 85, characters 14-21:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 99, characters 14-21:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 99, characters 26-33:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 105, characters 22-29:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 107, characters 6-13:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 108, characters 12-19:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 127, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 128, characters 43-50:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 129, characters 50-57:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 130, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 132, characters 12-19:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 133, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 147, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 147, characters 20-27:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 153, characters 16-23:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 172, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 174, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 201, characters 22-29:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 225, characters 22-29:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 230, characters 4-11:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 274, characters 15-35:
Error:
In environment
cf : checker_flags
Σ : global_env
ind : inductive × nat
mdecl : mutual_inductive_body
idecl : one_inductive_body
cdecl : constructor_body
wfΣ : wf Σ
declc :
  PCUICLookup.declared_constructor_gen (lookup_env Σ) ind mdecl idecl cdecl
onmind :
  on_inductive cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
    (inductive_mind ind.1) mdecl
oib :
  on_ind_body cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
    (inductive_mind ind.1) mdecl (inductive_ind ind.1) idecl
cunivs : constructor_univs
onc :
  on_constructor cumulSpec0 (lift_typing typing) (
    Σ, ind_universes mdecl) mdecl (inductive_ind ind.1) idecl
    (ind_indices idecl) cdecl cunivs
X :
  sorts_local_ctx (lift_typing typing) (Σ, ind_universes mdecl)
    (arities_context (ind_bodies mdecl),,, ind_params mdecl)
    (cstr_args cdecl) cunivs
The term "inductive_mind ind.1" has type "kername"
while it is expected to have type
 "lookup_env (Σ, ind_universes mdecl).1 ?c = Some (InductiveDecl mdecl)".

Command exited with non-zero status 1
theories/PCUICInductiveInversion.vo (real: 2.19, user: 2.02, sys: 0.16, mem: 847892 ko)
make[3]: *** [Makefile.rocq:815: theories/PCUICInductiveInversion.vo] Error 1
make[3]: *** [theories/PCUICInductiveInversion.vo] Deleting file 'theories/PCUICInductiveInversion.glob'
make[2]: *** [Makefile.rocq:411: all] Error 2
make[2]: Leaving directory '/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic'
make[1]: *** [Makefile:11: coq] Error 2
make[1]: Leaving directory '/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic'
make: *** [Makefile:153: pcuic] Error 2
+ code=2
+ printf '\n%s exit code: %s\n' metarocq 2
+ '[' metarocq '!=' stdlib_test ']'
+ echo 'Aggregating timing log...'
Aggregating timing log...
+ echo

+ tools/make-one-time-file.py --real _build_ci/metarocq.log
    Time |  Peak Mem | File Name                 
-------------------------------------------------
0m02.19s | 847892 ko | Total Time / Peak Mem     
-------------------------------------------------
0m02.19s | 847892 ko | PCUICInductiveInversion.vo
+ '[' '' ']'
+ exit 2
/github/workspace/builds/coq /github/workspace
::endgroup::
📜 🔎 Minimization Log (truncated to last 8.0KiB; full 96MiB file on GitHub Actions Artifacts under bug.log)
/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1188, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1193, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1197, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1204, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1211, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1225, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1233, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1238, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1245, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1252, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1258, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1271, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1277, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1283, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1293, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1299, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1303, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1309, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1315, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1321, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1327, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1334, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1337, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1340, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1346, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1360, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1367, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1374, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1401, characters 0-40:
Warning:
New coercion path [weaken_env_prop_full_to_strictly_on_decls;
                   weaken_env_prop_full_strictly_on_decls_to_strictly_decls] : weaken_env_prop_full >-> weaken_env_strictly_decls_prop_full is ambiguous with existing 
[weaken_env_prop_full_to_decls; weaken_env_prop_full_decls_to_strictly_decls] : weaken_env_prop_full >-> weaken_env_strictly_decls_prop_full.
[ambiguous-paths,coercions,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1401, characters 0-40:
Warning:
New coercion path [weaken_env_prop_to_strictly_on_decls;
                   weaken_env_prop_strictly_on_decls_to_strictly_decls] : weaken_env_prop >-> weaken_env_strictly_decls_prop is ambiguous with existing 
[weaken_env_prop_to_decls; weaken_env_prop_decls_to_strictly_decls] : weaken_env_prop >-> weaken_env_strictly_decls_prop.
[ambiguous-paths,coercions,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1408, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1411, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpegvcm88g/MetaRocq/PCUIC/PCUICInductiveInversion.v", line 1426, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
Error: The section OnConstructor needs to be closed.


�[93mIntermediate code not saved.�[0m
Failed to do everything at once; trying one at a time.
Admitting definitions unsuccessful.
No successful changes.

I will now attempt to add Proof using lines
�[92m
Adding Proof using lines successful.�[0m
Failed to do everything at once; trying one at a time.
Adding Proof using lines unsuccessful.
No successful changes.

I will now attempt to export modules
Module exportation successful

I will now attempt to split imports and exports
Import/Export splitting successful

I will now attempt to split := definitions
One-line definition splitting successful

I will now attempt to lift Requires to the top of the file while inserting option settings

I will now attempt to lift Requires to the top of the file while inserting option settings

I will now attempt to remove all lines, one at a time

If you have any comments on your experience of the minimizer, please share them in a reply (possibly tagging @JasonGross).
If you believe there's a bug in the bug minimizer, please report it on the bug minimizer issue tracker.

@coqbot-app

coqbot-app Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor
Minimization interrupted by timeout, being automatically continued. Partially Minimized File /home/runner/work/run-coq-bug-minimizer/run-coq-bug-minimizer/builds/coq/coq-failing/_build_ci/fiat_crypto/src/Bedrock/Field/Synthesis/Examples/redc.v in 5h 15m 10s (from ci-fiat_crypto) (interrupted by timeout, being automatically continued) (full log on GitHub Actions - verbose log)
⭐ ⏱️ Partially Minimized Coq File (timeout) (truncated to first and last 32KiB; full 46KiB file on GitHub Actions Artifacts under bug.v)
(* -*- mode: coq; coq-prog-args: ("-emacs" "-q" "-w" "+implicit-core-hint-db,+implicits-in-term,+non-reversible-notation,+deprecated-intros-until-0,+deprecated-focus,+unused-intro-pattern,+variable-collision,+unexpected-implicit-declaration,+omega-is-deprecated,+deprecated-instantiate-syntax,+non-recursive,+undeclared-scope,+deprecated-hint-rewrite-without-locality,+deprecated-hint-without-locality,+deprecated-instance-without-locality,+deprecated-typeclasses-transparency-without-locality,+fragile-hint-constr,-deprecated-since-9.0,-deprecated-since-8.20,-deprecated-from-Coq" "-w" "-notation-overridden,-native-compiler-disabled,-ambiguous-paths,-masking-absolute-name" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Coqprime" "Coqprime" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Kami" "Kami" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rewriter" "Rewriter" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rupicola" "Rupicola" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Crypto.Bedrock.Field.Synthesis.Examples.redc") -*- *)
(* File reduced by coq-bug-minimizer from original input, then from 577 lines to 117 lines, then from 131 lines to 869 lines, then from 877 lines to 453 lines, then from 468 lines to 1367 lines, then from 1372 lines to 533 lines, then from 548 lines to 1295 lines, then from 1303 lines to 616 lines, then from 631 lines to 1279 lines, then from 1286 lines to 653 lines, then from 668 lines to 953 lines, then from 961 lines to 662 lines, then from 677 lines to 1947 lines, then from 1949 lines to 996 lines, then from 1011 lines to 1284 lines, then from 1292 lines to 1026 lines, then from 1041 lines to 1079 lines, then from 1087 lines to 1042 lines, then from 1057 lines to 1205 lines, then from 1211 lines to 1085 lines, then from 1100 lines to 1221 lines, then from 1229 lines to 1123 lines, then from 1138 lines to 1177 lines, then from 1185 lines to 1151 lines, then from 1166 lines to 1480 lines, then from 1488 lines to 1182 lines, then from 1197 lines to 1464 lines, then from 1472 lines to 1195 lines *)
(* coqc version 9.3+alpha compiled with OCaml 4.14.2
   coqtop version 9.3+alpha
   Modules that could not be inlined: Crypto.Arithmetic.WordByWordMontgomery
   Expected coqc runtime on this file: 1.177 sec
   Expected coqc peak memory usage on this file: 976608.0 kb *)

Require bedrock2.Markers.
Require coqutil.Tactics.eabstract.
Require coqutil.Tactics.letexists.
Require coqutil.Tactics.ident_of_string.
Require coqutil.Tactics.reference_to_string.
Require bedrock2.NotationsCustomEntry.
Require bedrock2.WeakestPreconditionProperties.
Require coqutil.Word.Bitwidth64.
Require coqutil.Word.Naive.
Module Export SortedListWord.
Import coqutil.Word.Interface.
Import coqutil.Map.Interface.

Section __.
  Context {width} (word : word width) {word_ok : @word.ok width word}.

  Context (value : Type).
Definition map : map.map word value.
Admitted.
Global Instance ok : map.ok map.
Admitted.
End __.
End SortedListWord.

Module Export bedrock2_DOT_BasicC64Semantics_WRAPPED.
Module Export BasicC64Semantics.
Import Coq.ZArith.ZArith.
Import bedrock2.Semantics.
Export coqutil.Word.Bitwidth64.
#[export] Instance word: word.word 64.
exact (Naive.word64).
Defined.
#[export] Instance mem: Interface.map.map word Byte.byte.
exact (SortedListWord.map _ _).
Defined.
#[export] Instance locals: Interface.map.map String.string word.
exact (SortedListString.map _).
Defined.
#[export] Instance ext_spec: ExtSpec.
Admitted.
Add Ring wring : (Properties.word.ring_theory (word := word))
      (preprocess [autorewrite with rew_word_morphism],
       morphism (Properties.word.ring_morph (word := word)),
       constants [Properties.word_cst]).

End BasicC64Semantics.
Module Export bedrock2.
Module Export BasicC64Semantics.
Include bedrock2_DOT_BasicC64Semantics_WRAPPED.BasicC64Semantics.
End BasicC64Semantics.

End bedrock2.
Ltac rdelta x :=
  match constr:(Set) with
  | _ => progress_rdelta x
  | _ => x
  end
with progress_rdelta x :=
  let x := eval cbv delta [x] in x in
  rdelta x.

Ltac rdelta_var x :=
  match constr:(Set) with
  | _ => progress_rdelta_var x
  | _ => x
  end
with progress_rdelta_var x :=
  let __ := match constr:(Set) with _ => is_var x end in
  let x := eval cbv delta [x] in x in
  rdelta_var x.
Module Export coqutil_DOT_Tactics_DOT_rdelta.
Module Export coqutil.
Module Export Tactics.
Module Export rdelta.
End rdelta.

End Tactics.

End coqutil.

End coqutil_DOT_Tactics_DOT_rdelta.

Ltac _syntactic_unify_deltavar x y :=
  match constr:(Set) with
  | _ => is_evar x; unify x y
  | _ => is_evar y; unify x y
  | _ => is_var x; let x := eval cbv delta [x] in x in _syntactic_unify_deltavar x y
  | _ => is_var y; let y := eval cbv delta [y] in y in _syntactic_unify_deltavar x y
  | _ => lazymatch x with
         | ?f ?a => lazymatch y with ?g ?b => _syntactic_unify_deltavar f g; _syntactic_unify_deltavar a b end
         | (fun (a:?Ta) => ?f a)
           => lazymatch y with (fun (b:?Tb) => ?g b) =>
                               let __ := constr:(fun (a:Ta) (b:Tb) => ltac:(_syntactic_unify_deltavar f g; exact Set)) in idtac end
         | let a : ?Ta := ?v in ?f a
           => lazymatch y with let b : ?Tb := ?w in ?g b =>
                               _syntactic_unify_deltavar v w;
                               let __ := constr:(fun (a:Ta) (b:Tb) => ltac:(_syntactic_unify_deltavar f g; exact Set)) in idtac end

         | _ => first [ constr_eq x y
                      | first [has_evar x | has_evar y]; unify x y; constr_eq x y ]
         end
  end.
Tactic Notation "syntactic_unify_deltavar" open_constr(x) open_constr(y) :=  _syntactic_unify_deltavar x y.

Ltac _syntactic_exact_deltavar e :=
  let t := type of e in
  let g := lazymatch goal with |- ?g => g end in
  tryif syntactic_unify_deltavar t g then exact_no_check e else fail "syntactic_unify" t g.
Tactic Notation "syntactic_exact_deltavar" open_constr(e) :=
  _syntactic_exact_deltavar e.
Module Export coqutil_DOT_Tactics_DOT_syntactic_unify.
Module Export coqutil.
Module Export Tactics.
Module Export syntactic_unify.
End syntactic_unify.

End Tactics.

End coqutil.

End coqutil_DOT_Tactics_DOT_syntactic_unify.

Ltac list_get l i :=
  lazymatch l with
  | cons ?a ?l =>
    lazymatch i with
    | O  => a
    | S ?i => list_get l i
    end
  | _ => fail "list_get nil" i
  end.

Ltac index_and_element_of xs :=
  multimatch xs with
  | cons ?x _ => constr:((0%nat, x))
  | cons _ ?xs =>
    let r := index_and_element_of xs in
    multimatch r with
    | (?i, ?y) => constr:((S i, y))
    end
  end.

Ltac find_syntactic_unify_deltavar xs y :=
  multimatch xs with
  | cons ?x _ =>
    let __ := match constr:(Set) with _ => syntactic_unify_deltavar x y end in
    constr:(O)
  | cons _ ?xs => let i := find_syntactic_unify_deltavar xs y in constr:(S i)
  end.

Ltac find_constr_eq xs y :=
  match xs with
  | cons ?x _ => constr:(ltac:(constr_eq x y; exact 0%nat))
  | cons _ ?xs => let i := find_constr_eq xs y in constr:(S i)
  end.
Module Export coqutil.
Module Export Tactics.
Module Export ltac_list_ops.
End ltac_list_ops.

End Tactics.

End coqutil.
Module Export Lift1Prop.
Import Coq.Classes.Morphisms.

Section Binary.
  Context {T: Type} (P Q: T -> Prop).
  Definition impl1 := forall x, P x -> Q x.
  Definition iff1 := forall x, P x <-> Q x.
End Binary.
Global Instance subrelation_iff1_impl1 T : subrelation (@iff1 T) (@impl1 T).
Admitted.
Global Instance Equivalence_iff1 T : Equivalence (@iff1 T).
Admitted.
Module Export coqutil.
Module Export Lift1Prop.
End Lift1Prop.

End coqutil.
Module Export Separation.
Import coqutil.Map.Interface.
Import map.

Section Sep.
  Context {key value} {map : map key value}.
  Definition emp (P : Prop) := fun m : map => m = empty /\ P.
  Definition sep (p q : map -> Prop) m :=
    exists mp mq, split m mp mq /\ p mp /\ q mq.
  Definition ptsto k v := fun m : map => m = put empty k v.

  Fixpoint seps (xs : list (rep -> Prop)) : rep -> Prop :=
    match xs with
    | cons x nil => x
    | cons x xs => sep x (seps xs)
    | nil => emp True
    end.
End Sep.

Definition sepclause_of_map {key value map} (m : @map.rep key value map)
  : map.rep -> Prop := Logic.eq m.
Coercion sepclause_of_map : Interface.map.rep >-> Funclass.

Declare Scope sep_scope.
Delimit Scope sep_scope with sep.
Infix "*" := sep (at level 40, left associativity) : sep_scope.
Notation "m =* P" := ((P%sep) m) (at level 70, only parsing).
Module Export coqutil.
Module Export Map.
Module Export Separation.
End Separation.
Module Export SeparationLogic.
Import coqutil.Lift1Prop.
Import coqutil.Map.Interface.
Import coqutil.Tactics.ltac_list_ops.
Import Map.Interface.map.
Lemma impl1_refl{T: Type}: forall {P: T -> Prop}, Lift1Prop.impl1 P P.
Admitted.

Lemma iff1_refl{A: Type}(P: A -> Prop): iff1 P P.
Admitted.
Lemma iff1_sym{A: Type}{P Q: A -> Prop}: iff1 P Q -> iff1 Q P.
Admitted.

Ltac iff1_syntactic_reflexivity :=
  lazymatch goal with
  | |- iff1 ?x ?y => first [is_evar x | is_evar y | constr_eq x y]
  end;
  exact (iff1_refl _).

Section SepProperties.
  Context {key value} {map : map key value} {ok : ok map}.

  Local Definition hd {T} := Eval cbv delta in @List.hd T.
  Local Definition tl {T} := Eval cbv delta in @List.tl T.
  Local Definition firstn {T} := Eval cbv delta in @List.firstn T.
  Local Definition skipn {T} := Eval cbv delta in @List.skipn T.
  Local Definition app {T} := Eval cbv delta in @List.app T.

  Local Infix "++" := app.
  Let nth n xs := hd (emp(map:=map) True) (skipn n xs).
  Let remove_nth n (xs : list (map -> Prop)) :=
    (firstn n xs ++ tl (skipn n xs)).

  Lemma cancel_seps_at_indices i j xs ys
        (Hij : nth i xs = nth j ys)
        (Hrest : iff1 (seps (remove_nth i xs)) (seps (remove_nth j ys)))
    : iff1 (seps xs) (seps ys).
Admitted.

  Lemma cancel_seps_at_indices_by_implication i j xs ys
        (Hij : Lift1Prop.impl1 (nth i xs) (nth j ys))
        (Hrest : Lift1Prop.impl1 (seps (remove_nth i xs)) (seps (remove_nth j ys)))
    : Lift1Prop.impl1 (seps xs) (seps ys).
Admitted.

  Lemma cancel_emp_at_index_l i xs ys
        (Hi : nth i xs = emp True)
        (Hrest : iff1 (seps (remove_nth i xs)) (seps ys))
    : iff1 (seps xs) (seps ys).
Admitted.
  Lemma cancel_emp_at_index_r j xs ys
        (Hj : nth j ys = emp True)
        (Hrest : iff1 (seps xs) (seps (remove_nth j ys)))
    : iff1 (seps xs) (seps ys).
Admitted.

  Lemma cancel_emp_at_index_impl j xs ys
        (Hj : nth j ys = emp True)
        (Hrest : impl1 (seps xs) (seps (remove_nth j ys)))
    : impl1 (seps xs) (seps ys).
Admitted.
End SepProperties.
Import coqutil.Tactics.syntactic_unify.
Import coqutil.Tactics.rdelta.

Module Export Tree.
  Inductive Tree(A: Type): Type :=
  | Leaf(a: A)
  | Node(left right: Tree A).
  Arguments Leaf {A} _.
  Arguments Node {A} _ _.
  Section Interp.
    Context {A B: Type}.
    Context (interp_Leaf: A -> B).
    Context (interp_Node: B -> B -> B).
Fixpoint interp(t: Tree A): B.
exact (match t with
      | Leaf a => interp_Leaf a
      | Node t1 t2 => interp_Node (interp t1) (interp t2)
      end).
Defined.
  End Interp.
Definition flatten{A: Type}: Tree A -> list A.
exact (interp (fun a => cons a nil) (@app A)).
Defined.

  Section WithMap.
    Context {key value} {map : map key value} {ok : ok map}.
Definition to_sep: Tree (map -> Prop) -> map -> Prop.
exact (interp (fun x => x) sep).
Defined.

    Lemma flatten_iff1_to_sep(t : Tree.Tree (map -> Prop)):
      Lift1Prop.iff1 (seps (flatten t)) (to_sep t).
Admitted.

    Lemma iff1_to_sep_of_iff1_flatten(LHS RHS : Tree (map -> Prop)):
      Lift1Prop.iff1 (seps (flatten LHS)) (seps (flatten RHS)) ->
      Lift1Prop.iff1 (to_sep LHS) (to_sep RHS).
Admitted.

    Lemma impl1_to_sep_of_impl1_flatten(LHS RHS : Tree (map -> Prop)):
      Lift1Prop.impl1 (seps (flatten LHS)) (seps (flatten RHS)) ->
      Lift1Prop.impl1 (to_sep LHS) (to_sep RHS).
Admitted.

    Lemma flatten_to_sep_with_and(t : Tree.Tree (map -> Prop))(m: map)(C: Prop):
      seps (flatten t) m /\ C -> to_sep t m /\ C.
Admitted.
  End WithMap.

Ltac reify e :=
  lazymatch e with
  | @sep ?key ?value ?map ?a ?b =>
    let a := reify a in
    let b := reify b in
    uconstr:(@Tree.Node (@map.rep key value map -> Prop) a b)
  | ?a => uconstr:(Tree.Leaf a)
  end.

Ltac reify_goal :=
  lazymatch goal with
  | |- Lift1Prop.iff1 ?LHS ?RHS =>
    let LHS := reify LHS in
    let RHS := reify RHS in
    change (Lift1Prop.iff1 (Tree.to_sep LHS) (Tree.to_sep RHS));
    eapply Tree.iff1_to_sep_of_iff1_flatten
  | |- Lift1Prop.impl1 ?LHS ?RHS =>
    let LHS := reify LHS in
    let RHS := reify RHS in
    change (Lift1Prop.impl1 (Tree.to_sep LHS) (Tree.to_sep RHS));
    eapply Tree.impl1_to_sep_of_impl1_flatten
  end;
  cbv [Tree.flatten Tree.interp app].

Ltac flatten_seps_in H :=
  lazymatch type of H with
  | ?nested ?m =>
    let tmem := type of m in
    let E := fresh "E" in
    eassert (@iff1 tmem nested _) as E;
    [
      let stars := eval cbv [seps] in nested in
      let tree := reify stars in
      transitivity (Tree.to_sep tree); [
        cbv [seps Tree.to_sep Tree.interp]; iff1_syntactic_reflexivity
      |];

      transitivity (seps (Tree.flatten tree)); [
        exact (iff1_sym (Tree.flatten_iff1_to_sep tree))
      |];

      cbv [SeparationLogic.Tree.flatten SeparationLogic.Tree.interp SeparationLogic.app];
      iff1_syntactic_reflexivity
    | let HNew := fresh in pose proof (proj1 (E m) H) as HNew;
      move HNew before H;
      clear E H;
      rename HNew into H ]
  end.

Ltac flatten_seps_in_goal :=
  cbv [seps];
  lazymatch goal with
  | |- ?nested ?m /\ ?C =>
      let xs := reify nested in
      change (Tree.to_sep xs m /\ C);
      eapply Tree.flatten_to_sep_with_and
  | |- ?nested ?m =>
      let xs := reify nested in
      change (Tree.to_sep xs m);
      eapply Tree.flatten_iff1_to_sep
  end;
  cbv [Tree.flatten Tree.interp app].

Ltac cancel_emp_l :=
  lazymatch goal with
  | |- Lift1Prop.iff1 (@seps ?K ?V ?M ?LHS) (seps ?RHS) =>
    let i := find_constr_eq LHS constr:(@emp K V M True) in
    simple refine (cancel_emp_at_index_l i LHS RHS _ _);
    cbv [firstn skipn app hd tl];
    [syntactic_exact_deltavar (@eq_refl _ _)|]
  end.

Ltac cancel_emp_r :=
  lazymatch goal with
  | |- Lift1Prop.iff1 (seps ?LHS) (@seps ?K ?V ?M ?RHS) =>
    let j := find_constr_eq RHS constr:(@emp K V M True) in
    simple refine (cancel_emp_at_index_r j LHS RHS _ _);
    cbv [firstn skipn app hd tl];
    [syntactic_exact_deltavar (@eq_refl _ _)|]
  end.

Ltac cancel_emp_impl :=
  lazymatch goal with
  | |- Lift1Prop.impl1 (seps ?LHS) (@seps ?K ?V ?M ?RHS) =>
    let j := find_constr_eq RHS constr:(@emp K V M True) in

    simple refine (cancel_emp_at_index_impl j LHS RHS _ _);
    cbv [firstn skipn app hd tl];

    [syntactic_exact_deltavar (@eq_refl _ _)|]
  end.

Ltac cancel_seps_at_indices i j :=
  lazymatch goal with
  | |- Lift1Prop.iff1 (seps ?LHS) (seps ?RHS) =>
    simple refine (cancel_seps_at_indices i j LHS RHS _ _);
    cbv [firstn skipn app hd tl]
  end.

Ltac cancel_seps_at_indices_by_implication i j :=
  lazymatch goal with
  | |- Lift1Prop.impl1 (seps ?LHS) (seps ?RHS) =>
    simple refine (cancel_seps_at_indices_by_implication i j LHS RHS _ _);
    cbv [firstn skipn app hd tl]
  end.

Ltac find_implication xs y :=
  multimatch xs with
  | cons ?x _ => constr:(O)
  | cons _ ?xs => let i := find_implication xs y in constr:(S i)
  end.

Ltac cancel_step := once (
      let RHS := lazymatch goal with |- Lift1Prop.iff1 _ (seps ?RHS) => RHS end in
      let jy := index_and_element_of RHS in
      let j := lazymatch jy with (?i, _) => i end in
      let y := lazymatch jy with (_, ?y) => y end in
      assert_fails (has_evar y);
      let LHS := lazymatch goal with |- Lift1Prop.iff1 (seps ?LHS) _ => LHS end in
      let i := find_constr_eq LHS y in
      cancel_seps_at_indices i j; [exact eq_refl|]).

Ltac cancel_step_impl := once (
    let RHS := lazymatch goal with |- Lift1Prop.impl1 _ (seps ?RHS) => RHS end in
    let jy := index_and_element_of RHS in
    let j := lazymatch jy with (?i, _) => i end in
    let y := lazymatch jy with (_, ?y) => y end in
    assert_fails (has_evar y);
    let LHS := lazymatch goal with |- Lift1Prop.impl1 (seps ?LHS) _ => LHS end in
    let i := find_constr_eq LHS y in
    cancel_seps_at_indices_by_implication i j; [exact impl1_refl|]).

Ltac ecancel_step_at j :=
      let RHS := lazymatch goal with |- Lift1Prop.iff1 _ (seps ?RHS) => RHS end in
      let y := list_get RHS j in
      assert_fails (idtac; let y := rdelta_var y in is_evar y);
      let LHS := lazymatch goal with |- Lift1Prop.iff1 (seps ?LHS) _ => LHS end in
      let i := find_syntactic_unify_deltavar LHS y in
      cancel_seps_at_indices i j; [exact eq_refl|].

Ltac ecancel_steps_inbounds j :=
  let RHS := lazymatch goal with |- Lift1Prop.iff1 _ (seps ?RHS) => RHS end in
  let __ := list_get RHS j in
  idtac.

Ltac ecancel_steps_at j :=
   tryif (ecancel_steps_inbounds j) then (
    tryif (ecancel_step_at j)
    then (                         ecancel_steps_at j)
    else (let j := constr:(S j) in ecancel_steps_at j)
  ) else idtac.

Ltac ecancel_step_by_implication :=
      let RHS := lazymatch goal with |- Lift1Prop.impl1 _ (seps ?RHS) => RHS end in
      let jy := index_and_element_of RHS in
      let j := lazymatch jy with (?i, _) => i end in
      let y := lazymatch jy with (_, ?y) => y end in
      assert_fails (idtac; let y := rdelta_var y in is_evar y);
      let LHS := lazymatch goal with |- Lift1Prop.impl1 (seps ?LHS) _ => LHS end in
      let i := find_implication LHS y in
      cancel_seps_at_indices_by_implication i j; [solve [auto 1 with nocore ecancel_impl]|].

Ltac ecancel_done :=
  cbv [seps];
  syntactic_exact_deltavar
    (@RelationClasses.reflexivity _ _
        (@RelationClasses.Equivalence_Reflexive _ _ (@Equivalence_iff1 _)) _).

Ltac cancel_done :=
  lazymatch goal with
  | |- iff1 (seps (cons _ nil)) _ => idtac
  | |- iff1 _ (seps (cons _ nil )) => idtac
  | |- ?g => assert_fails (has_evar g)
  end;
  ecancel_done.

Ltac cancel_seps :=
  lazymatch goal with
  | |- Lift1Prop.iff1 _ _ =>
    repeat cancel_step;
    repeat cancel_emp_l;
    repeat cancel_emp_r
  | |- Lift1Prop.impl1 _ _ =>
    repeat cancel_step_impl;
    repeat cancel_emp_impl
  end;
  try solve [ cancel_done ].

Ltac cancel := reify_goal; cancel_seps.

Ltac ecancel :=
  cancel;
  lazymatch goal with
  | [|- impl1 _ _] =>
     repeat ecancel_step_by_implication;
     (solve [ cbv [seps]; exact impl1_refl ])
  | [|- iff1 _ _] =>
    ecancel_steps_at O;
    ecancel_done
  end.

Ltac ecancel_assumption :=
  multimatch goal with
  | |- _ ?m1 =>
    multimatch goal with
    | H: _ ?m2 |- _ =>
      syntactic_unify_deltavar m1 m2;
      refine (Lift1Prop.subrelation_iff1_impl1 _ _ _ _ _ H); clear H;
      solve [ecancel]
    end
  end.
Module Export coqutil.
Module Export Map.
Module Export SeparationLogic.
End SeparationLogic.

End Map.

End coqutil.
Require Crypto.Arithmetic.WordByWordMontgomery.
Export coqutil.Map.SeparationLogic.
Module Export bedrock2.
Module Export Map.
Module Export SeparationLogic.
End SeparationLogic.

End Map.

End bedrock2.
Module Export Array.
Import Stdlib.ZArith.ZArith.
Import coqutil.Map.Interface.
Import coqutil.Map.Separation.
Import coqutil.Word.Interface.
Import coqutil.Byte.

Section Array.
  Context {width : Z} {word : Word.Interface.word width} {word_ok : word.ok word}.
  Context {value} {mem : map.map word value} {mem_ok : map.ok mem}.
  Context {T} (element : word -> T -> mem -> Prop) (size : word).
  Fixpoint array (start : word) (xs : list T) :=
    match xs with
    | nil => emp True
    | cons x xs => sep (element start x) (array (word.add start size) xs)
    end.

End Array.

Section ByteArray.
  Context {width : Z} {word : Word.Interface.word width} {word_ok : word.ok word}.
  Context {mem : map.map word byte} {mem_ok : map.ok mem}.
  Local Notation array := (array (mem:=mem) ptsto (word.of_Z 1)).

  Lemma array_1_to_anybytes bs m (a: word) :
    array a bs m -> bedrock2.Memory.anybytes a (Z.of_nat (List.length bs)) m.
Admitted.

  Lemma anybytes_to_array_1 m (addr : word) n :
      bedrock2.Memory.anybytes addr n m ->
      exists bs, array  addr bs m /\ List.length bs = Z.to_nat n.
Admitted.
End ByteArray.
Module Export bedrock2.
Module Export Array.
End Array.

End bedrock2.
Module Export Scalars.
Import coqutil.Map.Interface.
Import coqutil.Map.Separation.
Import coqutil.Word.LittleEndianList.
Import bedrock2.Memory.
Import Coq.ZArith.ZArith.
Import coqutil.Word.Bitwidth.
Import coqutil.Byte.

Section Scalars.
  Context {width : Z} {BW: Bitwidth width} {word : Word.Interface.word width} {word_ok : word.ok word}.

  Context {mem : map.map word byte} {mem_ok : map.ok mem}.
  Implicit Types (m : mem).

  Definition truncated_scalar sz addr (value:Z) : mem -> Prop :=
    (le_split (bytes_per (width:=width) sz) value) $@ addr.

  Definition truncated_word sz addr (value: word) : mem -> Prop :=
    truncated_scalar sz addr (word.unsigned value).

  Notation scalar8 := ptsto (only parsing).

  Definition scalar16 := truncated_word Syntax.access_size.two.
  Definition scalar32 := truncated_word Syntax.access_size.four.
  Definition scalar := truncated_word Syntax.access_size.word.
Definition truncate_word(sz: Syntax.access_size)(w: word): word.
Admitted.

  Lemma load_one_of_sep addr value R m
    (Hsep : sep (scalar8 addr value) R m)
    : Memory.load Syntax.access_size.one m addr = Some (word.of_Z (byte.unsigned value)).
Admitted.

  Lemma load_two_of_sep addr value R m
    (Hsep : sep (scalar16 addr value) R m)
    : Memory.load Syntax.access_size.two m addr = Some (truncate_word Syntax.access_size.two value).
Admitted.

  Lemma load_four_of_sep addr value R m
    (Hsep : sep (scalar32 addr value) R m)
    : Memory.load Syntax.access_size.four m addr = Some (truncate_word Syntax.access_size.four value).
Admitted.

  Lemma load_four_of_sep_32bit(W32: width = 32) addr value R m
    (Hsep : sep (scalar32 addr value) R m)
    : Memory.load Syntax.access_size.four m addr = Some value.
Admitted.

  Lemma load_word_of_sep addr value R m
    (Hsep : sep (scalar addr value) R m)
    : Memory.load Syntax.access_size.word m addr = Some value.
Admitted.

  Lemma store_one_of_sep addr (oldvalue : byte) (value : word) R m (post:_->Prop)
    (Hsep : sep (scalar8 addr oldvalue) R m)
    (Hpost : forall m, sep (scalar8 addr (byte.of_Z (word.unsigned value))) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.one m addr value = Some m1 /\ post m1.
Admitted.

  Lemma store_two_of_sep addr (oldvalue : word) (value : word) R m (post:_->Prop)
    (Hsep : sep (scalar16 addr oldvalue) R m)
    (Hpost : forall m, sep (scalar16 addr value) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.two m addr value = Some m1 /\ post m1.
Admitted.

  Lemma store_four_of_sep addr (oldvalue : word) (value : word) R m (post:_->Prop)
    (Hsep : sep (scalar32 addr oldvalue) R m)
    (Hpost : forall m, sep (scalar32 addr value) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.four m addr value = Some m1 /\ post m1.
Admitted.

  Lemma store_word_of_sep addr (oldvalue value: word) R m (post:_->Prop)
    (Hsep : sep (scalar addr oldvalue) R m)
    (Hpost : forall m, sep (scalar addr value) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.word m addr value = Some m1 /\ post m1.
Admitted.

End Scalars.
Module Export bedrock2.
Module Export Scalars.
End Scalars.
Module Export Loops.
Import coqutil.Datatypes.PrimitivePair.
Import coqutil.Datatypes.HList.
Import coqutil.dlet.
Import Stdlib.ZArith.BinIntDef.
Import coqutil.Map.Interface.
Import coqutil.Word.Bitwidth.
Import bedrock2.Syntax.
Import bedrock2.Semantics.
Import bedrock2.WeakestPrecondition.

Section Loops.
  Context {width: Z} {BW: Bitwidth width} {word: word.word width} {mem: map.map word Byte.byte}.
  Context {locals: map.map String.string word}.
  Context {ext_spec: ExtSpec}.

  Context {fs : env}.
  Let call := fs.

  Local Notation "A /\ B" := (Markers.split (A /\ B)).
Definition reconstruct (variables:list String.string) (values:tuple word (length variables)) : locals.
exact (map.putmany_of_tuple (tuple.of_list variables) values map.empty).
Defined.
Fixpoint gather (variables : list String.string) (l : locals) : option (locals *  tuple word (length variables)).
exact (match variables with
    | nil => Some (l, tt)
    | cons x xs' =>
      match map.get l x with
      | None => None
      | Some v =>
        match gather xs' (map.remove l x) with
        | None => None
        | Some (l, vs') => Some (l, (pair.mk v vs'))
        end
      end
    end).
Defined.
Definition enforce (variables : list String.string) (values:tuple word (length variables)) (l:locals) : Prop.
exact (match gather variables l with
    | None => False
    | Some (remaining, r) => values = r /\ remaining = map.empty
    end).
Defined.

  Import pair.

  Lemma tailrec
    {e c t localsmap} {m : mem}
    (ghosttypes : polymorphic_list.list Type)
    (variables : list String.string)
    {l0 : tuple word (length variables)}
    {Pl : enforce variables l0 localsmap}
    {post : _->_->_-> Prop}
    {measure : Type} (spec:_->HList.arrows ghosttypes (_->_->ufunc word (length variables) (Prop*(_->_->ufunc word (length variables) Prop)))) lt
    (Hwf : well_founded lt)
    (v0 : measure)
    : hlist.foralls (fun (g0 : hlist ghosttypes) => forall
    (Hpre : (tuple.apply (hlist.apply (spec v0) g0 t m) l0).(1))
    (Hbody : forall v, hlist.foralls (fun g => forall t m, tuple.foralls (fun l =>
      @dlet _ (fun _ => Prop) (reconstruct variables l) (fun localsmap : locals =>
      match tuple.apply (hlist.apply (spec v) g t m) l with S_ =>
      S_.(1) ->
      Markers.unique (Markers.left (exists br, expr m localsmap e (eq br) /\ Markers.right (
      (word.unsigned br <> 0%Z -> cmd call c t m localsmap
        (fun t' m' localsmap' =>
          Markers.unique (Markers.left (hlist.existss (fun l' => enforce variables l' localsmap' /\ Markers.right (
          Markers.unique (Markers.left (hlist.existss (fun g' => exists v',
          match tuple.apply (hlist.apply (spec v') g' t' m') l' with S' =>
          S'.(1) /\ Markers.right (
            lt v' v /\
            forall T M, hlist.foralls (fun L => tuple.apply (S'.(2) T M) L -> tuple.apply (S_.(2) T M) L)) end))))))))) /\
      (word.unsigned br = 0%Z -> tuple.apply (S_.(2) t m) l))))end))))
    (Hpost : match (tuple.apply (hlist.apply (spec v0) g0 t m) l0).(2) with Q0 => forall t m, hlist.foralls (fun l =>  tuple.apply (Q0 t m) l -> post t m (reconstruct variables l))end)
    , cmd call (cmd.while e c) t m localsmap post ).
Admitted.
End Loops.
Module Export bedrock2.
Module Export Loops.
End Loops.
Import coqutil.Tactics.Tactics.
Import coqutil.Tactics.letexists.
Import coqutil.Tactics.eabstract.
Import coqutil.Tactics.rdelta.
Import coqutil.Tactics.reference_to_string.
Import coqutil.Tactics.ident_of_string.
Import coqutil.Map.Interface.
Import bedrock2.Syntax.
Import bedrock2.WeakestPrecondition.
Import bedrock2.WeakestPreconditionProperties.
Import bedrock2.Map.SeparationLogic.

Definition spec_of (procname:String.string) := Semantics.env -> Prop.
Existing Class spec_of.
Import Ltac2.Ltac2.

Local Ltac2 rec splitcmd (cmd : constr) : unit :=
  match! cmd with
    | cmd.seq ?cmd1 ?cmd2 =>
        set (cmd.seq $cmd1 $cmd2) in *; splitcmd cmd1; splitcmd cmd2
    | cmd.cond ?expr ?cmd1 ?cmd2 => set (cmd.cond $expr $cmd1 $cmd2) in *; splitcmd cmd1; splitcmd cmd2
    | cmd.while ?expr ?cmd => set (cmd.while $expr $cmd) in *; splitcmd cmd
    | _ => ()
  end.

Local Ltac2 Notation "instance_of" type(constr) :=
  lazy_match! Ltac2.Constr.pretype (preterm:(_ : $type)) with ?instance => instance end.

Local Ltac2 rec unfold_const x :=
  if Bool.neg (Constr.is_const x) then x else
    let ref := reference_to_string.reference_of_constr x in
    match! eval cbv delta [$ref] in $x with ?x => unfold_const x
  end.

Local Ltac2 function_body (proc : constr) : constr :=
  let unfolded := unfold_const proc in
  match! unfolded with (_, _, ?fbody) => fbody end.

Local Ltac2 rec callee_specs (cmd : constr) : constr list :=
  match! cmd with
    | cmd.cond _ ?c1 ?c2  => List.append (callee_specs c1) (callee_specs c2)
    | cmd.seq ?c1 ?c2 => List.append (callee_specs c1) (callee_specs c2)
    | cmd.while _ ?c => callee_specs c
    | cmd.stackalloc _ _ ?c => callee_specs c
    | cmd.call _ ?f _ => [instance_of (spec_of $f)]
    | cmd.skip => []
    | cmd.set _ _ => []
    | cmd.unset _ => []
    | cmd.store _ _ _ => []
    | cmd.interact _ _ _ => []
    | _ => Control.throw (Invalid_argument (Some (Message.concat
        (Message.of_string "Failed to recurse into the following command, consider reducing it before calling program_logic_goal_for: ")
        (Message.of_constr cmd))))
  end.

Local Ltac2 program_logic_goal_for_function (proc : constr) : unit :=
  let fname := constr_string_basename_of_constr_reference proc in
  let fname_spec := instance_of (spec_of $fname) in
  let fbody := function_body proc in
  let goal := (fun (functions : constr) =>
    List.fold_right (fun premise_spec conclusion => '(($premise_spec $functions) -> $conclusion)) (callee_specs fbody) '($fname_spec $functions)) in
  exact (forall (functions : @map.rep _ _ Semantics.env) (EnvContains : map.get functions $fname = Some $proc),
    ltac2:(let g := goal &functions in exact $g)
  ).

Set Default Proof Mode "Classic".

Definition program_logic_goal_for (_ : Syntax.func) (P : Prop) := P.

Notation "program_logic_goal_for_function! proc" := (program_logic_goal_for proc ltac2:(
   program_logic_goal_for_function (Ltac2.Constr.pretype proc)))
  (at level 10, only parsing).

Ltac normalize_body_of_function f := eval cbv in f.

Ltac bind_body_of_function f_ :=
  let f := normalize_body_of_function f_ in
  let fbody := open_constr:(_) in
  let funif := open_constr:((_, _, fbody)) in
  unify f funif;
  let go_split := ltac2:(fbody |-
    let fbody_value := Option.get (Ltac1.to_constr fbody) in
    splitcmd fbody_value) in
  change f_ with f;
  go_split fbody; intros.

Ltac enter f :=
  cbv beta delta [program_logic_goal_for];
  bind_body_of_function f;
  lazymatch goal with |- ?s ?p => let s := rdelta s in change (s p); cbv beta end.

Ltac is_context_variable H :=
  assert_succeeds (exfalso; clear -H; assert(H = H);
    let A := fresh in let B := fresh in destruct H as [A B]; pose H).

Ltac straightline_cleanup :=
  match goal with

  | x : Word.Interface.word.rep _ |- _ => clear x
  | x : Init.Byte.byte |- _ => clear x
  | x : Semantics.trace |- _ => clear x
  | x : Syntax.cmd |- _ => clear x
  | x : Syntax.expr |- _ => clear x
  | x : coqutil.Map.Interface.map.rep |- _ => clear x
  | x : BinNums.Z |- _ => clear x
  | x : unit |- _ => clear x
  | x : bool |- _ => clear x
  | x : list _ |- _ => clear x
  | x : nat |- _ => clear x

  | x := _ : Word.Interface.word.rep _ |- _ => clear x
  | x := _ : Init.Byte.byte |- _ => clear x
  | x := _ : Semantics.trace |- _ => clear x
  | x := _ : Syntax.cmd |- _ => clear x
  | x := _ : Syntax.expr |- _ => clear x
  | x := _ : coqutil.Map.Interface.map.rep |- _ => clear x
  | x := _ : BinNums.Z |- _ => clear x
  | x := _ : unit |- _ => clear x
  | x := _ : bool |- _ => clear x
  | x := _ : list _ |- _ => clear x
  | x := _ : nat |- _ => clear x
  | |- forall _, _ => intros
  | |- let _ := _ in _ => intros
  | |- dlet.dlet ?v (fun x => ?P) => change (let x := v in P); intros
  | _ => progress (cbn [Semantics.interp_binop] in * )
  | H: exists _, _ |- _ => tryif is_con

[...]

h type of H with
  | ?nested ?m =>
    let tmem := type of m in
    let E := fresh "E" in
    eassert (@iff1 tmem nested _) as E;
    [
      let stars := eval cbv [seps] in nested in
      let tree := reify stars in
      transitivity (Tree.to_sep tree); [
        cbv [seps Tree.to_sep Tree.interp]; iff1_syntactic_reflexivity
      |];

      transitivity (seps (Tree.flatten tree)); [
        exact (iff1_sym (Tree.flatten_iff1_to_sep tree))
      |];

      cbv [SeparationLogic.Tree.flatten SeparationLogic.Tree.interp SeparationLogic.app];
      iff1_syntactic_reflexivity
    | let HNew := fresh in pose proof (proj1 (E m) H) as HNew;
      move HNew before H;
      clear E H;
      rename HNew into H ]
  end.

Ltac flatten_seps_in_goal :=
  cbv [seps];
  lazymatch goal with
  | |- ?nested ?m /\ ?C =>
      let xs := reify nested in
      change (Tree.to_sep xs m /\ C);
      eapply Tree.flatten_to_sep_with_and
  | |- ?nested ?m =>
      let xs := reify nested in
      change (Tree.to_sep xs m);
      eapply Tree.flatten_iff1_to_sep
  end;
  cbv [Tree.flatten Tree.interp app].

Ltac cancel_emp_l :=
  lazymatch goal with
  | |- Lift1Prop.iff1 (@seps ?K ?V ?M ?LHS) (seps ?RHS) =>
    let i := find_constr_eq LHS constr:(@emp K V M True) in
    simple refine (cancel_emp_at_index_l i LHS RHS _ _);
    cbv [firstn skipn app hd tl];
    [syntactic_exact_deltavar (@eq_refl _ _)|]
  end.

Ltac cancel_emp_r :=
  lazymatch goal with
  | |- Lift1Prop.iff1 (seps ?LHS) (@seps ?K ?V ?M ?RHS) =>
    let j := find_constr_eq RHS constr:(@emp K V M True) in
    simple refine (cancel_emp_at_index_r j LHS RHS _ _);
    cbv [firstn skipn app hd tl];
    [syntactic_exact_deltavar (@eq_refl _ _)|]
  end.

Ltac cancel_emp_impl :=
  lazymatch goal with
  | |- Lift1Prop.impl1 (seps ?LHS) (@seps ?K ?V ?M ?RHS) =>
    let j := find_constr_eq RHS constr:(@emp K V M True) in

    simple refine (cancel_emp_at_index_impl j LHS RHS _ _);
    cbv [firstn skipn app hd tl];

    [syntactic_exact_deltavar (@eq_refl _ _)|]
  end.

Ltac cancel_seps_at_indices i j :=
  lazymatch goal with
  | |- Lift1Prop.iff1 (seps ?LHS) (seps ?RHS) =>
    simple refine (cancel_seps_at_indices i j LHS RHS _ _);
    cbv [firstn skipn app hd tl]
  end.

Ltac cancel_seps_at_indices_by_implication i j :=
  lazymatch goal with
  | |- Lift1Prop.impl1 (seps ?LHS) (seps ?RHS) =>
    simple refine (cancel_seps_at_indices_by_implication i j LHS RHS _ _);
    cbv [firstn skipn app hd tl]
  end.

Ltac find_implication xs y :=
  multimatch xs with
  | cons ?x _ => constr:(O)
  | cons _ ?xs => let i := find_implication xs y in constr:(S i)
  end.

Ltac cancel_step := once (
      let RHS := lazymatch goal with |- Lift1Prop.iff1 _ (seps ?RHS) => RHS end in
      let jy := index_and_element_of RHS in
      let j := lazymatch jy with (?i, _) => i end in
      let y := lazymatch jy with (_, ?y) => y end in
      assert_fails (has_evar y);
      let LHS := lazymatch goal with |- Lift1Prop.iff1 (seps ?LHS) _ => LHS end in
      let i := find_constr_eq LHS y in
      cancel_seps_at_indices i j; [exact eq_refl|]).

Ltac cancel_step_impl := once (
    let RHS := lazymatch goal with |- Lift1Prop.impl1 _ (seps ?RHS) => RHS end in
    let jy := index_and_element_of RHS in
    let j := lazymatch jy with (?i, _) => i end in
    let y := lazymatch jy with (_, ?y) => y end in
    assert_fails (has_evar y);
    let LHS := lazymatch goal with |- Lift1Prop.impl1 (seps ?LHS) _ => LHS end in
    let i := find_constr_eq LHS y in
    cancel_seps_at_indices_by_implication i j; [exact impl1_refl|]).

Ltac ecancel_step_at j :=
      let RHS := lazymatch goal with |- Lift1Prop.iff1 _ (seps ?RHS) => RHS end in
      let y := list_get RHS j in
      assert_fails (idtac; let y := rdelta_var y in is_evar y);
      let LHS := lazymatch goal with |- Lift1Prop.iff1 (seps ?LHS) _ => LHS end in
      let i := find_syntactic_unify_deltavar LHS y in
      cancel_seps_at_indices i j; [exact eq_refl|].

Ltac ecancel_steps_inbounds j :=
  let RHS := lazymatch goal with |- Lift1Prop.iff1 _ (seps ?RHS) => RHS end in
  let __ := list_get RHS j in
  idtac.

Ltac ecancel_steps_at j :=
   tryif (ecancel_steps_inbounds j) then (
    tryif (ecancel_step_at j)
    then (                         ecancel_steps_at j)
    else (let j := constr:(S j) in ecancel_steps_at j)
  ) else idtac.

Ltac ecancel_step_by_implication :=
      let RHS := lazymatch goal with |- Lift1Prop.impl1 _ (seps ?RHS) => RHS end in
      let jy := index_and_element_of RHS in
      let j := lazymatch jy with (?i, _) => i end in
      let y := lazymatch jy with (_, ?y) => y end in
      assert_fails (idtac; let y := rdelta_var y in is_evar y);
      let LHS := lazymatch goal with |- Lift1Prop.impl1 (seps ?LHS) _ => LHS end in
      let i := find_implication LHS y in
      cancel_seps_at_indices_by_implication i j; [solve [auto 1 with nocore ecancel_impl]|].

Ltac ecancel_done :=
  cbv [seps];
  syntactic_exact_deltavar
    (@RelationClasses.reflexivity _ _
        (@RelationClasses.Equivalence_Reflexive _ _ (@Equivalence_iff1 _)) _).

Ltac cancel_done :=
  lazymatch goal with
  | |- iff1 (seps (cons _ nil)) _ => idtac
  | |- iff1 _ (seps (cons _ nil )) => idtac
  | |- ?g => assert_fails (has_evar g)
  end;
  ecancel_done.

Ltac cancel_seps :=
  lazymatch goal with
  | |- Lift1Prop.iff1 _ _ =>
    repeat cancel_step;
    repeat cancel_emp_l;
    repeat cancel_emp_r
  | |- Lift1Prop.impl1 _ _ =>
    repeat cancel_step_impl;
    repeat cancel_emp_impl
  end;
  try solve [ cancel_done ].

Ltac cancel := reify_goal; cancel_seps.

Ltac ecancel :=
  cancel;
  lazymatch goal with
  | [|- impl1 _ _] =>
     repeat ecancel_step_by_implication;
     (solve [ cbv [seps]; exact impl1_refl ])
  | [|- iff1 _ _] =>
    ecancel_steps_at O;
    ecancel_done
  end.

Ltac ecancel_assumption :=
  multimatch goal with
  | |- _ ?m1 =>
    multimatch goal with
    | H: _ ?m2 |- _ =>
      syntactic_unify_deltavar m1 m2;
      refine (Lift1Prop.subrelation_iff1_impl1 _ _ _ _ _ H); clear H;
      solve [ecancel]
    end
  end.
Module Export coqutil.
Module Export Map.
Module Export SeparationLogic.
End SeparationLogic.

End Map.

End coqutil.
Require Crypto.Arithmetic.WordByWordMontgomery.
Export coqutil.Map.SeparationLogic.
Module Export bedrock2.
Module Export Map.
Module Export SeparationLogic.
End SeparationLogic.

End Map.

End bedrock2.
Module Export Array.
Import Stdlib.ZArith.ZArith.
Import coqutil.Map.Interface.
Import coqutil.Map.Separation.
Import coqutil.Word.Interface.
Import coqutil.Byte.

Section Array.
  Context {width : Z} {word : Word.Interface.word width} {word_ok : word.ok word}.
  Context {value} {mem : map.map word value} {mem_ok : map.ok mem}.
  Context {T} (element : word -> T -> mem -> Prop) (size : word).
  Fixpoint array (start : word) (xs : list T) :=
    match xs with
    | nil => emp True
    | cons x xs => sep (element start x) (array (word.add start size) xs)
    end.

End Array.

Section ByteArray.
  Context {width : Z} {word : Word.Interface.word width} {word_ok : word.ok word}.
  Context {mem : map.map word byte} {mem_ok : map.ok mem}.
  Local Notation array := (array (mem:=mem) ptsto (word.of_Z 1)).

  Lemma array_1_to_anybytes bs m (a: word) :
    array a bs m -> bedrock2.Memory.anybytes a (Z.of_nat (List.length bs)) m.
Admitted.

  Lemma anybytes_to_array_1 m (addr : word) n :
      bedrock2.Memory.anybytes addr n m ->
      exists bs, array  addr bs m /\ List.length bs = Z.to_nat n.
Admitted.
End ByteArray.
Module Export bedrock2.
Module Export Array.
End Array.

End bedrock2.
Module Export Scalars.
Import coqutil.Map.Interface.
Import coqutil.Map.Separation.
Import coqutil.Word.LittleEndianList.
Import bedrock2.Memory.
Import Coq.ZArith.ZArith.
Import coqutil.Word.Bitwidth.
Import coqutil.Byte.

Section Scalars.
  Context {width : Z} {BW: Bitwidth width} {word : Word.Interface.word width} {word_ok : word.ok word}.

  Context {mem : map.map word byte} {mem_ok : map.ok mem}.
  Implicit Types (m : mem).

  Definition truncated_scalar sz addr (value:Z) : mem -> Prop :=
    (le_split (bytes_per (width:=width) sz) value) $@ addr.

  Definition truncated_word sz addr (value: word) : mem -> Prop :=
    truncated_scalar sz addr (word.unsigned value).

  Notation scalar8 := ptsto (only parsing).

  Definition scalar16 := truncated_word Syntax.access_size.two.
  Definition scalar32 := truncated_word Syntax.access_size.four.
  Definition scalar := truncated_word Syntax.access_size.word.
Definition truncate_word(sz: Syntax.access_size)(w: word): word.
Admitted.

  Lemma load_one_of_sep addr value R m
    (Hsep : sep (scalar8 addr value) R m)
    : Memory.load Syntax.access_size.one m addr = Some (word.of_Z (byte.unsigned value)).
Admitted.

  Lemma load_two_of_sep addr value R m
    (Hsep : sep (scalar16 addr value) R m)
    : Memory.load Syntax.access_size.two m addr = Some (truncate_word Syntax.access_size.two value).
Admitted.

  Lemma load_four_of_sep addr value R m
    (Hsep : sep (scalar32 addr value) R m)
    : Memory.load Syntax.access_size.four m addr = Some (truncate_word Syntax.access_size.four value).
Admitted.

  Lemma load_four_of_sep_32bit(W32: width = 32) addr value R m
    (Hsep : sep (scalar32 addr value) R m)
    : Memory.load Syntax.access_size.four m addr = Some value.
Admitted.

  Lemma load_word_of_sep addr value R m
    (Hsep : sep (scalar addr value) R m)
    : Memory.load Syntax.access_size.word m addr = Some value.
Admitted.

  Lemma store_one_of_sep addr (oldvalue : byte) (value : word) R m (post:_->Prop)
    (Hsep : sep (scalar8 addr oldvalue) R m)
    (Hpost : forall m, sep (scalar8 addr (byte.of_Z (word.unsigned value))) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.one m addr value = Some m1 /\ post m1.
Admitted.

  Lemma store_two_of_sep addr (oldvalue : word) (value : word) R m (post:_->Prop)
    (Hsep : sep (scalar16 addr oldvalue) R m)
    (Hpost : forall m, sep (scalar16 addr value) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.two m addr value = Some m1 /\ post m1.
Admitted.

  Lemma store_four_of_sep addr (oldvalue : word) (value : word) R m (post:_->Prop)
    (Hsep : sep (scalar32 addr oldvalue) R m)
    (Hpost : forall m, sep (scalar32 addr value) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.four m addr value = Some m1 /\ post m1.
Admitted.

  Lemma store_word_of_sep addr (oldvalue value: word) R m (post:_->Prop)
    (Hsep : sep (scalar addr oldvalue) R m)
    (Hpost : forall m, sep (scalar addr value) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.word m addr value = Some m1 /\ post m1.
Admitted.

End Scalars.
Module Export bedrock2.
Module Export Scalars.
End Scalars.
Module Export Loops.
Import coqutil.Datatypes.PrimitivePair.
Import coqutil.Datatypes.HList.
Import coqutil.dlet.
Import Stdlib.ZArith.BinIntDef.
Import coqutil.Map.Interface.
Import coqutil.Word.Bitwidth.
Import bedrock2.Syntax.
Import bedrock2.Semantics.
Import bedrock2.WeakestPrecondition.

Section Loops.
  Context {width: Z} {BW: Bitwidth width} {word: word.word width} {mem: map.map word Byte.byte}.
  Context {locals: map.map String.string word}.
  Context {ext_spec: ExtSpec}.

  Context {fs : env}.
  Let call := fs.

  Local Notation "A /\ B" := (Markers.split (A /\ B)).
Definition reconstruct (variables:list String.string) (values:tuple word (length variables)) : locals.
exact (map.putmany_of_tuple (tuple.of_list variables) values map.empty).
Defined.
Fixpoint gather (variables : list String.string) (l : locals) : option (locals *  tuple word (length variables)).
exact (match variables with
    | nil => Some (l, tt)
    | cons x xs' =>
      match map.get l x with
      | None => None
      | Some v =>
        match gather xs' (map.remove l x) with
        | None => None
        | Some (l, vs') => Some (l, (pair.mk v vs'))
        end
      end
    end).
Defined.
Definition enforce (variables : list String.string) (values:tuple word (length variables)) (l:locals) : Prop.
exact (match gather variables l with
    | None => False
    | Some (remaining, r) => values = r /\ remaining = map.empty
    end).
Defined.

  Import pair.

  Lemma tailrec
    {e c t localsmap} {m : mem}
    (ghosttypes : polymorphic_list.list Type)
    (variables : list String.string)
    {l0 : tuple word (length variables)}
    {Pl : enforce variables l0 localsmap}
    {post : _->_->_-> Prop}
    {measure : Type} (spec:_->HList.arrows ghosttypes (_->_->ufunc word (length variables) (Prop*(_->_->ufunc word (length variables) Prop)))) lt
    (Hwf : well_founded lt)
    (v0 : measure)
    : hlist.foralls (fun (g0 : hlist ghosttypes) => forall
    (Hpre : (tuple.apply (hlist.apply (spec v0) g0 t m) l0).(1))
    (Hbody : forall v, hlist.foralls (fun g => forall t m, tuple.foralls (fun l =>
      @dlet _ (fun _ => Prop) (reconstruct variables l) (fun localsmap : locals =>
      match tuple.apply (hlist.apply (spec v) g t m) l with S_ =>
      S_.(1) ->
      Markers.unique (Markers.left (exists br, expr m localsmap e (eq br) /\ Markers.right (
      (word.unsigned br <> 0%Z -> cmd call c t m localsmap
        (fun t' m' localsmap' =>
          Markers.unique (Markers.left (hlist.existss (fun l' => enforce variables l' localsmap' /\ Markers.right (
          Markers.unique (Markers.left (hlist.existss (fun g' => exists v',
          match tuple.apply (hlist.apply (spec v') g' t' m') l' with S' =>
          S'.(1) /\ Markers.right (
            lt v' v /\
            forall T M, hlist.foralls (fun L => tuple.apply (S'.(2) T M) L -> tuple.apply (S_.(2) T M) L)) end))))))))) /\
      (word.unsigned br = 0%Z -> tuple.apply (S_.(2) t m) l))))end))))
    (Hpost : match (tuple.apply (hlist.apply (spec v0) g0 t m) l0).(2) with Q0 => forall t m, hlist.foralls (fun l =>  tuple.apply (Q0 t m) l -> post t m (reconstruct variables l))end)
    , cmd call (cmd.while e c) t m localsmap post ).
Admitted.
End Loops.
Module Export bedrock2.
Module Export Loops.
End Loops.
Import coqutil.Tactics.Tactics.
Import coqutil.Tactics.letexists.
Import coqutil.Tactics.eabstract.
Import coqutil.Tactics.rdelta.
Import coqutil.Tactics.reference_to_string.
Import coqutil.Tactics.ident_of_string.
Import coqutil.Map.Interface.
Import bedrock2.Syntax.
Import bedrock2.WeakestPrecondition.
Import bedrock2.WeakestPreconditionProperties.
Import bedrock2.Map.SeparationLogic.

Definition spec_of (procname:String.string) := Semantics.env -> Prop.
Existing Class spec_of.
Import Ltac2.Ltac2.

Local Ltac2 rec splitcmd (cmd : constr) : unit :=
  match! cmd with
    | cmd.seq ?cmd1 ?cmd2 =>
        set (cmd.seq $cmd1 $cmd2) in *; splitcmd cmd1; splitcmd cmd2
    | cmd.cond ?expr ?cmd1 ?cmd2 => set (cmd.cond $expr $cmd1 $cmd2) in *; splitcmd cmd1; splitcmd cmd2
    | cmd.while ?expr ?cmd => set (cmd.while $expr $cmd) in *; splitcmd cmd
    | _ => ()
  end.

Local Ltac2 Notation "instance_of" type(constr) :=
  lazy_match! Ltac2.Constr.pretype (preterm:(_ : $type)) with ?instance => instance end.

Local Ltac2 rec unfold_const x :=
  if Bool.neg (Constr.is_const x) then x else
    let ref := reference_to_string.reference_of_constr x in
    match! eval cbv delta [$ref] in $x with ?x => unfold_const x
  end.

Local Ltac2 function_body (proc : constr) : constr :=
  let unfolded := unfold_const proc in
  match! unfolded with (_, _, ?fbody) => fbody end.

Local Ltac2 rec callee_specs (cmd : constr) : constr list :=
  match! cmd with
    | cmd.cond _ ?c1 ?c2  => List.append (callee_specs c1) (callee_specs c2)
    | cmd.seq ?c1 ?c2 => List.append (callee_specs c1) (callee_specs c2)
    | cmd.while _ ?c => callee_specs c
    | cmd.stackalloc _ _ ?c => callee_specs c
    | cmd.call _ ?f _ => [instance_of (spec_of $f)]
    | cmd.skip => []
    | cmd.set _ _ => []
    | cmd.unset _ => []
    | cmd.store _ _ _ => []
    | cmd.interact _ _ _ => []
    | _ => Control.throw (Invalid_argument (Some (Message.concat
        (Message.of_string "Failed to recurse into the following command, consider reducing it before calling program_logic_goal_for: ")
        (Message.of_constr cmd))))
  end.

Local Ltac2 program_logic_goal_for_function (proc : constr) : unit :=
  let fname := constr_string_basename_of_constr_reference proc in
  let fname_spec := instance_of (spec_of $fname) in
  let fbody := function_body proc in
  let goal := (fun (functions : constr) =>
    List.fold_right (fun premise_spec conclusion => '(($premise_spec $functions) -> $conclusion)) (callee_specs fbody) '($fname_spec $functions)) in
  exact (forall (functions : @map.rep _ _ Semantics.env) (EnvContains : map.get functions $fname = Some $proc),
    ltac2:(let g := goal &functions in exact $g)
  ).

Set Default Proof Mode "Classic".

Definition program_logic_goal_for (_ : Syntax.func) (P : Prop) := P.

Notation "program_logic_goal_for_function! proc" := (program_logic_goal_for proc ltac2:(
   program_logic_goal_for_function (Ltac2.Constr.pretype proc)))
  (at level 10, only parsing).

Ltac normalize_body_of_function f := eval cbv in f.

Ltac bind_body_of_function f_ :=
  let f := normalize_body_of_function f_ in
  let fbody := open_constr:(_) in
  let funif := open_constr:((_, _, fbody)) in
  unify f funif;
  let go_split := ltac2:(fbody |-
    let fbody_value := Option.get (Ltac1.to_constr fbody) in
    splitcmd fbody_value) in
  change f_ with f;
  go_split fbody; intros.

Ltac enter f :=
  cbv beta delta [program_logic_goal_for];
  bind_body_of_function f;
  lazymatch goal with |- ?s ?p => let s := rdelta s in change (s p); cbv beta end.

Ltac is_context_variable H :=
  assert_succeeds (exfalso; clear -H; assert(H = H);
    let A := fresh in let B := fresh in destruct H as [A B]; pose H).

Ltac straightline_cleanup :=
  match goal with

  | x : Word.Interface.word.rep _ |- _ => clear x
  | x : Init.Byte.byte |- _ => clear x
  | x : Semantics.trace |- _ => clear x
  | x : Syntax.cmd |- _ => clear x
  | x : Syntax.expr |- _ => clear x
  | x : coqutil.Map.Interface.map.rep |- _ => clear x
  | x : BinNums.Z |- _ => clear x
  | x : unit |- _ => clear x
  | x : bool |- _ => clear x
  | x : list _ |- _ => clear x
  | x : nat |- _ => clear x

  | x := _ : Word.Interface.word.rep _ |- _ => clear x
  | x := _ : Init.Byte.byte |- _ => clear x
  | x := _ : Semantics.trace |- _ => clear x
  | x := _ : Syntax.cmd |- _ => clear x
  | x := _ : Syntax.expr |- _ => clear x
  | x := _ : coqutil.Map.Interface.map.rep |- _ => clear x
  | x := _ : BinNums.Z |- _ => clear x
  | x := _ : unit |- _ => clear x
  | x := _ : bool |- _ => clear x
  | x := _ : list _ |- _ => clear x
  | x := _ : nat |- _ => clear x
  | |- forall _, _ => intros
  | |- let _ := _ in _ => intros
  | |- dlet.dlet ?v (fun x => ?P) => change (let x := v in P); intros
  | _ => progress (cbn [Semantics.interp_binop] in * )
  | H: exists _, _ |- _ => tryif is_context_variable H then fail else destruct H
  | H: _ /\ _ |- _ => tryif is_context_variable H then fail else destruct H
  | x := ?y |- ?G => is_var y; subst x
  | H: ?x = ?y |- _ => constr_eq x y; clear H
  | H: ?x = ?y |- _ => is_var x; is_var y; assert_fails (idtac; let __ := eval cbv [x] in x in idtac); subst x
  | H: ?x = ?y |- _ => is_var x; is_var y; assert_fails (idtac; let __ := eval cbv [y] in y in idtac); subst y
  | H: ?x = ?v |- _ =>
    is_var x;
    assert_fails (idtac; let __ := eval cbv delta [x] in x in idtac);
    lazymatch v with context[x] => fail | _ => idtac end;
    let x' := fresh x in
    rename x into x';
    simple refine (let x := v in _);
    change (x' = x) in H;
    symmetry in H;
    destruct H
  end.

Ltac straightline_stackalloc :=
  match goal with Hanybytes: Memory.anybytes ?a ?n ?mStack |- _ =>
  let m := match goal with H : map.split ?mCobined ?m mStack |- _ => m end in
  let mCombined := match goal with H : map.split ?mCobined ?m mStack |- _ => mCobined end in
  let Hsplit := match goal with H : map.split ?mCobined ?m mStack |- _ => H end in
  let Hm := multimatch goal with H : _ m |- _ => H end in
  let Hm' := fresh Hm in
  let Htmp := fresh in
  let Pm := match type of Hm with ?P m => P end in
  assert_fails (assert (Separation.sep Pm (Array.array Separation.ptsto (Interface.word.of_Z (BinNums.Zpos BinNums.xH)) a _) mCombined) as _ by ecancel_assumption);
  rename Hm into Hm';
  let stack := fresh "stack" in
  let stack_length := fresh "length_" stack in
  destruct (Array.anybytes_to_array_1 mStack a n Hanybytes) as (stack&Htmp&stack_length);
  epose proof (ex_intro _ m (ex_intro _ mStack (conj Hsplit (conj Hm' Htmp)))
  : Separation.sep _ (Array.array Separation.ptsto (Interface.word.of_Z (BinNums.Zpos BinNums.xH)) a _) mCombined) as Hm;
  clear Htmp;
  try (let m' := fresh m in rename m into m'); rename mCombined into m;
  ( assert (BinInt.Z.of_nat (Datatypes.length stack) = n)
  by (rewrite stack_length; apply (ZifyInst.of_nat_to_nat_eq n))
  || fail 2 "negative stackalloc of size" n )
  end.

Ltac straightline_stackdealloc :=
  lazymatch goal with |- exists _ _, Memory.anybytes ?a ?n _ /\ map.split ?m _ _ /\ _ =>
  let Hm := multimatch goal with Hm : _ m |- _ => Hm end in
  let stack := match type of Hm with context [Array.array Separation.ptsto _ a ?stack] => stack end in
  let length_stack := match goal with H : Datatypes.length stack = _ |- _ => H end in
  let Hm' := fresh Hm in
  pose proof Hm as Hm';
  let Psep := match type of Hm with ?P _ => P end in
  let Htmp := fresh "Htmp" in
  eassert (Lift1Prop.iff1 Psep (Separation.sep _ (Array.array Separation.ptsto (Interface.word.of_Z (BinNums.Zpos BinNums.xH)) a stack))) as Htmp
  by ecancel || fail "failed to find stack frame in" Psep "using ecancel";
  eapply (fun m => proj1 (Htmp m)) in Hm;
  let m' := fresh m in
  rename m into m';
  let mStack := fresh in
  destruct Hm as (m&mStack&Hsplit&Hm&Harray1); move Hm at bottom;
  pose proof Array.array_1_to_anybytes _ _ _ Harray1 as Hanybytes;
  rewrite length_stack in Hanybytes;
  refine (ex_intro _ m (ex_intro _ mStack (conj Hanybytes (conj Hsplit _))));
  clear Htmp Hsplit mStack Harray1 Hanybytes
  end.

Ltac rename_to_different H :=
  idtac;
  let G := fresh H "'0" in
  rename H into G.
Ltac ensure_free H :=
  try rename_to_different H.

Ltac eq_uniq_step :=
  match goal with
  | |- ?x = ?y =>
      let x := rdelta x in
      let y := rdelta y in
      first [ is_evar x | is_evar y | constr_eq x y ]; exact eq_refl
  | |- ?lhs = ?rhs =>
      let lh := head lhs in
      is_constructor lh;
      let rh := head rhs in
      constr_eq lh rh;
      f_equal
  end.
Ltac eq_uniq := repeat eq_uniq_step.

Ltac fwd_uniq_step :=
  match goal with
  | |- exists x : ?T, _ =>
      let ev := open_constr:(match _ return T with x => x end) in
      eexists ev;
      let rec f :=
        tryif has_evar ev
        then fwd_uniq_step
        else idtac
      in f
  | |- _ /\ _ => split; [ solve [repeat fwd_uniq_step; eq_uniq] | ]
  | _ => solve [ eq_uniq ]
  end.

Ltac straightline :=
  match goal with
  | _ => straightline_cleanup
  | |- program_logic_goal_for ?f _ =>
    enter f; intros;
    match goal with
    | H: map.get ?functions ?fname = Some _ |- _ =>
        eapply start_func; [exact H | clear H]
    end;
    cbv match beta delta [WeakestPrecondition.func]
  | |- WeakestPrecondition.cmd _ (cmd.set ?s ?e) _ _ _ ?post =>
    unfold1_cmd_goal; cbv beta match delta [cmd_body];
    let __ := match s with String.String _ _ => idtac | String.EmptyString => idtac end in
    ident_of_constr_string_cps s ltac:(fun x =>
      ensure_free x;

      letexists _ as x; split; [solve [repeat straightline]|])
  | |- cmd _ ?c _ _ _ ?post =>
    let c := eval hnf in c in
    lazymatch c with
    | cmd.while _ _ => fail
    | cmd.cond _ _ _ => fail
    | cmd.interact _ _ _ => fail
    | _ => unfold1_cmd_goal; cbv beta match delta [cmd_body]
    end
  | |- @list_map _ _ (get _) _ _ => unfold1_list_map_goal; cbv beta match delta [list_map_body]
  | |- @list_map _ _ (expr _ _) _ _ => unfold1_list_map_goal; cbv beta match delta [list_map_body]
  | |- @list_map _ _ _ nil _ => cbv beta match fix delta [list_map list_map_body]
  | |- expr _ _ _ _ => unfold1_expr_goal; cbv beta match delta [expr_body]
  | |- dexpr _ _ _ _ => cbv beta delta [dexpr]
  | |- dexprs _ _ _ _ => cbv beta delta [dexprs]
  | |- literal _ _ => cbv beta delta [literal]
  | |- @get ?w ?W ?L ?l ?x ?P =>
      let get' := eval cbv [get] in @get in
      change (get' w W L l x P); cbv beta
  | |- load _ _ _ _ => cbv beta delta [load]
  | |- @Loops.enforce ?width ?word ?locals ?names ?values ?map =>
    let values := eval cbv in values in
    change (@Loops.enforce width word locals names values map);
    exact (conj (eq_refl values) eq_refl)
  | |- @eq (@coqutil.Map.Interface.map.rep String.string Interface.word.rep _) _ _ =>
    eapply SortedList.eq_value; exact eq_refl
  | |- @map.get String.string Interface.word.rep ?M ?m ?k = Some ?e' =>
    let e := rdelta e' in
    is_evar e;
    once (let v := multimatch goal with x := context[@map.put _ _ M _ k ?v] |- _ => v end in

          unify e v; exact (eq_refl (Some v)))
  | |- @coqutil.Map.Interface.map.get String.string Interface.word.rep _ _ _ = Some ?v =>
    let v' := rdelta v in is_evar v'; (change v with v'); exact eq_refl
  | |- ?x = ?y =>
    let y := rdelta y in is_evar y; change (x=y); exact eq_refl
  | |- ?x = ?y =>
    let x := rdelta x in is_evar x; change (x=y); exact eq_refl
  | |- ?x = ?y =>
    let x := rdelta x in let y := rdelta y in constr_eq x y; exact eq_refl
  | |- store Syntax.access_size.one _ _ _ _ =>
    eapply Scalars.store_one_of_sep; [solve[ecancel_assumption]|]
  | |- store Syntax.access_size.two _ _ _ _ =>
    eapply Scalars.store_two_of_sep; [solve[ecancel_assumption]|]
  | |- store Syntax.access_size.four _ _ _ _ =>
    eapply Scalars.store_four_of_sep; [solve[ecancel_assumption]|]
  | |- store Syntax.access_size.word _ _ _ _ =>
    eapply Scalars.store_word_of_sep; [solve[ecancel_assumption]|]
  | |- bedrock2.Memory.load Syntax.access_size.one ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_one_of_sep _ _ _ _ _ _ _ _ _ _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.two ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_two_of_sep _ _ word _ mem _ a _ _ m _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.four ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_four_of_sep_32bit _ _ word _ mem _ eq_refl a _ _ m _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.four ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_four_of_sep _ _ word _ mem _ a _ _ m _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.word ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_word_of_sep _ _ word _ mem _ a _ _ m _); ecancel_assumption
  | |- exists l', Interface.map.of_list_zip ?ks ?vs = Some l' /\ _ =>
    letexists; split; [exact eq_refl|]
  | |- exists l', Interface.map.putmany_of_list_zip ?ks ?vs ?l = Some l' /\ _ =>
    letexists; split; [exact eq_refl|]
  | _ => fwd_uniq_step
  | |- exists x, ?P /\ ?Q =>
    let x := fresh x in refine (let x := _ in ex_intro (fun x => P /\ Q) x _);
                        split; [solve [repeat straightline]|]
  | |- exists x, Markers.split (?P /\ ?Q) =>
    let x := fresh x in refine (let x := _ in ex_intro (fun x => P /\ Q) x _);
                        split; [solve [repeat straightline]|]
  | |- Markers.unique (exists x, Markers.split (?P /\ ?Q)) =>
    let x := fresh x in refine (let x := _ in ex_intro (fun x => P /\ Q) x _);
                        split; [solve [repeat straightline]|]
  | |- Markers.unique (Markers.left ?G) =>
    change G;
    unshelve (idtac; repeat match goal with
                     | |- Markers.split (?P /\ Markers.right ?Q) =>
                       split; [eabstract (repeat straightline) | change Q]
                     | |- exists _, _ => letexists
                     end); []
  | |- Markers.split ?G => change G; split
  | |- True => exact I
  | |- False \/ _ => right
  | |- _ \/ False => left
  | |- BinInt.Z.modulo ?z (Memory.bytes_per_word _) = BinInt.Z0 /\ _ =>
      lazymatch Coq.setoid_ring.InitialRing.isZcst z with
      | true => split; [exact eq_refl|]
      end
  | |- _ => straightline_stackalloc
  | |- _ => straightline_stackdealloc
  | |- context[sep (sep ?_a ?_b) ?_c] => progress (flatten_seps_in_goal; cbn [seps])
  | H : context[sep (sep ?_a ?_b) ?_c] |- _ => progress (flatten_seps_in H; cbn [seps] in H)
  end.
Import bedrock2.NotationsCustomEntry.
Local Open Scope string_scope.
Local Open Scope Z_scope.
Import coqutil.Word.Properties.
Import bedrock2.WeakestPrecondition.
Import bedrock2.BasicC64Semantics.
Import bedrock2.Scalars.
Import bedrock2.Array.
Import bedrock2.Loops.
Import bedrock2.Map.SeparationLogic.
Import coqutil.Map.Interface.
Import Stdlib.ZArith.ZArith.
Import Crypto.Arithmetic.WordByWordMontgomery.

Section WithParameters.
  Import WordByWordMontgomery.

  Context {prime: Z} (r := 64) {ri : Z}.
Instance spec_of_redc_alt : spec_of "redc_alt".
exact (fnspec! "redc_alt" Astart Bstart Sstart len / A (aval: Z) B (bval: Z) S R,
    { requires t m :=
        m =* array scalar (word.of_Z 8) Astart A *
                  array scalar (word.of_Z 8) Bstart B *
                  array scalar (word.of_Z 8) Sstart S * R /\
        word.unsigned len = Z.of_nat (List.length A)  /\
        word.unsigned len = Z.of_nat (List.length B)  /\
        word.unsigned len = Z.of_nat (List.length S) /\
        @eval r (Z.to_nat (word.unsigned len)) (List.map word.unsigned A) = aval /\
        @eval r (Z.to_nat (word.unsigned len)) (List.map word.unsigned B) = bval;
      ensures t' m' :=  t=t' /\ exists S',
          m' =*
             array scalar (word.of_Z 8) Astart A *
             array scalar (word.of_Z 8) Bstart B *
            array scalar (word.of_Z 8) Sstart S' * R /\
          ( aval * bval * ri^(word.unsigned len) ) mod prime =
            @eval r (Z.to_nat (word.unsigned len)) (List.map word.unsigned S') mod prime
    }).
Defined.
Instance spec_of_redc_step : spec_of "redc_step".
Admitted.

  Definition redc_alt :=
    func! (Astart, Bstart, Sstart, len) {
    i = $0;
    while (i < len) {
         store(Sstart + $8*i, $0);
         i = i + $1
      };
    i = $0;
    while (i < len) {
         redc_step ( load(Astart + $8*i), Bstart, Sstart, len );
          i = i + $1
      }
    }.

  Import Coq.Lists.List.

  Let zeros (n: Z) :=
        repeat (@word.of_Z _ word 0) (Z.to_nat n).

 Theorem redc_alt_ok :
      program_logic_goal_for_function! redc_alt.
 Proof.
   repeat straightline.

      refine ( tailrec (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ HList.polymorphic_list.nil))))))))
               ("Astart":: "Bstart" :: "Sstart" :: "len" :: "i" :: nil)
               (fun l A aval B bval S Ra Rb R t m Astart Bstart Sstart len i => PrimitivePair.pair.mk
                                    (m =* array scalar (word.of_Z 8) (word.add Sstart (word.mul (word.of_Z 8) i)) S * R /\
                                       word.unsigned len - word.unsigned i = Z.of_nat (List.length S) /\

                                    l = List.length S )
                                    (fun t' m' Astart' Bstart' Sstart' len' i' =>
                                       (
                                     t = t' /\ Astart = Astart' /\ Bstart = Bstart' /\ Sstart = Sstart' /\ len = len' /\
                                     m' =* array scalar (word.of_Z 8) (word.add Sstart (word.mul (word.of_Z 8) i)) (zeros (word.unsigned len - word.unsigned i)) * R
                                     )
                                    )
               )
               lt _ _ _ _ _ _ _ _ _ _ _ _ _);
        cbn [reconstruct map.putmany_of_list HList.tuple.to_list
         HList.hlist.foralls HList.tuple.foralls
         HList.hlist.existss HList.tuple.existss
         HList.hlist.apply  HList.tuple.apply
         HList.hlist
         List.repeat Datatypes.length
         HList.polymorphic_list.repeat HList.polymorphic_list.length
         PrimitivePair.pair._1 PrimitivePair.pair._2] in *.

      {
 repeat straightline.
}
      {
 exact Wf_nat.lt_wf.
}
      {
 repeat straightline.
        subst i.
        replace (word.add Sstart (word.mul (word.of_Z 8) (word.of_Z 0))) with (Sstart) by ring.
        repeat split; try eauto.
        -
 ecancel_assumption.
        -
 rewrite word.unsigned_of_Z_0.
Lia.lia.
}

      {
 repeat straightline.
eexists.
🛠️ Intermediate Coq File (useful for debugging if minimization did not go as far as you wanted) (truncated to 6.0KiB; full 88KiB file on GitHub Actions Artifacts under tmp.v)
(* -*- mode: coq; coq-prog-args: ("-emacs" "-q" "-w" "+implicit-core-hint-db,+implicits-in-term,+non-reversible-notation,+deprecated-intros-until-0,+deprecated-focus,+unused-intro-pattern,+variable-collision,+unexpected-implicit-declaration,+omega-is-deprecated,+deprecated-instantiate-syntax,+non-recursive,+undeclared-scope,+deprecated-hint-rewrite-without-locality,+deprecated-hint-without-locality,+deprecated-instance-without-locality,+deprecated-typeclasses-transparency-without-locality,+fragile-hint-constr,-deprecated-since-9.0,-deprecated-since-8.20,-deprecated-from-Coq" "-w" "-notation-overridden,-native-compiler-disabled,-ambiguous-paths,-masking-absolute-name" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Coqprime" "Coqprime" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Kami" "Kami" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rewriter" "Rewriter" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rupicola" "Rupicola" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Crypto.Bedrock.Field.Synthesis.Examples.redc") -*- *)
(* File reduced by coq-bug-minimizer from original input, then from 577 lines to 117 lines, then from 131 lines to 1915 lines *)
(* coqc version 9.3+alpha compiled with OCaml 4.14.2
   coqtop version 9.3+alpha
   Expected coqc runtime on this file: 0.000 sec
   Expected coqc peak memory usage on this file: 0.0 kb *)
Require Coq.Init.Ltac.
Module Export AdmitTactic.
Module Import LocalFalse.
Inductive False : Prop := .
End LocalFalse.
Axiom proof_admitted : False.
Import Coq.Init.Ltac.
Tactic Notation "admit" := abstract case proof_admitted.
End AdmitTactic.
Require bedrock2.NotationsCustomEntry.
Require bedrock2.BasicC64Semantics.
Require bedrock2.ProgramLogic.
Require Coqprime.Tactic.Tactic.
Require Corelib.BinNums.IntDef.
Require Corelib.BinNums.NatDef.
Require Corelib.BinNums.PosDef.
Require Corelib.Classes.CMorphisms.
Require Corelib.Classes.Morphisms.
Require Corelib.Classes.Morphisms_Prop.
Require Corelib.Classes.RelationClasses.
Require Corelib.Init.Byte.
Require Corelib.Init.Sumbool.
Require Corelib.Lists.ListDef.
Require Corelib.Numbers.BinNums.
Require Corelib.Program.Basics.
Require Corelib.Program.Wf.
Require Corelib.Relations.Relation_Definitions.
Require Corelib.Setoids.Setoid.
Require Corelib.derive.Derive.
Require Crypto.Util.Comparison.
Require Crypto.Util.GlobalSettings.
Require Crypto.Util.HProp.
Require Crypto.Util.Isomorphism.
Require Crypto.Util.Tactics.ConstrFail.
Require Crypto.Util.Tactics.Contains.
Require Crypto.Util.Tactics.GetGoal.
Require Crypto.Util.Tactics.OnSubterms.
Require Crypto.Util.Tactics.Revert.
Require Crypto.Util.Tactics.SetEvars.
Require Crypto.Util.Tactics.SubstEvars.
Require Crypto.Util.Tactics.Test.
Require Rewriter.Util.GlobalSettings.
Require Rewriter.Util.Tactics.GetGoal.
Require Stdlib.Classes.DecidableClass.
Require Stdlib.Logic.ConstructiveEpsilon.
Require Stdlib.Logic.Decidable.
Require Stdlib.Logic.EqdepFacts.
Require Stdlib.Logic.FunctionalExtensionality.
Require Stdlib.Logic.HLevelsBase.
Require Stdlib.Sets.Relations_1.
Require Stdlib.Wellfounded.Inverse_Image.
Require Stdlib.micromega.ZifyClasses.
Require Stdlib.setoid_ring.Algebra_syntax.
Require Crypto.Util.Tactics.DebugPrint.
Require Crypto.Util.Tactics.Not.
Require Crypto.Util.Tactics.SetoidSubst.
Require Stdlib.BinNums.IntDef.
Require Stdlib.BinNums.NatDef.
Require Stdlib.BinNums.PosDef.
Require Stdlib.Classes.CMorphisms.
Require Stdlib.Classes.Morphisms.
Require Stdlib.Classes.Morphisms_Prop.
Require Stdlib.Classes.RelationClasses.
Require Stdlib.Init.Byte.
Require Stdlib.Init.Sumbool.
Require Stdlib.Lists.ListDef.
Require Stdlib.Logic.Eqdep_dec.
Require Stdlib.Numbers.BinNums.
Require Stdlib.Program.Basics.
Require Stdlib.Program.Wf.
Require Stdlib.Relations.Relation_Definitions.
Require Stdlib.Setoids.Setoid.
Require Stdlib.derive.Derive.
Require Crypto.Util.IffT.
Require Crypto.Util.Pointed.
Require Stdlib.Bool.Bool.
Require Stdlib.Logic.HLevels.
Require Stdlib.Relations.Relation_Operators.
Require Crypto.Util.Bool.LeCompat.
Require Crypto.Util.FixCoqMistakes.
Require Rewriter.Util.FixCoqMistakes.
Require Stdlib.Relations.Operators_Properties.
Require Crypto.Util.Equality.
Require Crypto.Util.Logic.
Require Crypto.Util.Notations.
Require Crypto.Util.Tactics.DestructHyps.
Require Crypto.Util.Tactics.FindHyp.
Require Crypto.Util.Tactics.Head.
Require Crypto.Util.Tactics.SpecializeBy.
Require Crypto.Util.Tactics.SplitInContext.
Require Rewriter.Util.Notations.
Require Stdlib.PArith.BinPosDef.
Require Stdlib.Relations.Relations.
Require Crypto.Util.Tactics.BreakMatch.
Require Crypto.Util.Tactics.UniquePose.
Require Crypto.Util.Sigma.
Require Crypto.Util.Tactics.DestructHead.
Require Crypto.Util.Tactics.DoWithHyp.
Require Stdlib.Numbers.NumPrelude.
Require Crypto.Util.Relations.
Require Crypto.Util.Tactics.RewriteHyp.
Require Stdlib.Classes.RelationPairs.
Require Crypto.Util.Bool.
Require Rewriter.Util.LetIn.
Require Crypto.Util.PrimitiveProd.
Require Stdlib.Structures.Equalities.
Require Crypto.Util.Option.
Require Crypto.Util.LetIn.
Requi
🛠️ 📜 Intermediate Coq File log (useful for debugging if minimization did not go as far as you wanted) (truncated to last 2.0KiB; full 7.9KiB file on GitHub Actions Artifacts under tmp.log)
d,default]
File "/tmp/tmp6plrjb55/Crypto/Bedrock/Field/Synthesis/Examples/redc.v", line 1075, characters 12-20:
Warning: Use of "Notation" keyword for abbreviations is deprecated, use
"Abbreviation" instead.
[notation-for-abbreviation,deprecated-since-9.2,deprecated,default]
File "/tmp/tmp6plrjb55/Crypto/Bedrock/Field/Synthesis/Examples/redc.v", line 1076, characters 12-20:
Warning: Use of "Notation" keyword for abbreviations is deprecated, use
"Abbreviation" instead.
[notation-for-abbreviation,deprecated-since-9.2,deprecated,default]
File "/tmp/tmp6plrjb55/Crypto/Bedrock/Field/Synthesis/Examples/redc.v", line 1077, characters 12-20:
Warning: Use of "Notation" keyword for abbreviations is deprecated, use
"Abbreviation" instead.
[notation-for-abbreviation,deprecated-since-9.2,deprecated,default]
File "/tmp/tmp6plrjb55/Crypto/Bedrock/Field/Synthesis/Examples/redc.v", line 1078, characters 12-20:
Warning: Use of "Notation" keyword for abbreviations is deprecated, use
"Abbreviation" instead.
[notation-for-abbreviation,deprecated-since-9.2,deprecated,default]
File "/tmp/tmp6plrjb55/Crypto/Bedrock/Field/Synthesis/Examples/redc.v", line 1271, characters 36-59:
Warning: Reference Znumtheory.Zmod_div_mod is deprecated since Stdlib 9.1.
Use Zdiv.Z.mod_mod_divide instead.
[deprecated-reference-since-Stdlib-9.1,deprecated-since-Stdlib-9.1,deprecated-reference,deprecated,default]
File "/tmp/tmp6plrjb55/Crypto/Bedrock/Field/Synthesis/Examples/redc.v", line 1271, characters 36-59:
Warning: Reference Znumtheory.Zmod_div_mod is deprecated since Stdlib 9.1.
Use Zdiv.Z.mod_mod_divide instead.
[deprecated-reference-since-Stdlib-9.1,deprecated-since-Stdlib-9.1,deprecated-reference,deprecated,default]
File "/tmp/tmp6plrjb55/Crypto/Bedrock/Field/Synthesis/Examples/redc.v", line 1271, characters 36-59:
Warning: Reference Znumtheory.Zmod_div_mod is deprecated since Stdlib 9.1.
Use Zdiv.Z.mod_mod_divide instead.
[deprecated-reference-since-Stdlib-9.1,deprecated-since-Stdlib-9.1,deprecated-reference,deprecated,default]

Timeout! (external)
📜 Build Log (contains the Coq error message) (truncated to last 8.0KiB; full 14MiB file on GitHub Actions Artifacts under build.log)
Util/ZUtil/Tactics/SimplifyFractionsLe.vo
src/Util/ZUtil/Tactics/SolveRange.vo
src/Util/ZUtil/Tactics/SolveTestbit.vo
src/Util/ZUtil/Tactics/SplitMinMax.vo
src/Util/ZUtil/Tactics/ZeroBounds.vo
src/Util/ZUtil/Tactics/Ztestbit.vo
src/Util/ZUtil/Testbit.vo
src/Util/ZUtil/TruncatingShiftl.vo
src/Util/ZUtil/TwosComplement.vo
src/Util/ZUtil/Z2Nat.vo
src/Util/ZUtil/ZSimplify.vo
src/Util/ZUtil/ZSimplify/Autogenerated.vo
src/Util/ZUtil/ZSimplify/Core.vo
src/Util/ZUtil/ZSimplify/Simple.vo
src/Util/ZUtil/Zselect.vo


Files Not Made:
src/Bedrock/End2End/Poly1305/Field1305.vo
src/Bedrock/End2End/X25519/EdwardsXYZT.vo
src/Bedrock/End2End/X25519/Field25519.vo
src/Bedrock/End2End/X25519/GarageDoor.vo
src/Bedrock/End2End/X25519/GarageDoorTop.vo
src/Bedrock/End2End/X25519/MontgomeryLadder.vo
src/Bedrock/End2End/X25519/MontgomeryLadderRISCV.vo
src/Bedrock/Everything.vo
src/Bedrock/Field/Stringification/Stringification.vo
src/Bedrock/Field/Synthesis/Examples/p224_64_new.vo
src/Bedrock/Field/Synthesis/New/ComputedOp.vo
src/Bedrock/Field/Synthesis/New/Signature.vo
src/Bedrock/Field/Synthesis/New/UnsaturatedSolinas.vo
src/Bedrock/Field/Synthesis/New/WordByWordMontgomery.vo
src/Bedrock/Field/Translation/Cmd.vo
src/Bedrock/Field/Translation/Func.vo
src/Bedrock/Field/Translation/Parameters/Defaults.vo
src/Bedrock/Field/Translation/Parameters/Defaults32.vo
src/Bedrock/Field/Translation/Parameters/Defaults64.vo
src/Bedrock/Field/Translation/Parameters/FE310.vo
src/Bedrock/Field/Translation/Proofs/Cmd.vo
src/Bedrock/Field/Translation/Proofs/Func.vo
src/Bedrock/Field/Translation/Proofs/ValidComputable/Cmd.vo
src/Bedrock/Field/Translation/Proofs/ValidComputable/Func.vo
src/Bedrock/Group/ScalarMult/MontgomeryLadder.vo
src/Bedrock/P256.vo
src/Bedrock/P256/Coord.vo
src/Bedrock/P256/Coord32.vo
src/Bedrock/P256/Jacobian.vo
src/Bedrock/P256/JacobianAffine.vo
src/Bedrock/P256/Platform.vo
src/Bedrock/P256/PrecomputedMultiples.vo
src/Bedrock/P256/RecodeProofs.vo
src/Bedrock/P256/Scalarmult.vo
src/Bedrock/P256/Specs.vo
src/Bedrock/Secp256k1/Addchain.vo
src/Bedrock/Secp256k1/Field256k1.vo
src/Bedrock/Secp256k1/JacobianCoZ.vo
src/Bedrock/Secp256k1/JoyeLadder.vo
src/Bedrock/Standalone/StandaloneHaskellMain.vo
src/Bedrock/Standalone/StandaloneJsOfOCamlMain.vo
src/Bedrock/Standalone/StandaloneOCamlMain.vo
src/BoundsPipeline.vo
src/CLI.vo
src/CompilersTestCases.vo
src/Curves/Montgomery/AffineInstances.vo
src/Curves/Montgomery/AffineProofs.vo
src/Curves/Montgomery/XZProofs.vo
src/Curves/Weierstrass/AffineProofs.vo
src/Curves/Weierstrass/Jacobian/CoZ.vo
src/Curves/Weierstrass/Jacobian/Jacobian.vo
src/Curves/Weierstrass/Jacobian/ScalarMult.vo
src/Curves/Weierstrass/P256.vo
src/Curves/Weierstrass/Projective.vo
src/Everything.vo
src/ExtractionJsOfOCaml/WithBedrock/fiat_crypto.vo
src/ExtractionJsOfOCaml/bedrock2_fiat_crypto.vo
src/ExtractionJsOfOCaml/fiat_crypto.vo
src/Fancy/Barrett256.vo
src/Fancy/Montgomery256.vo
src/PerfTesting/PerfTestPrint.vo
src/PerfTesting/PerfTestSearch.vo
src/PerfTesting/PerfTestSearchPattern.vo
src/PushButtonSynthesis/BarrettReduction.vo
src/PushButtonSynthesis/BaseConversion.vo
src/PushButtonSynthesis/DettmanMultiplication.vo
src/PushButtonSynthesis/FancyMontgomeryReduction.vo
src/PushButtonSynthesis/Primitives.vo
src/PushButtonSynthesis/SaturatedSolinas.vo
src/PushButtonSynthesis/SmallExamples.vo
src/PushButtonSynthesis/SolinasReduction.vo
src/PushButtonSynthesis/UnsaturatedSolinas.vo
src/PushButtonSynthesis/WordByWordMontgomery.vo
src/Rewriter/All.vo
src/Rewriter/PerfTesting/Core.vo
src/Rewriter/PerfTesting/StandaloneOCamlMain.vo
src/Rewriter/RulesGood.vo
src/SlowPrimeSynthesisExamples.vo
src/StandaloneDebuggingExamples.vo
src/StandaloneHaskellMain.vo
src/StandaloneJsOfOCamlMain.vo
src/StandaloneMonadicUtils.vo
src/StandaloneOCamlMain.vo
ROCQ compile src/Bedrock/Field/Synthesis/Examples/redc.v
MINIMIZER_DEBUG_EXTRA: coqc: /github/workspace/builds/coq/coq-failing/_install_ci/bin///rocq
MINIMIZER_DEBUG_EXTRA: original invocation: '' 
MINIMIZER_DEBUG_EXTRA: new invocation: /github/workspace/builds/coq/coq-failing/_install_ci/bin/rocq.orig compile -q -w +implicit-core-hint-db\,+implicits-in-term\,+non-reversible-notation\,+deprecated-intros-until-0\,+deprecated-focus\,+unused-intro-pattern\,+variable-collision\,+unexpected-implicit-declaration\,+omega-is-deprecated\,+deprecated-instantiate-syntax\,+non-recursive\,+undeclared-scope\,+deprecated-hint-rewrite-without-locality\,+deprecated-hint-without-locality\,+deprecated-instance-without-locality\,+deprecated-typeclasses-transparency-without-locality\,+fragile-hint-constr\,-deprecated-since-9.0\,-deprecated-since-8.20\,-deprecated-from-Coq -w -notation-overridden\,-native-compiler-disabled\,-ambiguous-paths\,-masking-absolute-name -w -deprecated-native-compiler-option -native-compiler no -R /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src Crypto src/Bedrock/Field/Synthesis/Examples/redc.v 
MINIMIZER_DEBUG_EXTRA: coqpath: 
MINIMIZER_DEBUG_EXTRA: ocamlpath: /github/workspace/builds/coq/coq-failing/_install_ci/lib:
MINIMIZER_DEBUG_EXTRA: pwd: PWD=/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto
MINIMIZER_DEBUG_EXTRA: exec: /github/workspace/builds/coq/coq-failing/_install_ci/bin/rocq.orig compile -q -w +implicit-core-hint-db\,+implicits-in-term\,+non-reversible-notation\,+deprecated-intros-until-0\,+deprecated-focus\,+unused-intro-pattern\,+variable-collision\,+unexpected-implicit-declaration\,+omega-is-deprecated\,+deprecated-instantiate-syntax\,+non-recursive\,+undeclared-scope\,+deprecated-hint-rewrite-without-locality\,+deprecated-hint-without-locality\,+deprecated-instance-without-locality\,+deprecated-typeclasses-transparency-without-locality\,+fragile-hint-constr\,-deprecated-since-9.0\,-deprecated-since-8.20\,-deprecated-from-Coq -w -notation-overridden\,-native-compiler-disabled\,-ambiguous-paths\,-masking-absolute-name -w -deprecated-native-compiler-option -native-compiler no -R /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src Crypto src/Bedrock/Field/Synthesis/Examples/redc.v 
MINIMIZER_DEBUG_EXTRA: coqlib: Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//
MINIMIZER_DEBUG: info: /tmp/tmp-coqbot-minimizer.UOGCmZ9aPb
MINIMIZER_DEBUG: files:  src/Bedrock/Field/Synthesis/Examples/redc.v /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src/Bedrock/Field/Synthesis/Examples/redc.v
Warning, feedback message received but no listener to handle it!
Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]Warning, feedback message received but no listener to handle it!
Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
Warning: Deprecated environment variable COQCORELIB,
use ROCQRUNTIMELIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
File "./src/Bedrock/Field/Synthesis/Examples/redc.v", line 210, characters 29-37:
Error: Expected a single focused goal but 2 goals are focused.

Command exited with non-zero status 1
src/Bedrock/Field/Synthesis/Examples/redc.vo (real: 1.05, user: 0.91, sys: 0.13, mem: 554040 ko)
make: *** [Makefile.coq:815: src/Bedrock/Field/Synthesis/Examples/redc.vo] Error 1
make: *** [src/Bedrock/Field/Synthesis/Examples/redc.vo] Deleting file 'src/Bedrock/Field/Synthesis/Examples/redc.glob'
+ code=2
+ printf '\n%s exit code: %s\n' fiat_crypto 2
+ '[' fiat_crypto '!=' stdlib_test ']'
+ echo 'Aggregating timing log...'
Aggregating timing log...
+ echo

+ tools/make-one-time-file.py --real _build_ci/fiat_crypto.log
    Time |  Peak Mem | File Name                               
---------------------------------------------------------------
0m01.37s | 554040 ko | Total Time / Peak Mem                   
---------------------------------------------------------------
0m01.05s | 554040 ko | Bedrock/Field/Synthesis/Examples/redc.vo
0m00.32s |  34088 ko | .Makefile.coq.d                         
+ '[' '' ']'
+ exit 2
/github/workspace/builds/coq /github/workspace
::endgroup::
📜 🔎 Minimization Log (truncated to last 8.0KiB; full 18MiB file on GitHub Actions Artifacts under bug.log)
me" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Coqprime" "Coqprime" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Kami" "Kami" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rewriter" "Rewriter" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rupicola" "Rupicola" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Crypto.Bedrock.Field.Synthesis.Examples.redc" "/tmp/tmpg2b1u0yz/Crypto/Bedrock/Field/Synthesis/Examples/redc.v" "-q"

Running command: "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-q" "-w" "+implicit-core-hint-db,+implicits-in-term,+non-reversible-notation,+deprecated-intros-until-0,+deprecated-focus,+unused-intro-pattern,+variable-collision,+unexpected-implicit-declaration,+omega-is-deprecated,+deprecated-instantiate-syntax,+non-recursive,+undeclared-scope,+deprecated-hint-rewrite-without-locality,+deprecated-hint-without-locality,+deprecated-instance-without-locality,+deprecated-typeclasses-transparency-without-locality,+fragile-hint-constr,-deprecated-since-9.0,-deprecated-since-8.20,-deprecated-from-Coq" "-w" "-notation-overridden,-native-compiler-disabled,-ambiguous-paths,-masking-absolute-name" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Coqprime" "Coqprime" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Kami" "Kami" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rewriter" "Rewriter" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rupicola" "Rupicola" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Crypto.Bedrock.Field.Synthesis.Examples.redc" "/tmp/tmpg2b1u0yz/Crypto/Bedrock/Field/Synthesis/Examples/redc.v" "-q"

Running command: "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-q" "-w" "+implicit-core-hint-db,+implicits-in-term,+non-reversible-notation,+deprecated-intros-until-0,+deprecated-focus,+unused-intro-pattern,+variable-collision,+unexpected-implicit-declaration,+omega-is-deprecated,+deprecated-instantiate-syntax,+non-recursive,+undeclared-scope,+deprecated-hint-rewrite-without-locality,+deprecated-hint-without-locality,+deprecated-instance-without-locality,+deprecated-typeclasses-transparency-without-locality,+fragile-hint-constr,-deprecated-since-9.0,-deprecated-since-8.20,-deprecated-from-Coq" "-w" "-notation-overridden,-native-compiler-disabled,-ambiguous-paths,-masking-absolute-name" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Coqprime" "Coqprime" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Kami" "Kami" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rewriter" "Rewriter" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rupicola" "Rupicola" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Crypto.Bedrock.Field.Synthesis.Examples.redc" "/tmp/tmpg2b1u0yz/Crypto/Bedrock/Field/Synthesis/Examples/redc.v" "-q"

Running command: "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-q" "-w" "+implicit-core-hint-db,+implicits-in-term,+non-reversible-notation,+deprecated-intros-until-0,+deprecated-focus,+unused-intro-pattern,+variable-collision,+unexpected-implicit-declaration,+omega-is-deprecated,+deprecated-instantiate-syntax,+non-recursive,+undeclared-scope,+deprecated-hint-rewrite-without-locality,+deprecated-hint-without-locality,+deprecated-instance-without-locality,+deprecated-typeclasses-transparency-without-locality,+fragile-hint-constr,-deprecated-since-9.0,-deprecated-since-8.20,-deprecated-from-Coq" "-w" "-notation-overridden,-native-compiler-disabled,-ambiguous-paths,-masking-absolute-name" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Coqprime" "Coqprime" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Kami" "Kami" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rewriter" "Rewriter" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rupicola" "Rupicola" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Crypto.Bedrock.Field.Synthesis.Examples.redc" "/tmp/tmpg2b1u0yz/Crypto/Bedrock/Field/Synthesis/Examples/redc.v" "-q"

If you have any comments on your experience of the minimizer, please share them in a reply (possibly tagging @JasonGross).
If you believe there's a bug in the bug minimizer, please report it on the bug minimizer issue tracker.

cc @JasonGross

@coqbot-app

coqbot-app Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor
Minimization interrupted by timeout, being automatically continued. Partially Minimized File /home/runner/work/run-coq-bug-minimizer/run-coq-bug-minimizer/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories/PCUICInductiveInversion.v in 5h 15m 6s (from ci-metarocq) (interrupted by timeout, being automatically continued) (full log on GitHub Actions - verbose log)
⭐ ⏱️ Partially Minimized Coq File (timeout) (truncated to first and last 32KiB; full 47KiB file on GitHub Actions Artifacts under bug.v)
(* -*- mode: coq; coq-prog-args: ("-emacs" "-q" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/utils/theories" "MetaRocq.Utils" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/common/theories" "MetaRocq.Common" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories" "MetaRocq.PCUIC" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Equations" "Equations" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/ExtLib" "ExtLib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-top" "Top.bug_01") -*- *)
(* File reduced by coq-bug-minimizer from original input, then from 4603 lines to 39 lines, then from 53 lines to 39 lines, then from 52 lines to 39 lines, then from 51 lines to 3774 lines, then from 3773 lines to 46 lines, then from 58 lines to 2403 lines, then from 2409 lines to 57 lines, then from 69 lines to 995 lines, then from 1000 lines to 81 lines, then from 93 lines to 2645 lines, then from 2646 lines to 213 lines, then from 225 lines to 90 lines, then from 104 lines to 1099 lines, then from 1098 lines to 139 lines, then from 153 lines to 1878 lines, then from 1885 lines to 430 lines, then from 444 lines to 1595 lines, then from 1601 lines to 598 lines, then from 612 lines to 2689 lines, then from 2690 lines to 619 lines, then from 633 lines to 1387 lines, then from 1388 lines to 641 lines, then from 655 lines to 3123 lines, then from 3125 lines to 716 lines, then from 730 lines to 1577 lines, then from 1582 lines to 1230 lines *)
(* coqc version 9.3+alpha compiled with OCaml 4.14.2
   coqtop version 9.3+alpha
   Expected coqc runtime on this file: 2.281 sec
   Expected coqc peak memory usage on this file: 799128.0 kb *)









Require Corelib.Program.Basics.
Require Corelib.Init.Wf.
Require Corelib.Program.Wf.
Require Corelib.Classes.Morphisms.
Require Corelib.ssr.ssrbool.
Require Corelib.Classes.Morphisms_Prop.
Require Corelib.Classes.CMorphisms.
Require Corelib.Init.Sumbool.
Require Corelib.ssr.ssrfun.
Require Corelib.Numbers.BinNums.
Require Corelib.ssr.ssreflect.
Require Corelib.extraction.Extraction.
Require Corelib.Strings.PrimString.
Require Corelib.Classes.CRelationClasses.
Require Corelib.BinNums.PosDef.
Require Corelib.BinNums.IntDef.
Require Corelib.Floats.SpecFloat.
Require Corelib.Classes.RelationClasses.
Require Corelib.Numbers.Cyclic.Int63.PrimInt63.
Require Corelib.Init.Decimal.
Require Corelib.Init.Nat.
Require Corelib.Program.Utils.
Require Corelib.Setoids.Setoid.
Require Corelib.Program.Tactics.
Require Corelib.Lists.ListDef.
Require Corelib.Init.Byte.
Require Corelib.Numbers.Cyclic.Int63.Uint63Axioms.
Require Corelib.Numbers.Cyclic.Int63.Sint63Axioms.
Require Corelib.Floats.PrimFloat.
Require Corelib.Floats.FloatAxioms.
Require Corelib.BinNums.NatDef.
Require Corelib.Numbers.Cyclic.Int63.CarryType.
Require Corelib.Classes.SetoidTactics.
Require Corelib.Strings.PrimStringAxioms.
Require Corelib.Init.Hexadecimal.
Require Corelib.Relations.Relation_Definitions.
Require Corelib.Init.Ltac.
Require Corelib.Floats.FloatOps.
Require ExtLib.Core.Any.
Require ExtLib.Structures.BinOps.
Require MetaRocq.Utils.MREquality.
Require MetaRocq.Utils.MRSquash.
Require MetaRocq.Utils.MRTactics.DestructHyps.
Require MetaRocq.Utils.MRTactics.FindHyp.
Require MetaRocq.Utils.MRTactics.Head.
Require MetaRocq.Utils.MRTactics.SpecializeBy.
Require MetaRocq.Utils.MRTactics.SplitInContext.
Require MetaRocq.Utils.MRTactics.Zeta1.
Require Stdlib.Classes.DecidableClass.
Require Stdlib.Logic.Decidable.
Require Stdlib.Logic.EqdepFacts.
Require Stdlib.Logic.FunctionalExtensionality.
Require Stdlib.Logic.HLevelsBase.
Require Stdlib.Program.Syntax.
Require Stdlib.Sets.Relations_1.
Require Stdlib.Unicode.Utf8_core.
Require Stdlib.Wellfounded.Inverse_Image.
Require Stdlib.micromega.ZifyClasses.
Require Stdlib.setoid_ring.Algebra_syntax.
Require Equations.Init.
Require ExtLib.Structures.Functor.
Require ExtLib.Structures.Monoid.
Require Ltac2.Init.
Require MetaRocq.Utils.MRTactics.UniquePose.
Require Stdlib.BinNums.IntDef.
Require Stdlib.BinNums.PosDef.
Require Stdlib.BinNums.NatDef.
Require Stdlib.Classes.CMorphisms.
Require Stdlib.Classes.CRelationClasses.
Require Stdlib.Classes.Morphisms.
Require Stdlib.Classes.Morphisms_Prop.
Require Stdlib.Classes.RelationClasses.
Require Stdlib.Classes.SetoidTactics.
Require Stdlib.Floats.FloatOps.
Require Stdlib.Floats.SpecFloat.
Require Stdlib.Floats.PrimFloat.
Require Stdlib.Floats.FloatAxioms.
Require Stdlib.Init.Wf.
Require Stdlib.Init.Decimal.
Require Stdlib.Init.Hexadecimal.
Require Stdlib.Init.Nat.
Require Stdlib.Init.Sumbool.
Require Stdlib.Init.Byte.
Require Stdlib.Lists.ListDef.
Require Stdlib.Logic.Eqdep.
Require Stdlib.Logic.Eqdep_dec.
Require Stdlib.Logic.ProofIrrelevanceFacts.
Require Stdlib.Numbers.BinNums.
Require Stdlib.Numbers.Cyclic.Int63.CarryType.
Require Stdlib.Numbers.Cyclic.Int63.PrimInt63.
Require Stdlib.Numbers.Cyclic.Int63.Sint63Axioms.
Require Stdlib.Numbers.Cyclic.Int63.Uint63Axioms.
Require Stdlib.Program.Basics.
Require Stdlib.Program.Tactics.
Require Stdlib.Program.Utils.
Require Stdlib.Program.Wf.
Require Stdlib.Relations.Relation_Definitions.
Require Stdlib.Setoids.Setoid.
Require Stdlib.Strings.PrimString.
Require Stdlib.Strings.PrimStringAxioms.
Require Stdlib.Unicode.Utf8.
Require Stdlib.Wellfounded.Well_Ordering.
Require Stdlib.extraction.Extraction.
Require Stdlib.ssr.ssrbool.
Require Stdlib.ssr.ssreflect.
Require Stdlib.ssr.ssrfun.
Require Equations.Prop.SigmaNotations.
Require Equations.Signature.
Require ExtLib.Structures.Applicative.
Require Ltac2.Message.
Require Ltac2.Std.
Require MetaRocq.Utils.MRTactics.DestructHead.
Require MetaRocq.Utils.MRTactics.SpecializeAllWays.
Require Stdlib.Bool.Bool.
Require Stdlib.Logic.JMeq.
Require Stdlib.Logic.ProofIrrelevance.
Require Stdlib.Relations.Relation_Operators.
Require Stdlib.Wellfounded.Inclusion.
Require Equations.CoreTactics.
Require ExtLib.Structures.Monad.
Require Ltac2.Control.
Require MetaRocq.Utils.MRTactics.GeneralizeOverHoles.
Require Stdlib.Program.Combinators.
Require Stdlib.Relations.Operators_Properties.
Require Stdlib.Wellfounded.Disjoint_Union.
Require Stdlib.Wellfounded.Transitive_Closure.
Require ExtLib.Structures.MonadCont.
Require ExtLib.Structures.MonadExc.
Require ExtLib.Structures.MonadFix.
Require ExtLib.Structures.MonadPlus.
Require ExtLib.Structures.MonadReader.
Require ExtLib.Structures.MonadState.
Require ExtLib.Structures.MonadTrans.
Require ExtLib.Structures.MonadZero.
Require Stdlib.PArith.BinPosDef.
Require Stdlib.Relations.Relations.
Require Stdlib.Wellfounded.Union.
Require Equations.Type.Logic.
Require Ltac2.Ltac1.
Require Stdlib.Program.Equality.
Require Equations.Prop.Logic.
Require Equations.Type.Relation.
Require ExtLib.Structures.MonadWriter.
Require Stdlib.Numbers.NumPrelude.
Require Equations.Type.Relation_Properties.
Require MetaRocq.Utils.MRTactics.InHypUnderBindersDo.
Require MetaRocq.Utils.MRTactics.SpecializeUnderBindersBy.
Require Stdlib.Classes.RelationPairs.
Require Stdlib.Program.WfExtensionality.
Require Stdlib.Wellfounded.Lexicographic_Product.
Require Equations.Prop.Classes.
Require MetaRocq.Utils.MRProd.
Require Stdlib.Structures.Equalities.
Require Equations.Prop.EqDec.
Require Stdlib.Program.Subset.
Require MetaRocq.Utils.MRRelations.
Require Equations.Prop.DepElim.
Require Equations.Prop.FunctionalInduction.
Require ExtLib.Structures.Monads.
Require Stdlib.Structures.Orders.
Require ExtLib.Data.Monads.OptionMonad.
Require Equations.Prop.Constants.
Require Stdlib.Structures.OrdersTac.
Require Stdlib.Structures.OrdersFacts.
Require Stdlib.Structures.GenericMinMax.
Require Stdlib.Program.Program.
Require Stdlib.Numbers.NatInt.NZAxioms.
Require Stdlib.Numbers.NatInt.NZBase.
Require Stdlib.Numbers.NatInt.NZAdd.
Require Stdlib.Numbers.NatInt.NZMul.
Require Stdlib.Numbers.NatInt.NZOrder.
Require Stdlib.Numbers.NatInt.NZAddOrder.
Require Stdlib.Numbers.NatInt.NZMulOrder.
Require Stdlib.Numbers.NatInt.NZDiv.
Require Stdlib.Numbers.NatInt.NZGcd.
Require Stdlib.Numbers.NatInt.NZParity.
Require Stdlib.Numbers.NatInt.NZPow.
Require Stdlib.Numbers.NatInt.NZSqrt.
Require Stdlib.Numbers.NatInt.NZLog.
Require Stdlib.Numbers.NatInt.NZBits.
Require Stdlib.Numbers.Integer.Abstract.ZAxioms.
Require Stdlib.Numbers.Natural.Abstract.NAxioms.
Require Stdlib.Numbers.Integer.Abstract.ZBase.
Require Stdlib.Numbers.Natural.Abstract.NBase.
Require Stdlib.Numbers.Integer.Abstract.ZAdd.
Require Stdlib.Numbers.Natural.Abstract.NAdd.
Require Stdlib.Numbers.Integer.Abstract.ZMul.
Require Stdlib.Numbers.Natural.Abstract.NOrder.
Require Stdlib.Numbers.Integer.Abstract.ZLt.
Require Stdlib.Numbers.Natural.Abstract.NAddOrder.
Require Stdlib.Numbers.Integer.Abstract.ZAddOrder.
Require Stdlib.Numbers.Natural.Abstract.NMulOrder.
Require Stdlib.Numbers.Integer.Abstract.ZMulOrder.
Require Stdlib.Numbers.Natural.Abstract.NSub.
Require Stdlib.Numbers.Integer.Abstract.ZMaxMin.
Require Stdlib.Numbers.Integer.Abstract.ZParity.
Require Stdlib.Numbers.Integer.Abstract.ZSgnAbs.
Require Stdlib.Numbers.Natural.Abstract.NDiv.
Require Stdlib.Numbers.Natural.Abstract.NGcd.
Require Stdlib.Numbers.Natural.Abstract.NMaxMin.
Require Stdlib.Numbers.Natural.Abstract.NParity.
Require Stdlib.Numbers.Natural.Abstract.NSqrt.
Require Stdlib.Numbers.Integer.Abstract.ZDivFloor.
Require Stdlib.Numbers.Integer.Abstract.ZDivTrunc.
Require Stdlib.Numbers.Integer.Abstract.ZGcd.
Require Stdlib.Numbers.Natural.Abstract.NDiv0.
Require Stdlib.Numbers.Natural.Abstract.NPow.
Require Stdlib.Numbers.Integer.Abstract.ZPow.
Require Stdlib.Numbers.Natural.Abstract.NLcm.
Require Stdlib.Numbers.Natural.Abstract.NLog.
Require Stdlib.Numbers.Integer.Abstract.ZBits.
Require Stdlib.Numbers.Integer.Abstract.ZLcm.
Require Stdlib.Numbers.Natural.Abstract.NBits.
Require Stdlib.Numbers.Natural.Abstract.NLcm0.
Require Stdlib.Numbers.Integer.Abstract.ZProperties.
Require Stdlib.Numbers.Natural.Abstract.NProperties.
Require Stdlib.Arith.PeanoNat.
Require Stdlib.Arith.Between.
Require Stdlib.Arith.Compare_dec.
Require Stdlib.Arith.EqNat.
Require Stdlib.Arith.Factorial.
Require Stdlib.Arith.Wf_nat.
Require Stdlib.Arith.Peano_dec.
Require Stdlib.Lists.List.
Require Stdlib.Wellfounded.List_Extension.
Require Stdlib.micromega.Refl.
Require Stdlib.Sorting.Sorted.
Require Stdlib.micromega.Tauto.
Require Stdlib.Lists.ListTactics.
Require Stdlib.Sorting.SetoidList.
Require Stdlib.Structures.DecidableType.
Require Stdlib.Structures.OrderedType.
Require Stdlib.Wellfounded.Lexicographic_Exponentiation.
Require Stdlib.MSets.MSetInterface.
Require Stdlib.PArith.BinPos.
Require Stdlib.Structures.EqualitiesFacts.
Require Stdlib.Structures.OrderedTypeAlt.
Require Stdlib.Structures.OrdersAlt.
Require Stdlib.Arith.Arith_base.
Require Stdlib.FSets.FMapInterface.
Require Stdlib.PArith.POrderedType.
Require Stdlib.PArith.Pnat.
Require Stdlib.Structures.OrdersLists.
Require Stdlib.FSets.FMapList.
Require Stdlib.Vectors.Fin.
Require Stdlib.NArith.BinNatDef.
Require Stdlib.PArith.PArith.
Require Stdlib.Vectors.VectorDef.
Require Stdlib.NArith.BinNat.
Require Stdlib.setoid_ring.BinList.
Require Stdlib.MSets.MSetList.
Require Stdlib.NArith.Ndiv_def.
Require Stdlib.NArith.Ngcd_def.
Require Stdlib.NArith.Nsqrt_def.
Require Stdlib.setoid_ring.Ring_theory.
Require Stdlib.NArith.Nnat.
Require Stdlib.Wellfounded.Wellfounded.
Require Stdlib.Vectors.VectorSpec.
Require Stdlib.ZArith.BinIntDef.
Require Stdlib.Vectors.VectorEq.
Require Stdlib.Vectors.Vector.
Require Stdlib.NArith.NArith_base.
Require Stdlib.Strings.Byte.
Require MetaRocq.Utils.ByteCompare.
Require Stdlib.Strings.Ascii.
Require Stdlib.Vectors.Bvector.
Require Stdlib.Strings.String.
Require Stdlib.NArith.Ndec.
Require Stdlib.Numbers.DecimalString.
Require Stdlib.Numbers.HexadecimalString.
Require Equations.Prop.Subterm.
Require Stdlib.ZArith.BinInt.
Require Equations.Prop.Tactics.
Require Stdlib.ZArith.Int.
Require Stdlib.ZArith.Zcompare.
Require Stdlib.ZArith.Zeven.
Require Stdlib.ZArith.auxiliary.
Require Stdlib.ZArith.Zpow_def.
Require Stdlib.setoid_ring.Ncring.
Require Stdlib.Numbers.Cyclic.Abstract.DoubleType.
Require Stdlib.micromega.Env.
Require Stdlib.micromega.VarMap.
Require Stdlib.micromega.EnvRing.
Require Stdlib.setoid_ring.Ring_polynom.
Require Stdlib.setoid_ring.InitialRing.
Require Stdlib.ZArith.Znat.
Require Stdlib.ZArith.Zorder.
Require Stdlib.setoid_ring.Ncring_polynom.
Require Stdlib.setoid_ring.Ring_tac.
Require Stdlib.ZArith.Zmax.
Require Stdlib.ZArith.Zmin.
Require Stdlib.ZArith.Zminmax.
Require Stdlib.ZArith.Zmisc.
Require Stdlib.omega.OmegaLemmas.
Require Stdlib.setoid_ring.Ncring_initial.
Require Stdlib.setoid_ring.Ring_base.
Require Stdlib.micromega.ZifyInst.
Require Stdlib.setoid_ring.Ncring_tac.
Require Stdlib.setoid_ring.Ring.
Require Stdlib.ZArith.ZArith_dec.
Require Stdlib.micromega.OrderedRing.
Require Stdlib.micromega.Zify.
Require Stdlib.setoid_ring.NArithRing.
Require Stdlib.setoid_ring.ZArithRing.
Require Stdlib.ZArith.Wf_Z.
Require Stdlib.micromega.ZifyBool.
Require Stdlib.omega.PreOmega.
Require Stdlib.setoid_ring.ArithRing.
Require Stdlib.setoid_ring.Cring.
Require Stdlib.ZArith.Zbool.
Require Stdlib.setoid_ring.Integral_domain.
Require Stdlib.ZArith.Zabs.
Require Equations.Prop.NoConfusion.
Require Equations.Prop.EqDecInstances.
Require Stdlib.nsatz.NsatzTactic.
Require Equations.Prop.Loader.
Require Stdlib.NArith.NArith.
Require Stdlib.micromega.RingMicromega.
Require Equations.Prop.Telescopes.
Require Equations.Prop.Equations.
Require Stdlib.ZArith.Zhints.
Require Stdlib.Arith.Arith.
Require Stdlib.micromega.ZMicromega.
Require MetaRocq.Utils.ReflectEq.
Require Stdlib.ZArith.ZArith_base.
Require MetaRocq.Utils.MRCompare.
Require Stdlib.MSets.MSetGenTree.
Require Stdlib.MSets.MSetAVL.
Require Stdlib.ZArith.Zcomplements.
Require Stdlib.ZArith.Zdiv.
Require Stdlib.ZArith.Zpower.
Require Stdlib.micromega.Lia.
Require Stdlib.btauto.Algebra.
Require Stdlib.Structures.OrderedTypeEx.
Require Stdlib.btauto.Reflect.
Require Stdlib.btauto.Btauto.
Require Stdlib.Structures.DecidableTypeEx.
Require Stdlib.FSets.FMapFacts.
Require Stdlib.MSets.MSetFacts.
Require Stdlib.ZArith.ZNsatz.
Require Stdlib.MSets.MSetDecide.
Require Stdlib.ZArith.Zbitwise.
Require MetaRocq.Common.config.
Require Stdlib.micromega.ZArith_hints.
Require Stdlib.MSets.MSetProperties.
Require Stdlib.ZArith.Zdivisibility.
Require Stdlib.ZArith.Zcong.
Require Stdlib.ZArith.Zdiv_facts.
Require Stdlib.ZArith.ZModOffset.
Require Stdlib.ZArith.Znumtheory.
Require Stdlib.ZArith.Zgcd_alt.
Require Stdlib.ZArith.Zpow_facts.
Require Stdlib.ZArith.ZArith.
Require MetaRocq.Utils.MRArith.
Require Stdlib.Numbers.Cyclic.Abstract.CyclicAxioms.
Require Stdlib.FSets.FMapAVL.
Require Stdlib.Numbers.Cyclic.Int63.Uint63.
Require Stdlib.Numbers.Cyclic.Int63.Cyclic63.
Require MetaRocq.PCUIC.utils.PCUICAstUtils.
Module Export PCUICCases.
Import MetaRocq.Utils.utils.
Import MetaRocq.PCUIC.PCUICAst.
Import MetaRocq.PCUIC.utils.PCUICAstUtils.

Coercion ci_ind : case_info >-> inductive.

Definition ind_predicate_context ind mdecl idecl : context :=
  let ictx := (expand_lets_ctx mdecl.(ind_params) idecl.(ind_indices)) in
  let indty := mkApps (tInd ind (abstract_instance mdecl.(ind_universes)))
    (to_extended_list (smash_context [] mdecl.(ind_params) ,,, ictx)) in
  let inddecl :=
    {| decl_name :=
      {| binder_name := nNamed (ind_name idecl); binder_relevance := idecl.(ind_relevance) |};
       decl_body := None;
       decl_type := indty |}
  in (inddecl :: ictx).

Definition inst_case_context params puinst (pctx : context) :=
  subst_context (List.rev params) 0 (subst_instance puinst pctx).

Definition inst_case_predicate_context (p : predicate term) :=
  inst_case_context p.(pparams) p.(puinst) p.(pcontext).

Definition inst_case_branch_context (p : predicate term) (br : branch term) :=
  inst_case_context p.(pparams) p.(puinst) br.(bcontext).

Definition iota_red npar p args br :=
  subst (List.rev (List.skipn npar args)) 0
    (expand_lets (inst_case_branch_context p br) (bbody br)).

Definition pre_case_predicate_context_gen ind mdecl idecl params puinst : context :=
  inst_case_context params puinst (ind_predicate_context ind mdecl idecl).

Definition case_predicate_context_gen ind mdecl idecl params puinst pctx :=
  map2 set_binder_name pctx (pre_case_predicate_context_gen ind mdecl idecl params puinst).

Definition case_predicate_context ind mdecl idecl p : context :=
  case_predicate_context_gen ind mdecl idecl p.(pparams) p.(puinst) (forget_types p.(pcontext)).

Definition cstr_branch_context ind mdecl cdecl : context :=
  expand_lets_ctx mdecl.(ind_params)
    (subst_context (inds (inductive_mind ind) (abstract_instance mdecl.(ind_universes))
       mdecl.(ind_bodies)) #|mdecl.(ind_params)|
      cdecl.(cstr_args)).

Definition pre_case_branch_context_gen ind mdecl cdecl params puinst : context :=
  inst_case_context params puinst (cstr_branch_context ind mdecl cdecl).

Definition case_branch_context_gen ind mdecl params puinst pctx cdecl :=
  map2 set_binder_name pctx (pre_case_branch_context_gen ind mdecl cdecl params puinst).

Definition case_branch_type_gen ind mdecl (idecl : one_inductive_body) params puinst bctx ptm i cdecl : context * term :=
  let cstr := tConstruct ind i puinst in
  let args := to_extended_list cdecl.(cstr_args) in
  let cstrapp := mkApps cstr (map (lift0 #|cdecl.(cstr_args)|) params ++ args) in
  let brctx := case_branch_context_gen ind mdecl params puinst bctx cdecl in
  let upars := subst_instance puinst mdecl.(ind_params) in
  let indices :=
    (map (subst (List.rev params) #|cdecl.(cstr_args)|)
      (map (expand_lets_k upars #|cdecl.(cstr_args)|)
        (map (subst (inds (inductive_mind ind) puinst mdecl.(ind_bodies))
                    (#|mdecl.(ind_params)| + #|cdecl.(cstr_args)|))
          (map (subst_instance puinst) cdecl.(cstr_indices))))) in
  let ty := mkApps (lift0 #|cdecl.(cstr_args)| ptm) (indices ++ [cstrapp]) in
  (brctx, ty).

Definition case_branch_type ind mdecl idecl p (b : branch term) ptm i cdecl : context * term :=
  case_branch_type_gen ind mdecl idecl p.(pparams) p.(puinst) (forget_types b.(bcontext)) ptm i cdecl.

Definition idecl_binder idecl :=
  {| decl_name :=
    {| binder_name := nNamed idecl.(ind_name);
        binder_relevance := idecl.(ind_relevance) |};
     decl_body := None;
     decl_type := idecl.(ind_type) |}.

Definition wf_predicate_gen mdecl idecl (pparams : list term) (pcontext : list aname) : Prop :=
  let decl := idecl_binder idecl in
  (#|pparams| = mdecl.(ind_npars)) /\
  (Forall2 (fun na decl => eq_binder_annot na decl.(decl_name))
    pcontext (decl :: idecl.(ind_indices))).

Definition wf_predicate mdecl idecl (p : predicate term) : Prop :=
  wf_predicate_gen mdecl idecl p.(pparams) (forget_types p.(pcontext)).

Definition wf_branch_gen cdecl (bctx : list aname) : Prop :=
  (Forall2 (fun na decl => eq_binder_annot na decl.(decl_name))
    bctx cdecl.(cstr_args)).

Definition wf_branch cdecl (b : branch term) : Prop :=
  wf_branch_gen cdecl (forget_types b.(bcontext)).

Definition wf_branches idecl (brs : list (branch term)) : Prop :=
  Forall2 wf_branch idecl.(ind_ctors) brs.



Definition fix_subst (l : mfixpoint term) :=
  let fix aux n :=
      match n with
      | 0 => []
      | S n => tFix l n :: aux n
      end
  in aux (List.length l).

Definition unfold_fix (mfix : mfixpoint term) (idx : nat) :=
  match List.nth_error mfix idx with
  | Some d => Some (d.(rarg), subst0 (fix_subst mfix) d.(dbody))
  | None => None
  end.

Definition cofix_subst (l : mfixpoint term) :=
  let fix aux n :=
      match n with
      | 0 => []
      | S n => tCoFix l n :: aux n
      end
  in aux (List.length l).

Definition unfold_cofix (mfix : mfixpoint term) (idx : nat) :=
  match List.nth_error mfix idx with
  | Some d => Some (d.(rarg), subst0 (cofix_subst mfix) d.(dbody))
  | None => None
  end.

Definition is_constructor n ts :=
  match List.nth_error ts n with
  | Some a => isConstruct_app a
  | None => false
  end.

End PCUICCases.
Module Export MetaRocq_DOT_PCUIC_DOT_Syntax_DOT_PCUICCases.
Module Export MetaRocq.
Module Export PCUIC.
Module Export Syntax.
Module Export PCUICCases.
End PCUICCases.

End Syntax.

End PCUIC.

End MetaRocq.

End MetaRocq_DOT_PCUIC_DOT_Syntax_DOT_PCUICCases.

Module Export MetaRocq_DOT_PCUIC_DOT_PCUICEquality.
Module Export MetaRocq.
Module Export PCUIC.
Module Export PCUICEquality.
Import MetaRocq.Utils.utils.
Import MetaRocq.PCUIC.PCUICAst.
Definition cmp_universe_instance (cmp_univ : Universe.t -> Universe.t -> Prop) : Instance.t -> Instance.t -> Prop.
Admitted.

Definition cmp_universe_variance (cmp_univ : conv_pb -> Universe.t -> Universe.t -> Prop) pb v u u' :=
  match v with
  | Variance.Irrelevant => True
  | Variance.Covariant => on_rel (cmp_univ pb) Universe.make' u u'
  | Variance.Invariant => on_rel (cmp_univ Conv) Universe.make' u u'
  end.

Definition cmp_universe_instance_variance cmp_univ pb v u u' :=
  Forall3 (cmp_universe_variance cmp_univ pb) v u u'.

Definition global_variance_gen lookup gr napp :=
  match gr with
  | IndRef ind =>
    match lookup_inductive_gen lookup ind with
    | Some (mdecl, idecl) =>
      match destArity [] idecl.(ind_type) with
      | Some (ctx, _) => if (context_assumptions ctx) <=? napp then
          match mdecl.(ind_variance) with
          | Some var => Variance var
          | None => AllEqual
          end
        else AllEqual
      | None => AllEqual
      end
    | None => AllEqual
    end
  | ConstructRef ind k =>
    match lookup_constructor_gen lookup ind k with
    | Some (mdecl, idecl, cdecl) =>
      if (cdecl.(cstr_arity) + mdecl.(ind_npars))%nat <=? napp then

        AllIrrelevant
      else AllEqual
    | _ => AllEqual
    end
  | _ => AllEqual
  end.

Definition cmp_opt_variance cmp_univ pb v :=
  match v with
  | AllEqual => cmp_universe_instance (cmp_univ Conv)
  | AllIrrelevant => fun l l' => #|l| = #|l'|
  | Variance v => fun u u' => cmp_universe_instance (cmp_univ Conv) u u' \/ cmp_universe_instance_variance cmp_univ pb v u u'
  end.

Definition cmp_global_instance_gen Σ cmp_universe pb gr napp :=
  cmp_opt_variance cmp_universe pb (global_variance_gen Σ gr napp).

Abbreviation cmp_global_instance Σ := (cmp_global_instance_gen (lookup_env Σ)).

Inductive eq_decl_upto_names : context_decl -> context_decl -> Type :=
  | compare_vass {na na' T} :
    eq_binder_annot na na' -> eq_decl_upto_names (vass na T) (vass na' T)
  | compare_vdef {na na' b T} :
    eq_binder_annot na na' -> eq_decl_upto_names (vdef na b T) (vdef na' b T).

Abbreviation eq_context_upto_names := (All2 eq_decl_upto_names).

End PCUICEquality.

End PCUIC.

End MetaRocq.

End MetaRocq_DOT_PCUIC_DOT_PCUICEquality.

Import MetaRocq.Utils.utils.
Import MetaRocq.PCUIC.PCUICAst.

Inductive context_subst : context -> list term -> list term -> Type :=
| context_subst_nil : context_subst [] [] []
| context_subst_ass Γ args s na t a :
    context_subst Γ args s ->
    context_subst (vass na t :: Γ) (args ++ [a]) (a :: s)
| context_subst_def Γ args s na b t :
    context_subst Γ args s ->
    context_subst (vdef na b t :: Γ) args (subst s 0 b :: s).
Module Export MetaRocq_DOT_PCUIC_DOT_PCUICContextSubst.
Module Export MetaRocq.
Module Export PCUIC.
Module Export PCUICContextSubst.
End PCUICContextSubst.

End PCUIC.

End MetaRocq.

End MetaRocq_DOT_PCUIC_DOT_PCUICContextSubst.
Import Stdlib.ssr.ssrbool.
Import MetaRocq.Utils.utils.
Import MetaRocq.PCUIC.PCUICAst.

Definition shiftnP k p i :=
  (i <? k) || p (i - k).
Fixpoint on_free_vars (p : nat -> bool) (t : term) : bool.
Admitted.

Definition on_free_vars_decl P d :=
  test_decl (on_free_vars P) d.

Definition on_free_vars_ctx P ctx :=
  alli (fun k => (on_free_vars_decl (shiftnP k P))) 0 (List.rev ctx).

Abbreviation is_open_term Γ := (on_free_vars (shiftnP #|Γ| xpred0)).
Abbreviation is_closed_context := (on_free_vars_ctx xpred0).
Module Export MetaRocq_DOT_PCUIC_DOT_Syntax_DOT_PCUICOnFreeVars.
Module Export PCUICOnFreeVars.
End PCUICOnFreeVars.

End MetaRocq_DOT_PCUIC_DOT_Syntax_DOT_PCUICOnFreeVars.
Import MetaRocq.Utils.utils.
Import MetaRocq.Common.config.
Import MetaRocq.PCUIC.PCUICAst.
Import MetaRocq.PCUIC.PCUICEquality.
Import MetaRocq.PCUIC.Syntax.PCUICCases.

Implicit Types (cf : checker_flags).

Definition cumul_predicate (cumul : context -> term -> term -> Type) cumul_universe Γ p p' :=
  All2 (cumul Γ) p.(pparams) p'.(pparams) ×
  cmp_universe_instance cumul_universe p.(puinst) p'.(puinst) ×
  eq_context_upto_names p.(pcontext) p'.(pcontext) ×
  cumul (Γ ,,, inst_case_predicate_context p) p.(preturn) p'.(preturn).

Definition cumul_branch (cumul_term : context -> term -> term -> Type) Γ p br br' :=
  eq_context_upto_names br.(bcontext) br'.(bcontext) ×
  cumul_term (Γ ,,, inst_case_branch_context p br) br.(bbody) br'.(bbody).

Definition cumul_branches cumul_term Γ p brs brs' := All2 (cumul_branch cumul_term Γ p) brs brs'.

Definition cumul_mfixpoint (cumul_term : context -> term -> term -> Type) Γ mfix mfix' :=
  All2 (fun d d' =>
    cumul_term Γ d.(dtype) d'.(dtype) ×
    cumul_term (Γ ,,, fix_context mfix) d.(dbody) d'.(dbody) ×
    d.(rarg) = d'.(rarg) ×
    eq_binder_annot d.(dname) d'.(dname)
  ) mfix mfix'.

Reserved Notation " Σ ;;; Γ ⊢ t ≤s[ pb ] u" (at level 50, Γ, t, u at next level,
  format "Σ  ;;;  Γ  ⊢  t  ≤s[ pb ]  u").

Definition cumul_Ind_univ {cf} (Σ : global_env_ext) pb i napp :=
  cmp_global_instance Σ (compare_universe Σ) pb (IndRef i) napp.

Definition cumul_Construct_univ {cf} (Σ : global_env_ext) pb  i k napp :=
  cmp_global_instance Σ (compare_universe Σ) pb (ConstructRef i k) napp.
Inductive cumulSpec0 {cf : checker_flags} (Σ : global_env_ext) Γ (pb : conv_pb) : term -> term -> Type :=

| cumul_Trans : forall t u v,
    is_closed_context Γ -> is_open_term Γ u ->
    Σ ;;; Γ ⊢ t ≤s[pb] u ->
    Σ ;;; Γ ⊢ u ≤s[pb] v ->
    Σ ;;; Γ ⊢ t ≤s[pb] v

| cumul_Sym : forall t u,
    Σ ;;; Γ ⊢ t ≤s[Conv] u ->
    Σ ;;; Γ ⊢ u ≤s[pb] t

| cumul_Refl : forall t,
    Σ ;;; Γ ⊢ t ≤s[pb] t

| cumul_Ind : forall i u u' args args',
    cumul_Ind_univ Σ pb i #|args| u u' ->
    All2 (fun t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) args args' ->
    Σ ;;; Γ ⊢ mkApps (tInd i u) args ≤s[pb] mkApps (tInd i u') args'

| cumul_Construct : forall i k u u' args args',
    cumul_Construct_univ Σ pb i k #|args| u u' ->
    All2 (fun t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) args args' ->
    Σ ;;; Γ ⊢ mkApps (tConstruct i k u) args ≤s[pb] mkApps (tConstruct i k u') args'

| cumul_Sort : forall s s',
    compare_sort Σ pb s s' ->
    Σ ;;; Γ ⊢ tSort s ≤s[pb] tSort s'

| cumul_Const : forall c u u',
    cmp_universe_instance (compare_universe Σ Conv) u u' ->
    Σ ;;; Γ ⊢ tConst c u ≤s[pb] tConst c u'

| cumul_Evar : forall e args args',
    All2 (fun t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) args args' ->
    Σ ;;; Γ ⊢ tEvar e args ≤s[pb] tEvar e args'

| cumul_App : forall t t' u u',
    Σ ;;; Γ ⊢ t ≤s[pb] t' ->
    Σ ;;; Γ ⊢ u ≤s[Conv] u' ->
    Σ ;;; Γ ⊢ tApp t u ≤s[pb] tApp t' u'

| cumul_Lambda : forall na na' ty ty' t t',
    eq_binder_annot na na' ->
    Σ ;;; Γ ⊢ ty ≤s[Conv] ty' ->
    Σ ;;; Γ ,, vass na ty ⊢ t ≤s[Conv] t' ->
    Σ ;;; Γ ⊢ tLambda na ty t ≤s[pb] tLambda na' ty' t'

| cumul_Prod : forall na na' a a' b b',
    eq_binder_annot na na' ->
    Σ ;;; Γ ⊢ a ≤s[Conv] a' ->
    Σ ;;; Γ ,, vass na a ⊢ b ≤s[pb] b' ->
    Σ ;;; Γ ⊢ tProd na a b ≤s[pb] tProd na' a' b'

| cumul_LetIn : forall na na' t t' ty ty' u u',
    eq_binder_annot na na' ->
    Σ ;;; Γ ⊢ t ≤s[Conv] t' ->
    Σ ;;; Γ ⊢ ty ≤s[Conv] ty' ->
    Σ ;;; Γ ,, vdef na t ty ⊢ u ≤s[Conv] u' ->
    Σ ;;; Γ ⊢ tLetIn na t ty u ≤s[pb] tLetIn na' t' ty' u'

| cumul_Case indn : forall p p' c c' brs brs',
    cumul_predicate (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) (compare_universe Σ Conv) Γ p p' ->
    Σ ;;; Γ ⊢ c ≤s[Conv] c' ->
    cumul_branches (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) Γ p brs brs' ->
    Σ ;;; Γ ⊢ tCase indn p c brs ≤s[pb] tCase indn p' c' brs'

| cumul_Proj : forall p c c',
    Σ ;;; Γ ⊢ c ≤s[Conv] c' ->
    Σ ;;; Γ ⊢ tProj p c ≤s[pb] tProj p c'

| cumul_Fix : forall mfix mfix' idx,
    cumul_mfixpoint (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) Γ mfix mfix' ->
    Σ ;;; Γ ⊢ tFix mfix idx ≤s[pb] tFix mfix' idx

| cumul_CoFix : forall mfix mfix' idx,
    cumul_mfixpoint (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) Γ mfix mfix' ->
    Σ ;;; Γ ⊢ tCoFix mfix idx ≤s[pb] tCoFix mfix' idx

| cumul_Prim p p' :
  onPrims (fun x y => Σ ;;; Γ ⊢ x ≤s[Conv] y) (compare_universe Σ Conv) p p' ->
  Σ ;;; Γ ⊢ tPrim p ≤s[pb] tPrim p'

| cumul_beta : forall na t b a,
    Σ ;;; Γ ⊢ tApp (tLambda na t b) a ≤s[pb] b {0 := a}

| cumul_zeta : forall na b t b',
    Σ ;;; Γ ⊢ tLetIn na b t b' ≤s[pb] b' {0 := b}

| cumul_rel i body :
    option_map decl_body (nth_error Γ i) = Some (Some body) ->
    Σ ;;; Γ ⊢ tRel i ≤s[pb] lift0 (S i) body

| cumul_iota : forall ci c u args p brs br,
    nth_error brs c = Some br ->
    #|args| = (ci.(ci_npar) + context_assumptions br.(bcontext))%nat ->
    Σ ;;; Γ ⊢ tCase ci p (mkApps (tConstruct ci.(ci_ind) c u) args) brs  ≤s[pb] iota_red ci.(ci_npar) p args br

| cumul_fix : forall mfix idx args narg fn,
    unfold_fix mfix idx = Some (narg, fn) ->
    is_constructor narg args = true ->
    Σ ;;; Γ ⊢ mkApps (tFix mfix idx) args ≤s[pb] mkApps fn args

| cumul_cofix_case : forall ip p mfix idx args narg fn brs,
    unfold_cofix mfix idx = Some (narg, fn) ->
    Σ ;;; Γ ⊢ tCase ip p (mkApps (tCoFix mfix idx) args) brs ≤s[pb] tCase ip p (mkApps fn args) brs

| cumul_cofix_proj : forall p mfix idx args narg fn,
    unfold_cofix mfix idx = Some (narg, fn) ->
    Σ ;;; Γ ⊢ tProj p (mkApps (tCoFix mfix idx) args) ≤s[pb] tProj p (mkApps fn args)

| cumul_delta : forall c decl body (isdecl : declared_constant Σ c decl) u,
    decl.(cst_body) = Some body ->
    Σ ;;; Γ ⊢ tConst c u ≤s[pb] body@[u]

| cumul_proj : forall p args u arg,
    nth_error args (p.(proj_npars) + p.(proj_arg)) = Some arg ->
    Σ ;;; Γ ⊢ tProj p (mkApps (tConstruct p.(proj_ind) 0 u) args) ≤s[pb] arg

where " Σ ;;; Γ ⊢ t ≤s[ pb ] u " := (@cumulSpec0 _ Σ Γ pb t u) : type_scope.
Definition cumulSpec `{checker_flags} (Σ : global_env_ext) Γ := cumulSpec0 Σ Γ Cumul.

Notation " Σ ;;; Γ |- t <=s u " := (@cumulSpec _ Σ Γ t u) (at level 50, Γ, t, u at next level).

Module PCUICConversionParSpec <: EnvironmentTyping.ConversionParSig PCUICTerm PCUICEnvironment PCUICTermUtils PCUICEnvTyping.
  Definition cumul_gen := @cumulSpec0.
End PCUICConversionParSpec.
Module Export MetaRocq_DOT_PCUIC_DOT_PCUICCumulativitySpec.
Module Export PCUICCumulativitySpec.
End PCUICCumulativitySpec.

End MetaRocq_DOT_PCUIC_DOT_PCUICCumulativitySpec.

Import MetaRocq.Utils.utils.
Import MetaRocq.Common.config.
Import MetaRocq.PCUIC.PCUICAst.
Import MetaRocq.PCUIC.utils.PCUICAstUtils.
Import MetaRocq.PCUIC.utils.PCUICPrimitive.
Import MetaRocq.PCUIC.PCUICEquality.
Export MetaRocq.PCUIC.Syntax.PCUICCases.

Definition type_of_constructor mdecl (cdecl : constructor_body) (c : inductive * nat) (u : list Level.t) :=
  let mind := inductive_mind (fst c) in
  subst0 (inds mind u mdecl.(ind_bodies)) (subst_instance u (cstr_type cdecl)).

Include PCUICEnvTyping.

Inductive FixCoFix : Type := Fix | CoFix.

Class GuardChecker :=
{
  guard : FixCoFix -> global_env_ext -> context -> mfixpoint term -> Prop ;
}.

Axiom guard_checking : GuardChecker.
#[global]
Existing Instance guard_checking.

Definition fix_guard := guard Fix.
Definition cofix_guard := guard CoFix.

Definition destInd (t : term) :=
  match t with
  | tInd ind u => Some (ind, u)
  | _ => None
  end.

Definition isCoFinite (r : recursivity_kind) :=
  match r with
  | CoFinite => true
  | _ => false
  end.

Definition check_recursivity_kind
  (lookup: kername -> option global_decl) ind r :=
  match lookup ind with
  | Some (InductiveDecl mib) => ReflectEq.eqb mib.(ind_finite) r
  | _ => false
  end.

Definition check_one_fix d :=
  let '{| dname := na;
         dtype := ty;
         dbody := b;
         rarg := arg |} := 

[...]

uire Stdlib.FSets.FMapFacts.
Require Stdlib.MSets.MSetFacts.
Require Stdlib.ZArith.ZNsatz.
Require Stdlib.MSets.MSetDecide.
Require Stdlib.ZArith.Zbitwise.
Require MetaRocq.Common.config.
Require Stdlib.micromega.ZArith_hints.
Require Stdlib.MSets.MSetProperties.
Require Stdlib.ZArith.Zdivisibility.
Require Stdlib.ZArith.Zcong.
Require Stdlib.ZArith.Zdiv_facts.
Require Stdlib.ZArith.ZModOffset.
Require Stdlib.ZArith.Znumtheory.
Require Stdlib.ZArith.Zgcd_alt.
Require Stdlib.ZArith.Zpow_facts.
Require Stdlib.ZArith.ZArith.
Require MetaRocq.Utils.MRArith.
Require Stdlib.Numbers.Cyclic.Abstract.CyclicAxioms.
Require Stdlib.FSets.FMapAVL.
Require Stdlib.Numbers.Cyclic.Int63.Uint63.
Require Stdlib.Numbers.Cyclic.Int63.Cyclic63.
Require MetaRocq.PCUIC.utils.PCUICAstUtils.
Module Export PCUICCases.
Import MetaRocq.Utils.utils.
Import MetaRocq.PCUIC.PCUICAst.
Import MetaRocq.PCUIC.utils.PCUICAstUtils.

Coercion ci_ind : case_info >-> inductive.

Definition ind_predicate_context ind mdecl idecl : context :=
  let ictx := (expand_lets_ctx mdecl.(ind_params) idecl.(ind_indices)) in
  let indty := mkApps (tInd ind (abstract_instance mdecl.(ind_universes)))
    (to_extended_list (smash_context [] mdecl.(ind_params) ,,, ictx)) in
  let inddecl :=
    {| decl_name :=
      {| binder_name := nNamed (ind_name idecl); binder_relevance := idecl.(ind_relevance) |};
       decl_body := None;
       decl_type := indty |}
  in (inddecl :: ictx).

Definition inst_case_context params puinst (pctx : context) :=
  subst_context (List.rev params) 0 (subst_instance puinst pctx).

Definition inst_case_predicate_context (p : predicate term) :=
  inst_case_context p.(pparams) p.(puinst) p.(pcontext).

Definition inst_case_branch_context (p : predicate term) (br : branch term) :=
  inst_case_context p.(pparams) p.(puinst) br.(bcontext).

Definition iota_red npar p args br :=
  subst (List.rev (List.skipn npar args)) 0
    (expand_lets (inst_case_branch_context p br) (bbody br)).

Definition pre_case_predicate_context_gen ind mdecl idecl params puinst : context :=
  inst_case_context params puinst (ind_predicate_context ind mdecl idecl).

Definition case_predicate_context_gen ind mdecl idecl params puinst pctx :=
  map2 set_binder_name pctx (pre_case_predicate_context_gen ind mdecl idecl params puinst).

Definition case_predicate_context ind mdecl idecl p : context :=
  case_predicate_context_gen ind mdecl idecl p.(pparams) p.(puinst) (forget_types p.(pcontext)).

Definition cstr_branch_context ind mdecl cdecl : context :=
  expand_lets_ctx mdecl.(ind_params)
    (subst_context (inds (inductive_mind ind) (abstract_instance mdecl.(ind_universes))
       mdecl.(ind_bodies)) #|mdecl.(ind_params)|
      cdecl.(cstr_args)).

Definition pre_case_branch_context_gen ind mdecl cdecl params puinst : context :=
  inst_case_context params puinst (cstr_branch_context ind mdecl cdecl).

Definition case_branch_context_gen ind mdecl params puinst pctx cdecl :=
  map2 set_binder_name pctx (pre_case_branch_context_gen ind mdecl cdecl params puinst).

Definition case_branch_type_gen ind mdecl (idecl : one_inductive_body) params puinst bctx ptm i cdecl : context * term :=
  let cstr := tConstruct ind i puinst in
  let args := to_extended_list cdecl.(cstr_args) in
  let cstrapp := mkApps cstr (map (lift0 #|cdecl.(cstr_args)|) params ++ args) in
  let brctx := case_branch_context_gen ind mdecl params puinst bctx cdecl in
  let upars := subst_instance puinst mdecl.(ind_params) in
  let indices :=
    (map (subst (List.rev params) #|cdecl.(cstr_args)|)
      (map (expand_lets_k upars #|cdecl.(cstr_args)|)
        (map (subst (inds (inductive_mind ind) puinst mdecl.(ind_bodies))
                    (#|mdecl.(ind_params)| + #|cdecl.(cstr_args)|))
          (map (subst_instance puinst) cdecl.(cstr_indices))))) in
  let ty := mkApps (lift0 #|cdecl.(cstr_args)| ptm) (indices ++ [cstrapp]) in
  (brctx, ty).

Definition case_branch_type ind mdecl idecl p (b : branch term) ptm i cdecl : context * term :=
  case_branch_type_gen ind mdecl idecl p.(pparams) p.(puinst) (forget_types b.(bcontext)) ptm i cdecl.

Definition idecl_binder idecl :=
  {| decl_name :=
    {| binder_name := nNamed idecl.(ind_name);
        binder_relevance := idecl.(ind_relevance) |};
     decl_body := None;
     decl_type := idecl.(ind_type) |}.

Definition wf_predicate_gen mdecl idecl (pparams : list term) (pcontext : list aname) : Prop :=
  let decl := idecl_binder idecl in
  (#|pparams| = mdecl.(ind_npars)) /\
  (Forall2 (fun na decl => eq_binder_annot na decl.(decl_name))
    pcontext (decl :: idecl.(ind_indices))).

Definition wf_predicate mdecl idecl (p : predicate term) : Prop :=
  wf_predicate_gen mdecl idecl p.(pparams) (forget_types p.(pcontext)).

Definition wf_branch_gen cdecl (bctx : list aname) : Prop :=
  (Forall2 (fun na decl => eq_binder_annot na decl.(decl_name))
    bctx cdecl.(cstr_args)).

Definition wf_branch cdecl (b : branch term) : Prop :=
  wf_branch_gen cdecl (forget_types b.(bcontext)).

Definition wf_branches idecl (brs : list (branch term)) : Prop :=
  Forall2 wf_branch idecl.(ind_ctors) brs.



Definition fix_subst (l : mfixpoint term) :=
  let fix aux n :=
      match n with
      | 0 => []
      | S n => tFix l n :: aux n
      end
  in aux (List.length l).

Definition unfold_fix (mfix : mfixpoint term) (idx : nat) :=
  match List.nth_error mfix idx with
  | Some d => Some (d.(rarg), subst0 (fix_subst mfix) d.(dbody))
  | None => None
  end.

Definition cofix_subst (l : mfixpoint term) :=
  let fix aux n :=
      match n with
      | 0 => []
      | S n => tCoFix l n :: aux n
      end
  in aux (List.length l).

Definition unfold_cofix (mfix : mfixpoint term) (idx : nat) :=
  match List.nth_error mfix idx with
  | Some d => Some (d.(rarg), subst0 (cofix_subst mfix) d.(dbody))
  | None => None
  end.

Definition is_constructor n ts :=
  match List.nth_error ts n with
  | Some a => isConstruct_app a
  | None => false
  end.

End PCUICCases.
Module Export MetaRocq_DOT_PCUIC_DOT_Syntax_DOT_PCUICCases.
Module Export MetaRocq.
Module Export PCUIC.
Module Export Syntax.
Module Export PCUICCases.
End PCUICCases.

End Syntax.

End PCUIC.

End MetaRocq.

End MetaRocq_DOT_PCUIC_DOT_Syntax_DOT_PCUICCases.

Module Export MetaRocq_DOT_PCUIC_DOT_PCUICEquality.
Module Export MetaRocq.
Module Export PCUIC.
Module Export PCUICEquality.
Import MetaRocq.Utils.utils.
Import MetaRocq.PCUIC.PCUICAst.
Definition cmp_universe_instance (cmp_univ : Universe.t -> Universe.t -> Prop) : Instance.t -> Instance.t -> Prop.
Admitted.

Definition cmp_universe_variance (cmp_univ : conv_pb -> Universe.t -> Universe.t -> Prop) pb v u u' :=
  match v with
  | Variance.Irrelevant => True
  | Variance.Covariant => on_rel (cmp_univ pb) Universe.make' u u'
  | Variance.Invariant => on_rel (cmp_univ Conv) Universe.make' u u'
  end.

Definition cmp_universe_instance_variance cmp_univ pb v u u' :=
  Forall3 (cmp_universe_variance cmp_univ pb) v u u'.

Definition global_variance_gen lookup gr napp :=
  match gr with
  | IndRef ind =>
    match lookup_inductive_gen lookup ind with
    | Some (mdecl, idecl) =>
      match destArity [] idecl.(ind_type) with
      | Some (ctx, _) => if (context_assumptions ctx) <=? napp then
          match mdecl.(ind_variance) with
          | Some var => Variance var
          | None => AllEqual
          end
        else AllEqual
      | None => AllEqual
      end
    | None => AllEqual
    end
  | ConstructRef ind k =>
    match lookup_constructor_gen lookup ind k with
    | Some (mdecl, idecl, cdecl) =>
      if (cdecl.(cstr_arity) + mdecl.(ind_npars))%nat <=? napp then

        AllIrrelevant
      else AllEqual
    | _ => AllEqual
    end
  | _ => AllEqual
  end.

Definition cmp_opt_variance cmp_univ pb v :=
  match v with
  | AllEqual => cmp_universe_instance (cmp_univ Conv)
  | AllIrrelevant => fun l l' => #|l| = #|l'|
  | Variance v => fun u u' => cmp_universe_instance (cmp_univ Conv) u u' \/ cmp_universe_instance_variance cmp_univ pb v u u'
  end.

Definition cmp_global_instance_gen Σ cmp_universe pb gr napp :=
  cmp_opt_variance cmp_universe pb (global_variance_gen Σ gr napp).

Abbreviation cmp_global_instance Σ := (cmp_global_instance_gen (lookup_env Σ)).

Inductive eq_decl_upto_names : context_decl -> context_decl -> Type :=
  | compare_vass {na na' T} :
    eq_binder_annot na na' -> eq_decl_upto_names (vass na T) (vass na' T)
  | compare_vdef {na na' b T} :
    eq_binder_annot na na' -> eq_decl_upto_names (vdef na b T) (vdef na' b T).

Abbreviation eq_context_upto_names := (All2 eq_decl_upto_names).

End PCUICEquality.

End PCUIC.

End MetaRocq.

End MetaRocq_DOT_PCUIC_DOT_PCUICEquality.

Import MetaRocq.Utils.utils.
Import MetaRocq.PCUIC.PCUICAst.

Inductive context_subst : context -> list term -> list term -> Type :=
| context_subst_nil : context_subst [] [] []
| context_subst_ass Γ args s na t a :
    context_subst Γ args s ->
    context_subst (vass na t :: Γ) (args ++ [a]) (a :: s)
| context_subst_def Γ args s na b t :
    context_subst Γ args s ->
    context_subst (vdef na b t :: Γ) args (subst s 0 b :: s).
Module Export MetaRocq_DOT_PCUIC_DOT_PCUICContextSubst.
Module Export MetaRocq.
Module Export PCUIC.
Module Export PCUICContextSubst.
End PCUICContextSubst.

End PCUIC.

End MetaRocq.

End MetaRocq_DOT_PCUIC_DOT_PCUICContextSubst.
Import Stdlib.ssr.ssrbool.
Import MetaRocq.Utils.utils.
Import MetaRocq.PCUIC.PCUICAst.

Definition shiftnP k p i :=
  (i <? k) || p (i - k).
Fixpoint on_free_vars (p : nat -> bool) (t : term) : bool.
Admitted.

Definition on_free_vars_decl P d :=
  test_decl (on_free_vars P) d.

Definition on_free_vars_ctx P ctx :=
  alli (fun k => (on_free_vars_decl (shiftnP k P))) 0 (List.rev ctx).

Abbreviation is_open_term Γ := (on_free_vars (shiftnP #|Γ| xpred0)).
Abbreviation is_closed_context := (on_free_vars_ctx xpred0).
Module Export MetaRocq_DOT_PCUIC_DOT_Syntax_DOT_PCUICOnFreeVars.
Module Export PCUICOnFreeVars.
End PCUICOnFreeVars.

End MetaRocq_DOT_PCUIC_DOT_Syntax_DOT_PCUICOnFreeVars.
Import MetaRocq.Utils.utils.
Import MetaRocq.Common.config.
Import MetaRocq.PCUIC.PCUICAst.
Import MetaRocq.PCUIC.PCUICEquality.
Import MetaRocq.PCUIC.Syntax.PCUICCases.

Implicit Types (cf : checker_flags).

Definition cumul_predicate (cumul : context -> term -> term -> Type) cumul_universe Γ p p' :=
  All2 (cumul Γ) p.(pparams) p'.(pparams) ×
  cmp_universe_instance cumul_universe p.(puinst) p'.(puinst) ×
  eq_context_upto_names p.(pcontext) p'.(pcontext) ×
  cumul (Γ ,,, inst_case_predicate_context p) p.(preturn) p'.(preturn).

Definition cumul_branch (cumul_term : context -> term -> term -> Type) Γ p br br' :=
  eq_context_upto_names br.(bcontext) br'.(bcontext) ×
  cumul_term (Γ ,,, inst_case_branch_context p br) br.(bbody) br'.(bbody).

Definition cumul_branches cumul_term Γ p brs brs' := All2 (cumul_branch cumul_term Γ p) brs brs'.

Definition cumul_mfixpoint (cumul_term : context -> term -> term -> Type) Γ mfix mfix' :=
  All2 (fun d d' =>
    cumul_term Γ d.(dtype) d'.(dtype) ×
    cumul_term (Γ ,,, fix_context mfix) d.(dbody) d'.(dbody) ×
    d.(rarg) = d'.(rarg) ×
    eq_binder_annot d.(dname) d'.(dname)
  ) mfix mfix'.

Reserved Notation " Σ ;;; Γ ⊢ t ≤s[ pb ] u" (at level 50, Γ, t, u at next level,
  format "Σ  ;;;  Γ  ⊢  t  ≤s[ pb ]  u").

Definition cumul_Ind_univ {cf} (Σ : global_env_ext) pb i napp :=
  cmp_global_instance Σ (compare_universe Σ) pb (IndRef i) napp.

Definition cumul_Construct_univ {cf} (Σ : global_env_ext) pb  i k napp :=
  cmp_global_instance Σ (compare_universe Σ) pb (ConstructRef i k) napp.
Inductive cumulSpec0 {cf : checker_flags} (Σ : global_env_ext) Γ (pb : conv_pb) : term -> term -> Type :=

| cumul_Trans : forall t u v,
    is_closed_context Γ -> is_open_term Γ u ->
    Σ ;;; Γ ⊢ t ≤s[pb] u ->
    Σ ;;; Γ ⊢ u ≤s[pb] v ->
    Σ ;;; Γ ⊢ t ≤s[pb] v

| cumul_Sym : forall t u,
    Σ ;;; Γ ⊢ t ≤s[Conv] u ->
    Σ ;;; Γ ⊢ u ≤s[pb] t

| cumul_Refl : forall t,
    Σ ;;; Γ ⊢ t ≤s[pb] t

| cumul_Ind : forall i u u' args args',
    cumul_Ind_univ Σ pb i #|args| u u' ->
    All2 (fun t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) args args' ->
    Σ ;;; Γ ⊢ mkApps (tInd i u) args ≤s[pb] mkApps (tInd i u') args'

| cumul_Construct : forall i k u u' args args',
    cumul_Construct_univ Σ pb i k #|args| u u' ->
    All2 (fun t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) args args' ->
    Σ ;;; Γ ⊢ mkApps (tConstruct i k u) args ≤s[pb] mkApps (tConstruct i k u') args'

| cumul_Sort : forall s s',
    compare_sort Σ pb s s' ->
    Σ ;;; Γ ⊢ tSort s ≤s[pb] tSort s'

| cumul_Const : forall c u u',
    cmp_universe_instance (compare_universe Σ Conv) u u' ->
    Σ ;;; Γ ⊢ tConst c u ≤s[pb] tConst c u'

| cumul_Evar : forall e args args',
    All2 (fun t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) args args' ->
    Σ ;;; Γ ⊢ tEvar e args ≤s[pb] tEvar e args'

| cumul_App : forall t t' u u',
    Σ ;;; Γ ⊢ t ≤s[pb] t' ->
    Σ ;;; Γ ⊢ u ≤s[Conv] u' ->
    Σ ;;; Γ ⊢ tApp t u ≤s[pb] tApp t' u'

| cumul_Lambda : forall na na' ty ty' t t',
    eq_binder_annot na na' ->
    Σ ;;; Γ ⊢ ty ≤s[Conv] ty' ->
    Σ ;;; Γ ,, vass na ty ⊢ t ≤s[Conv] t' ->
    Σ ;;; Γ ⊢ tLambda na ty t ≤s[pb] tLambda na' ty' t'

| cumul_Prod : forall na na' a a' b b',
    eq_binder_annot na na' ->
    Σ ;;; Γ ⊢ a ≤s[Conv] a' ->
    Σ ;;; Γ ,, vass na a ⊢ b ≤s[pb] b' ->
    Σ ;;; Γ ⊢ tProd na a b ≤s[pb] tProd na' a' b'

| cumul_LetIn : forall na na' t t' ty ty' u u',
    eq_binder_annot na na' ->
    Σ ;;; Γ ⊢ t ≤s[Conv] t' ->
    Σ ;;; Γ ⊢ ty ≤s[Conv] ty' ->
    Σ ;;; Γ ,, vdef na t ty ⊢ u ≤s[Conv] u' ->
    Σ ;;; Γ ⊢ tLetIn na t ty u ≤s[pb] tLetIn na' t' ty' u'

| cumul_Case indn : forall p p' c c' brs brs',
    cumul_predicate (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) (compare_universe Σ Conv) Γ p p' ->
    Σ ;;; Γ ⊢ c ≤s[Conv] c' ->
    cumul_branches (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) Γ p brs brs' ->
    Σ ;;; Γ ⊢ tCase indn p c brs ≤s[pb] tCase indn p' c' brs'

| cumul_Proj : forall p c c',
    Σ ;;; Γ ⊢ c ≤s[Conv] c' ->
    Σ ;;; Γ ⊢ tProj p c ≤s[pb] tProj p c'

| cumul_Fix : forall mfix mfix' idx,
    cumul_mfixpoint (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) Γ mfix mfix' ->
    Σ ;;; Γ ⊢ tFix mfix idx ≤s[pb] tFix mfix' idx

| cumul_CoFix : forall mfix mfix' idx,
    cumul_mfixpoint (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) Γ mfix mfix' ->
    Σ ;;; Γ ⊢ tCoFix mfix idx ≤s[pb] tCoFix mfix' idx

| cumul_Prim p p' :
  onPrims (fun x y => Σ ;;; Γ ⊢ x ≤s[Conv] y) (compare_universe Σ Conv) p p' ->
  Σ ;;; Γ ⊢ tPrim p ≤s[pb] tPrim p'

| cumul_beta : forall na t b a,
    Σ ;;; Γ ⊢ tApp (tLambda na t b) a ≤s[pb] b {0 := a}

| cumul_zeta : forall na b t b',
    Σ ;;; Γ ⊢ tLetIn na b t b' ≤s[pb] b' {0 := b}

| cumul_rel i body :
    option_map decl_body (nth_error Γ i) = Some (Some body) ->
    Σ ;;; Γ ⊢ tRel i ≤s[pb] lift0 (S i) body

| cumul_iota : forall ci c u args p brs br,
    nth_error brs c = Some br ->
    #|args| = (ci.(ci_npar) + context_assumptions br.(bcontext))%nat ->
    Σ ;;; Γ ⊢ tCase ci p (mkApps (tConstruct ci.(ci_ind) c u) args) brs  ≤s[pb] iota_red ci.(ci_npar) p args br

| cumul_fix : forall mfix idx args narg fn,
    unfold_fix mfix idx = Some (narg, fn) ->
    is_constructor narg args = true ->
    Σ ;;; Γ ⊢ mkApps (tFix mfix idx) args ≤s[pb] mkApps fn args

| cumul_cofix_case : forall ip p mfix idx args narg fn brs,
    unfold_cofix mfix idx = Some (narg, fn) ->
    Σ ;;; Γ ⊢ tCase ip p (mkApps (tCoFix mfix idx) args) brs ≤s[pb] tCase ip p (mkApps fn args) brs

| cumul_cofix_proj : forall p mfix idx args narg fn,
    unfold_cofix mfix idx = Some (narg, fn) ->
    Σ ;;; Γ ⊢ tProj p (mkApps (tCoFix mfix idx) args) ≤s[pb] tProj p (mkApps fn args)

| cumul_delta : forall c decl body (isdecl : declared_constant Σ c decl) u,
    decl.(cst_body) = Some body ->
    Σ ;;; Γ ⊢ tConst c u ≤s[pb] body@[u]

| cumul_proj : forall p args u arg,
    nth_error args (p.(proj_npars) + p.(proj_arg)) = Some arg ->
    Σ ;;; Γ ⊢ tProj p (mkApps (tConstruct p.(proj_ind) 0 u) args) ≤s[pb] arg

where " Σ ;;; Γ ⊢ t ≤s[ pb ] u " := (@cumulSpec0 _ Σ Γ pb t u) : type_scope.
Definition cumulSpec `{checker_flags} (Σ : global_env_ext) Γ := cumulSpec0 Σ Γ Cumul.

Notation " Σ ;;; Γ |- t <=s u " := (@cumulSpec _ Σ Γ t u) (at level 50, Γ, t, u at next level).

Module PCUICConversionParSpec <: EnvironmentTyping.ConversionParSig PCUICTerm PCUICEnvironment PCUICTermUtils PCUICEnvTyping.
  Definition cumul_gen := @cumulSpec0.
End PCUICConversionParSpec.
Module Export MetaRocq_DOT_PCUIC_DOT_PCUICCumulativitySpec.
Module Export PCUICCumulativitySpec.
End PCUICCumulativitySpec.

End MetaRocq_DOT_PCUIC_DOT_PCUICCumulativitySpec.

Import MetaRocq.Utils.utils.
Import MetaRocq.Common.config.
Import MetaRocq.PCUIC.PCUICAst.
Import MetaRocq.PCUIC.utils.PCUICAstUtils.
Import MetaRocq.PCUIC.utils.PCUICPrimitive.
Import MetaRocq.PCUIC.PCUICEquality.
Export MetaRocq.PCUIC.Syntax.PCUICCases.

Definition type_of_constructor mdecl (cdecl : constructor_body) (c : inductive * nat) (u : list Level.t) :=
  let mind := inductive_mind (fst c) in
  subst0 (inds mind u mdecl.(ind_bodies)) (subst_instance u (cstr_type cdecl)).

Include PCUICEnvTyping.

Inductive FixCoFix : Type := Fix | CoFix.

Class GuardChecker :=
{
  guard : FixCoFix -> global_env_ext -> context -> mfixpoint term -> Prop ;
}.

Axiom guard_checking : GuardChecker.
#[global]
Existing Instance guard_checking.

Definition fix_guard := guard Fix.
Definition cofix_guard := guard CoFix.

Definition destInd (t : term) :=
  match t with
  | tInd ind u => Some (ind, u)
  | _ => None
  end.

Definition isCoFinite (r : recursivity_kind) :=
  match r with
  | CoFinite => true
  | _ => false
  end.

Definition check_recursivity_kind
  (lookup: kername -> option global_decl) ind r :=
  match lookup ind with
  | Some (InductiveDecl mib) => ReflectEq.eqb mib.(ind_finite) r
  | _ => false
  end.

Definition check_one_fix d :=
  let '{| dname := na;
         dtype := ty;
         dbody := b;
         rarg := arg |} := d in
  let '(ctx, ty) := decompose_prod_assum [] ty in
  match nth_error (List.rev (smash_context [] ctx)) arg with
  | Some argd =>
    let (hd, args) := decompose_app argd.(decl_type) in
    match destInd hd with
    | Some (mkInd mind _, u) => Some mind
    | None => None
    end
  | None => None
  end.

Definition wf_fixpoint_gen
  (lookup: kername -> option global_decl) mfix :=
  forallb (isLambda ∘ dbody) mfix &&
  let checks := map check_one_fix mfix in
  match map_option_out checks with
  | Some (ind :: inds) =>

    forallb (eqb ind) inds &&
    check_recursivity_kind lookup ind Finite
  | _ => false
  end.

Definition wf_fixpoint (Σ : global_env) := wf_fixpoint_gen (lookup_env Σ).

Definition check_one_cofix d :=
  let '{| dname := na;
         dtype := ty;
         dbody := b;
         rarg := arg |} := d in
  let '(ctx, ty) := decompose_prod_assum [] ty in
  let (hd, args) := decompose_app ty in
  match destInd hd with
  | Some (mkInd ind _, u) => Some ind
  | None => None
  end.

Definition wf_cofixpoint_gen
  (lookup: kername -> option global_decl) mfix :=
  let checks := map check_one_cofix mfix in
  match map_option_out checks with
  | Some (ind :: inds) =>

    forallb (eqb ind) inds &&
    check_recursivity_kind lookup ind CoFinite
  | _ => false
  end.

Definition wf_cofixpoint (Σ : global_env) := wf_cofixpoint_gen (lookup_env Σ).

Reserved Notation "'wf_local' Σ Γ " (at level 9, Σ, Γ at next level).

Reserved Notation " Σ ;;; Γ |- t : T " (at level 50, Γ, t, T at next level).

Variant case_side_conditions `{checker_flags} wf_local_funΣ typingΣ Σ Γ ci p ps mdecl idecl indices predctx :=
| case_side_info
    (eq_npars : mdecl.(ind_npars) = ci.(ci_npar))
    (wf_pred : wf_predicate mdecl idecl p)
    (cons : consistent_instance_ext Σ (ind_universes mdecl) p.(puinst))
    (wf_pctx : wf_local_funΣ (Γ ,,, predctx))

    (conv_pctx : eq_context_upto_names p.(pcontext) (ind_predicate_context ci.(ci_ind) mdecl idecl))
    (allowed_elim : is_allowed_elimination Σ idecl.(ind_kelim) ps)
    (elim_relevance : isSortRel ps ci.(ci_relevance))
    (ind_inst : ctx_inst typingΣ Γ (p.(pparams) ++ indices)
                         (List.rev (subst_instance p.(puinst)
                                                   (ind_params mdecl ,,, ind_indices idecl : context))))
    (not_cofinite : isCoFinite mdecl.(ind_finite) = false).

Variant case_branch_typing `{checker_flags} wf_local_funΣ typingΣ Γ (ci:case_info) p ps mdecl idecl ptm  brs :=
| case_branch_info
    (wf_brs : wf_branches idecl brs)
    (brs_ty :
       All2i (fun i cdecl br =>

                eq_context_upto_names br.(bcontext) (cstr_branch_context ci mdecl cdecl) ×
                let brctxty := case_branch_type ci.(ci_ind) mdecl idecl p br ptm i cdecl in
                (wf_local_funΣ (Γ ,,, brctxty.1) ×
                ((typingΣ (Γ ,,, brctxty.1) br.(bbody) (brctxty.2)) ×
                (typingΣ (Γ ,,, brctxty.1) brctxty.2 (tSort ps)))))
             0 idecl.(ind_ctors) brs).

Variant primitive_typing_hyps `{checker_flags}
  (typingΣ : forall (Γ : context), term -> term -> Type)
  Σ Γ : prim_val term -> Type :=
| prim_int_hyps i : primitive_typing_hyps typingΣ Σ Γ (primInt; primIntModel i)
| prim_float_hyps f : primitive_typing_hyps typingΣ Σ Γ (primFloat; primFloatModel f)
| prim_string_hyps s : primitive_typing_hyps typingΣ Σ Γ (primString; primStringModel s)
| prim_array_hyps a
  (wfl : wf_universe Σ (Universe.make' a.(array_level)))
  (hty : typingΣ Γ a.(array_type) (tSort (sType (Universe.make' a.(array_level)))))
  (hdef : typingΣ Γ a.(array_default) a.(array_type))
  (hvalue : All (fun x => typingΣ Γ x a.(array_type)) a.(array_value)) :
  primitive_typing_hyps typingΣ Σ Γ (primArray; primArrayModel a).

Equations prim_type (p : prim_val term) (cst : kername) : term :=
prim_type (primInt; _) cst := tConst cst [];
prim_type (primFloat; _) cst := tConst cst [];
prim_type (primString; _) cst := tConst cst [];
prim_type (primArray; primArrayModel a) cst := tApp (tConst cst [a.(array_level)]) a.(array_type).

Inductive typing `{checker_flags} (Σ : global_env_ext) (Γ : context) : term -> term -> Type :=
| type_Rel : forall n decl,
    wf_local Σ Γ ->
    nth_error Γ n = Some decl ->
    Σ ;;; Γ |- tRel n : lift0 (S n) decl.(decl_type)

| type_Sort : forall s,
    wf_local Σ Γ ->
    wf_sort Σ s ->
    Σ ;;; Γ |- tSort s : tSort (Sort.super s)

| type_Prod : forall na A B s1 s2,
    lift_typing typing Σ Γ (j_vass_s na A s1) ->
    Σ ;;; Γ ,, vass na A |- B : tSort s2 ->
    Σ ;;; Γ |- tProd na A B : tSort (Sort.sort_of_product s1 s2)

| type_Lambda : forall na A t B,
    lift_typing typing Σ Γ (j_vass na A) ->
    Σ ;;; Γ ,, vass na A |- t : B ->
    Σ ;;; Γ |- tLambda na A t : tProd na A B

| type_LetIn : forall na b B t A,
    lift_typing typing Σ Γ (j_vdef na b B) ->
    Σ ;;; Γ ,, vdef na b B |- t : A ->
    Σ ;;; Γ |- tLetIn na b B t : tLetIn na b B A

| type_App : forall t na A B s u,

    Σ ;;; Γ |- tProd na A B : tSort s ->
    Σ ;;; Γ |- t : tProd na A B ->
    Σ ;;; Γ |- u : A ->
    Σ ;;; Γ |- tApp t u : B{0 := u}

| type_Const : forall cst u decl,
    wf_local Σ Γ ->
    declared_constant Σ cst decl ->
    consistent_instance_ext Σ decl.(cst_universes) u ->
    Σ ;;; Γ |- tConst cst u : decl.(cst_type)@[u]

| type_Ind : forall ind u mdecl idecl,
    wf_local Σ Γ ->
    declared_inductive Σ ind mdecl idecl ->
    consistent_instance_ext Σ mdecl.(ind_universes) u ->
    Σ ;;; Γ |- tInd ind u : idecl.(ind_type)@[u]

| type_Construct : forall ind i u mdecl idecl cdecl,
    wf_local Σ Γ ->
    declared_constructor Σ (ind, i) mdecl idecl cdecl ->
    consistent_instance_ext Σ mdecl.(ind_universes) u ->
    Σ ;;; Γ |- tConstruct ind i u : type_of_constructor mdecl cdecl (ind, i) u

| type_Case : forall ci p c brs indices ps mdecl idecl,
    let predctx := case_predicate_context ci.(ci_ind) mdecl idecl p in
    let ptm := it_mkLambda_or_LetIn predctx p.(preturn) in
    declared_inductive Σ ci.(ci_ind) mdecl idecl ->
    Σ ;;; Γ ,,, predctx |- p.(preturn) : tSort ps ->
    Σ ;;; Γ |- c : mkApps (tInd ci.(ci_ind) p.(puinst)) (p.(pparams) ++ indices) ->
    case_side_conditions (fun Γ => wf_local Σ Γ) (typing Σ) Σ Γ ci p ps
                         mdecl idecl indices predctx  ->
    case_branch_typing (fun Γ => wf_local Σ Γ) (typing Σ) Γ ci p ps
                        mdecl idecl ptm brs ->
    Σ ;;; Γ |- tCase ci p c brs : mkApps ptm (indices ++ [c])

| type_Proj : forall p c u mdecl idecl cdecl pdecl args,
    declared_projection Σ p mdecl idecl cdecl pdecl ->
    Σ ;;; Γ |- c : mkApps (tInd p.(proj_ind) u) args ->
    #|args| = ind_npars mdecl ->
    Σ ;;; Γ |- tProj p c : subst0 (c :: List.rev args) pdecl.(proj_type)@[u]

| type_Fix : forall mfix n decl,
    wf_local Σ Γ ->
    fix_guard Σ Γ mfix ->
    nth_error mfix n = Some decl ->
    All (on_def_type (lift_typing1 (typing Σ)) Γ) mfix ->
    All (on_def_body (lift_typing1 (typing Σ)) (fix_context mfix) Γ) mfix ->
    wf_fixpoint Σ mfix ->
    Σ ;;; Γ |- tFix mfix n : decl.(dtype)

| type_CoFix : forall mfix n decl,
    wf_local Σ Γ ->
    cofix_guard Σ Γ mfix ->
    nth_error mfix n = Some decl ->
    All (on_def_type (lift_typing1 (typing Σ)) Γ) mfix ->
    All (on_def_body (lift_typing1 (typing Σ)) (fix_context mfix) Γ) mfix ->
    wf_cofixpoint Σ mfix ->
    Σ ;;; Γ |- tCoFix mfix n : decl.(dtype)

| type_Prim p prim_ty cdecl :
    wf_local Σ Γ ->
    primitive_constant Σ (prim_val_tag p) = Some prim_ty ->
    declared_constant Σ prim_ty cdecl ->
    primitive_invariants (prim_val_tag p) cdecl ->
    primitive_typing_hyps (typing Σ) Σ Γ p ->
    Σ ;;; Γ |- tPrim p : prim_type p prim_ty

| type_Cumul : forall t A B s,
    Σ ;;; Γ |- t : A ->
    Σ ;;; Γ |- B : tSort s ->
    Σ ;;; Γ |- A <=s B ->
    Σ ;;; Γ |- t : B

where " Σ ;;; Γ |- t : T " := (typing Σ Γ t T)
and "'wf_local' Σ Γ " := (All_local_env (lift_typing1 (typing Σ)) Γ).

Module PCUICTypingDef <: EnvironmentTyping.Typing PCUICTerm PCUICEnvironment PCUICTermUtils PCUICEnvTyping PCUICConversion PCUICConversionParSpec.

  Definition typing := @typing.

End PCUICTypingDef.

Module PCUICDeclarationTyping :=
  EnvironmentTyping.DeclarationTyping
    PCUICTerm
    PCUICEnvironment
    PCUICTermUtils
    PCUICEnvTyping
    PCUICConversion
    PCUICConversionParSpec
    PCUICTypingDef
    PCUICLookup
    PCUICGlobalMaps.
Include PCUICDeclarationTyping.

Definition wf `{checker_flags} := on_global_env cumulSpec0 (lift_typing typing).
Existing Class wf.
Module Export MetaRocq_DOT_PCUIC_DOT_PCUICTyping.
Module Export MetaRocq.
Module Export PCUIC.
Module Export PCUICTyping.
End PCUICTyping.

End PCUIC.

End MetaRocq.

End MetaRocq_DOT_PCUIC_DOT_PCUICTyping.
Import MetaRocq.Common.config.
Import MetaRocq.PCUIC.PCUICAst.

Definition on_udecl_prop (Σ : global_env) (udecl : universes_decl)
  := let levels := levels_of_udecl udecl in
     let global_levels := global_levels Σ.(universes) in
     let all_levels := LevelSet.union levels global_levels in
     ConstraintSet.For_all (declared_cstr_levels all_levels) (constraints_of_udecl udecl).

Section ExtendsWf.
  Context {cf : checker_flags}.
  Context {Pcmp: global_env_ext -> context -> conv_pb -> term -> term -> Type}.
  Context {P: global_env_ext -> context -> judgment -> Type}.

  Let wf := on_global_env Pcmp P.

Lemma weaken_lookup_on_global_env' Σ c decl :
  wf Σ ->
  lookup_env Σ c = Some decl ->
  on_udecl_prop Σ (universes_decl_of_decl decl).
Admitted.

Definition weaken_env_prop_gen
           (R : global_env_ext -> global_env_ext -> Type)
           (P : global_env_ext -> context -> judgment -> Type) :=
  forall Σ Σ' φ, wf Σ -> wf Σ' -> R (Σ, φ) (Σ', φ) -> forall Γ j, P (Σ, φ) Γ j -> P (Σ', φ) Γ j.

Definition weaken_env_prop := weaken_env_prop_gen extends.
Definition weaken_env_decls_prop := weaken_env_prop_gen extends_decls.
Definition weaken_env_strictly_decls_prop := weaken_env_prop_gen strictly_extends_decls.

End ExtendsWf.
Arguments weaken_env_prop {cf} (Pcmp P)%_function_scope _%_function_scope.
Arguments weaken_env_strictly_decls_prop {cf} (Pcmp P)%_function_scope _%_function_scope.

#[warnings="-ambiguous-paths"]
Global Coercion weaken_env_prop_to_decls {cf Pcmp P P0} : @weaken_env_prop cf Pcmp P P0 -> @weaken_env_decls_prop cf Pcmp P P0.
Admitted.
#[warnings="-ambiguous-paths"]
Global Coercion weaken_env_prop_decls_to_strictly_decls {cf Pcmp P P0} : @weaken_env_decls_prop cf Pcmp P P0 -> @weaken_env_strictly_decls_prop cf Pcmp P P0.
Admitted.
Module Export MetaRocq.
Module Export PCUIC.
Module Export PCUICWeakeningEnv.
End PCUICWeakeningEnv.

End PCUIC.

End MetaRocq.
Import MetaRocq.Utils.utils.
Import MetaRocq.Common.config.
Import MetaRocq.PCUIC.PCUICAst.
Import MetaRocq.PCUIC.PCUICTyping.
Import MetaRocq.PCUIC.PCUICWeakeningEnv.

Definition wf_ext_wk {cf : checker_flags} (Σ : global_env_ext)
  := wf Σ.1 × on_udecl_prop Σ.1 Σ.2.

Definition wf_global_ext {cf : checker_flags} Σ ext := wf_ext_wk (Σ, ext).

Import MetaRocq.Utils.utils.
Import MetaRocq.Common.config.
Import MetaRocq.PCUIC.PCUICAst.
Import MetaRocq.PCUIC.PCUICTyping.
Import MetaRocq.PCUIC.PCUICWeakeningEnv.

Lemma declared_inductive_inv `{checker_flags} {Σ P ind mdecl idecl} :
  weaken_env_strictly_decls_prop cumulSpec0 (lift_typing typing) P ->
  wf Σ -> on_global_env cumulSpec0 P Σ ->
  declared_inductive Σ ind mdecl idecl ->
  on_ind_body cumulSpec0 P (Σ, ind_universes mdecl) (inductive_mind ind) mdecl (inductive_ind ind) idecl.
Admitted.

Lemma weaken_env_prop_typing `{checker_flags} : weaken_env_prop cumulSpec0 (lift_typing typing) (lift_typing typing).
Admitted.

Lemma on_declared_constructor `{checker_flags} {Σ ref mdecl idecl cdecl}
  {wfΣ : wf Σ}
  (Hdecl : declared_constructor Σ ref mdecl idecl cdecl) :
  on_inductive cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
               (inductive_mind (fst ref)) mdecl *
  on_ind_body cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
              (inductive_mind (fst ref)) mdecl (inductive_ind (fst ref)) idecl *
  ∑ ind_ctor_sort,
    let onib := declared_inductive_inv weaken_env_prop_typing wfΣ wfΣ (let (x, _) := Hdecl in x) in
     nth_error (ind_cunivs onib) ref.2 = Some ind_ctor_sort
    ×  on_constructor cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
                 mdecl (inductive_ind (fst ref))
                 idecl idecl.(ind_indices) cdecl ind_ctor_sort.
Admitted.

Inductive subslet {cf:checker_flags} Σ (Γ : context) : list term -> context -> Type :=
| emptyslet : subslet Σ Γ [] []
| cons_let_ass Δ s na t T : subslet Σ Γ s Δ ->
              Σ ;;; Γ |- t : subst0 s T ->
             subslet Σ Γ (t :: s) (Δ ,, vass na T)
| cons_let_def Δ s na t T :
    subslet Σ Γ s Δ ->
    Σ ;;; Γ |- subst0 s t : subst0 s T ->
    subslet Σ Γ (subst0 s t :: s) (Δ ,, vdef na t T).
Import MetaRocq.PCUIC.PCUICContextSubst.

Record spine_subst {cf:checker_flags} Σ Γ inst s (Δ : context) := mkSpineSubst {
  spine_dom_wf : wf_local Σ Γ;
  spine_codom_wf : wf_local Σ (Γ ,,, Δ);
  inst_ctx_subst :> context_subst Δ inst s;
  inst_subslet :> subslet Σ Γ s Δ }.

Section OnConstructor.
  Context {cf:checker_flags} {Σ : global_env} {ind mdecl idecl cdecl}
    {wfΣ: wf Σ} (declc : declared_constructor Σ ind mdecl idecl cdecl).

  Lemma on_constructor_subst :
    wf_global_ext Σ (ind_universes mdecl) *
    wf_local (Σ, ind_universes mdecl)
    (arities_context (ind_bodies mdecl) ,,, ind_params mdecl ,,, cstr_args cdecl) *
    ∑ inst,
    spine_subst (Σ, ind_universes mdecl)
              (arities_context (ind_bodies mdecl) ,,, ind_params mdecl ,,,
                cstr_args cdecl)
              ((to_extended_list_k (ind_params mdecl) #|cstr_args cdecl|) ++
                (cstr_indices cdecl)) inst
            (ind_params mdecl ,,, ind_indices idecl).
  Proof using declc wfΣ.
    pose proof (on_declared_constructor declc) as [[onmind oib] [cunivs [hnth onc]]].
    pose proof (onc.(on_cargs)).
simpl in X.
    split.
split.
split.
    2:{
 eapply (weaken_lookup_on_global_env' _ _ (InductiveDecl mdecl)); tea.
        clear hnth.
unshelve eapply declared_constructor_to_gen in declc; eauto.
        exact (inductive_mind ind.1).
🛠️ Intermediate Coq File (useful for debugging if minimization did not go as far as you wanted)
🛠️ 📜 Intermediate Coq File log (useful for debugging if minimization did not go as far as you wanted)
📜 Build Log (contains the Coq error message) (truncated to last 8.0KiB; full 8.0MiB file on GitHub Actions Artifacts under build.log)
cated,default]Warning, feedback message received but no listener to handle it!
Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
Warning: Deprecated environment variable COQCORELIB,
use ROCQRUNTIMELIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 5, characters 0-758:
Warning:
New coercion path [weaken_env_prop_full_to_strictly_on_decls;
                   weaken_env_prop_full_strictly_on_decls_to_strictly_decls] : weaken_env_prop_full >-> weaken_env_strictly_decls_prop_full is ambiguous with existing 
[weaken_env_prop_full_to_decls; weaken_env_prop_full_decls_to_strictly_decls] : weaken_env_prop_full >-> weaken_env_strictly_decls_prop_full.
[ambiguous-paths,coercions,default]
File "./theories/PCUICInductiveInversion.v", line 5, characters 0-758:
Warning:
New coercion path [weaken_env_prop_to_strictly_on_decls;
                   weaken_env_prop_strictly_on_decls_to_strictly_decls] : weaken_env_prop >-> weaken_env_strictly_decls_prop is ambiguous with existing 
[weaken_env_prop_to_decls; weaken_env_prop_decls_to_strictly_decls] : weaken_env_prop >-> weaken_env_strictly_decls_prop.
[ambiguous-paths,coercions,default]
File "./theories/PCUICInductiveInversion.v", line 65, characters 23-30:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 79, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 80, characters 49-56:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 81, characters 56-63:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 82, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 84, characters 18-25:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 85, characters 14-21:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 99, characters 14-21:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 99, characters 26-33:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 105, characters 22-29:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 107, characters 6-13:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 108, characters 12-19:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 127, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 128, characters 43-50:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 129, characters 50-57:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 130, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 132, characters 12-19:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 133, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 147, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 147, characters 20-27:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 153, characters 16-23:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 172, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 174, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 201, characters 22-29:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 225, characters 22-29:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 230, characters 4-11:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 274, characters 15-35:
Error:
In environment
cf : checker_flags
Σ : global_env
ind : inductive × nat
mdecl : mutual_inductive_body
idecl : one_inductive_body
cdecl : constructor_body
wfΣ : wf Σ
declc :
  PCUICLookup.declared_constructor_gen (lookup_env Σ) ind mdecl idecl cdecl
onmind :
  on_inductive cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
    (inductive_mind ind.1) mdecl
oib :
  on_ind_body cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
    (inductive_mind ind.1) mdecl (inductive_ind ind.1) idecl
cunivs : constructor_univs
onc :
  on_constructor cumulSpec0 (lift_typing typing) (
    Σ, ind_universes mdecl) mdecl (inductive_ind ind.1) idecl
    (ind_indices idecl) cdecl cunivs
X :
  sorts_local_ctx (lift_typing typing) (Σ, ind_universes mdecl)
    (arities_context (ind_bodies mdecl),,, ind_params mdecl)
    (cstr_args cdecl) cunivs
The term "inductive_mind ind.1" has type "kername"
while it is expected to have type
 "lookup_env (Σ, ind_universes mdecl).1 ?c = Some (InductiveDecl mdecl)".

Command exited with non-zero status 1
theories/PCUICInductiveInversion.vo (real: 3.01, user: 2.20, sys: 0.19, mem: 847448 ko)
make[3]: *** [Makefile.rocq:815: theories/PCUICInductiveInversion.vo] Error 1
make[3]: *** [theories/PCUICInductiveInversion.vo] Deleting file 'theories/PCUICInductiveInversion.glob'
make[2]: *** [Makefile.rocq:411: all] Error 2
make[2]: Leaving directory '/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic'
make[1]: *** [Makefile:11: coq] Error 2
make[1]: Leaving directory '/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic'
make: *** [Makefile:153: pcuic] Error 2
+ code=2
+ printf '\n%s exit code: %s\n' metarocq 2
+ '[' metarocq '!=' stdlib_test ']'
+ echo 'Aggregating timing log...'
Aggregating timing log...
+ echo

+ tools/make-one-time-file.py --real _build_ci/metarocq.log
    Time |  Peak Mem | File Name                 
-------------------------------------------------
0m03.01s | 847448 ko | Total Time / Peak Mem     
-------------------------------------------------
0m03.01s | 847448 ko | PCUICInductiveInversion.vo
+ '[' '' ']'
+ exit 2
/github/workspace/builds/coq /github/workspace
::endgroup::
📜 🔎 Minimization Log (truncated to last 8.0KiB; full 4.9MiB file on GitHub Actions Artifacts under bug.log)
le "/tmp/tmpf9uru4hu/Top/bug_01.v", line 334, characters 0-34:
Warning: Library File Stdlib.ZArith.ZArith_base is deprecated
since Stdlib 9.0. use ZArith instead
[deprecated-library-file-since-Stdlib-9.0,deprecated-since-Stdlib-9.0,deprecated-library-file,deprecated,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 406, characters 7-20:
Warning: Coq.Init.Ltac has been replaced by Corelib.Init.Ltac.
[deprecated-dirpath-Coq,deprecated-since-9.0,deprecated,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 433, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 439, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 454, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 463, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 470, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 479, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 486, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 510, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 517, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 558, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 564, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 569, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 594, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 607, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 619, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 627, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 632, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 637, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 642, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 647, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 652, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 657, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 663, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 668, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 673, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 678, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 711, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 714, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 717, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 730, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 735, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 763, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 860, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 1353, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 1370, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 1373, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 1404, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 1407, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpf9uru4hu/Top/bug_01.v", line 1422, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
Error: The section OnConstructor needs to be closed.


�[93mIntermediate code not saved.�[0m
Failed to do everything at once; trying one at a time.
Admitting definitions unsuccessful.
No successful changes.

I will now attempt to add Proof using lines
�[92m
Adding Proof using lines successful.�[0m
Failed to do everything at once; trying one at a time.
Adding Proof using lines unsuccessful.
No successful changes.

I will now attempt to export modules
Module exportation successful

I will now attempt to split imports and exports
Import/Export splitting successful

I will now attempt to split := definitions
One-line definition splitting successful

I will now attempt to lift Requires to the top of the file while inserting option settings

I will now attempt to lift Requires to the top of the file while inserting option settings

I will now attempt to remove all lines, one at a time

If you have any comments on your experience of the minimizer, please share them in a reply (possibly tagging @JasonGross).
If you believe there's a bug in the bug minimizer, please report it on the bug minimizer issue tracker.

@coqbot-app

coqbot-app Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor
Minimization interrupted by timeout, being automatically continued. Partially Minimized File /home/runner/work/run-coq-bug-minimizer/run-coq-bug-minimizer/builds/coq/coq-failing/_build_ci/fiat_crypto/src/Bedrock/Field/Synthesis/Examples/redc.v in 5h 15m 6s (from ci-fiat_crypto) (interrupted by timeout, being automatically continued) (full log on GitHub Actions - verbose log)
⭐ ⏱️ Partially Minimized Coq File (timeout) (truncated to first and last 32KiB; full 69KiB file on GitHub Actions Artifacts under bug.v)
(* -*- mode: coq; coq-prog-args: ("-emacs" "-q" "-w" "+implicit-core-hint-db,+implicits-in-term,+non-reversible-notation,+deprecated-intros-until-0,+deprecated-focus,+unused-intro-pattern,+variable-collision,+unexpected-implicit-declaration,+omega-is-deprecated,+deprecated-instantiate-syntax,+non-recursive,+undeclared-scope,+deprecated-hint-rewrite-without-locality,+deprecated-hint-without-locality,+deprecated-instance-without-locality,+deprecated-typeclasses-transparency-without-locality,+fragile-hint-constr,-deprecated-since-9.0,-deprecated-since-8.20,-deprecated-from-Coq" "-w" "-notation-overridden,-native-compiler-disabled,-ambiguous-paths,-masking-absolute-name" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Coqprime" "Coqprime" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Kami" "Kami" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rewriter" "Rewriter" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rupicola" "Rupicola" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Top.bug_01") -*- *)
(* File reduced by coq-bug-minimizer from original input, then from 577 lines to 117 lines, then from 131 lines to 869 lines, then from 877 lines to 453 lines, then from 468 lines to 1367 lines, then from 1372 lines to 533 lines, then from 548 lines to 1295 lines, then from 1303 lines to 616 lines, then from 631 lines to 1279 lines, then from 1286 lines to 653 lines, then from 668 lines to 953 lines, then from 961 lines to 662 lines, then from 677 lines to 1947 lines, then from 1949 lines to 996 lines, then from 1011 lines to 1284 lines, then from 1292 lines to 1026 lines, then from 1041 lines to 1079 lines, then from 1087 lines to 1042 lines, then from 1057 lines to 1205 lines, then from 1211 lines to 1085 lines, then from 1100 lines to 1221 lines, then from 1229 lines to 1123 lines, then from 1138 lines to 1177 lines, then from 1185 lines to 1151 lines, then from 1166 lines to 1480 lines, then from 1488 lines to 1182 lines, then from 1197 lines to 1464 lines, then from 1472 lines to 1195 lines, then from 1216 lines to 1089 lines, then from 1103 lines to 1492 lines, then from 1500 lines to 1101 lines, then from 1116 lines to 1306 lines, then from 1314 lines to 1114 lines, then from 1129 lines to 1859 lines, then from 1867 lines to 1133 lines, then from 1148 lines to 1714 lines, then from 1722 lines to 1326 lines, then from 1341 lines to 1990 lines, then from 1998 lines to 1486 lines, then from 1501 lines to 1869 lines, then from 1877 lines to 1526 lines, then from 1541 lines to 1966 lines, then from 1974 lines to 1564 lines, then from 1579 lines to 2023 lines, then from 2031 lines to 1594 lines, then from 1609 lines to 1995 lines, then from 2003 lines to 1621 lines, then from 1636 lines to 1925 lines, then from 1933 lines to 1639 lines, then from 1654 lines to 2735 lines, then from 2740 lines to 1705 lines, then from 1720 lines to 2134 lines, then from 2142 lines to 1716 lines, then from 1731 lines to 2049 lines, then from 2057 lines to 1876 lines *)
(* coqc version 9.3+alpha compiled with OCaml 4.14.2
   coqtop version 9.3+alpha
   Modules that could not be inlined: Crypto.Arithmetic.WordByWordMontgomery
   Expected coqc runtime on this file: 1.417 sec
   Expected coqc peak memory usage on this file: 1316348.0 kb *)










Require Coq.Init.Ltac.
Module Export AdmitTactic.
Module Import LocalFalse.
Inductive False : Prop := .
End LocalFalse.
Axiom proof_admitted : False.
Import Coq.Init.Ltac.
Tactic Notation "admit" := abstract case proof_admitted.
End AdmitTactic.

Require bedrock2.Markers.
Require coqutil.Tactics.eabstract.
Require coqutil.Tactics.letexists.
Require coqutil.Tactics.ident_of_string.
Require coqutil.Tactics.reference_to_string.
Require bedrock2.NotationsCustomEntry.
Require coqutil.dlet.
Require coqutil.Word.Bitwidth.
Require coqutil.Map.SortedListString.
Require Corelib.BinNums.IntDef.
Require Corelib.BinNums.NatDef.
Require Corelib.BinNums.PosDef.
Require Corelib.Classes.Morphisms.
Require Corelib.Classes.Morphisms_Prop.
Require Corelib.Classes.RelationClasses.
Require Corelib.Init.Byte.
Require Corelib.Init.Sumbool.
Require Corelib.Lists.ListDef.
Require Corelib.Numbers.BinNums.
Require Corelib.Program.Basics.
Require Corelib.Relations.Relation_Definitions.
Require Corelib.Setoids.Setoid.
Require Stdlib.Classes.DecidableClass.
Require Stdlib.Logic.Decidable.
Require Stdlib.Logic.EqdepFacts.
Require Stdlib.Logic.HLevelsBase.
Require Stdlib.micromega.ZifyClasses.
Require Stdlib.setoid_ring.Algebra_syntax.
Require Stdlib.BinNums.IntDef.
Require Stdlib.BinNums.NatDef.
Require Stdlib.BinNums.PosDef.
Require Stdlib.Classes.Morphisms.
Require Stdlib.Classes.Morphisms_Prop.
Require Stdlib.Classes.RelationClasses.
Require Stdlib.Init.Byte.
Require Stdlib.Init.Sumbool.
Require Stdlib.Lists.ListDef.
Require Stdlib.Logic.Eqdep_dec.
Require Stdlib.Numbers.BinNums.
Require Stdlib.Program.Basics.
Require Stdlib.Relations.Relation_Definitions.
Require Stdlib.Setoids.Setoid.
Require Stdlib.Bool.Bool.
Require Stdlib.Relations.Relation_Operators.
Require Stdlib.Relations.Operators_Properties.
Require Stdlib.PArith.BinPosDef.
Require Stdlib.Relations.Relations.
Require Stdlib.Numbers.NumPrelude.
Require Stdlib.Structures.Equalities.
Require Stdlib.Structures.Orders.
Require Stdlib.Structures.OrdersTac.
Require Stdlib.Structures.OrdersFacts.
Require Stdlib.Structures.GenericMinMax.
Require Stdlib.Numbers.NatInt.NZAxioms.
Require Stdlib.Numbers.NatInt.NZBase.
Require Stdlib.Numbers.NatInt.NZAdd.
Require Stdlib.Numbers.NatInt.NZMul.
Require Stdlib.Numbers.NatInt.NZOrder.
Require Stdlib.Numbers.NatInt.NZAddOrder.
Require Stdlib.Numbers.NatInt.NZMulOrder.
Require Stdlib.Numbers.NatInt.NZDiv.
Require Stdlib.Numbers.NatInt.NZGcd.
Require Stdlib.Numbers.NatInt.NZParity.
Require Stdlib.Numbers.NatInt.NZPow.
Require Stdlib.Numbers.NatInt.NZSqrt.
Require Stdlib.Numbers.NatInt.NZLog.
Require Stdlib.Numbers.NatInt.NZBits.
Require Stdlib.Numbers.Integer.Abstract.ZAxioms.
Require Stdlib.Numbers.Natural.Abstract.NAxioms.
Require Stdlib.Numbers.Integer.Abstract.ZBase.
Require Stdlib.Numbers.Natural.Abstract.NBase.
Require Stdlib.Numbers.Integer.Abstract.ZAdd.
Require Stdlib.Numbers.Natural.Abstract.NAdd.
Require Stdlib.Numbers.Integer.Abstract.ZMul.
Require Stdlib.Numbers.Natural.Abstract.NOrder.
Require Stdlib.Numbers.Integer.Abstract.ZLt.
Require Stdlib.Numbers.Natural.Abstract.NAddOrder.
Require Stdlib.Numbers.Integer.Abstract.ZAddOrder.
Require Stdlib.Numbers.Natural.Abstract.NMulOrder.
Require Stdlib.Numbers.Integer.Abstract.ZMulOrder.
Require Stdlib.Numbers.Natural.Abstract.NSub.
Require Stdlib.Numbers.Integer.Abstract.ZMaxMin.
Require Stdlib.Numbers.Integer.Abstract.ZParity.
Require Stdlib.Numbers.Integer.Abstract.ZSgnAbs.
Require Stdlib.Numbers.Natural.Abstract.NDiv.
Require Stdlib.Numbers.Natural.Abstract.NGcd.
Require Stdlib.Numbers.Natural.Abstract.NMaxMin.
Require Stdlib.Numbers.Natural.Abstract.NParity.
Require Stdlib.Numbers.Natural.Abstract.NSqrt.
Require Stdlib.Numbers.Integer.Abstract.ZDivFloor.
Require Stdlib.Numbers.Integer.Abstract.ZDivTrunc.
Require Stdlib.Numbers.Integer.Abstract.ZGcd.
Require Stdlib.Numbers.Natural.Abstract.NDiv0.
Require Stdlib.Numbers.Natural.Abstract.NPow.
Require Stdlib.Numbers.Integer.Abstract.ZPow.
Require Stdlib.Numbers.Natural.Abstract.NLcm.
Require Stdlib.Numbers.Natural.Abstract.NLog.
Require Stdlib.Numbers.Integer.Abstract.ZBits.
Require Stdlib.Numbers.Integer.Abstract.ZLcm.
Require Stdlib.Numbers.Natural.Abstract.NBits.
Require Stdlib.Numbers.Natural.Abstract.NLcm0.
Require Stdlib.Numbers.Integer.Abstract.ZProperties.
Require Stdlib.Numbers.Natural.Abstract.NProperties.
Require Stdlib.Arith.PeanoNat.
Require Stdlib.Arith.Between.
Require Stdlib.Arith.Compare_dec.
Require Stdlib.Arith.EqNat.
Require Stdlib.Arith.Factorial.
Require Stdlib.Arith.Wf_nat.
Require Stdlib.Arith.Peano_dec.
Require Stdlib.Lists.List.
Require Stdlib.micromega.Refl.
Require Stdlib.micromega.Tauto.
Require Stdlib.Lists.ListTactics.
Require Stdlib.PArith.BinPos.
Require Stdlib.Arith.Arith_base.
Require Stdlib.PArith.POrderedType.
Require Stdlib.PArith.Pnat.
Require Stdlib.NArith.BinNatDef.
Require Stdlib.PArith.PArith.
Require Stdlib.NArith.BinNat.
Require Stdlib.setoid_ring.BinList.
Require Stdlib.setoid_ring.Ring_theory.
Require Stdlib.NArith.Nnat.
Require Stdlib.ZArith.BinIntDef.
Import Coq.ZArith.ZArith.

Local Open Scope Z_scope.

Notation byte := (Coq.Init.Byte.byte: Type).


Module Export byte.
Definition unsigned(b: byte): Z. exact (Z.of_N (Byte.to_N b)). Defined.
Definition wrap(z: Z): Z. exact (z mod 2 ^ 8). Defined.

  Lemma Byte_of_N_of_mod_not_None: forall z, Byte.of_N (Z.to_N (wrap z)) <> None.
Admitted.
Definition of_Z(z: Z): byte. exact (let r := Byte.of_N (Z.to_N (wrap z)) in
    match r as o return (r = o -> byte) with
    | Some b => fun _ => b
    | None => fun E => False_rect byte (Byte_of_N_of_mod_not_None z E)
    end eq_refl). Defined.
Module Export coqutil_DOT_Byte.
Module Export coqutil.
Module Export Byte.
End Byte.

End coqutil.

End coqutil_DOT_Byte.
Module Export LittleEndianList.
Import Coq.ZArith.ZArith.
Import coqutil.Byte.
Fixpoint le_combine(l: list byte): Z.
Admitted.
Fixpoint le_split (n : nat) (w : Z) : list byte.
Admitted.
Module Export coqutil.
Module Export Word.
Module Export LittleEndianList.
End LittleEndianList.
Module Export Properties.
Import Stdlib.ZArith.ZArith.
Import Coq.ZArith.Znumtheory.
Import coqutil.Word.Interface.
Import word.

Module Export word.
  Section WithWord.
    Context {width} {word : word width} {word_ok : word.ok word}.
    Local Hint Mode word.word - : typeclass_instances.

    Lemma unsigned_of_Z_0 : word.unsigned (word.of_Z 0) = 0.
Admitted.

    Lemma ring_theory : Ring_theory.ring_theory (of_Z 0) (of_Z 1) add mul sub opp Logic.eq.
Admitted.
    Lemma ring_morph_add : forall x y : Z, of_Z (x + y) = add (of_Z x) (of_Z y).
Admitted.
    Lemma ring_morph_sub : forall x y : Z, of_Z (x - y) = sub (of_Z x) (of_Z y).
Admitted.
    Lemma ring_morph_mul : forall x y : Z, of_Z (x * y) = mul (of_Z x) (of_Z y).
Admitted.
    Lemma ring_morph_opp : forall x : Z, of_Z (- x) = opp (of_Z x).
Admitted.
    Lemma ring_morph :
      Ring_theory.ring_morph (of_Z 0) (of_Z 1) add   mul   sub   opp   Logic.eq
                             0        1        Z.add Z.mul Z.sub Z.opp Zbool.Zeq_bool of_Z.
Admitted.

  End WithWord.

  Section WordConvenienceKitchenSink.
  End WordConvenienceKitchenSink.
End word.

Ltac word_cst w :=
  match w with
  | word.of_Z ?x => let b := isZcst x in
                    match b with
                    | true => x
                    | _ => constr:(NotConstant)
                    end
  | _ => constr:(NotConstant)
  end.

#[global] Hint Rewrite
  @word.ring_morph_add
  @word.ring_morph_sub
  @word.ring_morph_mul
  @word.ring_morph_opp
  using typeclasses eauto
  : rew_word_morphism.

Section RingDemoAndTest.

End RingDemoAndTest.
Module Export coqutil_DOT_Word_DOT_Properties.
Module Export coqutil.
Module Export Word.
Module Export Properties.
End Properties.

End Word.

End coqutil.

End coqutil_DOT_Word_DOT_Properties.
Module Export MapKeys.
Import coqutil.Map.Interface.
Import Interface.map.

Module Export map.
  Section MapKeys.
    Context {key value} {map : map key value} {ok : map.ok map}.
    Context {key'} {map' : Interface.map.map key' value} {ok' : map.ok map'}.

    Definition map_keys f (m:map) : map' := fold (fun m k v => put m (f k) v) empty m.
  End MapKeys.
End map.

End MapKeys.
Module Export coqutil_DOT_Map_DOT_MapKeys.
Module Export MapKeys.
End MapKeys.

End coqutil_DOT_Map_DOT_MapKeys.
Module Export OfFunc.
Import coqutil.Map.Interface.
Import Interface.map.

Module Export map.
  Section OfFunc.
    Context {key value} {map : map key value} {ok : map.ok map}.

    Context (f : key -> option value).
Fixpoint of_func (support : list key) : map.
exact (match support with
      | nil => empty
      | cons k support => update (of_func support) k (f k)
      end).
Defined.
  End OfFunc.
End map.

End OfFunc.
Module Export coqutil.
Module Export Map.
Module Export OfFunc.
End OfFunc.

End Map.

End coqutil.
Import Stdlib.ZArith.ZArith.
Import Coq.Lists.List.
Import coqutil.Map.Interface.
Import coqutil.Map.OfFunc.
Import Interface.map.
Import MapKeys.map.
Import coqutil.Word.Interface.

Module Export map.
  Section __.
    Context {width} {word : word width} {word_ok : word.ok word}.
    Context {value : Type} {map : map word value} {ok : map.ok map}.
Definition of_list_word (xs : list value) : map.
exact (map.of_func
      (fun w => nth_error xs (Z.to_nat (word.unsigned w)))
      (List.map (fun n => word.of_Z (Z.of_nat n)) (seq 0 (length xs)))).
Defined.
Definition of_list_word_at (a : word) (xs : list value) : map.
exact (map_keys (word.add a) (of_list_word xs)).
Defined.
  End __.
Module Export coqutil.
Module Export Map.
Module Export OfListWord.
End OfListWord.

End Map.

End coqutil.
Module Export Memory.
Import Stdlib.ZArith.ZArith.
Import coqutil.Map.Interface.
Import coqutil.Word.Interface.
Import coqutil.Byte.
Import coqutil.Map.OfListWord.

Notation "xs $@ a" := (map.of_list_word_at a xs) (at level 10, format "xs $@ a").

Open Scope Z_scope.
Definition bytes_per_word(width: Z): Z.
Admitted.

Section Memory.
  Context {width: Z} {word: word width} {mem: map.map word byte}.
Definition load_bytes (m : mem) (a : word) (n : nat) : option (list byte).
Admitted.
Definition store_bytes (m : mem) (a : word) (bs : list byte) : option mem.
Admitted.

  Definition load_Z (m : mem) (a : word) n: option Z :=
    match load_bytes m a n with
    | Some bs => Some (LittleEndianList.le_combine bs)
    | None => None
    end.

  Definition store_Z (m : mem) (a : word) n (v : Z) : option mem :=
    store_bytes m a (LittleEndianList.le_split n v).
End Memory.
Module Export coqutil.
Module Export Map.
Module Export Memory.
End Memory.

End Map.

End coqutil.

Module Export bedrock2_DOT_Memory_WRAPPED.
Module Export Memory.
Export coqutil.Map.OfListWord.
Export coqutil.Map.Memory.
Import Stdlib.ZArith.ZArith.
Import coqutil.Map.Interface.
Import coqutil.Word.Interface.
Import bedrock2.Syntax.
Import coqutil.Byte.

Definition bytes_per {width} sz :=
  match sz with
    | access_size.one => 1 | access_size.two => 2 | access_size.four => 4
    | access_size.word => Z.to_nat (bytes_per_word width)
  end%nat.

Definition load {width} {word : word width} {mem : map.map word byte}
  sz (m : mem) (a: word): option word :=
  match load_Z m a (bytes_per (width:=width) sz) with
  | Some z => Some (word.of_Z z)
  | None => None
  end.

Definition store {width} {word : word width} {mem : map.map word byte}
  sz (m : mem) (a v : word) : option mem :=
  store_Z m a (bytes_per (width:=width) sz) (word.unsigned v).

Definition anybytes {width} {word : word width} {mem : map.map word byte}
  (a : word) (n : Z) (m : mem) :=
  exists bs: list byte, map.of_list_word_at a bs = m /\
  Z.of_nat (length bs) = n /\ Z.of_nat (length bs) <= 2 ^ width.

Section Deprecated.
End Deprecated.

End Memory.
Module Export bedrock2.
Module Export Memory.
Include bedrock2_DOT_Memory_WRAPPED.Memory.
End Memory.
Module Export Semantics.
Import coqutil.Byte.
Import bedrock2.Syntax.
Import coqutil.Map.Interface.
Import Stdlib.ZArith.BinIntDef.
Import coqutil.Word.Bitwidth.
Import Coq.Lists.List.

Definition LogItem{width: Z}{BW: Bitwidth width}{word: word.word width}{mem: map.map word byte} :=
  ((mem * String.string * list word) * (mem * list word))%type.

Definition trace{width: Z}{BW: Bitwidth width}{word: word.word width}{mem: map.map word byte} :=
  list LogItem.

Definition ExtSpec{width: Z}{BW: Bitwidth width}{word: word.word width}{mem: map.map word byte} :=

  trace -> mem -> String.string -> list word ->

  (mem -> list word -> Prop) ->

  Prop.

Existing Class ExtSpec.

Module Export ext_spec.
End ext_spec.

Section operators.
  Context {width : Z} {word : Word.Interface.word width}.
Definition interp_op1 (op : op1) : word -> word.
Admitted.
Definition interp_binop (bop : bopname) : word -> word -> word.
Admitted.
End operators.
Definition env: map.map String.string Syntax.func.
Admitted.

Section semantics.
  Context {width: Z} {BW: Bitwidth width} {word: word.word width} {mem: map.map word byte}.
  Context {locals: map.map String.string word}.
    Context (m : mem) (l : locals).

    Local Notation "x <- a ; f" := (match a with Some x => f | None => None end)
      (right associativity, at level 70).
Fixpoint eval_expr (e : expr) : option word.
Admitted.

    Fixpoint eval_call_args (arges : list expr) :=
      match arges with
      | e :: tl =>
        v <- eval_expr e;
        args <- eval_call_args tl;
        Some (v :: args)
      | _ => Some nil
      end.
End semantics.

Module exec.
Section WithParams.
  Context {width: Z} {BW: Bitwidth width} {word: word.word width} {mem: map.map word byte}.
  Context {locals: map.map String.string word}.
  Context {ext_spec: ExtSpec}.
  Context (e: env).

  Inductive exec: cmd -> trace -> mem -> locals ->
                  (trace -> mem -> locals -> Prop) -> Prop :=
  | skip: forall t m l post,
      post t m l ->
      exec cmd.skip t m l post
  | set: forall x e t m l post v,
      eval_expr m l e = Some v ->
      post t m (map.put l x v) ->
      exec (cmd.set x e) t m l post
  | unset: forall x t m l post,
      post t m (map.remove l x) ->
      exec (cmd.unset x) t m l post
  | store: forall sz ea ev t m l post a v m',
      eval_expr m l ea = Some a ->
      eval_expr m l ev = Some v ->
      store sz m a v = Some m' ->
      post t m' l ->
      exec (cmd.store sz ea ev) t m l post
  | stackalloc: forall x n body t mSmall l post,
      Z.modulo n (bytes_per_word width) = 0 ->
      (forall a mStack mCombined,
        anybytes a n mStack ->
        map.split mCombined mSmall mStack ->
        exec body t mCombined (map.put l x a)
          (fun t' mCombined' l' =>
            exists mSmall' mStack',
              anybytes a n mStack' /\
              map.split mCombined' mSmall' mStack' /\
              post t' mSmall' l')) ->
      exec (cmd.stackalloc x n body) t mSmall l post
  | if_true: forall t m l e c1 c2 post v,
      eval_expr m l e = Some v ->
      word.unsigned v <> 0 ->
      exec c1 t m l post ->
      exec (cmd.cond e c1 c2) t m l post
  | if_false: forall e c1 c2 t m l post v,
      eval_expr m l e = Some v ->
      word.unsigned v = 0 ->
      exec c2 t m l post ->
      exec (cmd.cond e c1 c2) t m l post
  | seq: forall c1 c2 t m l post mid,
      exec c1 t m l mid ->
      (forall t' m' l', mid t' m' l' -> exec c2 t' m' l' post) ->
      exec (cmd.seq c1 c2) t m l post
  | while_false: forall e c t m l post v,
      eval_expr m l e = Some v ->
      word.unsigned v = 0 ->
      post t m l ->
      exec (cmd.while e c) t m l post
  | while_true: forall e c t m l post v mid,
      eval_expr m l e = Some v ->
      word.unsigned v <> 0 ->
      exec c t m l mid ->
      (forall t' m' l', mid t' m' l' -> exec (cmd.while e c) t' m' l' post) ->
      exec (cmd.while e c) t m l post
  | call: forall binds fname arges t m l post params rets fbody args lf mid,
      map.get e fname = Some (params, rets, fbody) ->
      eval_call_args m l arges = Some args ->
      map.of_list_zip params args = Some lf ->
      exec fbody t m lf mid ->
      (forall t' m' st1, mid t' m' st1 ->
          exists retvs, map.getmany_of_list st1 rets = Some retvs /\
          exists l', map.putmany_of_list_zip binds retvs l = Some l' /\
          post t' m' l') ->
      exec (cmd.call binds fname arges) t m l post
  | interact: forall binds action arges args t m l post mKeep mGive mid,
      map.split m mKeep mGive ->
      eval_call_args m l arges = Some args ->
      ext_spec t mGive action args mid ->
      (forall mReceive resvals, mid mReceive resvals ->
          exists l', map.putmany_of_list_zip binds resvals l = Some l' /\
          forall m', map.split m' mKeep mReceive ->
          post (cons ((mGive, action, args), (mReceive, resvals)) t) m' l') ->
      exec (cmd.interact binds action arges) t m l post.

  End WithParams.
End exec.
Notation exec := exec.exec.

Section WithParams.
  Context {width: Z} {BW: Bitwidth width} {word: word.word width} {mem: map.map word byte}.
  Context {locals: map.map String.string word}.
  Context {ext_spec: ExtSpec}.

  Definition call e fname t m args post :=
    exists argnames retnames body,
      map.get e fname = Some (argnames, retnames, body) /\
      exists l, map.of_list_zip argnames args = Some l /\
        exec e body t m l (fun t' m' l' => exists rets,
          map.getmany_of_list l' retnames = Some rets /\ post t' m' rets).
End WithParams.
Module Export bedrock2.
Module Export Semantics.
End Semantics.

Module Export bedrock2_DOT_WeakestPrecondition_WRAPPED.
Module Export WeakestPrecondition.
Import coqutil.Map.Interface.
Import Coq.ZArith.BinIntDef.
Import coqutil.Word.Bitwidth.
Import coqutil.dlet.
Import bedrock2.Syntax.

Section WeakestPrecondition.
  Context {width: Z} {BW: Bitwidth width} {word: word.word width} {mem: map.map word Byte.byte}.
  Context {locals: map.map String.string word}.
  Context {ext_spec: ExtSpec}.
  Implicit Types (t : trace) (m : mem) (l : locals).

  Definition literal v (post : word -> Prop) : Prop :=
    dlet! v := word.of_Z v in post v.
Definition get (l : locals) (x : String.string) (post : word -> Prop) : Prop.
exact (exists v, map.get l x = Some v /\ post v).
Defined.
  Definition load s m a (post : _ -> Prop) : Prop :=
    exists v, load s m a = Some v /\ post v.
  Definition store sz m a v post :=
    exists m', store sz m a v = Some m' /\ post m'.

  Section WithMemAndLocals.
    Context (m : mem) (l : locals).
    Definition expr_body rec (e : Syntax.expr) (post : word -> Prop) : Prop :=
      match e with
      | expr.literal v =>
        literal v post
      | expr.var x =>
        get l x post
      | expr.op1 op e =>
        rec e (fun v =>
        post (interp_op1 op v))
      | expr.op op e1 e2 =>
        rec e1 (fun v1 =>
        rec e2 (fun v2 =>
        post (interp_binop op v1 v2)))
      | expr.load s e =>
        rec e (fun a =>
        load s m a post)
      | expr.inlinetable s t e =>
        rec e (fun a =>
        load s (map.of_list_word t) a post)
      | expr.ite c e1 e2 =>
        rec c (fun b => rec (if word.eqb b (word.of_Z 0) then e2 else e1) post)
    end.
    Fixpoint expr e := expr_body expr e.
  End WithMemAndLocals.

  Section WithF.
    Context {A B} (f: A -> (B -> Prop) -> Prop).
    Definition list_map_body rec (xs : list A) (post : list B -> Prop) : Prop :=
      match xs with
      | nil => post nil
      | cons x xs' =>
        f x (fun y =>
        rec xs' (fun ys' =>
        post (cons y ys')))
      end.
    Fixpoint list_map xs := list_map_body list_map xs.
  End WithF.

  Section WithFunctions.
    Context (e: env).
    Definition dexpr m l e v := expr m l e (eq v).
    Definition dexprs m l es vs := list_map (expr m l) es (eq vs).

    Definition cmd_body (rec:_->_->_->_->_->Prop) (c : cmd) (t : trace) (m : mem) (l : locals)
             (post : trace -> mem -> locals -> Prop) : Prop :=

      match c with
      | cmd.skip => post t m l
      | cmd.set x ev =>
        exists v, dexpr m l ev v /\
        dlet! l := map.put l x v in
        post t m l
      | cmd.unset x =>
        dlet! l := map.remove l x in
        post t m l
      | cmd.store sz ea ev =>
        exists a, dexpr m l ea a /\
        exists v, dexpr m l ev v /\
        store sz m a v (fun m =>
        post t m l)
      | cmd.stackalloc x n c =>
        Z.modulo n (bytes_per_word width) = 0 /\
        forall a mStack mCombined,
          anybytes a n mStack -> map.split mCombined m mStack ->
          dlet! l := map.put l x a in
          rec c t mCombined l (fun t' mCombined' l' =>
          exists m' mStack',
          anybytes a n mStack' /\ map.split mCombined' m' mStack' /\
          post t' m' l')
      | cmd.cond br ct cf =>
        exists v, dexpr m l br v /\
        (word.unsigned v <> 0%Z -> rec ct t m l post) /\
        (word.unsigned v = 0%Z -> rec cf t m l post)
      | cmd.seq c1 c2 =>
        rec c1 t m l (fun t m l => rec c2 t m l post)
      | cmd.while _ _ => Semantics.exec e c t m l post
      | cmd.call binds fname arges =>
        exists args, dexprs m l arges args /\
        Semantics.call e fname t m args (fun t m rets =>
          exists l', map.putmany_of_list_zip binds rets l = Some l' /\
          post t m l')
      | cmd.interact binds action arges =>
        exists args, dexprs m l arges args /\
        exists mKeep mGive, map.split m mKeep mGive /\
        ext_spec t mGive action args (fun mReceive rets =>
          exists l', map.putmany_of_list_zip binds rets l = Some l' /\
          forall m', map.split m' mKeep mReceive ->
          post (cons ((mGive, action, args), (mReceive, rets)) t) m' l')
      end.
    Fixpoint cmd c := cmd_body cmd c.
  End WithFunctions.

  Definition func call '(innames, outnames, c) (t : trace) (m : mem) (args : list word) (post : trace -> mem -> list word -> Prop) :=
      exists l, map.of_list_zip innames args = Some l /\
      cmd call c t m l (fun t m l =>
        list_map (get l) outnames (fun rets =>
        post t m rets)).
End WeakestPrecondition.
Notation call := Semantics.call (only parsing).

Ltac unfold1_cmd e :=
  lazymatch e with
    @cmd ?width ?BW ?word ?mem ?locals ?ext_spec ?CA ?c ?t ?m ?l ?post =>
    let c := eval hnf in c in
    constr:(@cmd_body width BW word mem locals ext_spec CA
                      (@cmd width BW word mem locals ext_spec CA) c t m l post)
  end.
Ltac unfold1_cmd_goal :=
  let G := lazymatch goal with |- ?G => G end in
  let G := unfold1_cmd G in
  change G.

Ltac unfold1_expr e :=
  lazymatch e with
    @expr ?width ?word ?mem ?locals ?m ?l ?arg ?post =>
    let arg := eval hnf in arg in
    constr:(@expr_body width word mem locals m l (@expr width word mem locals m l) arg post)
  end.
Ltac unfold1_expr_goal :=
  let G := lazymatch goal with |- ?G => G end in
  let G := unfold1_expr G in
  change G.

Ltac unfold1_list_map e :=
  lazymatch e with
    @list_map ?A ?B ?P ?arg ?post =>
    let arg := eval hnf in arg in
    constr:(@list_map_body A B P (@list_map A B P) arg post)
  end.
Ltac unfold1_list_map_goal :=
  let G := lazymatch goal with |- ?G => G end in
  let G := unfold1_list_map G in
  change G.

Notation "'fnspec!' name a0 .. an '/' g0 .. gn ',' '{' 'requires' tr mem := pre ';' 'ensures' tr' mem' ':=' post '}'" :=
  (fun functions =>
     (forall a0,
        .. (forall an,
              (forall g0,
                  .. (forall gn,
                         (forall tr mem,
                             pre ->
                             WeakestPrecondition.call
                               functions name tr mem (cons a0 .. (cons an nil) ..)
                               (fun tr' mem' rets =>
                                  rets = nil /\ post))) ..)) ..))
    (at level 200,
     name at level 0,
     a0 binder, an binder,
     g0 binder, gn binder,
     tr name, tr' name, mem name, mem' name,
     pre at level 200,
     post at level 200).

End WeakestPrecondition.
Module Export bedrock2_DOT_WeakestPrecondition.
Module Export bedrock2.
Module Export WeakestPrecondition.
Include bedrock2_DOT_WeakestPrecondition_WRAPPED.WeakestPrecondition.
End WeakestPrecondition.

End bedrock2.

End bedrock2_DOT_WeakestPrecondition.
Import coqutil.Map.Interface.
Import coqutil.Word.Bitwidth.

Section WeakestPrecondition.
  Context {width} {BW: Bitwidth width} {word: word.word width} {mem: map.map word Byte.byte}.
  Context {locals: map.map String.string word}.
  Context {ext_spec: Semantics.ExtSpec}.

  Lemma start_func: forall e fname fimpl t m args post,
      map.get e fname = Some fimpl ->
      WeakestPrecondition.func e fimpl t m args post ->
      WeakestPrecondition.call e fname t m args post.
Admitted.
End WeakestPrecondition.
Module Export bedrock2.
Module Export WeakestPreconditionProperties.
End WeakestPreconditionProperties.

End bedrock2.
Import Coq.ZArith.ZArith.
Export coqutil.Word.Bitwidth.

#[export] Instance BW64: Bitwidth 64 := {
  width_cases := or_intror eq_refl
}.
Module Export coqutil.
Module Export Word.
Module Export Bitwidth64.
End Bitwidth64.

End Word.

End coqutil.
Module Export Naive.
Import Coq.ZArith.BinInt.
Import coqutil.Word.Interface.

Section WithWidth.
End WithWidth.
Definition word width: word.word width.
Admitted.
Notation word64 := (word 64%Z).
#[global] Instance word64_ok : word.ok word64.
Admitted.
End Naive.
Module Export SortedListWord.
Import coqutil.Word.Interface.
Import coqutil.Map.Interface.

Section __.
  Context {width} (word : word width) {word_ok : @word.ok width word}.

  Context (value : Type).
Definition map : map.map word value.
Admitted.
Global Instance ok : map.ok map.
Admitted.
End __.
Import Coq.ZArith.ZArith.
Import bedrock2.Semantics.
Export coqutil.Word.Bitwidth64.
#[export] Instance word: word.word 64.
exact (Naive.word64).
Defined.
#[export] Instance mem: Interface.map.map word Byte.byte.
exact (SortedListWord.map _ _).
Defined.
#[export] Instance locals: Interface.map.map String.string word.
exact (SortedListString.map _).
Defined.
#[export] Instance ext_spec: ExtSpec.
Admitted.
Add Ring wring : (Properties.word.ring_theory (word := word))
      (preprocess [autorewrite with rew_word_morphism],
       morphism (Properties.word.ring_morph (word := word)),
       constants [Properties.word_cst]).
Module Export bedrock2.
Module Export BasicC64Semantics.
End BasicC64Semantics.
Ltac rdelta x :=
  match constr:(Set) with
  | _ => progress_rdelta x
  | _ => x
  end
with progress_rdelta x :=
  let x := eval cbv delta [x] in x in
  rdelta x.

Ltac rdelta_var x :=
  match constr:(Set) with
  | _ => progress_rdelta_var x
  | _ => x
  end
with progress_rdelta_var x :=
  let __ := match constr:(Set) with _ => is_var x end in
  let x := eval cbv delta [x] in x in
  rdelta_var x.

Ltac _syntactic_unify_deltavar x y :=
  match constr:(Set) with
  | _ => is_evar x; unify x y
  | _ => is_evar y; unify x y
  | _ => is_var x; let x := eval cbv delta [x] in x in _syntactic_unify_deltavar x y
  | _ => is_var y; let y := eval cbv delta [y] in y in _syntactic_unify_deltavar x y
  | _ => lazymatch x with
         | ?f ?a => lazymatch y with ?g ?b => _syntactic_unify_deltavar f g; _syntactic_unify_deltavar a b end
         | (fun (a:?Ta) => ?f a)
           => lazymatch y with (fun (b:?Tb) => ?g b) =>
                               let __ := constr:(fun (a:Ta) (b:Tb) => ltac:(_syntactic_unify_deltavar f g; exact Set)) in idtac end
         | let a : ?Ta := ?v in ?f a
           => lazymatch y with let b : ?Tb := ?w in ?g b =>
                               _syntactic_unify_deltavar v w;
                               let __ := constr:(fun (a:Ta) (b:Tb) => ltac:(_syntactic_unify_deltavar f g; exact Set)) in idtac end

         | _ => first [ constr_eq x y
                      | first [has_evar x | has_evar y]; unify x y; constr_eq x y ]
         end
  end.
Tactic Notation "syntactic_unify_deltavar" open_constr(x) open_constr(y) :=  _syntactic_unify_deltavar x y.

Ltac _syntactic_exact_deltavar e :=
  let t := type of e in
  let g := lazymatch goal with |- ?g => g end in
  tryif syntactic_unify_deltavar t g then exact_no_check e else fail "syntactic_unify" t g.
Tactic Notation "syntactic_exact_deltavar" open_constr(e) :=
  _syntactic_exact_deltavar e.

Ltac list_get l i :=
  lazymatch l with
  | cons ?a ?l =>
    lazymatch i with
    | O  => a
    | S ?i => list_get l i
    end
  | _ => fail "list_get nil" i
  end.

Ltac index_and_element_of

[...]

ep LHS) (to_sep RHS).
Admitted.

    Lemma impl1_to_sep_of_impl1_flatten(LHS RHS : Tree (map -> Prop)):
      Lift1Prop.impl1 (seps (flatten LHS)) (seps (flatten RHS)) ->
      Lift1Prop.impl1 (to_sep LHS) (to_sep RHS).
Admitted.

    Lemma flatten_to_sep_with_and(t : Tree.Tree (map -> Prop))(m: map)(C: Prop):
      seps (flatten t) m /\ C -> to_sep t m /\ C.
Admitted.
  End WithMap.

Ltac reify e :=
  lazymatch e with
  | @sep ?key ?value ?map ?a ?b =>
    let a := reify a in
    let b := reify b in
    uconstr:(@Tree.Node (@map.rep key value map -> Prop) a b)
  | ?a => uconstr:(Tree.Leaf a)
  end.

Ltac reify_goal :=
  lazymatch goal with
  | |- Lift1Prop.iff1 ?LHS ?RHS =>
    let LHS := reify LHS in
    let RHS := reify RHS in
    change (Lift1Prop.iff1 (Tree.to_sep LHS) (Tree.to_sep RHS));
    eapply Tree.iff1_to_sep_of_iff1_flatten
  | |- Lift1Prop.impl1 ?LHS ?RHS =>
    let LHS := reify LHS in
    let RHS := reify RHS in
    change (Lift1Prop.impl1 (Tree.to_sep LHS) (Tree.to_sep RHS));
    eapply Tree.impl1_to_sep_of_impl1_flatten
  end;
  cbv [Tree.flatten Tree.interp app].

Ltac flatten_seps_in H :=
  lazymatch type of H with
  | ?nested ?m =>
    let tmem := type of m in
    let E := fresh "E" in
    eassert (@iff1 tmem nested _) as E;
    [
      let stars := eval cbv [seps] in nested in
      let tree := reify stars in
      transitivity (Tree.to_sep tree); [
        cbv [seps Tree.to_sep Tree.interp]; iff1_syntactic_reflexivity
      |];

      transitivity (seps (Tree.flatten tree)); [
        exact (iff1_sym (Tree.flatten_iff1_to_sep tree))
      |];

      cbv [SeparationLogic.Tree.flatten SeparationLogic.Tree.interp SeparationLogic.app];
      iff1_syntactic_reflexivity
    | let HNew := fresh in pose proof (proj1 (E m) H) as HNew;
      move HNew before H;
      clear E H;
      rename HNew into H ]
  end.

Ltac flatten_seps_in_goal :=
  cbv [seps];
  lazymatch goal with
  | |- ?nested ?m /\ ?C =>
      let xs := reify nested in
      change (Tree.to_sep xs m /\ C);
      eapply Tree.flatten_to_sep_with_and
  | |- ?nested ?m =>
      let xs := reify nested in
      change (Tree.to_sep xs m);
      eapply Tree.flatten_iff1_to_sep
  end;
  cbv [Tree.flatten Tree.interp app].

Ltac cancel_emp_l :=
  lazymatch goal with
  | |- Lift1Prop.iff1 (@seps ?K ?V ?M ?LHS) (seps ?RHS) =>
    let i := find_constr_eq LHS constr:(@emp K V M True) in
    simple refine (cancel_emp_at_index_l i LHS RHS _ _);
    cbv [firstn skipn app hd tl];
    [syntactic_exact_deltavar (@eq_refl _ _)|]
  end.

Ltac cancel_emp_r :=
  lazymatch goal with
  | |- Lift1Prop.iff1 (seps ?LHS) (@seps ?K ?V ?M ?RHS) =>
    let j := find_constr_eq RHS constr:(@emp K V M True) in
    simple refine (cancel_emp_at_index_r j LHS RHS _ _);
    cbv [firstn skipn app hd tl];
    [syntactic_exact_deltavar (@eq_refl _ _)|]
  end.

Ltac cancel_emp_impl :=
  lazymatch goal with
  | |- Lift1Prop.impl1 (seps ?LHS) (@seps ?K ?V ?M ?RHS) =>
    let j := find_constr_eq RHS constr:(@emp K V M True) in

    simple refine (cancel_emp_at_index_impl j LHS RHS _ _);
    cbv [firstn skipn app hd tl];

    [syntactic_exact_deltavar (@eq_refl _ _)|]
  end.

Ltac cancel_seps_at_indices i j :=
  lazymatch goal with
  | |- Lift1Prop.iff1 (seps ?LHS) (seps ?RHS) =>
    simple refine (cancel_seps_at_indices i j LHS RHS _ _);
    cbv [firstn skipn app hd tl]
  end.

Ltac cancel_seps_at_indices_by_implication i j :=
  lazymatch goal with
  | |- Lift1Prop.impl1 (seps ?LHS) (seps ?RHS) =>
    simple refine (cancel_seps_at_indices_by_implication i j LHS RHS _ _);
    cbv [firstn skipn app hd tl]
  end.

Ltac find_implication xs y :=
  multimatch xs with
  | cons ?x _ => constr:(O)
  | cons _ ?xs => let i := find_implication xs y in constr:(S i)
  end.

Ltac cancel_step := once (
      let RHS := lazymatch goal with |- Lift1Prop.iff1 _ (seps ?RHS) => RHS end in
      let jy := index_and_element_of RHS in
      let j := lazymatch jy with (?i, _) => i end in
      let y := lazymatch jy with (_, ?y) => y end in
      assert_fails (has_evar y);
      let LHS := lazymatch goal with |- Lift1Prop.iff1 (seps ?LHS) _ => LHS end in
      let i := find_constr_eq LHS y in
      cancel_seps_at_indices i j; [exact eq_refl|]).

Ltac cancel_step_impl := once (
    let RHS := lazymatch goal with |- Lift1Prop.impl1 _ (seps ?RHS) => RHS end in
    let jy := index_and_element_of RHS in
    let j := lazymatch jy with (?i, _) => i end in
    let y := lazymatch jy with (_, ?y) => y end in
    assert_fails (has_evar y);
    let LHS := lazymatch goal with |- Lift1Prop.impl1 (seps ?LHS) _ => LHS end in
    let i := find_constr_eq LHS y in
    cancel_seps_at_indices_by_implication i j; [exact impl1_refl|]).

Ltac ecancel_step_at j :=
      let RHS := lazymatch goal with |- Lift1Prop.iff1 _ (seps ?RHS) => RHS end in
      let y := list_get RHS j in
      assert_fails (idtac; let y := rdelta_var y in is_evar y);
      let LHS := lazymatch goal with |- Lift1Prop.iff1 (seps ?LHS) _ => LHS end in
      let i := find_syntactic_unify_deltavar LHS y in
      cancel_seps_at_indices i j; [exact eq_refl|].

Ltac ecancel_steps_inbounds j :=
  let RHS := lazymatch goal with |- Lift1Prop.iff1 _ (seps ?RHS) => RHS end in
  let __ := list_get RHS j in
  idtac.

Ltac ecancel_steps_at j :=
   tryif (ecancel_steps_inbounds j) then (
    tryif (ecancel_step_at j)
    then (                         ecancel_steps_at j)
    else (let j := constr:(S j) in ecancel_steps_at j)
  ) else idtac.

Ltac ecancel_step_by_implication :=
      let RHS := lazymatch goal with |- Lift1Prop.impl1 _ (seps ?RHS) => RHS end in
      let jy := index_and_element_of RHS in
      let j := lazymatch jy with (?i, _) => i end in
      let y := lazymatch jy with (_, ?y) => y end in
      assert_fails (idtac; let y := rdelta_var y in is_evar y);
      let LHS := lazymatch goal with |- Lift1Prop.impl1 (seps ?LHS) _ => LHS end in
      let i := find_implication LHS y in
      cancel_seps_at_indices_by_implication i j; [solve [auto 1 with nocore ecancel_impl]|].

Ltac ecancel_done :=
  cbv [seps];
  syntactic_exact_deltavar
    (@RelationClasses.reflexivity _ _
        (@RelationClasses.Equivalence_Reflexive _ _ (@Equivalence_iff1 _)) _).

Ltac cancel_done :=
  lazymatch goal with
  | |- iff1 (seps (cons _ nil)) _ => idtac
  | |- iff1 _ (seps (cons _ nil )) => idtac
  | |- ?g => assert_fails (has_evar g)
  end;
  ecancel_done.

Ltac cancel_seps :=
  lazymatch goal with
  | |- Lift1Prop.iff1 _ _ =>
    repeat cancel_step;
    repeat cancel_emp_l;
    repeat cancel_emp_r
  | |- Lift1Prop.impl1 _ _ =>
    repeat cancel_step_impl;
    repeat cancel_emp_impl
  end;
  try solve [ cancel_done ].

Ltac cancel := reify_goal; cancel_seps.

Ltac ecancel :=
  cancel;
  lazymatch goal with
  | [|- impl1 _ _] =>
     repeat ecancel_step_by_implication;
     (solve [ cbv [seps]; exact impl1_refl ])
  | [|- iff1 _ _] =>
    ecancel_steps_at O;
    ecancel_done
  end.

Ltac ecancel_assumption :=
  multimatch goal with
  | |- _ ?m1 =>
    multimatch goal with
    | H: _ ?m2 |- _ =>
      syntactic_unify_deltavar m1 m2;
      refine (Lift1Prop.subrelation_iff1_impl1 _ _ _ _ _ H); clear H;
      solve [ecancel]
    end
  end.
Require Crypto.Arithmetic.WordByWordMontgomery.
Module Export Array.
Import Stdlib.ZArith.ZArith.
Import coqutil.Byte.

Section Array.
  Context {width : Z} {word : Word.Interface.word width} {word_ok : word.ok word}.
  Context {value} {mem : map.map word value} {mem_ok : map.ok mem}.
  Context {T} (element : word -> T -> mem -> Prop) (size : word).
  Fixpoint array (start : word) (xs : list T) :=
    match xs with
    | nil => emp True
    | cons x xs => sep (element start x) (array (word.add start size) xs)
    end.

End Array.

Section ByteArray.
  Context {width : Z} {word : Word.Interface.word width} {word_ok : word.ok word}.
  Context {mem : map.map word byte} {mem_ok : map.ok mem}.
  Local Notation array := (array (mem:=mem) ptsto (word.of_Z 1)).

  Lemma array_1_to_anybytes bs m (a: word) :
    array a bs m -> bedrock2.Memory.anybytes a (Z.of_nat (List.length bs)) m.
Admitted.

  Lemma anybytes_to_array_1 m (addr : word) n :
      bedrock2.Memory.anybytes addr n m ->
      exists bs, array  addr bs m /\ List.length bs = Z.to_nat n.
Admitted.
End ByteArray.
Module Export Scalars.
Import coqutil.Word.LittleEndianList.
Import bedrock2.Memory.

Section Scalars.
  Context {width : Z} {BW: Bitwidth width} {word : Word.Interface.word width} {word_ok : word.ok word}.

  Context {mem : map.map word byte} {mem_ok : map.ok mem}.
  Implicit Types (m : mem).

  Definition truncated_scalar sz addr (value:Z) : mem -> Prop :=
    (le_split (bytes_per (width:=width) sz) value) $@ addr.

  Definition truncated_word sz addr (value: word) : mem -> Prop :=
    truncated_scalar sz addr (word.unsigned value).

  Notation scalar8 := ptsto (only parsing).

  Definition scalar16 := truncated_word Syntax.access_size.two.
  Definition scalar32 := truncated_word Syntax.access_size.four.
  Definition scalar := truncated_word Syntax.access_size.word.
Definition truncate_word(sz: Syntax.access_size)(w: word): word.
Admitted.

  Lemma load_one_of_sep addr value R m
    (Hsep : sep (scalar8 addr value) R m)
    : Memory.load Syntax.access_size.one m addr = Some (word.of_Z (byte.unsigned value)).
Admitted.

  Lemma load_two_of_sep addr value R m
    (Hsep : sep (scalar16 addr value) R m)
    : Memory.load Syntax.access_size.two m addr = Some (truncate_word Syntax.access_size.two value).
Admitted.

  Lemma load_four_of_sep addr value R m
    (Hsep : sep (scalar32 addr value) R m)
    : Memory.load Syntax.access_size.four m addr = Some (truncate_word Syntax.access_size.four value).
Admitted.

  Lemma load_four_of_sep_32bit(W32: width = 32) addr value R m
    (Hsep : sep (scalar32 addr value) R m)
    : Memory.load Syntax.access_size.four m addr = Some value.
Admitted.

  Lemma load_word_of_sep addr value R m
    (Hsep : sep (scalar addr value) R m)
    : Memory.load Syntax.access_size.word m addr = Some value.
Admitted.

  Lemma store_one_of_sep addr (oldvalue : byte) (value : word) R m (post:_->Prop)
    (Hsep : sep (scalar8 addr oldvalue) R m)
    (Hpost : forall m, sep (scalar8 addr (byte.of_Z (word.unsigned value))) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.one m addr value = Some m1 /\ post m1.
Admitted.

  Lemma store_two_of_sep addr (oldvalue : word) (value : word) R m (post:_->Prop)
    (Hsep : sep (scalar16 addr oldvalue) R m)
    (Hpost : forall m, sep (scalar16 addr value) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.two m addr value = Some m1 /\ post m1.
Admitted.

  Lemma store_four_of_sep addr (oldvalue : word) (value : word) R m (post:_->Prop)
    (Hsep : sep (scalar32 addr oldvalue) R m)
    (Hpost : forall m, sep (scalar32 addr value) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.four m addr value = Some m1 /\ post m1.
Admitted.

  Lemma store_word_of_sep addr (oldvalue value: word) R m (post:_->Prop)
    (Hsep : sep (scalar addr oldvalue) R m)
    (Hpost : forall m, sep (scalar addr value) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.word m addr value = Some m1 /\ post m1.
Admitted.

End Scalars.
Module Export Loops.
Import coqutil.Datatypes.PrimitivePair.
Import coqutil.Datatypes.HList.
Import coqutil.dlet.
Import bedrock2.Syntax.
Import bedrock2.Semantics.
Import bedrock2.WeakestPrecondition.

Section Loops.
  Context {width: Z} {BW: Bitwidth width} {word: word.word width} {mem: map.map word Byte.byte}.
  Context {locals: map.map String.string word}.
  Context {ext_spec: ExtSpec}.

  Context {fs : env}.
  Let call := fs.

  Local Notation "A /\ B" := (Markers.split (A /\ B)).
Definition reconstruct (variables:list String.string) (values:tuple word (length variables)) : locals.
exact (map.putmany_of_tuple (tuple.of_list variables) values map.empty).
Defined.
Fixpoint gather (variables : list String.string) (l : locals) : option (locals *  tuple word (length variables)).
exact (match variables with
    | nil => Some (l, tt)
    | cons x xs' =>
      match map.get l x with
      | None => None
      | Some v =>
        match gather xs' (map.remove l x) with
        | None => None
        | Some (l, vs') => Some (l, (pair.mk v vs'))
        end
      end
    end).
Defined.
Definition enforce (variables : list String.string) (values:tuple word (length variables)) (l:locals) : Prop.
exact (match gather variables l with
    | None => False
    | Some (remaining, r) => values = r /\ remaining = map.empty
    end).
Defined.

  Import pair.

  Lemma tailrec
    {e c t localsmap} {m : mem}
    (ghosttypes : polymorphic_list.list Type)
    (variables : list String.string)
    {l0 : tuple word (length variables)}
    {Pl : enforce variables l0 localsmap}
    {post : _->_->_-> Prop}
    {measure : Type} (spec:_->HList.arrows ghosttypes (_->_->ufunc word (length variables) (Prop*(_->_->ufunc word (length variables) Prop)))) lt
    (Hwf : well_founded lt)
    (v0 : measure)
    : hlist.foralls (fun (g0 : hlist ghosttypes) => forall
    (Hpre : (tuple.apply (hlist.apply (spec v0) g0 t m) l0).(1))
    (Hbody : forall v, hlist.foralls (fun g => forall t m, tuple.foralls (fun l =>
      @dlet _ (fun _ => Prop) (reconstruct variables l) (fun localsmap : locals =>
      match tuple.apply (hlist.apply (spec v) g t m) l with S_ =>
      S_.(1) ->
      Markers.unique (Markers.left (exists br, expr m localsmap e (eq br) /\ Markers.right (
      (word.unsigned br <> 0%Z -> cmd call c t m localsmap
        (fun t' m' localsmap' =>
          Markers.unique (Markers.left (hlist.existss (fun l' => enforce variables l' localsmap' /\ Markers.right (
          Markers.unique (Markers.left (hlist.existss (fun g' => exists v',
          match tuple.apply (hlist.apply (spec v') g' t' m') l' with S' =>
          S'.(1) /\ Markers.right (
            lt v' v /\
            forall T M, hlist.foralls (fun L => tuple.apply (S'.(2) T M) L -> tuple.apply (S_.(2) T M) L)) end))))))))) /\
      (word.unsigned br = 0%Z -> tuple.apply (S_.(2) t m) l))))end))))
    (Hpost : match (tuple.apply (hlist.apply (spec v0) g0 t m) l0).(2) with Q0 => forall t m, hlist.foralls (fun l =>  tuple.apply (Q0 t m) l -> post t m (reconstruct variables l))end)
    , cmd call (cmd.while e c) t m localsmap post ).
Admitted.
End Loops.
Import coqutil.Tactics.Tactics.
Import coqutil.Tactics.letexists.
Import coqutil.Tactics.eabstract.
Import coqutil.Tactics.reference_to_string.
Import coqutil.Tactics.ident_of_string.
Import bedrock2.WeakestPrecondition.
Import bedrock2.WeakestPreconditionProperties.

Definition spec_of (procname:String.string) := Semantics.env -> Prop.
Existing Class spec_of.
Import Ltac2.Ltac2.

Local Ltac2 rec splitcmd (cmd : constr) : unit :=
  match! cmd with
    | cmd.seq ?cmd1 ?cmd2 =>
        set (cmd.seq $cmd1 $cmd2) in *; splitcmd cmd1; splitcmd cmd2
    | cmd.cond ?expr ?cmd1 ?cmd2 => set (cmd.cond $expr $cmd1 $cmd2) in *; splitcmd cmd1; splitcmd cmd2
    | cmd.while ?expr ?cmd => set (cmd.while $expr $cmd) in *; splitcmd cmd
    | _ => ()
  end.

Local Ltac2 Notation "instance_of" type(constr) :=
  lazy_match! Ltac2.Constr.pretype (preterm:(_ : $type)) with ?instance => instance end.

Local Ltac2 rec unfold_const x :=
  if Bool.neg (Constr.is_const x) then x else
    let ref := reference_to_string.reference_of_constr x in
    match! eval cbv delta [$ref] in $x with ?x => unfold_const x
  end.

Local Ltac2 function_body (proc : constr) : constr :=
  let unfolded := unfold_const proc in
  match! unfolded with (_, _, ?fbody) => fbody end.

Local Ltac2 rec callee_specs (cmd : constr) : constr list :=
  match! cmd with
    | cmd.cond _ ?c1 ?c2  => List.append (callee_specs c1) (callee_specs c2)
    | cmd.seq ?c1 ?c2 => List.append (callee_specs c1) (callee_specs c2)
    | cmd.while _ ?c => callee_specs c
    | cmd.stackalloc _ _ ?c => callee_specs c
    | cmd.call _ ?f _ => [instance_of (spec_of $f)]
    | cmd.skip => []
    | cmd.set _ _ => []
    | cmd.unset _ => []
    | cmd.store _ _ _ => []
    | cmd.interact _ _ _ => []
    | _ => Control.throw (Invalid_argument (Some (Message.concat
        (Message.of_string "Failed to recurse into the following command, consider reducing it before calling program_logic_goal_for: ")
        (Message.of_constr cmd))))
  end.

Local Ltac2 program_logic_goal_for_function (proc : constr) : unit :=
  let fname := constr_string_basename_of_constr_reference proc in
  let fname_spec := instance_of (spec_of $fname) in
  let fbody := function_body proc in
  let goal := (fun (functions : constr) =>
    List.fold_right (fun premise_spec conclusion => '(($premise_spec $functions) -> $conclusion)) (callee_specs fbody) '($fname_spec $functions)) in
  exact (forall (functions : @map.rep _ _ Semantics.env) (EnvContains : map.get functions $fname = Some $proc),
    ltac2:(let g := goal &functions in exact $g)
  ).

Set Default Proof Mode "Classic".

Definition program_logic_goal_for (_ : Syntax.func) (P : Prop) := P.

Notation "program_logic_goal_for_function! proc" := (program_logic_goal_for proc ltac2:(
   program_logic_goal_for_function (Ltac2.Constr.pretype proc)))
  (at level 10, only parsing).

Ltac normalize_body_of_function f := eval cbv in f.

Ltac bind_body_of_function f_ :=
  let f := normalize_body_of_function f_ in
  let fbody := open_constr:(_) in
  let funif := open_constr:((_, _, fbody)) in
  unify f funif;
  let go_split := ltac2:(fbody |-
    let fbody_value := Option.get (Ltac1.to_constr fbody) in
    splitcmd fbody_value) in
  change f_ with f;
  go_split fbody; intros.

Ltac enter f :=
  cbv beta delta [program_logic_goal_for];
  bind_body_of_function f;
  lazymatch goal with |- ?s ?p => let s := rdelta s in change (s p); cbv beta end.

Ltac is_context_variable H :=
  assert_succeeds (exfalso; clear -H; assert(H = H);
    let A := fresh in let B := fresh in destruct H as [A B]; pose H).

Ltac straightline_cleanup :=
  match goal with

  | x : Word.Interface.word.rep _ |- _ => clear x
  | x : Init.Byte.byte |- _ => clear x
  | x : Semantics.trace |- _ => clear x
  | x : Syntax.cmd |- _ => clear x
  | x : Syntax.expr |- _ => clear x
  | x : coqutil.Map.Interface.map.rep |- _ => clear x
  | x : BinNums.Z |- _ => clear x
  | x : unit |- _ => clear x
  | x : bool |- _ => clear x
  | x : list _ |- _ => clear x
  | x : nat |- _ => clear x

  | x := _ : Word.Interface.word.rep _ |- _ => clear x
  | x := _ : Init.Byte.byte |- _ => clear x
  | x := _ : Semantics.trace |- _ => clear x
  | x := _ : Syntax.cmd |- _ => clear x
  | x := _ : Syntax.expr |- _ => clear x
  | x := _ : coqutil.Map.Interface.map.rep |- _ => clear x
  | x := _ : BinNums.Z |- _ => clear x
  | x := _ : unit |- _ => clear x
  | x := _ : bool |- _ => clear x
  | x := _ : list _ |- _ => clear x
  | x := _ : nat |- _ => clear x
  | |- forall _, _ => intros
  | |- let _ := _ in _ => intros
  | |- dlet.dlet ?v (fun x => ?P) => change (let x := v in P); intros
  | _ => progress (cbn [Semantics.interp_binop] in * )
  | H: exists _, _ |- _ => tryif is_context_variable H then fail else destruct H
  | H: _ /\ _ |- _ => tryif is_context_variable H then fail else destruct H
  | x := ?y |- ?G => is_var y; subst x
  | H: ?x = ?y |- _ => constr_eq x y; clear H
  | H: ?x = ?y |- _ => is_var x; is_var y; assert_fails (idtac; let __ := eval cbv [x] in x in idtac); subst x
  | H: ?x = ?y |- _ => is_var x; is_var y; assert_fails (idtac; let __ := eval cbv [y] in y in idtac); subst y
  | H: ?x = ?v |- _ =>
    is_var x;
    assert_fails (idtac; let __ := eval cbv delta [x] in x in idtac);
    lazymatch v with context[x] => fail | _ => idtac end;
    let x' := fresh x in
    rename x into x';
    simple refine (let x := v in _);
    change (x' = x) in H;
    symmetry in H;
    destruct H
  end.

Ltac straightline_stackalloc :=
  match goal with Hanybytes: Memory.anybytes ?a ?n ?mStack |- _ =>
  let m := match goal with H : map.split ?mCobined ?m mStack |- _ => m end in
  let mCombined := match goal with H : map.split ?mCobined ?m mStack |- _ => mCobined end in
  let Hsplit := match goal with H : map.split ?mCobined ?m mStack |- _ => H end in
  let Hm := multimatch goal with H : _ m |- _ => H end in
  let Hm' := fresh Hm in
  let Htmp := fresh in
  let Pm := match type of Hm with ?P m => P end in
  assert_fails (assert (Separation.sep Pm (Array.array Separation.ptsto (Interface.word.of_Z (BinNums.Zpos BinNums.xH)) a _) mCombined) as _ by ecancel_assumption);
  rename Hm into Hm';
  let stack := fresh "stack" in
  let stack_length := fresh "length_" stack in
  destruct (Array.anybytes_to_array_1 mStack a n Hanybytes) as (stack&Htmp&stack_length);
  epose proof (ex_intro _ m (ex_intro _ mStack (conj Hsplit (conj Hm' Htmp)))
  : Separation.sep _ (Array.array Separation.ptsto (Interface.word.of_Z (BinNums.Zpos BinNums.xH)) a _) mCombined) as Hm;
  clear Htmp;
  try (let m' := fresh m in rename m into m'); rename mCombined into m;
  ( assert (BinInt.Z.of_nat (Datatypes.length stack) = n)
  by (rewrite stack_length; apply (ZifyInst.of_nat_to_nat_eq n))
  || fail 2 "negative stackalloc of size" n )
  end.

Ltac straightline_stackdealloc :=
  lazymatch goal with |- exists _ _, Memory.anybytes ?a ?n _ /\ map.split ?m _ _ /\ _ =>
  let Hm := multimatch goal with Hm : _ m |- _ => Hm end in
  let stack := match type of Hm with context [Array.array Separation.ptsto _ a ?stack] => stack end in
  let length_stack := match goal with H : Datatypes.length stack = _ |- _ => H end in
  let Hm' := fresh Hm in
  pose proof Hm as Hm';
  let Psep := match type of Hm with ?P _ => P end in
  let Htmp := fresh "Htmp" in
  eassert (Lift1Prop.iff1 Psep (Separation.sep _ (Array.array Separation.ptsto (Interface.word.of_Z (BinNums.Zpos BinNums.xH)) a stack))) as Htmp
  by ecancel || fail "failed to find stack frame in" Psep "using ecancel";
  eapply (fun m => proj1 (Htmp m)) in Hm;
  let m' := fresh m in
  rename m into m';
  let mStack := fresh in
  destruct Hm as (m&mStack&Hsplit&Hm&Harray1); move Hm at bottom;
  pose proof Array.array_1_to_anybytes _ _ _ Harray1 as Hanybytes;
  rewrite length_stack in Hanybytes;
  refine (ex_intro _ m (ex_intro _ mStack (conj Hanybytes (conj Hsplit _))));
  clear Htmp Hsplit mStack Harray1 Hanybytes
  end.

Ltac rename_to_different H :=
  idtac;
  let G := fresh H "'0" in
  rename H into G.
Ltac ensure_free H :=
  try rename_to_different H.

Ltac eq_uniq_step :=
  match goal with
  | |- ?x = ?y =>
      let x := rdelta x in
      let y := rdelta y in
      first [ is_evar x | is_evar y | constr_eq x y ]; exact eq_refl
  | |- ?lhs = ?rhs =>
      let lh := head lhs in
      is_constructor lh;
      let rh := head rhs in
      constr_eq lh rh;
      f_equal
  end.
Ltac eq_uniq := repeat eq_uniq_step.

Ltac fwd_uniq_step :=
  match goal with
  | |- exists x : ?T, _ =>
      let ev := open_constr:(match _ return T with x => x end) in
      eexists ev;
      let rec f :=
        tryif has_evar ev
        then fwd_uniq_step
        else idtac
      in f
  | |- _ /\ _ => split; [ solve [repeat fwd_uniq_step; eq_uniq] | ]
  | _ => solve [ eq_uniq ]
  end.

Ltac straightline :=
  match goal with
  | _ => straightline_cleanup
  | |- program_logic_goal_for ?f _ =>
    enter f; intros;
    match goal with
    | H: map.get ?functions ?fname = Some _ |- _ =>
        eapply start_func; [exact H | clear H]
    end;
    cbv match beta delta [WeakestPrecondition.func]
  | |- WeakestPrecondition.cmd _ (cmd.set ?s ?e) _ _ _ ?post =>
    unfold1_cmd_goal; cbv beta match delta [cmd_body];
    let __ := match s with String.String _ _ => idtac | String.EmptyString => idtac end in
    ident_of_constr_string_cps s ltac:(fun x =>
      ensure_free x;

      letexists _ as x; split; [solve [repeat straightline]|])
  | |- cmd _ ?c _ _ _ ?post =>
    let c := eval hnf in c in
    lazymatch c with
    | cmd.while _ _ => fail
    | cmd.cond _ _ _ => fail
    | cmd.interact _ _ _ => fail
    | _ => unfold1_cmd_goal; cbv beta match delta [cmd_body]
    end
  | |- @list_map _ _ (get _) _ _ => unfold1_list_map_goal; cbv beta match delta [list_map_body]
  | |- @list_map _ _ (expr _ _) _ _ => unfold1_list_map_goal; cbv beta match delta [list_map_body]
  | |- @list_map _ _ _ nil _ => cbv beta match fix delta [list_map list_map_body]
  | |- expr _ _ _ _ => unfold1_expr_goal; cbv beta match delta [expr_body]
  | |- dexpr _ _ _ _ => cbv beta delta [dexpr]
  | |- dexprs _ _ _ _ => cbv beta delta [dexprs]
  | |- literal _ _ => cbv beta delta [literal]
  | |- @get ?w ?W ?L ?l ?x ?P =>
      let get' := eval cbv [get] in @get in
      change (get' w W L l x P); cbv beta
  | |- load _ _ _ _ => cbv beta delta [load]
  | |- @Loops.enforce ?width ?word ?locals ?names ?values ?map =>
    let values := eval cbv in values in
    change (@Loops.enforce width word locals names values map);
    exact (conj (eq_refl values) eq_refl)
  | |- @eq (@coqutil.Map.Interface.map.rep String.string Interface.word.rep _) _ _ =>
    eapply SortedList.eq_value; exact eq_refl
  | |- @map.get String.string Interface.word.rep ?M ?m ?k = Some ?e' =>
    let e := rdelta e' in
    is_evar e;
    once (let v := multimatch goal with x := context[@map.put _ _ M _ k ?v] |- _ => v end in

          unify e v; exact (eq_refl (Some v)))
  | |- @coqutil.Map.Interface.map.get String.string Interface.word.rep _ _ _ = Some ?v =>
    let v' := rdelta v in is_evar v'; (change v with v'); exact eq_refl
  | |- ?x = ?y =>
    let y := rdelta y in is_evar y; change (x=y); exact eq_refl
  | |- ?x = ?y =>
    let x := rdelta x in is_evar x; change (x=y); exact eq_refl
  | |- ?x = ?y =>
    let x := rdelta x in let y := rdelta y in constr_eq x y; exact eq_refl
  | |- store Syntax.access_size.one _ _ _ _ =>
    eapply Scalars.store_one_of_sep; [solve[ecancel_assumption]|]
  | |- store Syntax.access_size.two _ _ _ _ =>
    eapply Scalars.store_two_of_sep; [solve[ecancel_assumption]|]
  | |- store Syntax.access_size.four _ _ _ _ =>
    eapply Scalars.store_four_of_sep; [solve[ecancel_assumption]|]
  | |- store Syntax.access_size.word _ _ _ _ =>
    eapply Scalars.store_word_of_sep; [solve[ecancel_assumption]|]
  | |- bedrock2.Memory.load Syntax.access_size.one ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_one_of_sep _ _ _ _ _ _ _ _ _ _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.two ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_two_of_sep _ _ word _ mem _ a _ _ m _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.four ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_four_of_sep_32bit _ _ word _ mem _ eq_refl a _ _ m _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.four ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_four_of_sep _ _ word _ mem _ a _ _ m _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.word ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_word_of_sep _ _ word _ mem _ a _ _ m _); ecancel_assumption
  | |- exists l', Interface.map.of_list_zip ?ks ?vs = Some l' /\ _ =>
    letexists; split; [exact eq_refl|]
  | |- exists l', Interface.map.putmany_of_list_zip ?ks ?vs ?l = Some l' /\ _ =>
    letexists; split; [exact eq_refl|]
  | _ => fwd_uniq_step
  | |- exists x, ?P /\ ?Q =>
    let x := fresh x in refine (let x := _ in ex_intro (fun x => P /\ Q) x _);
                        split; [solve [repeat straightline]|]
  | |- exists x, Markers.split (?P /\ ?Q) =>
    let x := fresh x in refine (let x := _ in ex_intro (fun x => P /\ Q) x _);
                        split; [solve [repeat straightline]|]
  | |- Markers.unique (exists x, Markers.split (?P /\ ?Q)) =>
    let x := fresh x in refine (let x := _ in ex_intro (fun x => P /\ Q) x _);
                        split; [solve [repeat straightline]|]
  | |- Markers.unique (Markers.left ?G) =>
    change G;
    unshelve (idtac; repeat match goal with
                     | |- Markers.split (?P /\ Markers.right ?Q) =>
                       split; [eabstract (repeat straightline) | change Q]
                     | |- exists _, _ => letexists
                     end); []
  | |- Markers.split ?G => change G; split
  | |- True => exact I
  | |- False \/ _ => right
  | |- _ \/ False => left
  | |- BinInt.Z.modulo ?z (Memory.bytes_per_word _) = BinInt.Z0 /\ _ =>
      lazymatch Coq.setoid_ring.InitialRing.isZcst z with
      | true => split; [exact eq_refl|]
      end
  | |- _ => straightline_stackalloc
  | |- _ => straightline_stackdealloc
  | |- context[sep (sep ?_a ?_b) ?_c] => progress (flatten_seps_in_goal; cbn [seps])
  | H : context[sep (sep ?_a ?_b) ?_c] |- _ => progress (flatten_seps_in H; cbn [seps] in H)
  end.
Import bedrock2.NotationsCustomEntry.
Local Open Scope string_scope.
Import coqutil.Word.Properties.
Import bedrock2.BasicC64Semantics.
Import Crypto.Arithmetic.WordByWordMontgomery.

Section WithParameters.
  Import WordByWordMontgomery.

  Context {prime: Z} (r := 64) {ri : Z}.
Instance spec_of_redc_alt : spec_of "redc_alt".
exact (fnspec! "redc_alt" Astart Bstart Sstart len / A (aval: Z) B (bval: Z) S R,
    { requires t m :=
        m =* array scalar (word.of_Z 8) Astart A *
                  array scalar (word.of_Z 8) Bstart B *
                  array scalar (word.of_Z 8) Sstart S * R /\
        word.unsigned len = Z.of_nat (List.length A)  /\
        word.unsigned len = Z.of_nat (List.length B)  /\
        word.unsigned len = Z.of_nat (List.length S) /\
        @eval r (Z.to_nat (word.unsigned len)) (List.map word.unsigned A) = aval /\
        @eval r (Z.to_nat (word.unsigned len)) (List.map word.unsigned B) = bval;
      ensures t' m' :=  t=t' /\ exists S',
          m' =*
             array scalar (word.of_Z 8) Astart A *
             array scalar (word.of_Z 8) Bstart B *
            array scalar (word.of_Z 8) Sstart S' * R /\
          ( aval * bval * ri^(word.unsigned len) ) mod prime =
            @eval r (Z.to_nat (word.unsigned len)) (List.map word.unsigned S') mod prime
    }).
Defined.
Instance spec_of_redc_step : spec_of "redc_step".
Admitted.

  Definition redc_alt :=
    func! (Astart, Bstart, Sstart, len) {
    i = $0;
    while (i < len) {
         store(Sstart + $8*i, $0);
         i = i + $1
      };
    i = $0;
    while (i < len) {
         redc_step ( load(Astart + $8*i), Bstart, Sstart, len );
          i = i + $1
      }
    }.

  Import Coq.Lists.List.

  Let zeros (n: Z) :=
        repeat (@word.of_Z _ word 0) (Z.to_nat n).

 Theorem redc_alt_ok :
      program_logic_goal_for_function! redc_alt.
 Proof.
   repeat straightline.

      refine ( tailrec (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ HList.polymorphic_list.nil))))))))
               ("Astart":: "Bstart" :: "Sstart" :: "len" :: "i" :: nil)
               (fun l A aval B bval S Ra Rb R t m Astart Bstart Sstart len i => PrimitivePair.pair.mk
                                    (m =* array scalar (word.of_Z 8) (word.add Sstart (word.mul (word.of_Z 8) i)) S * R /\
                                       word.unsigned len - word.unsigned i = Z.of_nat (List.length S) /\

                                    l = List.length S )
                                    (fun t' m' Astart' Bstart' Sstart' len' i' =>
                                       (
                                     t = t' /\ Astart = Astart' /\ Bstart = Bstart' /\ Sstart = Sstart' /\ len = len' /\
                                     m' =* array scalar (word.of_Z 8) (word.add Sstart (word.mul (word.of_Z 8) i)) (zeros (word.unsigned len - word.unsigned i)) * R
                                     )
                                    )
               )
               lt _ _ _ _ _ _ _ _ _ _ _ _ _);
        cbn [reconstruct map.putmany_of_list HList.tuple.to_list
         HList.hlist.foralls HList.tuple.foralls
         HList.hlist.existss HList.tuple.existss
         HList.hlist.apply  HList.tuple.apply
         HList.hlist
         List.repeat Datatypes.length
         HList.polymorphic_list.repeat HList.polymorphic_list.length
         PrimitivePair.pair._1 PrimitivePair.pair._2] in *.

      {
 repeat straightline.
}
      {
 exact Wf_nat.lt_wf.
}
      {
 repeat straightline.
        subst i.
        replace (word.add Sstart (word.mul (word.of_Z 8) (word.of_Z 0))) with (Sstart) by ring.
        repeat split; try eauto.
        -
 ecancel_assumption.
        -
 rewrite word.unsigned_of_Z_0.
Lia.lia.
}

      {
 repeat straightline.
eexists.
🛠️ Intermediate Coq File (useful for debugging if minimization did not go as far as you wanted) (truncated to 6.0KiB; full 125KiB file on GitHub Actions Artifacts under tmp.v)
(* -*- mode: coq; coq-prog-args: ("-emacs" "-q" "-w" "+implicit-core-hint-db,+implicits-in-term,+non-reversible-notation,+deprecated-intros-until-0,+deprecated-focus,+unused-intro-pattern,+variable-collision,+unexpected-implicit-declaration,+omega-is-deprecated,+deprecated-instantiate-syntax,+non-recursive,+undeclared-scope,+deprecated-hint-rewrite-without-locality,+deprecated-hint-without-locality,+deprecated-instance-without-locality,+deprecated-typeclasses-transparency-without-locality,+fragile-hint-constr,-deprecated-since-9.0,-deprecated-since-8.20,-deprecated-from-Coq" "-w" "-notation-overridden,-native-compiler-disabled,-ambiguous-paths,-masking-absolute-name" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Coqprime" "Coqprime" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Kami" "Kami" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rewriter" "Rewriter" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rupicola" "Rupicola" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Top.bug_01") -*- *)
(* File reduced by coq-bug-minimizer from original input, then from 577 lines to 117 lines, then from 131 lines to 869 lines, then from 877 lines to 453 lines, then from 468 lines to 1367 lines, then from 1372 lines to 533 lines, then from 548 lines to 1295 lines, then from 1303 lines to 616 lines, then from 631 lines to 1279 lines, then from 1286 lines to 653 lines, then from 668 lines to 953 lines, then from 961 lines to 662 lines, then from 677 lines to 1947 lines, then from 1949 lines to 996 lines, then from 1011 lines to 1284 lines, then from 1292 lines to 1026 lines, then from 1041 lines to 1079 lines, then from 1087 lines to 1042 lines, then from 1057 lines to 1205 lines, then from 1211 lines to 1085 lines, then from 1100 lines to 1221 lines, then from 1229 lines to 1123 lines, then from 1138 lines to 1177 lines, then from 1185 lines to 1151 lines, then from 1166 lines to 1480 lines, then from 1488 lines to 1182 lines, then from 1197 lines to 1464 lines, then from 1472 lines to 1195 lines, then from 1216 lines to 1089 lines, then from 1103 lines to 2887 lines *)
(* coqc version 9.3+alpha compiled with OCaml 4.14.2
   coqtop version 9.3+alpha
   Expected coqc runtime on this file: 0.000 sec
   Expected coqc peak memory usage on this file: 0.0 kb *)
Require Coq.Init.Ltac.
Module Export AdmitTactic.
Module Import LocalFalse.
Inductive False : Prop := .
End LocalFalse.
Axiom proof_admitted : False.
Import Coq.Init.Ltac.
Tactic Notation "admit" := abstract case proof_admitted.
End AdmitTactic.
Require bedrock2.Markers.
Require coqutil.Tactics.eabstract.
Require coqutil.Tactics.letexists.
Require coqutil.Tactics.ident_of_string.
Require coqutil.Tactics.reference_to_string.
Require bedrock2.NotationsCustomEntry.
Require bedrock2.WeakestPreconditionProperties.
Require coqutil.Word.Bitwidth64.
Require coqutil.Word.Naive.
Module Export SortedListWord.
Import coqutil.Word.Interface.
Import coqutil.Map.Interface.

Section __.
  Context {width} (word : word width) {word_ok : @word.ok width word}.

  Context (value : Type).
Definition map : map.map word value.
Admitted.
Global Instance ok : map.ok map.
Admitted.
End __.
Import Coq.ZArith.ZArith.
Import bedrock2.Semantics.
Export coqutil.Word.Bitwidth64.
#[export] Instance word: word.word 64.
exact (Naive.word64).
Defined.
#[export] Instance mem: Interface.map.map word Byte.byte.
exact (SortedListWord.map _ _).
Defined.
#[export] Instance locals: Interface.map.map String.string word.
exact (SortedListString.map _).
Defined.
#[export] Instance ext_spec: ExtSpec.
Admitted.
Add Ring wring : (Properties.word.ring_theory (word := word))
      (preprocess [autorewrite with rew_word_morphism],
       morphism (Properties.word.ring_morph (word := word)),
       constants [Properties.word_cst]).
Module Export bedrock2.
Module Export BasicC64Semantics.
End BasicC64Semantics.
Ltac rdelta x :=
  match constr:(Set) with
  | _ => progress_rdelta x
  | _ => x
  end
with progress_rdelta x :=
  let x := eval cbv delta [x] in x in
  rdelta x.

Ltac rdelta_var x :=
  match constr:(Set) with
  | _ => progress_rdelta_var x
  | _ => x
  end
with progress_rdelta_var x :=
  let __ := match constr:(Set) with _ => is_var x end in
  let x := eval cbv delta [x] in x in
  rdelta_var x.

Ltac _syntactic_unify_deltavar x y :=
  match constr:(Set) with
  | _ => is_evar x; unify x y
  | _ => is_evar y; unify x y
  | _ => is_var x; let x := eval cbv delta [x] in x in _syntactic_unify_deltavar x y
  | _ => is_var y; let y := eval cbv delta [y] in y in _syntactic_unify_deltavar x y
  | _ => lazymatch x with
         | ?f ?a => lazymatch y with ?g ?b => _syntactic_unify_deltavar f g; _syntactic_unify_deltavar a b end
         | (fun (a:?Ta) => ?f a)
           => lazymatch y with (fun (b:?Tb) => ?g b) =>
                               let __ := constr:(fun (a:Ta) (b:Tb) => ltac:(_syntactic_unify_deltavar f g; exact Set)) in idtac end
         | let a : ?Ta := ?v in ?f a
           => lazymatch y with let b : ?Tb := ?w in ?g b =>
                               _syntactic_unify_d
🛠️ 📜 Intermediate Coq File log (useful for debugging if minimization did not go as far as you wanted)
📜 Build Log (contains the Coq error message) (truncated to last 8.0KiB; full 14MiB file on GitHub Actions Artifacts under build.log)
Util/ZUtil/Tactics/SimplifyFractionsLe.vo
src/Util/ZUtil/Tactics/SolveRange.vo
src/Util/ZUtil/Tactics/SolveTestbit.vo
src/Util/ZUtil/Tactics/SplitMinMax.vo
src/Util/ZUtil/Tactics/ZeroBounds.vo
src/Util/ZUtil/Tactics/Ztestbit.vo
src/Util/ZUtil/Testbit.vo
src/Util/ZUtil/TruncatingShiftl.vo
src/Util/ZUtil/TwosComplement.vo
src/Util/ZUtil/Z2Nat.vo
src/Util/ZUtil/ZSimplify.vo
src/Util/ZUtil/ZSimplify/Autogenerated.vo
src/Util/ZUtil/ZSimplify/Core.vo
src/Util/ZUtil/ZSimplify/Simple.vo
src/Util/ZUtil/Zselect.vo


Files Not Made:
src/Bedrock/End2End/Poly1305/Field1305.vo
src/Bedrock/End2End/X25519/EdwardsXYZT.vo
src/Bedrock/End2End/X25519/Field25519.vo
src/Bedrock/End2End/X25519/GarageDoor.vo
src/Bedrock/End2End/X25519/GarageDoorTop.vo
src/Bedrock/End2End/X25519/MontgomeryLadder.vo
src/Bedrock/End2End/X25519/MontgomeryLadderRISCV.vo
src/Bedrock/Everything.vo
src/Bedrock/Field/Stringification/Stringification.vo
src/Bedrock/Field/Synthesis/Examples/p224_64_new.vo
src/Bedrock/Field/Synthesis/New/ComputedOp.vo
src/Bedrock/Field/Synthesis/New/Signature.vo
src/Bedrock/Field/Synthesis/New/UnsaturatedSolinas.vo
src/Bedrock/Field/Synthesis/New/WordByWordMontgomery.vo
src/Bedrock/Field/Translation/Cmd.vo
src/Bedrock/Field/Translation/Func.vo
src/Bedrock/Field/Translation/Parameters/Defaults.vo
src/Bedrock/Field/Translation/Parameters/Defaults32.vo
src/Bedrock/Field/Translation/Parameters/Defaults64.vo
src/Bedrock/Field/Translation/Parameters/FE310.vo
src/Bedrock/Field/Translation/Proofs/Cmd.vo
src/Bedrock/Field/Translation/Proofs/Func.vo
src/Bedrock/Field/Translation/Proofs/ValidComputable/Cmd.vo
src/Bedrock/Field/Translation/Proofs/ValidComputable/Func.vo
src/Bedrock/Group/ScalarMult/MontgomeryLadder.vo
src/Bedrock/P256.vo
src/Bedrock/P256/Coord.vo
src/Bedrock/P256/Coord32.vo
src/Bedrock/P256/Jacobian.vo
src/Bedrock/P256/JacobianAffine.vo
src/Bedrock/P256/Platform.vo
src/Bedrock/P256/PrecomputedMultiples.vo
src/Bedrock/P256/RecodeProofs.vo
src/Bedrock/P256/Scalarmult.vo
src/Bedrock/P256/Specs.vo
src/Bedrock/Secp256k1/Addchain.vo
src/Bedrock/Secp256k1/Field256k1.vo
src/Bedrock/Secp256k1/JacobianCoZ.vo
src/Bedrock/Secp256k1/JoyeLadder.vo
src/Bedrock/Standalone/StandaloneHaskellMain.vo
src/Bedrock/Standalone/StandaloneJsOfOCamlMain.vo
src/Bedrock/Standalone/StandaloneOCamlMain.vo
src/BoundsPipeline.vo
src/CLI.vo
src/CompilersTestCases.vo
src/Curves/Montgomery/AffineInstances.vo
src/Curves/Montgomery/AffineProofs.vo
src/Curves/Montgomery/XZProofs.vo
src/Curves/Weierstrass/AffineProofs.vo
src/Curves/Weierstrass/Jacobian/CoZ.vo
src/Curves/Weierstrass/Jacobian/Jacobian.vo
src/Curves/Weierstrass/Jacobian/ScalarMult.vo
src/Curves/Weierstrass/P256.vo
src/Curves/Weierstrass/Projective.vo
src/Everything.vo
src/ExtractionJsOfOCaml/WithBedrock/fiat_crypto.vo
src/ExtractionJsOfOCaml/bedrock2_fiat_crypto.vo
src/ExtractionJsOfOCaml/fiat_crypto.vo
src/Fancy/Barrett256.vo
src/Fancy/Montgomery256.vo
src/PerfTesting/PerfTestPrint.vo
src/PerfTesting/PerfTestSearch.vo
src/PerfTesting/PerfTestSearchPattern.vo
src/PushButtonSynthesis/BarrettReduction.vo
src/PushButtonSynthesis/BaseConversion.vo
src/PushButtonSynthesis/DettmanMultiplication.vo
src/PushButtonSynthesis/FancyMontgomeryReduction.vo
src/PushButtonSynthesis/Primitives.vo
src/PushButtonSynthesis/SaturatedSolinas.vo
src/PushButtonSynthesis/SmallExamples.vo
src/PushButtonSynthesis/SolinasReduction.vo
src/PushButtonSynthesis/UnsaturatedSolinas.vo
src/PushButtonSynthesis/WordByWordMontgomery.vo
src/Rewriter/All.vo
src/Rewriter/PerfTesting/Core.vo
src/Rewriter/PerfTesting/StandaloneOCamlMain.vo
src/Rewriter/RulesGood.vo
src/SlowPrimeSynthesisExamples.vo
src/StandaloneDebuggingExamples.vo
src/StandaloneHaskellMain.vo
src/StandaloneJsOfOCamlMain.vo
src/StandaloneMonadicUtils.vo
src/StandaloneOCamlMain.vo
ROCQ compile src/Bedrock/Field/Synthesis/Examples/redc.v
MINIMIZER_DEBUG_EXTRA: coqc: /github/workspace/builds/coq/coq-failing/_install_ci/bin///rocq
MINIMIZER_DEBUG_EXTRA: original invocation: '' 
MINIMIZER_DEBUG_EXTRA: new invocation: /github/workspace/builds/coq/coq-failing/_install_ci/bin/rocq.orig compile -q -w +implicit-core-hint-db\,+implicits-in-term\,+non-reversible-notation\,+deprecated-intros-until-0\,+deprecated-focus\,+unused-intro-pattern\,+variable-collision\,+unexpected-implicit-declaration\,+omega-is-deprecated\,+deprecated-instantiate-syntax\,+non-recursive\,+undeclared-scope\,+deprecated-hint-rewrite-without-locality\,+deprecated-hint-without-locality\,+deprecated-instance-without-locality\,+deprecated-typeclasses-transparency-without-locality\,+fragile-hint-constr\,-deprecated-since-9.0\,-deprecated-since-8.20\,-deprecated-from-Coq -w -notation-overridden\,-native-compiler-disabled\,-ambiguous-paths\,-masking-absolute-name -w -deprecated-native-compiler-option -native-compiler no -R /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src Crypto src/Bedrock/Field/Synthesis/Examples/redc.v 
MINIMIZER_DEBUG_EXTRA: coqpath: 
MINIMIZER_DEBUG_EXTRA: ocamlpath: /github/workspace/builds/coq/coq-failing/_install_ci/lib:
MINIMIZER_DEBUG_EXTRA: pwd: PWD=/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto
MINIMIZER_DEBUG_EXTRA: exec: /github/workspace/builds/coq/coq-failing/_install_ci/bin/rocq.orig compile -q -w +implicit-core-hint-db\,+implicits-in-term\,+non-reversible-notation\,+deprecated-intros-until-0\,+deprecated-focus\,+unused-intro-pattern\,+variable-collision\,+unexpected-implicit-declaration\,+omega-is-deprecated\,+deprecated-instantiate-syntax\,+non-recursive\,+undeclared-scope\,+deprecated-hint-rewrite-without-locality\,+deprecated-hint-without-locality\,+deprecated-instance-without-locality\,+deprecated-typeclasses-transparency-without-locality\,+fragile-hint-constr\,-deprecated-since-9.0\,-deprecated-since-8.20\,-deprecated-from-Coq -w -notation-overridden\,-native-compiler-disabled\,-ambiguous-paths\,-masking-absolute-name -w -deprecated-native-compiler-option -native-compiler no -R /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src Crypto src/Bedrock/Field/Synthesis/Examples/redc.v 
MINIMIZER_DEBUG_EXTRA: coqlib: Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//
MINIMIZER_DEBUG: info: /tmp/tmp-coqbot-minimizer.Mhunh42v3f
MINIMIZER_DEBUG: files:  src/Bedrock/Field/Synthesis/Examples/redc.v /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src/Bedrock/Field/Synthesis/Examples/redc.v
Warning, feedback message received but no listener to handle it!
Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]Warning, feedback message received but no listener to handle it!
Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
Warning: Deprecated environment variable COQCORELIB,
use ROCQRUNTIMELIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
File "./src/Bedrock/Field/Synthesis/Examples/redc.v", line 210, characters 29-37:
Error: Expected a single focused goal but 2 goals are focused.

Command exited with non-zero status 1
src/Bedrock/Field/Synthesis/Examples/redc.vo (real: 1.13, user: 0.97, sys: 0.16, mem: 539976 ko)
make: *** [Makefile.coq:815: src/Bedrock/Field/Synthesis/Examples/redc.vo] Error 1
make: *** [src/Bedrock/Field/Synthesis/Examples/redc.vo] Deleting file 'src/Bedrock/Field/Synthesis/Examples/redc.glob'
+ code=2
+ printf '\n%s exit code: %s\n' fiat_crypto 2
+ '[' fiat_crypto '!=' stdlib_test ']'
+ echo 'Aggregating timing log...'
Aggregating timing log...
+ echo

+ tools/make-one-time-file.py --real _build_ci/fiat_crypto.log
    Time |  Peak Mem | File Name                               
---------------------------------------------------------------
0m01.56s | 539976 ko | Total Time / Peak Mem                   
---------------------------------------------------------------
0m01.13s | 539976 ko | Bedrock/Field/Synthesis/Examples/redc.vo
0m00.43s |  34212 ko | .Makefile.coq.d                         
+ '[' '' ']'
+ exit 2
/github/workspace/builds/coq /github/workspace
::endgroup::
📜 🔎 Minimization Log (truncated to last 8.0KiB; full 34MiB file on GitHub Actions Artifacts under bug.log)
implicit-create-rewrite-hint-db,deprecated-since-9.2,deprecated,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 393, characters 0-6:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 420, characters 0-6:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 423, characters 0-6:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 445, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 450, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 452, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 542, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 544, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 547, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 557, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 653, characters 0-8:
Warning: Use of "Notation" keyword for abbreviations is deprecated, use
"Abbreviation" instead.
[notation-for-abbreviation,deprecated-since-9.2,deprecated,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 688, characters 0-6:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 795, characters 0-8:
Warning: Use of "Notation" keyword for abbreviations is deprecated, use
"Abbreviation" instead.
[notation-for-abbreviation,deprecated-since-9.2,deprecated,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 831, characters 0-760:
Warning: Closed notations (i.e. starting and ending with a terminal symbol)
should usually be at level 0 (default).
[closed-notation-not-level-0,parsing,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 831, characters 0-760:
Warning:
For backwards compatibility non left recursive notations declared at level 200
are actually at level 10, with any right-recursion being at level 200.
In the future level 200 will be treated as a normal level.
To keep the current behaviour, use "at level 10",
remove any "right associativity" annotation,
and if right recursive add "x at level 200" where "x" is the last argument.
[at-level-200-changed,deprecated-since-9.3,deprecated,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 873, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 901, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 902, characters 0-8:
Warning: Use of "Notation" keyword for abbreviations is deprecated, use
"Abbreviation" instead.
[notation-for-abbreviation,deprecated-since-9.2,deprecated,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 904, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 915, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 917, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 923, characters 0-6:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 926, characters 0-6:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 929, characters 0-6:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 932, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpxbfihjzh/Top/bug_01.v", line 933, characters 18-45:
Error: Could not find an instance for "word.ok word".



�[93mIntermediate code not saved.�[0m
Failed to do everything at once; trying one at a time.
Admitting definitions unsuccessful.
No successful changes.

I will now attempt to add Proof using lines
�[92m
Adding Proof using lines successful.�[0m
Failed to do everything at once; trying one at a time.
Adding Proof using lines unsuccessful.
No successful changes.

I will now attempt to export modules
Module exportation successful

I will now attempt to split imports and exports
Import/Export splitting unsuccessful.

I will now attempt to split := definitions
One-line definition splitting successful

I will now attempt to lift Requires to the top of the file while inserting option settings

I will now attempt to lift Requires to the top of the file while inserting option settings

Running command: "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-q" "-w" "+implicit-core-hint-db,+implicits-in-term,+non-reversible-notation,+deprecated-intros-until-0,+deprecated-focus,+unused-intro-pattern,+variable-collision,+unexpected-implicit-declaration,+omega-is-deprecated,+deprecated-instantiate-syntax,+non-recursive,+undeclared-scope,+deprecated-hint-rewrite-without-locality,+deprecated-hint-without-locality,+deprecated-instance-without-locality,+deprecated-typeclasses-transparency-without-locality,+fragile-hint-constr,-deprecated-since-9.0,-deprecated-since-8.20,-deprecated-from-Coq" "-w" "-notation-overridden,-native-compiler-disabled,-ambiguous-paths,-masking-absolute-name" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Coqprime" "Coqprime" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Kami" "Kami" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rewriter" "Rewriter" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rupicola" "Rupicola" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Top.bug_01" "/tmp/tmp5bhxqw20/Top/bug_01.v" "-q"
Sending statements to coqtop...
Done.  Splitting to definitions...

I will now attempt to remove all lines, one at a time

If you have any comments on your experience of the minimizer, please share them in a reply (possibly tagging @JasonGross).
If you believe there's a bug in the bug minimizer, please report it on the bug minimizer issue tracker.

cc @JasonGross

@coqbot-app

coqbot-app Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor
Minimization interrupted by timeout, being automatically continued. Partially Minimized File /home/runner/work/run-coq-bug-minimizer/run-coq-bug-minimizer/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories/PCUICInductiveInversion.v in 5h 15m 5s (from ci-metarocq) (interrupted by timeout, being automatically continued) (full log on GitHub Actions - verbose log)
⭐ ⏱️ Partially Minimized Coq File (timeout) (truncated to first and last 32KiB; full 65KiB file on GitHub Actions Artifacts under bug.v)
(* -*- mode: coq; coq-prog-args: ("-emacs" "-q" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/utils/theories" "MetaRocq.Utils" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/common/theories" "MetaRocq.Common" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories" "MetaRocq.PCUIC" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Equations" "Equations" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/ExtLib" "ExtLib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-top" "Top.bug_01") -*- *)
(* File reduced by coq-bug-minimizer from original input, then from 4603 lines to 39 lines, then from 53 lines to 39 lines, then from 52 lines to 39 lines, then from 51 lines to 3774 lines, then from 3773 lines to 46 lines, then from 58 lines to 2403 lines, then from 2409 lines to 57 lines, then from 69 lines to 995 lines, then from 1000 lines to 81 lines, then from 93 lines to 2645 lines, then from 2646 lines to 213 lines, then from 225 lines to 90 lines, then from 104 lines to 1099 lines, then from 1098 lines to 139 lines, then from 153 lines to 1878 lines, then from 1885 lines to 430 lines, then from 444 lines to 1595 lines, then from 1601 lines to 598 lines, then from 612 lines to 2689 lines, then from 2690 lines to 619 lines, then from 633 lines to 1387 lines, then from 1388 lines to 641 lines, then from 655 lines to 3123 lines, then from 3125 lines to 716 lines, then from 730 lines to 1577 lines, then from 1582 lines to 1230 lines, then from 1240 lines to 765 lines, then from 779 lines to 2311 lines, then from 2312 lines to 795 lines, then from 809 lines to 2691 lines, then from 2694 lines to 1082 lines, then from 1096 lines to 1769 lines, then from 1775 lines to 1159 lines, then from 1173 lines to 4005 lines, then from 4004 lines to 1740 lines *)
(* coqc version 9.3+alpha compiled with OCaml 4.14.2
   coqtop version 9.3+alpha
   Expected coqc runtime on this file: 2.786 sec
   Expected coqc peak memory usage on this file: 746252.0 kb *)
Require MetaRocq.Common.Reflect.
Require MetaRocq.Common.Environment.
Module Export EnvironmentTyping.
Import Stdlib.ssr.ssrbool.
Import MetaRocq.Utils.utils.
Import MetaRocq.Common.config.
Import MetaRocq.Common.BasicAst.
Import MetaRocq.Common.Universes.
Import MetaRocq.Common.Environment.

Module Lookup (T : Term) (E : EnvironmentSig T).
Import E.

  Definition declared_constant (Σ : global_env) id decl := In (id,ConstantDecl decl) (declarations Σ).

  Definition declared_minductive_gen (lookup : kername -> option global_decl) mind decl :=
    lookup mind = Some (InductiveDecl decl).

  Definition declared_minductive Σ mind decl := In (mind,InductiveDecl decl) (declarations Σ).

  Definition declared_inductive_gen lookup ind mdecl decl :=
    declared_minductive_gen lookup (inductive_mind ind) mdecl /\
    List.nth_error mdecl.(ind_bodies) (inductive_ind ind) = Some decl.

  Definition declared_inductive Σ ind mdecl decl :=
    declared_minductive Σ (inductive_mind ind) mdecl /\
    List.nth_error mdecl.(ind_bodies) (inductive_ind ind) = Some decl.

  Definition declared_constructor_gen lookup cstr mdecl idecl cdecl : Prop :=
    declared_inductive_gen lookup (fst cstr) mdecl idecl /\
    List.nth_error idecl.(ind_ctors) (snd cstr) = Some cdecl.

  Definition declared_constructor Σ cstr mdecl idecl cdecl :=
    declared_inductive Σ (fst cstr) mdecl idecl /\
    List.nth_error idecl.(ind_ctors) (snd cstr) = Some cdecl.

  Definition declared_projection Σ (proj : projection) mdecl idecl cdecl pdecl
  : Prop :=
    declared_constructor Σ (proj.(proj_ind), 0) mdecl idecl cdecl /\
    List.nth_error idecl.(ind_projs) proj.(proj_arg) = Some pdecl /\
    mdecl.(ind_npars) = proj.(proj_npars).

  Definition lookup_minductive_gen (lookup : kername -> option global_decl) mind :=
    match lookup mind with
    | Some (InductiveDecl decl) => Some decl
    | _ => None
    end.

  Definition lookup_inductive_gen lookup ind :=
    match lookup_minductive_gen lookup (inductive_mind ind) with
    | Some mdecl =>
      match nth_error mdecl.(ind_bodies) (inductive_ind ind) with
      | Some idecl => Some (mdecl, idecl)
      | None => None
      end
    | None => None
    end.

  Definition lookup_constructor_gen lookup ind k :=
    match lookup_inductive_gen lookup ind with
    | Some (mdecl, idecl) =>
      match nth_error idecl.(ind_ctors) k with
      | Some cdecl => Some (mdecl, idecl, cdecl)
      | None => None
      end
    | _ => None
    end.

  Definition on_udecl_decl {A} (F : universes_decl -> A) d : A :=
  match d with
  | ConstantDecl cb => F cb.(cst_universes)
  | InductiveDecl mb => F mb.(ind_universes)
  end.

  Definition universes_decl_of_decl := on_udecl_decl (fun x => x).
Definition global_levels (univs : ContextSet.t) : LevelSet.t.
Admitted.
Definition global_ext_levels (Σ : global_env_ext) : LevelSet.t.
Admitted.
Definition global_ext_constraints (Σ : global_env_ext) : ConstraintSet.t.
Admitted.

  Coercion global_ext_constraints : global_env_ext >-> ConstraintSet.t.

  Definition consistent_instance `{checker_flags} (lvs : LevelSet.t) (φ : ConstraintSet.t) uctx (u : Instance.t) :=
    match uctx with
    | Monomorphic_ctx => List.length u = 0
    | Polymorphic_ctx c =>

      forallb (fun l => LevelSet.mem l lvs) u /\
      List.length u = List.length c.1 /\
      valid_constraints φ (subst_instance_cstrs u c.2)
    end.

  Definition consistent_instance_ext `{checker_flags} Σ :=
    consistent_instance (global_ext_levels Σ) (global_ext_constraints Σ).

  Definition wf_universe Σ (u : Universe.t) : Prop :=
    forall l, LevelExprSet.In l u -> LevelSet.In (LevelExpr.get_level l) (global_ext_levels Σ).

  Definition wf_sort Σ (s : sort) : Prop :=
    Sort.on_sort (wf_universe Σ) True s.

End Lookup.

Module Type LookupSig (T : Term) (E : EnvironmentSig T).
  Include Lookup T E.
End LookupSig.

Module EnvTyping (T : Term) (E : EnvironmentSig T) (TU : TermUtils T E).
Import T.
Import E.

  Definition on_def_type (P : context -> judgment -> Type) Γ d :=
    P Γ (TypRel d.(dtype) d.(dname).(binder_relevance)).

  Definition on_def_body (P : context -> judgment -> Type) types Γ d :=
    P (Γ ,,, types) (TermTypRel d.(dbody) (lift0 #|types| d.(dtype)) d.(dname).(binder_relevance)).

  Definition lift_sorting checking sorting : judgment -> Type :=
    fun j => option_default (fun tm => checking tm (j_typ j)) (j_term j) (unit : Type) ×
                                ∑ s, sorting (j_typ j) s ×
                                  option_default (fun u => u = s) (j_univ j) True /\
                                  isSortRelOpt s (j_rel j).

  Abbreviation typing_sort typing := (fun T s => typing T (tSort s)).

  Definition lift_typing0 typing := lift_sorting typing (typing_sort typing).
  Abbreviation lift_typing1 typing := (fun Γ => lift_typing0 (typing Γ)).
  Abbreviation lift_typing typing := (fun Σ Γ => lift_typing0 (typing Σ Γ)).

  Section TypeLocal.
    Context (typing : forall (Γ : context), judgment -> Type).

    Inductive All_local_env : context -> Type :=
    | localenv_nil :
        All_local_env []

    | localenv_cons_abs Γ na t :
        All_local_env Γ ->
        typing Γ (j_vass na t) ->
        All_local_env (Γ ,, vass na t)

    | localenv_cons_def Γ na b t :
        All_local_env Γ ->
        typing Γ (j_vdef na b t) ->
        All_local_env (Γ ,, vdef na b t).
  End TypeLocal.

  Section TypeCtxInst.
    Context (typing : forall (Γ : context), term -> term -> Type).

    Inductive ctx_inst (Γ : context) : list term -> context -> Type :=
    | ctx_inst_nil : ctx_inst Γ [] []
    | ctx_inst_ass na t i inst Δ :
        typing Γ i t ->
        ctx_inst Γ inst (subst_telescope [i] 0 Δ) ->
        ctx_inst Γ (i :: inst) (vass na t :: Δ)
    | ctx_inst_def na b t inst Δ :
        ctx_inst Γ inst (subst_telescope [b] 0 Δ) ->
        ctx_inst Γ inst (vdef na b t :: Δ).
  End TypeCtxInst.

End EnvTyping.

Module Type EnvTypingSig (T : Term) (E : EnvironmentSig T) (TU : TermUtils T E).
  Include EnvTyping T E TU.
End EnvTypingSig.

Module Conversion (T : Term) (E : EnvironmentSig T) (TU : TermUtils T E) (ET : EnvTypingSig T E TU).
Import T.
Import E.

  Section Conversion.
  Context (cumul_gen : global_env_ext -> context -> conv_pb -> term -> term -> Type).

  Inductive All_decls_alpha_pb {pb} {P : conv_pb -> term -> term -> Type} :
    context_decl -> context_decl -> Type :=
  | all_decls_alpha_vass {na na' : binder_annot name} {t t' : term}
    (eqna : eq_binder_annot na na')
    (eqt : P pb t t') :
    All_decls_alpha_pb (vass na t) (vass na' t')

  | all_decls_alpha_vdef {na na' : binder_annot name} {b t b' t' : term}
    (eqna : eq_binder_annot na na')
    (eqb : P Conv b b')
    (eqt : P pb t t') :
    All_decls_alpha_pb (vdef na b t) (vdef na' b' t').

  Arguments All_decls_alpha_pb pb P : clear implicits.

  Definition cumul_pb_decls pb (Σ : global_env_ext) (Γ Γ' : context) : forall (x y : context_decl), Type :=
    All_decls_alpha_pb pb (cumul_gen Σ Γ).

  Definition cumul_ctx_rel Σ Γ Δ Δ' :=
    All2_fold (fun Δ Δ' => cumul_pb_decls Cumul Σ (Γ ,,, Δ) (Γ ,,, Δ')) Δ Δ'.
  End Conversion.
End Conversion.

Module Type ConversionSig (T : Term) (E : EnvironmentSig T) (TU : TermUtils T E) (ET : EnvTypingSig T E TU).
  Include Conversion T E TU ET.
End ConversionSig.

Module GlobalMaps (T: Term) (E: EnvironmentSig T) (TU : TermUtils T E) (ET: EnvTypingSig T E TU) (C: ConversionSig T E TU ET) (L: LookupSig T E).
Import T.
Import E.
Import TU.
Import ET.
Import C.
Import L.

  Section GlobalMaps.

    Context {cf: checker_flags}.
    Context (Pcmp: global_env_ext -> context -> conv_pb -> term -> term -> Type).
    Context (P : global_env_ext -> context -> judgment -> Type).
    Definition on_context Σ ctx :=
      All_local_env (P Σ) ctx.

    Fixpoint type_local_ctx Σ (Γ Δ : context) (u : sort) : Type :=
      match Δ with
      | [] => wf_sort Σ u
      | {| decl_name := na; decl_body := None; decl_type := t |} :: Δ =>
          type_local_ctx Σ Γ Δ u × P Σ (Γ ,,, Δ) (TypUnivRel t u na.(binder_relevance))
      | {| decl_body := Some _; |} as d :: Δ =>
          type_local_ctx Σ Γ Δ u × P Σ (Γ ,,, Δ) (j_decl d)
      end.

    Fixpoint sorts_local_ctx Σ (Γ Δ : context) (us : list sort) : Type :=
      match Δ, us with
      | [], [] => unit
      | {| decl_name := na; decl_body := None;   decl_type := t |} :: Δ, u :: us =>
        sorts_local_ctx Σ Γ Δ us × P Σ (Γ ,,, Δ) (TypUnivRel t u na.(binder_relevance))
      | {| decl_body := Some _ |} as d :: Δ, us =>
        sorts_local_ctx Σ Γ Δ us × P Σ (Γ ,,, Δ) (j_decl d)
      | _, _ => False
      end.
    Definition on_type_rel Σ Γ T r := P Σ Γ (TypRel T r).

    Definition ind_realargs (o : one_inductive_body) :=
      match destArity [] o.(ind_type) with
      | Some (ctx, _) => #|smash_context [] ctx|
      | _ => 0
      end.

    Definition mdecl_at_i mdecl i (Γ:context) k : Prop :=
      #|Γ| <= k /\ k < #|Γ| + #|mdecl.(ind_bodies)| /\
       nth_error (List.rev mdecl.(ind_bodies)) (k - #|Γ|) = Some i.

    Reserved Notation " mdecl ;;; Γ |arg+> t " (at level 50, Γ, t at next level).
    Notation "M { j := N }" := (subst [N] j M) (at level 10, right associativity).

    Inductive positive_cstr_arg mdecl Γ : term -> Type :=
    | pos_arg_closed ty :
      closedn #|Γ| ty ->
      mdecl ;;; Γ |arg+> ty

    | pos_arg_concl l k i :

      #|l| = ind_realargs i -> All (closedn #|Γ|) l ->
      mdecl_at_i mdecl i Γ k ->
      mdecl ;;; Γ |arg+> mkApps (tRel k) l

    | pos_arg_let na b ty ty' :
      mdecl ;;; Γ |arg+> ty' {0 := b} ->
      mdecl ;;; Γ |arg+> tLetIn na b ty ty'

    | pos_arg_ass na ty ty' :
      closedn #|Γ| ty ->
      mdecl ;;; (vass na ty :: Γ) |arg+> ty' ->
      mdecl ;;; Γ |arg+> tProd na ty ty'

  where " mdecl ;;; Γ |arg+> t " := (positive_cstr_arg mdecl Γ t) : type_scope.

    Reserved Notation " mdecl @ i ;;; Γ |+> t " (at level 50, i, Γ, t at next level).

    Inductive positive_cstr mdecl i Γ : term -> Type :=
    | pos_concl l (headrel := (#|mdecl.(ind_bodies)| - S i + #|Γ|)%nat) :
      All (closedn #|Γ|) l ->
      mdecl @ i ;;; Γ |+> mkApps (tRel headrel) l

    | pos_let na b ty ty' :
      mdecl @ i ;;; Γ |+> ty' {0 := b} ->
      mdecl @ i ;;; Γ |+> tLetIn na b ty ty'

    | pos_ass na ty ty' :
      mdecl ;;; Γ |arg+> ty ->
      mdecl @ i ;;; (vass na ty :: Γ) |+> ty' ->
      mdecl @ i ;;; Γ |+> tProd na ty ty'

    where " mdecl @ i ;;; Γ |+> t " := (positive_cstr mdecl i Γ t) : type_scope.

    Definition lift_level n l :=
      match l with
      | Level.lzero | Level.level _ => l
      | Level.lvar k => Level.lvar (n + k)
      end.

    Definition lift_instance n l :=
      map (lift_level n) l.

    Definition lift_constraint n (c : Level.t * ConstraintType.t * Level.t) :=
      let '((l, r), l') := c in
      ((lift_level n l, r), lift_level n l').

    Definition lift_constraints n cstrs :=
      ConstraintSet.fold (fun elt acc => ConstraintSet.add (lift_constraint n elt) acc)
        cstrs ConstraintSet.empty.

    Definition level_var_instance n (inst : list name) :=
      mapi_rec (fun i _ => Level.lvar i) inst n.

    Fixpoint variance_cstrs (v : list Variance.t) (u u' : Instance.t) :=
      match v, u, u' with
      | _, [], [] => ConstraintSet.empty
      | v :: vs, u :: us, u' :: us' =>
        match v with
        | Variance.Irrelevant => variance_cstrs vs us us'
        | Variance.Covariant => ConstraintSet.add (u, ConstraintType.Le 0, u') (variance_cstrs vs us us')
        | Variance.Invariant => ConstraintSet.add (u, ConstraintType.Eq, u') (variance_cstrs vs us us')
        end
      | _, _, _ =>  ConstraintSet.empty
      end.

    Definition variance_universes univs v :=
      match univs with
      | Monomorphic_ctx => None
      | Polymorphic_ctx auctx =>
        let (inst, cstrs) := auctx in
        let u' := level_var_instance 0 inst in
        let u := lift_instance #|inst| u' in
        let cstrs := ConstraintSet.union cstrs (lift_constraints #|inst| cstrs) in
        let cstrv := variance_cstrs v u u' in
        let auctx' := (inst ++ inst, ConstraintSet.union cstrs cstrv) in
        Some (Polymorphic_ctx auctx', u, u')
      end.

    Definition ind_arities mdecl := arities_context (ind_bodies mdecl).

    Definition ind_respects_variance Σ mdecl v indices :=
      let univs := ind_universes mdecl in
      match variance_universes univs v with
      | Some (univs, u, u') =>
        cumul_ctx_rel Pcmp (Σ, univs) (smash_context [] (ind_params mdecl))@[u]
          (expand_lets_ctx (ind_params mdecl) (smash_context [] indices))@[u]
          (expand_lets_ctx (ind_params mdecl) (smash_context [] indices))@[u']
      | None => False
      end.

    Definition cstr_respects_variance Σ mdecl v cs :=
      let univs := ind_universes mdecl in
      match variance_universes univs v with
      | Some (univs, u, u') =>
        cumul_ctx_rel Pcmp (Σ, univs) (ind_arities mdecl ,,, smash_context [] (ind_params mdecl))@[u]
          (expand_lets_ctx (ind_params mdecl) (smash_context [] (cstr_args cs)))@[u]
          (expand_lets_ctx (ind_params mdecl) (smash_context [] (cstr_args cs)))@[u'] *
        All2
          (Pcmp (Σ, univs) (ind_arities mdecl ,,, smash_context [] (ind_params mdecl ,,, cstr_args cs))@[u] Conv)
          (map (subst_instance u ∘ expand_lets (ind_params mdecl ,,, cstr_args cs)) (cstr_indices cs))
          (map (subst_instance u' ∘ expand_lets (ind_params mdecl ,,, cstr_args cs)) (cstr_indices cs))
      | None => False
      end.

    Definition cstr_concl_head mdecl i cdecl :=
      tRel (#|mdecl.(ind_bodies)| - S i + #|mdecl.(ind_params)| + #|cstr_args cdecl|).

    Definition cstr_concl mdecl i cdecl :=
      (mkApps (cstr_concl_head mdecl i cdecl)
        (to_extended_list_k mdecl.(ind_params) #|cstr_args cdecl|
          ++ cstr_indices cdecl)).

    Record on_constructor Σ mdecl i idecl ind_indices cdecl cunivs := {

      cstr_args_length : context_assumptions (cstr_args cdecl) = cstr_arity cdecl;

      cstr_eq : cstr_type cdecl =
       it_mkProd_or_LetIn mdecl.(ind_params)
        (it_mkProd_or_LetIn (cstr_args cdecl)
          (cstr_concl mdecl i cdecl));

      on_ctype : on_type_rel Σ (arities_context mdecl.(ind_bodies)) (cstr_type cdecl) idecl.(ind_relevance);
      on_cargs :
        sorts_local_ctx Σ (arities_context mdecl.(ind_bodies) ,,, mdecl.(ind_params))
                      cdecl.(cstr_args) cunivs;
      on_cindices :
        ctx_inst (fun Γ t T => P Σ Γ (TermTyp t T)) (arities_context mdecl.(ind_bodies) ,,, mdecl.(ind_params) ,,, cdecl.(cstr_args))
                      cdecl.(cstr_indices)
                      (List.rev (lift_context #|cdecl.(cstr_args)| 0 ind_indices));

      on_ctype_positive :
        positive_cstr mdecl i [] (cstr_type cdecl);

      on_ctype_variance :
        forall v, ind_variance mdecl = Some v ->
        cstr_respects_variance Σ mdecl v cdecl;

      on_lets_in_type : if lets_in_constructor_types
                        then True else is_true (is_assumption_context (cstr_args cdecl))
    }.

    Definition on_constructors Σ mdecl i idecl ind_indices :=
      All2 (on_constructor Σ mdecl i idecl ind_indices).

    Record on_proj mdecl mind i k (p : projection_body) decl :=
      { on_proj_name :
          binder_name (decl_name decl) = nNamed p.(proj_name);
        on_proj_type :

          let u := abstract_instance mdecl.(ind_universes) in
          let ind := {| inductive_mind := mind; inductive_ind := i |} in
          p.(proj_type) = subst (inds mind u mdecl.(ind_bodies)) (S (ind_npars mdecl))
            (subst (projs ind mdecl.(ind_npars) k) 0
              (lift 1 k (decl_type decl)));
        on_proj_relevance : p.(proj_relevance) = decl.(decl_name).(binder_relevance) }.

    Definition on_projection mdecl mind i cdecl (k : nat) (p : projection_body) :=
      let Γ := smash_context [] (cdecl.(cstr_args) ++ mdecl.(ind_params)) in
      match nth_error Γ (context_assumptions cdecl.(cstr_args) - S k) with
      | None => False
      | Some decl => on_proj mdecl mind i k p decl
      end.

    Record on_projections mdecl mind i idecl (ind_indices : context) cdecl :=
      { on_projs_record : #|idecl.(ind_ctors)| = 1;

        on_projs_noidx : #|ind_indices| = 0;

        on_projs_elim : idecl.(ind_kelim) = IntoAny;

        on_projs_all : #|idecl.(ind_projs)| = context_assumptions (cstr_args cdecl);

        on_projs : Alli (on_projection mdecl mind i cdecl) 0 idecl.(ind_projs) }.

    Definition check_constructors_smaller φ cunivss ind_sort :=
      Forall (fun cunivs =>
        Forall (fun argsort => leq_sort φ argsort ind_sort) cunivs) cunivss.

    Definition constructor_univs := list sort.

    Definition elim_sort_prop_ind (ind_ctors_sort : list constructor_univs) :=
      match ind_ctors_sort with
      | [] =>  IntoAny
      | [ s ] =>
        if forallb Sort.is_propositional s then
          IntoAny
        else
          IntoPropSProp
      | _ =>  IntoPropSProp
      end.

    Definition elim_sort_sprop_ind (ind_ctors_sort : list constructor_univs) :=
      match ind_ctors_sort with
      | [] =>  IntoAny
      | _ =>  IntoSProp
      end.

    Definition check_ind_sorts (Σ : global_env_ext)
              params kelim ind_indices cdecls ind_sort : Type :=
      match Sort.to_family ind_sort with
      | Sort.fProp =>

        (allowed_eliminations_subset kelim (elim_sort_prop_ind cdecls) : Type)
      | Sort.fSProp =>

        (allowed_eliminations_subset kelim (elim_sort_sprop_ind cdecls) : Type)
      | _ =>

        check_constructors_smaller Σ cdecls ind_sort
        × if indices_matter then
            type_local_ctx Σ params ind_indices ind_sort
          else True
      end.

    Record on_ind_body Σ mind mdecl i idecl :=
      {
        ind_arity_eq : idecl.(ind_type)
                      = it_mkProd_or_LetIn mdecl.(ind_params)
                                (it_mkProd_or_LetIn idecl.(ind_indices) (tSort idecl.(ind_sort)));

        onArity : on_type_rel Σ [] idecl.(ind_type) rel_of_Type;

        ind_cunivs : list constructor_univs;

        onConstructors :
          on_constructors Σ mdecl i idecl idecl.(ind_indices) idecl.(ind_ctors) ind_cunivs;

        onProjections :
          match idecl.(ind_projs), idecl.(ind_ctors) return Type with
          | [], _ => True
          | _, [ o ] =>
              on_projections mdecl mind i idecl idecl.(ind_indices) o
          | _, _ => False
          end;

        ind_sorts :
          check_ind_sorts Σ mdecl.(ind_params) idecl.(ind_kelim)
                          idecl.(ind_indices) ind_cunivs idecl.(ind_sort);

        ind_relevance_compat : isSortRel idecl.(ind_sort) idecl.(ind_relevance);

        onIndices :

          match ind_variance mdecl with
          | Some v => ind_respects_variance Σ mdecl v idecl.(ind_indices)
          | None => True
          end
      }.

    Definition on_variance Σ univs (variances : option (list Variance.t)) :=
      match univs return Type with
      | Monomorphic_ctx => variances = None
      | Polymorphic_ctx auctx =>
        match variances with
        | None => unit
        | Some v =>
          ∑ univs' i i',
            [/\ (variance_universes univs v = Some (univs', i, i')),
              consistent_instance_ext (Σ, univs') univs i,
              consistent_instance_ext (Σ, univs') univs i' &
              List.length v = #|UContext.instance (AUContext.repr auctx)|]
        end
      end.

    Record on_inductive Σ mind mdecl :=
      { onInductives : Alli (on_ind_body Σ mind mdecl) 0 mdecl.(ind_bodies);

        onParams : on_context Σ mdecl.(ind_params);
        onNpars : context_assumptions mdecl.(ind_params) = mdecl.(ind_npars);

        onVariance : on_variance Σ mdecl.(ind_universes) mdecl.(ind_variance);
      }.
Definition on_global_env (g : global_env) : Type.
Admitted.

  End GlobalMaps.
  Arguments on_cargs {_ Pcmp P Σ mdecl i idecl ind_indices cdecl cunivs}.
  Arguments ind_cunivs {_ Pcmp P Σ mind mdecl i idecl}.

End GlobalMaps.

Module Type GlobalMapsSig (T: Term) (E: EnvironmentSig T) (TU : TermUtils T E) (ET: EnvTypingSig T E TU) (C: ConversionSig T E TU ET) (L: LookupSig T E).
  Include GlobalMaps T E TU ET C L.
End GlobalMapsSig.

Module Type ConversionParSig (T : Term) (E : EnvironmentSig T) (TU : TermUtils T E) (ET : EnvTypingSig T E TU).

End ConversionParSig.

Module Type Typing (T : Term) (E : EnvironmentSig T) (TU : TermUtils T E) (ET : EnvTypingSig T E TU)
  (CT : ConversionSig T E TU ET) (CS : ConversionParSig T E TU ET).

End Typing.

Module DeclarationTyping (T : Term) (E : EnvironmentSig T) (TU : TermUtils T E)
  (ET : EnvTypingSig T E TU) (CT : ConversionSig T E TU ET)
  (CS : ConversionParSig T E TU ET) (Ty : Typing T E TU ET CT CS)
  (L : LookupSig T E) (GM : GlobalMapsSig T E TU ET CT L).
Import T.
Import E.
Import L.
Import GM.

  Section Properties.
    Context {cf : checker_flags}.
    Context {Pcmp: global_env_ext -> context -> conv_pb -> term -> term -> Type}.
    Context {P: global_env_ext -> context -> judgment -> Type}.

  Let wf := on_global_env Pcmp P.

  Lemma declared_constructor_to_gen {Σ id mdecl idecl cdecl}
    {wfΣ : wf Σ} :
    declared_constructor Σ id mdecl idecl cdecl ->
    declared_constructor_gen (lookup_env Σ) id mdecl idecl cdecl.
Admitted.
  End Properties.
End DeclarationTyping.

Module Type DeclarationTypingSig (T : Term) (E : EnvironmentSig T) (TU : TermUtils T E)
       (ET : EnvTypingSig T E TU) (CT : ConversionSig T E TU ET)
       (CS : ConversionParSig T E TU ET) (Ty : Typing T E TU ET CT CS)
       (L : LookupSig T E) (GM : GlobalMapsSig T E TU ET CT L).
End DeclarationTypingSig.
End EnvironmentTyping.
Module Export PCUICPrimitive.

Import MetaRocq.Utils.utils.
Import MetaRocq.Common.Universes.
Import MetaRocq.Common.Primitive.

Record array_model {term : Type} :=
  { array_level : Level.t;
    array_type : term;
    array_default : term;
    array_value : list term }.

Arguments array_model : clear implicits.

Inductive prim_model (term : Type) : prim_tag -> Type :=
| primIntModel (i : PrimInt63.int) : prim_model term primInt
| primFloatModel (f : PrimFloat.float) : prim_model term primFloat
| primStringModel (s : PrimString.string) : prim_model term primString
| primArrayModel (a : array_model term) : prim_model term primArray.

Arguments primIntModel {term}.
Arguments primFloatModel {term}.
Arguments primStringModel {term}.
Arguments primArrayModel {term}.

Definition prim_val term := ∑ t : prim_tag, prim_model term t.
Definition prim_val_tag {term} (s : prim_val term) := s.π1.

Inductive onPrims {term} (eq_term : term -> term -> Type) Re : prim_val term -> prim_val term -> Type :=
  | onPrimsInt i : onPrims eq_term Re (primInt; primIntModel i) (primInt; primIntModel i)
  | onPrimsFloat f : onPrims eq_term Re (primFloat; primFloatModel f) (primFloat; primFloatModel f)
  | onPrimsString s : onPrims eq_term Re (primString; primStringModel s) (primString; primStringModel s)
  | onPrimsArray a a' :
    Re (Universe.make' a.(array_level)) (Universe.make' a'.(array_level)) ->
    eq_term a.(array_default) a'.(array_default) ->
    eq_term a.(array_type) a'.(array_type) ->
    All2 eq_term a.(array_value) a'.(array_value) ->
    onPrims eq_term Re (primArray; primArrayModel a) (primArray; primArrayModel a').
Definition mapu_array_model {term term'} (fl : Level.t -> Level.t) (f : term -> term')
  (ar : array_model term) : array_model term'.
exact ({| array_level := fl ar.(array_level);
      array_value := map f ar.(array_value);
      array_default := f ar.(array_default);
      array_type := f ar.(array_type) |}).
Defined.

Equations mapu_prim {term term'} (f : Level.t -> Level.t) (g : term -> term')
  (p : PCUICPrimitive.prim_val term) : PCUICPrimitive.prim_val term' :=
| _, _, (primInt; primIntModel i) => (primInt; primIntModel i)
| _, _, (primFloat; primFloatModel fl) => (primFloat; primFloatModel fl)
| _, _, (primString; primStringModel s) => (primString; primStringModel s)
| f, g, (primArray; primArrayModel ar) =>
  (primArray; primArrayModel (mapu_array_model f g ar)).
Abbreviation map_prim := (mapu_prim id).

Equations test_prim {term} (p : term -> bool) (p : prim_val term) : bool :=
| p, (primInt; _) => true
| p, (primFloat; _) => true
| p, (primString; _) => true
| p, (primArray; primArrayModel ar) =>
  List.forallb p ar.(array_value) && p ar.(array_default) && p ar.(array_type).

End PCUICPrimitive.
Module Export MetaRocq_DOT_PCUIC_DOT_utils_DOT_PCUICPrimitive.
Module Export MetaRocq.
Module Export PCUIC.
Module Export utils.
Module Export PCUICPrimitive.
End PCUICPrimitive.

End utils.

End PCUIC.

End MetaRocq.

End MetaRocq_DOT_PCUIC_DOT_utils_DOT_PCUICPrimitive.
Import MetaRocq.Utils.utils.
Export MetaRocq.Common.Primitive.
Export MetaRocq.Common.Universes.
Export MetaRocq.Common.BasicAst.
Export MetaRocq.Common.Environment.

Record predicate {term} := mk_predicate {
  pparams : list term;
  puinst : Instance.t;
  pcontext : list (context_decl term);

  preturn : term;  }.
Arguments predicate : clear implicits.

Section map_predicate.

End map_predicate.

Section map_predicate_k.
  Context {term : Type}.
  Context (uf : Instance.t -> Instance.t).
  Context (f : nat -> term -> term).

  Definition map_predicate_k k (p : predicate term) :=
    {| pparams := map (f k) p.(pparams);
        puinst := uf p.(puinst);
        pcontext := p.(pcontext);
        preturn := f (#|p.(pcontext)| + k) p.(preturn) |}.

  Definition test_predicate_k (instp : Instance.t -> bool)
    (p : nat -> term -> bool) k (pred : predicate term) :=
    instp pred.(puinst) && forallb (p k) pred.(pparams) &&
    test_context_k p #|pred.(pparams)| pred.(pcontext) &&
    p (#|pred.(pcontext)| + k) pred.(preturn).

End map_predicate_k.

Section Branch.
  Context {term : Type}.

  Record branch := mk_branch {
    bcontext : list (context_decl term);

    bbody : term;  }.

  Definition test_branch_k (pred : predicate term) (p : nat -> term -> bool) k (b : branch) :=
    test_context_k p #|pred.(pparams)| b.(bcontext) && p (#|b.(bcontext)| + k) b.(bbody).

End Branch.

Arguments branch : clear implicits.

Section map_branch.
End map_branch.

Section map_branch_k.
  Context {term term' : Type}.
  Context (f : nat -> term -> term').
  Context (g : list (BasicAst.context_decl term) -> list (BasicAst.context_decl term')).
  Definition map_branch_k k (b : branch term) :=
  {| bcontext := g b.(bcontext);
     bbody := f (#|b.(bcontext)| + k) b.(bbody) |}.
End map_branch_k.

Abbreviation map_branches_k f h k brs :=
  (List.map (map_branch_k f h k) brs).

Abbreviation test_branches_k p test k brs :=
  (List.forallb (test_branch_k p test k) brs).

Inductive term :=
| tRel (n : nat)
| tVar (i : ident)
| tEvar (n : nat) (l : list term)
| tSort (u : sort)
| tProd (na : aname) (A B : term)
| tLambda (na : aname) (A t : term)
| tLetIn (na : aname) (b B t : term)
| tApp (u v : term)
| tConst (k : kername) (ui : Instance.t)
| tInd (ind : inductive) (ui : Instance.t)
| tConstruct (ind : inductive) (n : nat) (ui : Instance.t)
| tCase (indn : case_info) (p : predicate term) (c : term) (brs : list (branch term))
| tProj (p : projection) (c : term)
| tFix (mfix : mfixpoint term) (idx : nat)
| tCoFix (mfix : mfixpoint term) (idx : nat)
| tPrim (prim : prim_val term).

Fixpoint mkApps t us :=
  match us with
  | nil => t
  | u :: us => mkApps (tApp t u) us
  end.

Definition isLambda t :=
  match t with
  | tLambda _ _ _ => true
  | _ => false
  end.

Fixpoint lift n k t : term :=
  match t with
  | tRel i => tRel (if Nat.leb k i then (n + i) else i)
  | tEvar ev args => tEvar ev (List.map (lift n k) args)
  | tLambda na T M => tLambda na (lift n k T) (lift n (S k) M)
  | tApp u v => tApp (lift n k u) (lift n k v)
  | tProd na A B => tProd na (lift n k A) (lift n (S k) B)
  | tLetIn na b t b' => tLetIn na (lift n k b) (lift n k t) (lift n (S k) b')
  | tCase ind p c brs =>
    let p' := map_predicate_k id (lift n) k p in
    let brs' := map_branches_k (lift n) id k brs in
    tCase ind p' (lift n k c) brs'
  | tProj p c => tProj p (lift n k c)
  | tFix mfix idx =>
    let k' := List.length mfix + k in
    let mfix' := List.map (map_def (lift n k) (lift n k')) mfix in
    tFix mfix' idx
  | tCoFix mfix idx =>
    let k' := List.length mfix + k in
    let mfix' := List.map (map_def (lift n k) (lift n k')) mfix in
    tCoFix mfix' idx
  | tPrim p => tPrim (map_prim (lift n k) p)
  | x => x
  end.

Abbreviation lift0 n := (lift n 0).

Fixpoint subst s k u :=
  match u with
  | tRel n =>
    if Nat.leb k n then
      match nth_error s (n - k) with
      | Some b => lift0 k b
      | None => tRel (n - List.length s)
      end
    else tRel n
  | tEvar ev args => tEvar ev (List.map (subst s k) args)
  | tLambda na T M => tLambda na (subst s k T) (subst s (S k) M)
  | tApp u v => tApp (subst s k u) (subst s k v)
  | tProd na A B => tProd na (subst s k A) (subst s (S k) B)
  | tLetIn na b ty b' => tLetIn na (subst s k b) (subst s k ty) (subst s (S k) b')
  | tCase ind p c brs =>
    let p' := map_predicate_k id (subst s) k p in
    let brs' := map_branches_k (subst s) id k brs in
    tCase ind p' (subst s k c) brs'
  | tProj p c => tProj p (subst s k c)
  | tFix mfix idx =>
    let k' := List.length mfix + k in
    let mfix' := List.map (map_def (subst s k) (subst s k')) mfix in
    tFix mfix' idx
  | tCoFix mfix idx =>
    let k' := List.length mfix + k in
    let mfix' := List.map (map_def (subst s k) (subst s k')) mfix in
    tCoFix mfix' idx
  | tPrim p => tPrim (map_prim (subst s k) p)
  | x => x
  end.

Abbreviation subst0 t := (subst t 0).
Definition subst1 t k u := subst [t] k u.
Notation "M { j := N }" := (subst1 N j M) (at level 10, right associativity).

Fixpoint closedn k (t : term) : bool :=
  match t with
  | tRel i => Nat.ltb i k
  | tEvar ev args => List.forallb (closedn k) args
  | tLambda _ T M | tProd _ T M => closedn k T && closedn (S k) M
  | tApp u v => closedn k u && closedn k v
  | tLetIn na b t b' => closedn k b && closedn k t && closedn (S k) b'
  | tCase ind p c brs =>
    let p' := test_predicate_k (fun _ => true) c

[...]

k (fun _ => true) (fun k' => noccur_between k' n) k p in
    let brs' := test_branches_k p (fun k => noccur_between k n) k brs in
    p' && noccur_between k n c && brs'
  | tProj p c => noccur_between k n c
  | tFix mfix idx =>
    let k' := List.length mfix + k in
    List.forallb (test_def (noccur_between k n) (noccur_between k' n)) mfix
  | tCoFix mfix idx =>
    let k' := List.length mfix + k in
    List.forallb (test_def (noccur_between k n) (noccur_between k' n)) mfix
  | tPrim p => test_prim (noccur_between k n) p
  | _ => true
  end.
#[global]
Instance subst_instance_constr : UnivSubst term.
Admitted.

Module PCUICTerm <: Term.

  Definition term := term.

  Definition tRel := tRel.
  Definition tSort := tSort.
  Definition tProd := tProd.
  Definition tLambda := tLambda.
  Definition tLetIn := tLetIn.
  Definition tInd := tInd.
  Definition tProj := tProj.
  Definition mkApps := mkApps.

  Definition lift := lift.
  Definition subst := subst.
  Definition closedn := closedn.
  Definition noccur_between := noccur_between.
  Definition subst_instance_constr := subst_instance.
End PCUICTerm.

Module PCUICEnvironment := Environment PCUICTerm.
Export PCUICEnvironment.

Fixpoint destArity Γ (t : term) :=
  match t with
  | tProd na t b => destArity (Γ ,, vass na t) b
  | tLetIn na b b_ty b' => destArity (Γ ,, vdef na b b_ty) b'
  | tSort s => Some (Γ, s)
  | _ => None
  end.

Definition inds ind u (l : list one_inductive_body) :=
  let fix aux n :=
      match n with
      | 0 => []
      | S n => tInd (mkInd ind n) u :: aux n
      end
  in aux (List.length l).

Module PCUICTermUtils <: TermUtils PCUICTerm PCUICEnvironment.

Definition destArity := destArity.
Definition inds := inds.

End PCUICTermUtils.

Module PCUICEnvTyping := EnvironmentTyping.EnvTyping PCUICTerm PCUICEnvironment PCUICTermUtils.

Module PCUICConversion := EnvironmentTyping.Conversion PCUICTerm PCUICEnvironment PCUICTermUtils PCUICEnvTyping.

Module PCUICLookup := EnvironmentTyping.Lookup PCUICTerm PCUICEnvironment.
Include PCUICLookup.

Module PCUICGlobalMaps := EnvironmentTyping.GlobalMaps
  PCUICTerm
  PCUICEnvironment
  PCUICTermUtils
  PCUICEnvTyping
  PCUICConversion
  PCUICLookup
.
Include PCUICGlobalMaps.
Module Export MetaRocq_DOT_PCUIC_DOT_PCUICAst.
Module Export MetaRocq.
Module Export PCUIC.
Module Export PCUICAst.
End PCUICAst.

End PCUIC.

End MetaRocq.

End MetaRocq_DOT_PCUIC_DOT_PCUICAst.

Import MetaRocq.Utils.utils.
Import MetaRocq.PCUIC.PCUICAst.

Fixpoint decompose_app_rec (t : term) l :=
  match t with
  | tApp f a => decompose_app_rec f (a :: l)
  | _ => (t, l)
  end.

Definition decompose_app t := decompose_app_rec t [].

Definition isConstruct_app t :=
  match fst (decompose_app t) with
  | tConstruct _ _ _ => true
  | _ => false
  end.
Fixpoint decompose_prod_assum (Γ : context) (t : term) : context * term.
Admitted.
Module Export MetaRocq.
Module Export PCUIC.
Module Export utils.
Module Export PCUICAstUtils.
End PCUICAstUtils.

End utils.

End PCUIC.

End MetaRocq.
Import MetaRocq.Utils.utils.
Import MetaRocq.PCUIC.PCUICAst.
Import MetaRocq.PCUIC.utils.PCUICAstUtils.

Coercion ci_ind : case_info >-> inductive.

Definition ind_predicate_context ind mdecl idecl : context :=
  let ictx := (expand_lets_ctx mdecl.(ind_params) idecl.(ind_indices)) in
  let indty := mkApps (tInd ind (abstract_instance mdecl.(ind_universes)))
    (to_extended_list (smash_context [] mdecl.(ind_params) ,,, ictx)) in
  let inddecl :=
    {| decl_name :=
      {| binder_name := nNamed (ind_name idecl); binder_relevance := idecl.(ind_relevance) |};
       decl_body := None;
       decl_type := indty |}
  in (inddecl :: ictx).

Definition inst_case_context params puinst (pctx : context) :=
  subst_context (List.rev params) 0 (subst_instance puinst pctx).

Definition inst_case_predicate_context (p : predicate term) :=
  inst_case_context p.(pparams) p.(puinst) p.(pcontext).

Definition inst_case_branch_context (p : predicate term) (br : branch term) :=
  inst_case_context p.(pparams) p.(puinst) br.(bcontext).

Definition iota_red npar p args br :=
  subst (List.rev (List.skipn npar args)) 0
    (expand_lets (inst_case_branch_context p br) (bbody br)).

Definition pre_case_predicate_context_gen ind mdecl idecl params puinst : context :=
  inst_case_context params puinst (ind_predicate_context ind mdecl idecl).

Definition case_predicate_context_gen ind mdecl idecl params puinst pctx :=
  map2 set_binder_name pctx (pre_case_predicate_context_gen ind mdecl idecl params puinst).

Definition case_predicate_context ind mdecl idecl p : context :=
  case_predicate_context_gen ind mdecl idecl p.(pparams) p.(puinst) (forget_types p.(pcontext)).

Definition cstr_branch_context ind mdecl cdecl : context :=
  expand_lets_ctx mdecl.(ind_params)
    (subst_context (inds (inductive_mind ind) (abstract_instance mdecl.(ind_universes))
       mdecl.(ind_bodies)) #|mdecl.(ind_params)|
      cdecl.(cstr_args)).

Definition pre_case_branch_context_gen ind mdecl cdecl params puinst : context :=
  inst_case_context params puinst (cstr_branch_context ind mdecl cdecl).

Definition case_branch_context_gen ind mdecl params puinst pctx cdecl :=
  map2 set_binder_name pctx (pre_case_branch_context_gen ind mdecl cdecl params puinst).

Definition case_branch_type_gen ind mdecl (idecl : one_inductive_body) params puinst bctx ptm i cdecl : context * term :=
  let cstr := tConstruct ind i puinst in
  let args := to_extended_list cdecl.(cstr_args) in
  let cstrapp := mkApps cstr (map (lift0 #|cdecl.(cstr_args)|) params ++ args) in
  let brctx := case_branch_context_gen ind mdecl params puinst bctx cdecl in
  let upars := subst_instance puinst mdecl.(ind_params) in
  let indices :=
    (map (subst (List.rev params) #|cdecl.(cstr_args)|)
      (map (expand_lets_k upars #|cdecl.(cstr_args)|)
        (map (subst (inds (inductive_mind ind) puinst mdecl.(ind_bodies))
                    (#|mdecl.(ind_params)| + #|cdecl.(cstr_args)|))
          (map (subst_instance puinst) cdecl.(cstr_indices))))) in
  let ty := mkApps (lift0 #|cdecl.(cstr_args)| ptm) (indices ++ [cstrapp]) in
  (brctx, ty).

Definition case_branch_type ind mdecl idecl p (b : branch term) ptm i cdecl : context * term :=
  case_branch_type_gen ind mdecl idecl p.(pparams) p.(puinst) (forget_types b.(bcontext)) ptm i cdecl.

Definition idecl_binder idecl :=
  {| decl_name :=
    {| binder_name := nNamed idecl.(ind_name);
        binder_relevance := idecl.(ind_relevance) |};
     decl_body := None;
     decl_type := idecl.(ind_type) |}.

Definition wf_predicate_gen mdecl idecl (pparams : list term) (pcontext : list aname) : Prop :=
  let decl := idecl_binder idecl in
  (#|pparams| = mdecl.(ind_npars)) /\
  (Forall2 (fun na decl => eq_binder_annot na decl.(decl_name))
    pcontext (decl :: idecl.(ind_indices))).

Definition wf_predicate mdecl idecl (p : predicate term) : Prop :=
  wf_predicate_gen mdecl idecl p.(pparams) (forget_types p.(pcontext)).

Definition wf_branch_gen cdecl (bctx : list aname) : Prop :=
  (Forall2 (fun na decl => eq_binder_annot na decl.(decl_name))
    bctx cdecl.(cstr_args)).

Definition wf_branch cdecl (b : branch term) : Prop :=
  wf_branch_gen cdecl (forget_types b.(bcontext)).

Definition wf_branches idecl (brs : list (branch term)) : Prop :=
  Forall2 wf_branch idecl.(ind_ctors) brs.

Definition fix_subst (l : mfixpoint term) :=
  let fix aux n :=
      match n with
      | 0 => []
      | S n => tFix l n :: aux n
      end
  in aux (List.length l).

Definition unfold_fix (mfix : mfixpoint term) (idx : nat) :=
  match List.nth_error mfix idx with
  | Some d => Some (d.(rarg), subst0 (fix_subst mfix) d.(dbody))
  | None => None
  end.

Definition cofix_subst (l : mfixpoint term) :=
  let fix aux n :=
      match n with
      | 0 => []
      | S n => tCoFix l n :: aux n
      end
  in aux (List.length l).

Definition unfold_cofix (mfix : mfixpoint term) (idx : nat) :=
  match List.nth_error mfix idx with
  | Some d => Some (d.(rarg), subst0 (cofix_subst mfix) d.(dbody))
  | None => None
  end.

Definition is_constructor n ts :=
  match List.nth_error ts n with
  | Some a => isConstruct_app a
  | None => false
  end.
Import MetaRocq.Utils.utils.
Import MetaRocq.PCUIC.PCUICAst.
Definition cmp_universe_instance (cmp_univ : Universe.t -> Universe.t -> Prop) : Instance.t -> Instance.t -> Prop.
Admitted.

Definition cmp_universe_variance (cmp_univ : conv_pb -> Universe.t -> Universe.t -> Prop) pb v u u' :=
  match v with
  | Variance.Irrelevant => True
  | Variance.Covariant => on_rel (cmp_univ pb) Universe.make' u u'
  | Variance.Invariant => on_rel (cmp_univ Conv) Universe.make' u u'
  end.

Definition cmp_universe_instance_variance cmp_univ pb v u u' :=
  Forall3 (cmp_universe_variance cmp_univ pb) v u u'.

Definition global_variance_gen lookup gr napp :=
  match gr with
  | IndRef ind =>
    match lookup_inductive_gen lookup ind with
    | Some (mdecl, idecl) =>
      match destArity [] idecl.(ind_type) with
      | Some (ctx, _) => if (context_assumptions ctx) <=? napp then
          match mdecl.(ind_variance) with
          | Some var => Variance var
          | None => AllEqual
          end
        else AllEqual
      | None => AllEqual
      end
    | None => AllEqual
    end
  | ConstructRef ind k =>
    match lookup_constructor_gen lookup ind k with
    | Some (mdecl, idecl, cdecl) =>
      if (cdecl.(cstr_arity) + mdecl.(ind_npars))%nat <=? napp then

        AllIrrelevant
      else AllEqual
    | _ => AllEqual
    end
  | _ => AllEqual
  end.

Definition cmp_opt_variance cmp_univ pb v :=
  match v with
  | AllEqual => cmp_universe_instance (cmp_univ Conv)
  | AllIrrelevant => fun l l' => #|l| = #|l'|
  | Variance v => fun u u' => cmp_universe_instance (cmp_univ Conv) u u' \/ cmp_universe_instance_variance cmp_univ pb v u u'
  end.

Definition cmp_global_instance_gen Σ cmp_universe pb gr napp :=
  cmp_opt_variance cmp_universe pb (global_variance_gen Σ gr napp).

Abbreviation cmp_global_instance Σ := (cmp_global_instance_gen (lookup_env Σ)).

Inductive eq_decl_upto_names : context_decl -> context_decl -> Type :=
  | compare_vass {na na' T} :
    eq_binder_annot na na' -> eq_decl_upto_names (vass na T) (vass na' T)
  | compare_vdef {na na' b T} :
    eq_binder_annot na na' -> eq_decl_upto_names (vdef na b T) (vdef na' b T).

Abbreviation eq_context_upto_names := (All2 eq_decl_upto_names).

Import MetaRocq.Utils.utils.
Import MetaRocq.PCUIC.PCUICAst.

Inductive context_subst : context -> list term -> list term -> Type :=
| context_subst_nil : context_subst [] [] []
| context_subst_ass Γ args s na t a :
    context_subst Γ args s ->
    context_subst (vass na t :: Γ) (args ++ [a]) (a :: s)
| context_subst_def Γ args s na b t :
    context_subst Γ args s ->
    context_subst (vdef na b t :: Γ) args (subst s 0 b :: s).
Import Stdlib.ssr.ssrbool.

Definition shiftnP k p i :=
  (i <? k) || p (i - k).
Fixpoint on_free_vars (p : nat -> bool) (t : term) : bool.
Admitted.

Definition on_free_vars_decl P d :=
  test_decl (on_free_vars P) d.

Definition on_free_vars_ctx P ctx :=
  alli (fun k => (on_free_vars_decl (shiftnP k P))) 0 (List.rev ctx).

Abbreviation is_open_term Γ := (on_free_vars (shiftnP #|Γ| xpred0)).
Abbreviation is_closed_context := (on_free_vars_ctx xpred0).
Import MetaRocq.Common.config.

Implicit Types (cf : checker_flags).

Definition cumul_predicate (cumul : context -> term -> term -> Type) cumul_universe Γ p p' :=
  All2 (cumul Γ) p.(pparams) p'.(pparams) ×
  cmp_universe_instance cumul_universe p.(puinst) p'.(puinst) ×
  eq_context_upto_names p.(pcontext) p'.(pcontext) ×
  cumul (Γ ,,, inst_case_predicate_context p) p.(preturn) p'.(preturn).

Definition cumul_branch (cumul_term : context -> term -> term -> Type) Γ p br br' :=
  eq_context_upto_names br.(bcontext) br'.(bcontext) ×
  cumul_term (Γ ,,, inst_case_branch_context p br) br.(bbody) br'.(bbody).

Definition cumul_branches cumul_term Γ p brs brs' := All2 (cumul_branch cumul_term Γ p) brs brs'.

Definition cumul_mfixpoint (cumul_term : context -> term -> term -> Type) Γ mfix mfix' :=
  All2 (fun d d' =>
    cumul_term Γ d.(dtype) d'.(dtype) ×
    cumul_term (Γ ,,, fix_context mfix) d.(dbody) d'.(dbody) ×
    d.(rarg) = d'.(rarg) ×
    eq_binder_annot d.(dname) d'.(dname)
  ) mfix mfix'.

Reserved Notation " Σ ;;; Γ ⊢ t ≤s[ pb ] u" (at level 50, Γ, t, u at next level,
  format "Σ  ;;;  Γ  ⊢  t  ≤s[ pb ]  u").

Definition cumul_Ind_univ {cf} (Σ : global_env_ext) pb i napp :=
  cmp_global_instance Σ (compare_universe Σ) pb (IndRef i) napp.

Definition cumul_Construct_univ {cf} (Σ : global_env_ext) pb  i k napp :=
  cmp_global_instance Σ (compare_universe Σ) pb (ConstructRef i k) napp.
Inductive cumulSpec0 {cf : checker_flags} (Σ : global_env_ext) Γ (pb : conv_pb) : term -> term -> Type :=

| cumul_Trans : forall t u v,
    is_closed_context Γ -> is_open_term Γ u ->
    Σ ;;; Γ ⊢ t ≤s[pb] u ->
    Σ ;;; Γ ⊢ u ≤s[pb] v ->
    Σ ;;; Γ ⊢ t ≤s[pb] v

| cumul_Sym : forall t u,
    Σ ;;; Γ ⊢ t ≤s[Conv] u ->
    Σ ;;; Γ ⊢ u ≤s[pb] t

| cumul_Refl : forall t,
    Σ ;;; Γ ⊢ t ≤s[pb] t

| cumul_Ind : forall i u u' args args',
    cumul_Ind_univ Σ pb i #|args| u u' ->
    All2 (fun t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) args args' ->
    Σ ;;; Γ ⊢ mkApps (tInd i u) args ≤s[pb] mkApps (tInd i u') args'

| cumul_Construct : forall i k u u' args args',
    cumul_Construct_univ Σ pb i k #|args| u u' ->
    All2 (fun t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) args args' ->
    Σ ;;; Γ ⊢ mkApps (tConstruct i k u) args ≤s[pb] mkApps (tConstruct i k u') args'

| cumul_Sort : forall s s',
    compare_sort Σ pb s s' ->
    Σ ;;; Γ ⊢ tSort s ≤s[pb] tSort s'

| cumul_Const : forall c u u',
    cmp_universe_instance (compare_universe Σ Conv) u u' ->
    Σ ;;; Γ ⊢ tConst c u ≤s[pb] tConst c u'

| cumul_Evar : forall e args args',
    All2 (fun t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) args args' ->
    Σ ;;; Γ ⊢ tEvar e args ≤s[pb] tEvar e args'

| cumul_App : forall t t' u u',
    Σ ;;; Γ ⊢ t ≤s[pb] t' ->
    Σ ;;; Γ ⊢ u ≤s[Conv] u' ->
    Σ ;;; Γ ⊢ tApp t u ≤s[pb] tApp t' u'

| cumul_Lambda : forall na na' ty ty' t t',
    eq_binder_annot na na' ->
    Σ ;;; Γ ⊢ ty ≤s[Conv] ty' ->
    Σ ;;; Γ ,, vass na ty ⊢ t ≤s[Conv] t' ->
    Σ ;;; Γ ⊢ tLambda na ty t ≤s[pb] tLambda na' ty' t'

| cumul_Prod : forall na na' a a' b b',
    eq_binder_annot na na' ->
    Σ ;;; Γ ⊢ a ≤s[Conv] a' ->
    Σ ;;; Γ ,, vass na a ⊢ b ≤s[pb] b' ->
    Σ ;;; Γ ⊢ tProd na a b ≤s[pb] tProd na' a' b'

| cumul_LetIn : forall na na' t t' ty ty' u u',
    eq_binder_annot na na' ->
    Σ ;;; Γ ⊢ t ≤s[Conv] t' ->
    Σ ;;; Γ ⊢ ty ≤s[Conv] ty' ->
    Σ ;;; Γ ,, vdef na t ty ⊢ u ≤s[Conv] u' ->
    Σ ;;; Γ ⊢ tLetIn na t ty u ≤s[pb] tLetIn na' t' ty' u'

| cumul_Case indn : forall p p' c c' brs brs',
    cumul_predicate (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) (compare_universe Σ Conv) Γ p p' ->
    Σ ;;; Γ ⊢ c ≤s[Conv] c' ->
    cumul_branches (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) Γ p brs brs' ->
    Σ ;;; Γ ⊢ tCase indn p c brs ≤s[pb] tCase indn p' c' brs'

| cumul_Proj : forall p c c',
    Σ ;;; Γ ⊢ c ≤s[Conv] c' ->
    Σ ;;; Γ ⊢ tProj p c ≤s[pb] tProj p c'

| cumul_Fix : forall mfix mfix' idx,
    cumul_mfixpoint (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) Γ mfix mfix' ->
    Σ ;;; Γ ⊢ tFix mfix idx ≤s[pb] tFix mfix' idx

| cumul_CoFix : forall mfix mfix' idx,
    cumul_mfixpoint (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) Γ mfix mfix' ->
    Σ ;;; Γ ⊢ tCoFix mfix idx ≤s[pb] tCoFix mfix' idx

| cumul_Prim p p' :
  onPrims (fun x y => Σ ;;; Γ ⊢ x ≤s[Conv] y) (compare_universe Σ Conv) p p' ->
  Σ ;;; Γ ⊢ tPrim p ≤s[pb] tPrim p'

| cumul_beta : forall na t b a,
    Σ ;;; Γ ⊢ tApp (tLambda na t b) a ≤s[pb] b {0 := a}

| cumul_zeta : forall na b t b',
    Σ ;;; Γ ⊢ tLetIn na b t b' ≤s[pb] b' {0 := b}

| cumul_rel i body :
    option_map decl_body (nth_error Γ i) = Some (Some body) ->
    Σ ;;; Γ ⊢ tRel i ≤s[pb] lift0 (S i) body

| cumul_iota : forall ci c u args p brs br,
    nth_error brs c = Some br ->
    #|args| = (ci.(ci_npar) + context_assumptions br.(bcontext))%nat ->
    Σ ;;; Γ ⊢ tCase ci p (mkApps (tConstruct ci.(ci_ind) c u) args) brs  ≤s[pb] iota_red ci.(ci_npar) p args br

| cumul_fix : forall mfix idx args narg fn,
    unfold_fix mfix idx = Some (narg, fn) ->
    is_constructor narg args = true ->
    Σ ;;; Γ ⊢ mkApps (tFix mfix idx) args ≤s[pb] mkApps fn args

| cumul_cofix_case : forall ip p mfix idx args narg fn brs,
    unfold_cofix mfix idx = Some (narg, fn) ->
    Σ ;;; Γ ⊢ tCase ip p (mkApps (tCoFix mfix idx) args) brs ≤s[pb] tCase ip p (mkApps fn args) brs

| cumul_cofix_proj : forall p mfix idx args narg fn,
    unfold_cofix mfix idx = Some (narg, fn) ->
    Σ ;;; Γ ⊢ tProj p (mkApps (tCoFix mfix idx) args) ≤s[pb] tProj p (mkApps fn args)

| cumul_delta : forall c decl body (isdecl : declared_constant Σ c decl) u,
    decl.(cst_body) = Some body ->
    Σ ;;; Γ ⊢ tConst c u ≤s[pb] body@[u]

| cumul_proj : forall p args u arg,
    nth_error args (p.(proj_npars) + p.(proj_arg)) = Some arg ->
    Σ ;;; Γ ⊢ tProj p (mkApps (tConstruct p.(proj_ind) 0 u) args) ≤s[pb] arg

where " Σ ;;; Γ ⊢ t ≤s[ pb ] u " := (@cumulSpec0 _ Σ Γ pb t u) : type_scope.
Definition cumulSpec `{checker_flags} (Σ : global_env_ext) Γ := cumulSpec0 Σ Γ Cumul.

Notation " Σ ;;; Γ |- t <=s u " := (@cumulSpec _ Σ Γ t u) (at level 50, Γ, t, u at next level).

Module PCUICConversionParSpec <: EnvironmentTyping.ConversionParSig PCUICTerm PCUICEnvironment PCUICTermUtils PCUICEnvTyping.
  Definition cumul_gen := @cumulSpec0.
End PCUICConversionParSpec.
Import MetaRocq.PCUIC.utils.PCUICAstUtils.
Import MetaRocq.PCUIC.utils.PCUICPrimitive.

Definition type_of_constructor mdecl (cdecl : constructor_body) (c : inductive * nat) (u : list Level.t) :=
  let mind := inductive_mind (fst c) in
  subst0 (inds mind u mdecl.(ind_bodies)) (subst_instance u (cstr_type cdecl)).

Include PCUICEnvTyping.

Inductive FixCoFix : Type := Fix | CoFix.

Class GuardChecker :=
{
  guard : FixCoFix -> global_env_ext -> context -> mfixpoint term -> Prop ;
}.

Axiom guard_checking : GuardChecker.
#[global]
Existing Instance guard_checking.

Definition fix_guard := guard Fix.
Definition cofix_guard := guard CoFix.

Definition destInd (t : term) :=
  match t with
  | tInd ind u => Some (ind, u)
  | _ => None
  end.

Definition isCoFinite (r : recursivity_kind) :=
  match r with
  | CoFinite => true
  | _ => false
  end.

Definition check_recursivity_kind
  (lookup: kername -> option global_decl) ind r :=
  match lookup ind with
  | Some (InductiveDecl mib) => ReflectEq.eqb mib.(ind_finite) r
  | _ => false
  end.

Definition check_one_fix d :=
  let '{| dname := na;
         dtype := ty;
         dbody := b;
         rarg := arg |} := d in
  let '(ctx, ty) := decompose_prod_assum [] ty in
  match nth_error (List.rev (smash_context [] ctx)) arg with
  | Some argd =>
    let (hd, args) := decompose_app argd.(decl_type) in
    match destInd hd with
    | Some (mkInd mind _, u) => Some mind
    | None => None
    end
  | None => None
  end.

Definition wf_fixpoint_gen
  (lookup: kername -> option global_decl) mfix :=
  forallb (isLambda ∘ dbody) mfix &&
  let checks := map check_one_fix mfix in
  match map_option_out checks with
  | Some (ind :: inds) =>

    forallb (eqb ind) inds &&
    check_recursivity_kind lookup ind Finite
  | _ => false
  end.

Definition wf_fixpoint (Σ : global_env) := wf_fixpoint_gen (lookup_env Σ).

Definition check_one_cofix d :=
  let '{| dname := na;
         dtype := ty;
         dbody := b;
         rarg := arg |} := d in
  let '(ctx, ty) := decompose_prod_assum [] ty in
  let (hd, args) := decompose_app ty in
  match destInd hd with
  | Some (mkInd ind _, u) => Some ind
  | None => None
  end.

Definition wf_cofixpoint_gen
  (lookup: kername -> option global_decl) mfix :=
  let checks := map check_one_cofix mfix in
  match map_option_out checks with
  | Some (ind :: inds) =>

    forallb (eqb ind) inds &&
    check_recursivity_kind lookup ind CoFinite
  | _ => false
  end.

Definition wf_cofixpoint (Σ : global_env) := wf_cofixpoint_gen (lookup_env Σ).

Reserved Notation "'wf_local' Σ Γ " (at level 9, Σ, Γ at next level).

Reserved Notation " Σ ;;; Γ |- t : T " (at level 50, Γ, t, T at next level).

Variant case_side_conditions `{checker_flags} wf_local_funΣ typingΣ Σ Γ ci p ps mdecl idecl indices predctx :=
| case_side_info
    (eq_npars : mdecl.(ind_npars) = ci.(ci_npar))
    (wf_pred : wf_predicate mdecl idecl p)
    (cons : consistent_instance_ext Σ (ind_universes mdecl) p.(puinst))
    (wf_pctx : wf_local_funΣ (Γ ,,, predctx))

    (conv_pctx : eq_context_upto_names p.(pcontext) (ind_predicate_context ci.(ci_ind) mdecl idecl))
    (allowed_elim : is_allowed_elimination Σ idecl.(ind_kelim) ps)
    (elim_relevance : isSortRel ps ci.(ci_relevance))
    (ind_inst : ctx_inst typingΣ Γ (p.(pparams) ++ indices)
                         (List.rev (subst_instance p.(puinst)
                                                   (ind_params mdecl ,,, ind_indices idecl : context))))
    (not_cofinite : isCoFinite mdecl.(ind_finite) = false).

Variant case_branch_typing `{checker_flags} wf_local_funΣ typingΣ Γ (ci:case_info) p ps mdecl idecl ptm  brs :=
| case_branch_info
    (wf_brs : wf_branches idecl brs)
    (brs_ty :
       All2i (fun i cdecl br =>

                eq_context_upto_names br.(bcontext) (cstr_branch_context ci mdecl cdecl) ×
                let brctxty := case_branch_type ci.(ci_ind) mdecl idecl p br ptm i cdecl in
                (wf_local_funΣ (Γ ,,, brctxty.1) ×
                ((typingΣ (Γ ,,, brctxty.1) br.(bbody) (brctxty.2)) ×
                (typingΣ (Γ ,,, brctxty.1) brctxty.2 (tSort ps)))))
             0 idecl.(ind_ctors) brs).

Variant primitive_typing_hyps `{checker_flags}
  (typingΣ : forall (Γ : context), term -> term -> Type)
  Σ Γ : prim_val term -> Type :=
| prim_int_hyps i : primitive_typing_hyps typingΣ Σ Γ (primInt; primIntModel i)
| prim_float_hyps f : primitive_typing_hyps typingΣ Σ Γ (primFloat; primFloatModel f)
| prim_string_hyps s : primitive_typing_hyps typingΣ Σ Γ (primString; primStringModel s)
| prim_array_hyps a
  (wfl : wf_universe Σ (Universe.make' a.(array_level)))
  (hty : typingΣ Γ a.(array_type) (tSort (sType (Universe.make' a.(array_level)))))
  (hdef : typingΣ Γ a.(array_default) a.(array_type))
  (hvalue : All (fun x => typingΣ Γ x a.(array_type)) a.(array_value)) :
  primitive_typing_hyps typingΣ Σ Γ (primArray; primArrayModel a).

Equations prim_type (p : prim_val term) (cst : kername) : term :=
prim_type (primInt; _) cst := tConst cst [];
prim_type (primFloat; _) cst := tConst cst [];
prim_type (primString; _) cst := tConst cst [];
prim_type (primArray; primArrayModel a) cst := tApp (tConst cst [a.(array_level)]) a.(array_type).

Inductive typing `{checker_flags} (Σ : global_env_ext) (Γ : context) : term -> term -> Type :=
| type_Rel : forall n decl,
    wf_local Σ Γ ->
    nth_error Γ n = Some decl ->
    Σ ;;; Γ |- tRel n : lift0 (S n) decl.(decl_type)

| type_Sort : forall s,
    wf_local Σ Γ ->
    wf_sort Σ s ->
    Σ ;;; Γ |- tSort s : tSort (Sort.super s)

| type_Prod : forall na A B s1 s2,
    lift_typing typing Σ Γ (j_vass_s na A s1) ->
    Σ ;;; Γ ,, vass na A |- B : tSort s2 ->
    Σ ;;; Γ |- tProd na A B : tSort (Sort.sort_of_product s1 s2)

| type_Lambda : forall na A t B,
    lift_typing typing Σ Γ (j_vass na A) ->
    Σ ;;; Γ ,, vass na A |- t : B ->
    Σ ;;; Γ |- tLambda na A t : tProd na A B

| type_LetIn : forall na b B t A,
    lift_typing typing Σ Γ (j_vdef na b B) ->
    Σ ;;; Γ ,, vdef na b B |- t : A ->
    Σ ;;; Γ |- tLetIn na b B t : tLetIn na b B A

| type_App : forall t na A B s u,

    Σ ;;; Γ |- tProd na A B : tSort s ->
    Σ ;;; Γ |- t : tProd na A B ->
    Σ ;;; Γ |- u : A ->
    Σ ;;; Γ |- tApp t u : B{0 := u}

| type_Const : forall cst u decl,
    wf_local Σ Γ ->
    declared_constant Σ cst decl ->
    consistent_instance_ext Σ decl.(cst_universes) u ->
    Σ ;;; Γ |- tConst cst u : decl.(cst_type)@[u]

| type_Ind : forall ind u mdecl idecl,
    wf_local Σ Γ ->
    declared_inductive Σ ind mdecl idecl ->
    consistent_instance_ext Σ mdecl.(ind_universes) u ->
    Σ ;;; Γ |- tInd ind u : idecl.(ind_type)@[u]

| type_Construct : forall ind i u mdecl idecl cdecl,
    wf_local Σ Γ ->
    declared_constructor Σ (ind, i) mdecl idecl cdecl ->
    consistent_instance_ext Σ mdecl.(ind_universes) u ->
    Σ ;;; Γ |- tConstruct ind i u : type_of_constructor mdecl cdecl (ind, i) u

| type_Case : forall ci p c brs indices ps mdecl idecl,
    let predctx := case_predicate_context ci.(ci_ind) mdecl idecl p in
    let ptm := it_mkLambda_or_LetIn predctx p.(preturn) in
    declared_inductive Σ ci.(ci_ind) mdecl idecl ->
    Σ ;;; Γ ,,, predctx |- p.(preturn) : tSort ps ->
    Σ ;;; Γ |- c : mkApps (tInd ci.(ci_ind) p.(puinst)) (p.(pparams) ++ indices) ->
    case_side_conditions (fun Γ => wf_local Σ Γ) (typing Σ) Σ Γ ci p ps
                         mdecl idecl indices predctx  ->
    case_branch_typing (fun Γ => wf_local Σ Γ) (typing Σ) Γ ci p ps
                        mdecl idecl ptm brs ->
    Σ ;;; Γ |- tCase ci p c brs : mkApps ptm (indices ++ [c])

| type_Proj : forall p c u mdecl idecl cdecl pdecl args,
    declared_projection Σ p mdecl idecl cdecl pdecl ->
    Σ ;;; Γ |- c : mkApps (tInd p.(proj_ind) u) args ->
    #|args| = ind_npars mdecl ->
    Σ ;;; Γ |- tProj p c : subst0 (c :: List.rev args) pdecl.(proj_type)@[u]

| type_Fix : forall mfix n decl,
    wf_local Σ Γ ->
    fix_guard Σ Γ mfix ->
    nth_error mfix n = Some decl ->
    All (on_def_type (lift_typing1 (typing Σ)) Γ) mfix ->
    All (on_def_body (lift_typing1 (typing Σ)) (fix_context mfix) Γ) mfix ->
    wf_fixpoint Σ mfix ->
    Σ ;;; Γ |- tFix mfix n : decl.(dtype)

| type_CoFix : forall mfix n decl,
    wf_local Σ Γ ->
    cofix_guard Σ Γ mfix ->
    nth_error mfix n = Some decl ->
    All (on_def_type (lift_typing1 (typing Σ)) Γ) mfix ->
    All (on_def_body (lift_typing1 (typing Σ)) (fix_context mfix) Γ) mfix ->
    wf_cofixpoint Σ mfix ->
    Σ ;;; Γ |- tCoFix mfix n : decl.(dtype)

| type_Prim p prim_ty cdecl :
    wf_local Σ Γ ->
    primitive_constant Σ (prim_val_tag p) = Some prim_ty ->
    declared_constant Σ prim_ty cdecl ->
    primitive_invariants (prim_val_tag p) cdecl ->
    primitive_typing_hyps (typing Σ) Σ Γ p ->
    Σ ;;; Γ |- tPrim p : prim_type p prim_ty

| type_Cumul : forall t A B s,
    Σ ;;; Γ |- t : A ->
    Σ ;;; Γ |- B : tSort s ->
    Σ ;;; Γ |- A <=s B ->
    Σ ;;; Γ |- t : B

where " Σ ;;; Γ |- t : T " := (typing Σ Γ t T)
and "'wf_local' Σ Γ " := (All_local_env (lift_typing1 (typing Σ)) Γ).

Module PCUICTypingDef <: EnvironmentTyping.Typing PCUICTerm PCUICEnvironment PCUICTermUtils PCUICEnvTyping PCUICConversion PCUICConversionParSpec.

  Definition typing := @typing.

End PCUICTypingDef.

Module PCUICDeclarationTyping :=
  EnvironmentTyping.DeclarationTyping
    PCUICTerm
    PCUICEnvironment
    PCUICTermUtils
    PCUICEnvTyping
    PCUICConversion
    PCUICConversionParSpec
    PCUICTypingDef
    PCUICLookup
    PCUICGlobalMaps.
Include PCUICDeclarationTyping.

Definition wf `{checker_flags} := on_global_env cumulSpec0 (lift_typing typing).
Existing Class wf.

Definition on_udecl_prop (Σ : global_env) (udecl : universes_decl)
  := let levels := levels_of_udecl udecl in
     let global_levels := global_levels Σ.(universes) in
     let all_levels := LevelSet.union levels global_levels in
     ConstraintSet.For_all (declared_cstr_levels all_levels) (constraints_of_udecl udecl).

Section ExtendsWf.
  Context {cf : checker_flags}.
  Context {Pcmp: global_env_ext -> context -> conv_pb -> term -> term -> Type}.
  Context {P: global_env_ext -> context -> judgment -> Type}.

  Let wf := on_global_env Pcmp P.

Lemma weaken_lookup_on_global_env' Σ c decl :
  wf Σ ->
  lookup_env Σ c = Some decl ->
  on_udecl_prop Σ (universes_decl_of_decl decl).
Admitted.

Definition weaken_env_prop_gen
           (R : global_env_ext -> global_env_ext -> Type)
           (P : global_env_ext -> context -> judgment -> Type) :=
  forall Σ Σ' φ, wf Σ -> wf Σ' -> R (Σ, φ) (Σ', φ) -> forall Γ j, P (Σ, φ) Γ j -> P (Σ', φ) Γ j.

Definition weaken_env_prop := weaken_env_prop_gen extends.
Definition weaken_env_decls_prop := weaken_env_prop_gen extends_decls.
Definition weaken_env_strictly_decls_prop := weaken_env_prop_gen strictly_extends_decls.

End ExtendsWf.
Arguments weaken_env_prop {cf} (Pcmp P)%_function_scope _%_function_scope.
Arguments weaken_env_strictly_decls_prop {cf} (Pcmp P)%_function_scope _%_function_scope.

#[warnings="-ambiguous-paths"]
Global Coercion weaken_env_prop_to_decls {cf Pcmp P P0} : @weaken_env_prop cf Pcmp P P0 -> @weaken_env_decls_prop cf Pcmp P P0.
Admitted.
#[warnings="-ambiguous-paths"]
Global Coercion weaken_env_prop_decls_to_strictly_decls {cf Pcmp P P0} : @weaken_env_decls_prop cf Pcmp P P0 -> @weaken_env_strictly_decls_prop cf Pcmp P P0.
Admitted.

Definition wf_ext_wk {cf : checker_flags} (Σ : global_env_ext)
  := wf Σ.1 × on_udecl_prop Σ.1 Σ.2.

Definition wf_global_ext {cf : checker_flags} Σ ext := wf_ext_wk (Σ, ext).

Lemma declared_inductive_inv `{checker_flags} {Σ P ind mdecl idecl} :
  weaken_env_strictly_decls_prop cumulSpec0 (lift_typing typing) P ->
  wf Σ -> on_global_env cumulSpec0 P Σ ->
  declared_inductive Σ ind mdecl idecl ->
  on_ind_body cumulSpec0 P (Σ, ind_universes mdecl) (inductive_mind ind) mdecl (inductive_ind ind) idecl.
Admitted.

Lemma weaken_env_prop_typing `{checker_flags} : weaken_env_prop cumulSpec0 (lift_typing typing) (lift_typing typing).
Admitted.

Lemma on_declared_constructor `{checker_flags} {Σ ref mdecl idecl cdecl}
  {wfΣ : wf Σ}
  (Hdecl : declared_constructor Σ ref mdecl idecl cdecl) :
  on_inductive cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
               (inductive_mind (fst ref)) mdecl *
  on_ind_body cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
              (inductive_mind (fst ref)) mdecl (inductive_ind (fst ref)) idecl *
  ∑ ind_ctor_sort,
    let onib := declared_inductive_inv weaken_env_prop_typing wfΣ wfΣ (let (x, _) := Hdecl in x) in
     nth_error (ind_cunivs onib) ref.2 = Some ind_ctor_sort
    ×  on_constructor cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
                 mdecl (inductive_ind (fst ref))
                 idecl idecl.(ind_indices) cdecl ind_ctor_sort.
Admitted.

Inductive subslet {cf:checker_flags} Σ (Γ : context) : list term -> context -> Type :=
| emptyslet : subslet Σ Γ [] []
| cons_let_ass Δ s na t T : subslet Σ Γ s Δ ->
              Σ ;;; Γ |- t : subst0 s T ->
             subslet Σ Γ (t :: s) (Δ ,, vass na T)
| cons_let_def Δ s na t T :
    subslet Σ Γ s Δ ->
    Σ ;;; Γ |- subst0 s t : subst0 s T ->
    subslet Σ Γ (subst0 s t :: s) (Δ ,, vdef na t T).

Record spine_subst {cf:checker_flags} Σ Γ inst s (Δ : context) := mkSpineSubst {
  spine_dom_wf : wf_local Σ Γ;
  spine_codom_wf : wf_local Σ (Γ ,,, Δ);
  inst_ctx_subst :> context_subst Δ inst s;
  inst_subslet :> subslet Σ Γ s Δ }.

Section OnConstructor.
  Context {cf:checker_flags} {Σ : global_env} {ind mdecl idecl cdecl}
    {wfΣ: wf Σ} (declc : declared_constructor Σ ind mdecl idecl cdecl).

  Lemma on_constructor_subst :
    wf_global_ext Σ (ind_universes mdecl) *
    wf_local (Σ, ind_universes mdecl)
    (arities_context (ind_bodies mdecl) ,,, ind_params mdecl ,,, cstr_args cdecl) *
    ∑ inst,
    spine_subst (Σ, ind_universes mdecl)
              (arities_context (ind_bodies mdecl) ,,, ind_params mdecl ,,,
                cstr_args cdecl)
              ((to_extended_list_k (ind_params mdecl) #|cstr_args cdecl|) ++
                (cstr_indices cdecl)) inst
            (ind_params mdecl ,,, ind_indices idecl).
  Proof using declc wfΣ.
    pose proof (on_declared_constructor declc) as [[onmind oib] [cunivs [hnth onc]]].
    pose proof (onc.(on_cargs)).
simpl in X.
    split.
split.
split.
    2:{
 eapply (weaken_lookup_on_global_env' _ _ (InductiveDecl mdecl)); tea.
        clear hnth.
unshelve eapply declared_constructor_to_gen in declc; eauto.
        exact (inductive_mind ind.1).
🛠️ Intermediate Coq File (useful for debugging if minimization did not go as far as you wanted)
🛠️ 📜 Intermediate Coq File log (useful for debugging if minimization did not go as far as you wanted)
📜 Build Log (contains the Coq error message) (truncated to last 8.0KiB; full 8.0MiB file on GitHub Actions Artifacts under build.log)
cated,default]Warning, feedback message received but no listener to handle it!
Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
Warning: Deprecated environment variable COQCORELIB,
use ROCQRUNTIMELIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 5, characters 0-758:
Warning:
New coercion path [weaken_env_prop_full_to_strictly_on_decls;
                   weaken_env_prop_full_strictly_on_decls_to_strictly_decls] : weaken_env_prop_full >-> weaken_env_strictly_decls_prop_full is ambiguous with existing 
[weaken_env_prop_full_to_decls; weaken_env_prop_full_decls_to_strictly_decls] : weaken_env_prop_full >-> weaken_env_strictly_decls_prop_full.
[ambiguous-paths,coercions,default]
File "./theories/PCUICInductiveInversion.v", line 5, characters 0-758:
Warning:
New coercion path [weaken_env_prop_to_strictly_on_decls;
                   weaken_env_prop_strictly_on_decls_to_strictly_decls] : weaken_env_prop >-> weaken_env_strictly_decls_prop is ambiguous with existing 
[weaken_env_prop_to_decls; weaken_env_prop_decls_to_strictly_decls] : weaken_env_prop >-> weaken_env_strictly_decls_prop.
[ambiguous-paths,coercions,default]
File "./theories/PCUICInductiveInversion.v", line 65, characters 23-30:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 79, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 80, characters 49-56:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 81, characters 56-63:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 82, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 84, characters 18-25:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 85, characters 14-21:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 99, characters 14-21:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 99, characters 26-33:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 105, characters 22-29:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 107, characters 6-13:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 108, characters 12-19:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 127, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 128, characters 43-50:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 129, characters 50-57:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 130, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 132, characters 12-19:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 133, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 147, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 147, characters 20-27:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 153, characters 16-23:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 172, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 174, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 201, characters 22-29:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 225, characters 22-29:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 230, characters 4-11:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 274, characters 15-35:
Error:
In environment
cf : checker_flags
Σ : global_env
ind : inductive × nat
mdecl : mutual_inductive_body
idecl : one_inductive_body
cdecl : constructor_body
wfΣ : wf Σ
declc :
  PCUICLookup.declared_constructor_gen (lookup_env Σ) ind mdecl idecl cdecl
onmind :
  on_inductive cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
    (inductive_mind ind.1) mdecl
oib :
  on_ind_body cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
    (inductive_mind ind.1) mdecl (inductive_ind ind.1) idecl
cunivs : constructor_univs
onc :
  on_constructor cumulSpec0 (lift_typing typing) (
    Σ, ind_universes mdecl) mdecl (inductive_ind ind.1) idecl
    (ind_indices idecl) cdecl cunivs
X :
  sorts_local_ctx (lift_typing typing) (Σ, ind_universes mdecl)
    (arities_context (ind_bodies mdecl),,, ind_params mdecl)
    (cstr_args cdecl) cunivs
The term "inductive_mind ind.1" has type "kername"
while it is expected to have type
 "lookup_env (Σ, ind_universes mdecl).1 ?c = Some (InductiveDecl mdecl)".

Command exited with non-zero status 1
theories/PCUICInductiveInversion.vo (real: 2.32, user: 2.14, sys: 0.18, mem: 847952 ko)
make[3]: *** [Makefile.rocq:815: theories/PCUICInductiveInversion.vo] Error 1
make[3]: *** [theories/PCUICInductiveInversion.vo] Deleting file 'theories/PCUICInductiveInversion.glob'
make[2]: *** [Makefile.rocq:411: all] Error 2
make[2]: Leaving directory '/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic'
make[1]: *** [Makefile:11: coq] Error 2
make[1]: Leaving directory '/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic'
make: *** [Makefile:153: pcuic] Error 2
+ code=2
+ printf '\n%s exit code: %s\n' metarocq 2
+ '[' metarocq '!=' stdlib_test ']'
+ echo 'Aggregating timing log...'
Aggregating timing log...
+ echo

+ tools/make-one-time-file.py --real _build_ci/metarocq.log
    Time |  Peak Mem | File Name                 
-------------------------------------------------
0m02.32s | 847952 ko | Total Time / Peak Mem     
-------------------------------------------------
0m02.32s | 847952 ko | PCUICInductiveInversion.vo
+ '[' '' ']'
+ exit 2
/github/workspace/builds/coq /github/workspace
::endgroup::
📜 🔎 Minimization Log (truncated to last 8.0KiB; full 3.0MiB file on GitHub Actions Artifacts under bug.log)

Running command: "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-q" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/utils/theories" "MetaRocq.Utils" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/common/theories" "MetaRocq.Common" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories" "MetaRocq.PCUIC" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Equations" "Equations" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/ExtLib" "ExtLib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-top" "Top.bug_01" "/tmp/tmptklg_d6v/Top/bug_01.v" "-q"

Running command: "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-q" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/utils/theories" "MetaRocq.Utils" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/common/theories" "MetaRocq.Common" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories" "MetaRocq.PCUIC" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Equations" "Equations" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/ExtLib" "ExtLib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-top" "Top.bug_01" "/tmp/tmptklg_d6v/Top/bug_01.v" "-q"

Running command: "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-q" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/utils/theories" "MetaRocq.Utils" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/common/theories" "MetaRocq.Common" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories" "MetaRocq.PCUIC" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Equations" "Equations" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/ExtLib" "ExtLib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-top" "Top.bug_01" "/tmp/tmptklg_d6v/Top/bug_01.v" "-q"

Running command: "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-q" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/utils/theories" "MetaRocq.Utils" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/common/theories" "MetaRocq.Common" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories" "MetaRocq.PCUIC" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Equations" "Equations" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/ExtLib" "ExtLib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-top" "Top.bug_01" "/tmp/tmptklg_d6v/Top/bug_01.v" "-q"

Running command: "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-q" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/utils/theories" "MetaRocq.Utils" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/common/theories" "MetaRocq.Common" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories" "MetaRocq.PCUIC" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Equations" "Equations" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/ExtLib" "ExtLib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-top" "Top.bug_01" "/tmp/tmptklg_d6v/Top/bug_01.v" "-q"

Running command: "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-q" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/utils/theories" "MetaRocq.Utils" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/common/theories" "MetaRocq.Common" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories" "MetaRocq.PCUIC" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Equations" "Equations" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/ExtLib" "ExtLib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-top" "Top.bug_01" "/tmp/tmptklg_d6v/Top/bug_01.v" "-q"

Running command: "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-q" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/utils/theories" "MetaRocq.Utils" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/common/theories" "MetaRocq.Common" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories" "MetaRocq.PCUIC" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Equations" "Equations" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/ExtLib" "ExtLib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-top" "Top.bug_01" "/tmp/tmptklg_d6v/Top/bug_01.v" "-q"

Running command: "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-q" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/utils/theories" "MetaRocq.Utils" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/common/theories" "MetaRocq.Common" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories" "MetaRocq.PCUIC" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Equations" "Equations" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/ExtLib" "ExtLib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-top" "Top.bug_01" "/tmp/tmptklg_d6v/Top/bug_01.v" "-q"

If you have any comments on your experience of the minimizer, please share them in a reply (possibly tagging @JasonGross).
If you believe there's a bug in the bug minimizer, please report it on the bug minimizer issue tracker.

@coqbot-app

coqbot-app Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor
Minimization interrupted by timeout, being automatically continued. Partially Minimized File /home/runner/work/run-coq-bug-minimizer/run-coq-bug-minimizer/builds/coq/coq-failing/_build_ci/fiat_crypto/src/Bedrock/Field/Synthesis/Examples/redc.v in 5h 15m 5s (from ci-fiat_crypto) (interrupted by timeout, being automatically continued) (full log on GitHub Actions - verbose log)
⭐ ⏱️ Partially Minimized Coq File (timeout) (truncated to first and last 32KiB; full 87KiB file on GitHub Actions Artifacts under bug.v)
(* -*- mode: coq; coq-prog-args: ("-emacs" "-q" "-w" "+implicit-core-hint-db,+implicits-in-term,+non-reversible-notation,+deprecated-intros-until-0,+deprecated-focus,+unused-intro-pattern,+variable-collision,+unexpected-implicit-declaration,+omega-is-deprecated,+deprecated-instantiate-syntax,+non-recursive,+undeclared-scope,+deprecated-hint-rewrite-without-locality,+deprecated-hint-without-locality,+deprecated-instance-without-locality,+deprecated-typeclasses-transparency-without-locality,+fragile-hint-constr,-deprecated-since-9.0,-deprecated-since-8.20,-deprecated-from-Coq" "-w" "-notation-overridden,-native-compiler-disabled,-ambiguous-paths,-masking-absolute-name" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Coqprime" "Coqprime" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Kami" "Kami" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rewriter" "Rewriter" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rupicola" "Rupicola" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Top.bug_01") -*- *)
(* File reduced by coq-bug-minimizer from original input, then from 577 lines to 117 lines, then from 131 lines to 869 lines, then from 877 lines to 453 lines, then from 468 lines to 1367 lines, then from 1372 lines to 533 lines, then from 548 lines to 1295 lines, then from 1303 lines to 616 lines, then from 631 lines to 1279 lines, then from 1286 lines to 653 lines, then from 668 lines to 953 lines, then from 961 lines to 662 lines, then from 677 lines to 1947 lines, then from 1949 lines to 996 lines, then from 1011 lines to 1284 lines, then from 1292 lines to 1026 lines, then from 1041 lines to 1079 lines, then from 1087 lines to 1042 lines, then from 1057 lines to 1205 lines, then from 1211 lines to 1085 lines, then from 1100 lines to 1221 lines, then from 1229 lines to 1123 lines, then from 1138 lines to 1177 lines, then from 1185 lines to 1151 lines, then from 1166 lines to 1480 lines, then from 1488 lines to 1182 lines, then from 1197 lines to 1464 lines, then from 1472 lines to 1195 lines, then from 1216 lines to 1089 lines, then from 1103 lines to 1492 lines, then from 1500 lines to 1101 lines, then from 1116 lines to 1306 lines, then from 1314 lines to 1114 lines, then from 1129 lines to 1859 lines, then from 1867 lines to 1133 lines, then from 1148 lines to 1714 lines, then from 1722 lines to 1326 lines, then from 1341 lines to 1990 lines, then from 1998 lines to 1486 lines, then from 1501 lines to 1869 lines, then from 1877 lines to 1526 lines, then from 1541 lines to 1966 lines, then from 1974 lines to 1564 lines, then from 1579 lines to 2023 lines, then from 2031 lines to 1594 lines, then from 1609 lines to 1995 lines, then from 2003 lines to 1621 lines, then from 1636 lines to 1925 lines, then from 1933 lines to 1639 lines, then from 1654 lines to 2735 lines, then from 2740 lines to 1705 lines, then from 1720 lines to 2134 lines, then from 2142 lines to 1716 lines, then from 1731 lines to 2049 lines, then from 2057 lines to 1876 lines, then from 1878 lines to 1549 lines, then from 1561 lines to 1814 lines, then from 1821 lines to 1557 lines, then from 1570 lines to 2174 lines, then from 2181 lines to 1646 lines, then from 1659 lines to 2032 lines, then from 2039 lines to 1731 lines, then from 1744 lines to 4295 lines, then from 4301 lines to 1732 lines, then from 1745 lines to 2060 lines, then from 2067 lines to 1741 lines, then from 1754 lines to 2010 lines, then from 2017 lines to 1752 lines, then from 1765 lines to 2001 lines, then from 2008 lines to 1851 lines, then from 1864 lines to 1897 lines, then from 1904 lines to 1874 lines, then from 1887 lines to 2076 lines, then from 2083 lines to 1884 lines, then from 1897 lines to 2091 lines, then from 2098 lines to 1986 lines, then from 1999 lines to 2013 lines, then from 2020 lines to 2001 lines, then from 2014 lines to 2596 lines, then from 2602 lines to 2069 lines, then from 2082 lines to 2231 lines, then from 2238 lines to 2074 lines, then from 2087 lines to 2251 lines, then from 2258 lines to 2142 lines, then from 2155 lines to 2165 lines, then from 2172 lines to 2142 lines, then from 2155 lines to 2172 lines, then from 2179 lines to 2155 lines, then from 2168 lines to 2342 lines, then from 2349 lines to 2186 lines, then from 2199 lines to 2398 lines, then from 2405 lines to 2225 lines, then from 2238 lines to 2426 lines, then from 2433 lines to 2279 lines, then from 2292 lines to 2348 lines, then from 2355 lines to 2291 lines, then from 2304 lines to 2974 lines, then from 2981 lines to 2343 lines *)
(* coqc version 9.3+alpha compiled with OCaml 4.14.2
   coqtop version 9.3+alpha
   Modules that could not be inlined: Crypto.Arithmetic.WordByWordMontgomery
   Expected coqc runtime on this file: 1.290 sec
   Expected coqc peak memory usage on this file: 1761492.0 kb *)
Axiom proof_admitted : False.
Tactic Notation "admit" := abstract case proof_admitted.

Require bedrock2.Markers.
Require coqutil.Tactics.eabstract.
Require coqutil.Tactics.letexists.
Require Ltac2.Ident.
Require Ltac2.String.
Require Ltac2.Char.
Require Ltac2.Env.
Require Ltac2.Ltac1.
Require Ltac2.Option.
Require Ltac2.Pattern.
Require Ltac2.List.
Require Ltac2.Constr.
Import Ltac2.Init.



Ltac2 Notation "lazy_match!" t(tactic(6)) "with" m(constr_matching) "end" : 0 :=
  Pattern.lazy_match0 t m.

Ltac2 Notation "match!" t(tactic(6)) "with" m(constr_matching) "end" : 0 :=
  Pattern.one_match0 t m.

Ltac2 default_on_concl cl :=
match cl with
| None => { Std.on_hyps := Some []; Std.on_concl := Std.AllOccurrences }
| Some cl => cl
end.

Ltac2 Notation "set" p(thunk(pose)) cl(opt(clause)) :=
  Std.set false p (default_on_concl cl).

Ltac2 Notation "eval" "red" "in" c(constr) :=
  Std.eval_red c.

Ltac2 Notation "eval" "cbv" s(strategy) "in" c(constr) :=
  Std.eval_cbv s c.

Ltac2 Notation "eval" "vm_compute" pl(opt(seq(pattern, occurrences))) "in" c(constr) :=
  Std.eval_vm pl c.

Ltac2 exact1 ev c :=
  Control.enter (fun () =>
    let c :=
      Constr.Pretype.pretype
        (if ev then Constr.Pretype.Flags.open_constr_flags_with_tc else Constr.Pretype.Flags.constr_flags)
        (Constr.Pretype.expected_oftype (Control.goal()))
        c
    in
    Std.exact_no_check c).

Ltac2 Notation "exact" c(preterm) := exact1 false c.

Ltac2 Abbreviation refine := Control.refine.
Module Export Ltac2_DOT_Notations.
Module Export Ltac2.
Module Export Notations.
End Notations.

End Ltac2.

End Ltac2_DOT_Notations.

Export Ltac2.Init.
Export Ltac2.Notations.
Module Export Ltac2.
Module Export Ltac2.

End Ltac2.
Require Stdlib.Strings.String.
Import Ltac2.Ltac2.
Import Ltac2.Constr.
Import Ltac2.Constr.Unsafe.

Ltac2 rec length_constr_string (xs : constr) : int :=
  match kind xs with
  | App _ args =>
    match Int.equal (Array.length args) 2 with
    | true => Int.add 1 (length_constr_string (Array.get args 1))
    | _ => if equal xs 'String.EmptyString then 0 else Control.throw No_value
    end
  | Constr.Unsafe.Constructor _ _ => 0
  | _ => Control.throw No_value
  end.

Ltac2 string_of_constr_string (s : constr) : string :=
  let s := eval vm_compute in ($s : String.string) in
  let ret := String.make (length_constr_string s) (Char.of_int 0) in
  let t := constr:(true) in
  let rec fill i s :=
    match kind s with
    | App _ args =>
      if Int.equal (Array.length args) 2 then
        String.set ret i (match kind (Array.get args 0) with App _ b => Char.of_int (
            Int.add (if equal (Array.get b 0) t then 1 else 0) (
            Int.add (if equal (Array.get b 1) t then 2 else 0) (
            Int.add (if equal (Array.get b 2) t then 4 else 0) (
            Int.add (if equal (Array.get b 3) t then 8 else 0) (
            Int.add (if equal (Array.get b 4) t then 16 else 0) (
            Int.add (if equal (Array.get b 5) t then 32 else 0) (
            Int.add (if equal (Array.get b 6) t then 64 else 0) (
                    (if equal (Array.get b 7) t then 128 else 0)))))))))
          | _ => Control.throw No_value end);
        fill (Int.add i 1) (Array.get args 1)
      else ()
    | _ => ()
    end in
  fill 0 s; ret.
Ltac2 ident_of_constr_string (s : constr) := Option.get (Ident.of_string (string_of_constr_string s)).

Ltac ident_of_constr_string_cps := ltac2:(s tac |-
  Ltac1.apply tac [Ltac1.of_ident (ident_of_constr_string (Option.get (Ltac1.to_constr s)))] Ltac1.run).
Module Export coqutil_DOT_Tactics_DOT_ident_of_string.
Module Export coqutil.
Module Export Tactics.
Module Export ident_of_string.
End ident_of_string.

End Tactics.

End coqutil.

End coqutil_DOT_Tactics_DOT_ident_of_string.
Import Ltac2.Ltac2.
Import Ltac2.Constr.
Import Ltac2.Constr.Unsafe.
Import Coq.Lists.List.
Import Coq.Strings.Ascii.
Import Stdlib.NArith.BinNat.
  Local Ltac2 rec list_constr_of_constr_list xs :=
    match! xs with cons ?x ?xs => x :: list_constr_of_constr_list xs | nil => [] end.
Local Definition f : ltac:(do 256 refine (ascii->_); exact unit).
Admitted.
Definition app : unit.
exact (ltac2:(
    let args := eval cbv in (map (fun n => ascii_of_N (N.of_nat n)) (seq 0 256)) in
    refine (make (App 'f (Array.of_list (list_constr_of_constr_list args)))))).
Defined.

Ltac2 constr_string_of_string (s : string) :=
  let asciis := match kind (eval red in app) with App _ x => x | _ => Control.throw No_value end in
  let scons := 'String.String in
  let l := String.length s in
  let rec f i :=
    if Int.equal i l then 'String.EmptyString else
    make (App scons (Array.of_list [Array.get asciis (Char.to_int (String.get s i)); f (Int.add i 1)])) in
  f 0.

Ltac2 constr_string_of_ident (i : ident) := constr_string_of_string (Ident.to_string i).
Ltac2 constr_string_of_lambda (c : constr) :=
  match kind c with
  | Lambda b _i =>
      match Binder.name b with
      | Some n => constr_string_of_ident n
      | _ => Control.throw_invalid_argument "a Lambda with unnamed binder"
      end
  | _ => Control.throw_invalid_argument "not a Lambda"
  end.
Ltac constr_string_of_lambda_cps := ltac2:( lam tac |-
  Ltac1.apply tac [Ltac1.of_constr (constr_string_of_lambda (Option.get (Ltac1.to_constr lam)))] Ltac1.run).
Module Export coqutil.
Module Export Tactics.
Module Export ident_to_string.
End ident_to_string.
Module Export reference_to_string.
Import Ltac2.Ltac2.
Import Ltac2.Constr.Unsafe.

Ltac2 reference_of_constr c :=
  match kind c with
  | Var id => Std.VarRef id
  | Constant const _inst => Std.ConstRef const
  | Ind ind _inst => Std.IndRef ind
  | Constructor cnstr _inst => Std.ConstructRef cnstr
  | _ => Control.throw No_value
  end.

Ltac2 constr_string_basename_of_reference r :=
  constr_string_of_string (Ident.to_string (List.last (Env.path r))).

Ltac2 constr_string_basename_of_constr_reference c :=
  constr_string_basename_of_reference (reference_of_constr c).
Local Set Default Proof Mode "Classic".
Module Export coqutil_DOT_Tactics_DOT_reference_to_string.
Module Export coqutil.
Module Export Tactics.
Module Export reference_to_string.
End reference_to_string.

End Tactics.

End coqutil.

End coqutil_DOT_Tactics_DOT_reference_to_string.
Notation "'unique!' cls" := (ltac:(
  match constr:(Set) with
  | _ => let __ := constr:(_:cls) in fail 1 "unique!: already have an instance of" cls
  | _ => exact cls%type
  end))
  (at level 10, only parsing).
Module Export coqutil.
Module Export Macros.
Module Export unique.
End unique.

End Macros.

End coqutil.
Global Set Default Goal Selector "!".

Module Export bedrock2_DOT_Syntax_WRAPPED.
Module Export Syntax.
Import Coq.Numbers.BinNums.

Module Import op1.
  Inductive op1 : Set := not | opp.
End op1.
Notation op1:= op1.op1.

Module Import bopname.
  Inductive bopname: Set := add | sub | mul | mulhuu | divu | remu | and | or | xor | sru | slu | srs | lts | ltu | eq.
End bopname.
Notation bopname := bopname.bopname.

Module access_size.
  Variant access_size: Set := one | two | four | word.
End access_size.
Notation access_size := access_size.access_size.

Module expr.
  Inductive expr: Set :=
  | literal (v: Z)
  | var (x: String.string)
  | load (_ : access_size) (addr:expr)
  | inlinetable (_ : access_size) (table: list Byte.byte) (index: expr)
  | op1 (op: op1) (e : expr)
  | op (op: bopname) (e1 e2: expr)
  | ite (c e1 e2: expr).

End expr.
Notation expr := expr.expr.

Module cmd.
  Inductive cmd: Set :=
  | skip
  | set (lhs : String.string) (rhs : expr)
  | unset (lhs : String.string)
  | store (_ : access_size) (address : expr) (value : expr)
  | stackalloc (lhs : String.string) (nbytes : Z) (body : cmd)

  | cond (condition : expr) (nonzero_branch zero_branch : cmd)
  | seq (s1 s2: cmd)
  | while (test : expr) (body : cmd)
  | call (binds : list String.string) (function : String.string) (args: list expr)
  | interact (binds : list String.string) (action : String.string) (args: list expr).
End cmd.
Notation cmd := cmd.cmd.

Definition func : Type := (list String.string * list String.string * cmd).

Module Export Coercions.
  Import Stdlib.Strings.String.
  Coercion expr.var : string >-> expr.
  Coercion expr.literal : Z >-> expr.
End Coercions.

End Syntax.
Module Export bedrock2_DOT_Syntax.
Module Export bedrock2.
Module Export Syntax.
Include bedrock2_DOT_Syntax_WRAPPED.Syntax.
End Syntax.

End bedrock2.

End bedrock2_DOT_Syntax.
Require Stdlib.ZArith.BinInt.
Import coqutil.Tactics.ident_to_string.

Notation "ident_to_string! x" := (
  match (fun x : Set => x) return String.string with x => ltac:(
    let lam := lazymatch goal with _ := ?lam |- _ => lam end in
    constr_string_of_lambda_cps lam ltac:(fun s => exact s))
  end) (at level 10, only parsing).
Module Export NotationsCustomEntry.
Import Coq.ZArith.BinInt.
Import Coq.Strings.String.
Import bedrock2.Syntax.
Export bedrock2.Syntax.Coercions.

Import bopname.
Declare Custom Entry bedrock_expr.
Notation "$ e"                := e%string%Z (in custom bedrock_expr at level 0, e constr at level 0, format "'$' e").
Notation  "( e )" := e             (in custom bedrock_expr).
Notation "x" := (ident_to_string! x) (in custom bedrock_expr, x ident, only parsing).

Infix "*"   := (expr.op mul)  (in custom bedrock_expr at level 4, left associativity).

Infix "+"   := (expr.op add)  (in custom bedrock_expr at level 6, left associativity).

Infix  "<"  := (expr.op ltu)  (in custom bedrock_expr at level 10, no associativity).
Notation  "load( a )" := (expr.load access_size.word a)
  (in custom bedrock_expr, a custom bedrock_expr, format "load( a )").

Import cmd.
Declare Custom Entry bedrock_cmd.
Declare Scope bedrock_nontail.
Delimit Scope bedrock_nontail with bedrock_nontail.

Notation "c1 ; c2" := (seq c1%bedrock_nontail c2)
  (in custom bedrock_cmd at level 1, right associativity, format "'[v' c1 ; '/' c2 ']'").

Notation "'while' e { c }" := (while e c%bedrock_nontail)
  (in custom bedrock_cmd at level 0, e custom bedrock_expr, format "'[v' 'while'  e  {  '/  ' c '/' } ']'").

Notation "x = e" := (set (ident_to_string! x) e) (in custom bedrock_cmd, x ident, only parsing, e custom bedrock_expr).
Notation  "store( a , v )" := (store access_size.word a v)  (in custom bedrock_cmd,
  a custom bedrock_expr , v custom bedrock_expr, format "store( a ,  v )").

Declare Custom Entry bedrock_ident.
Notation "x" := (ident_to_string! x) (in custom bedrock_ident, x ident, only parsing).

Declare Custom Entry bedrock_call_lhs.
Notation "x , y , .. , z" := (@cons String.string x (@cons String.string y .. (@cons String.string z (@nil String.string)) ..))
  (in custom bedrock_call_lhs at level 0, x custom bedrock_ident, y custom bedrock_ident, z custom bedrock_ident).

Declare Custom Entry bedrock_args.
Notation "( x , y , .. , z )" := (@cons expr x (@cons expr y .. (@cons expr z (@nil expr)) ..))
  (in custom bedrock_args at level 0, x custom bedrock_expr , y custom bedrock_expr , z custom bedrock_expr ).
Notation "f args" :=  (call nil (ident_to_string! f) args) (in custom bedrock_cmd at level 0,
  f ident, args custom bedrock_args, only parsing).

Declare Scope bedrock_tail.
Delimit Scope bedrock_tail with bedrock_tail.

Declare Custom Entry bedrock_cmd_in_braces.
Notation "{ c }" := c             (in custom bedrock_cmd_in_braces, c custom bedrock_cmd).

Import Coq.Lists.List.ListNotations.
Local Open Scope list_scope.
Notation "'func!' ( xs ) c" := ((xs, [], c%bedrock_tail) : func)
  (only parsing, at level 10, xs custom bedrock_call_lhs, c custom bedrock_cmd_in_braces).

End NotationsCustomEntry.
Module Export bedrock2.
Module Export NotationsCustomEntry.
End NotationsCustomEntry.

End bedrock2.
Module Export dlet.
Definition dlet {A P} (x : A) (f : forall a : A, P a) : P x.
exact (let y := x in f y).
Defined.
Notation "'dlet!' x .. y := v 'in' f" :=
  (dlet v (fun x => .. (fun y => f) .. ))
    (at level 200, x binder, y binder, f at level 200,
     format "'dlet!'  x .. y  :=  v  'in' '//' f").
Module Export coqutil_DOT_dlet.
Module Export coqutil.
Module Export dlet.
End dlet.

End coqutil.

End coqutil_DOT_dlet.

Module Export coqutil_DOT_Word_DOT_Interface.
Module Export coqutil.
Module Export Word.
Module Export Interface.
Import Coq.ZArith.BinInt.
Local Open Scope Z_scope.

Module Export word.
  Class word {width : Z} := {
    rep : Type;

    unsigned : rep -> Z;
    signed : rep -> Z;
    of_Z : Z -> rep;

    add : rep -> rep -> rep;
    sub : rep -> rep -> rep;
    opp : rep -> rep;

    or : rep -> rep -> rep;
    and : rep -> rep -> rep;
    xor : rep -> rep -> rep;
    not : rep -> rep;
    ndn : rep -> rep -> rep;

    mul : rep -> rep -> rep;
    mulhss : rep -> rep -> rep;
    mulhsu : rep -> rep -> rep;
    mulhuu : rep -> rep -> rep;

    divu : rep -> rep -> rep;
    divs : rep -> rep -> rep;
    modu : rep -> rep -> rep;
    mods : rep -> rep -> rep;

    slu : rep -> rep -> rep;
    sru : rep -> rep -> rep;
    srs : rep -> rep -> rep;

    eqb : rep -> rep -> bool;
    ltu : rep -> rep -> bool;
    lts : rep -> rep -> bool;

    gtu x y := ltu y x;
    gts x y := lts y x;

    swrap z := (z + 2^(width-1)) mod 2^width - 2^(width-1);

    sextend: Z -> rep -> rep;
  }.
  Arguments word : clear implicits.
  Local Hint Mode word - : typeclass_instances.

  Class ok {width} {word : word width}: Prop := {
    wrap z := z mod 2^width;

    width_pos: 0 < width;

    unsigned_of_Z : forall z, unsigned (of_Z z) = wrap z;
    signed_of_Z : forall z, signed (of_Z z) = swrap z;
    of_Z_unsigned : forall x, of_Z (unsigned x) = x;

    unsigned_add : forall x y, unsigned (add x y) = wrap (Z.add (unsigned x) (unsigned y));
    unsigned_sub : forall x y, unsigned (sub x y) = wrap (Z.sub (unsigned x) (unsigned y));
    unsigned_opp : forall x, unsigned (opp x) = wrap (Z.opp (unsigned x));

    unsigned_or : forall x y, unsigned (or x y) = wrap (Z.lor (unsigned x) (unsigned y));
    unsigned_and : forall x y, unsigned (and x y) = wrap (Z.land (unsigned x) (unsigned y));
    unsigned_xor : forall x y, unsigned (xor x y) = wrap (Z.lxor (unsigned x) (unsigned y));
    unsigned_not : forall x, unsigned (not x) = wrap (Z.lnot (unsigned x));
    unsigned_ndn : forall x y, unsigned (ndn x y) = wrap (Z.ldiff (unsigned x) (unsigned y));

    unsigned_mul : forall x y, unsigned (mul x y) = wrap (Z.mul (unsigned x) (unsigned y));
    signed_mulhss : forall x y, signed (mulhss x y) = swrap (Z.mul (signed x) (signed y) / 2^width);
    signed_mulhsu : forall x y, signed (mulhsu x y) = swrap (Z.mul (signed x) (unsigned y) / 2^width);
    unsigned_mulhuu : forall x y, unsigned (mulhuu x y) = wrap (Z.mul (unsigned x) (unsigned y) / 2^width);

    unsigned_divu : forall x y, unsigned y <> 0 -> unsigned (divu x y) = wrap (Z.div (unsigned x) (unsigned y));
    signed_divs : forall x y, signed y <> 0 -> signed x <> -2^(width-1) \/ signed y <> -1 -> signed (divs x y) = swrap (Z.quot (signed x) (signed y));
    unsigned_modu : forall x y, unsigned y <> 0 -> unsigned (modu x y) = wrap (Z.modulo (unsigned x) (unsigned y));
    signed_mods : forall x y, signed y <> 0 -> signed (mods x y) = swrap (Z.rem (signed x) (signed y));

    unsigned_slu : forall x y, Z.lt (unsigned y) width -> unsigned (slu x y) = wrap (Z.shiftl (unsigned x) (unsigned y));
    unsigned_sru : forall x y, Z.lt (unsigned y) width -> unsigned (sru x y) = wrap (Z.shiftr (unsigned x) (unsigned y));
    signed_srs : forall x y, Z.lt (unsigned y) width -> signed (srs x y) = swrap (Z.shiftr (signed x) (unsigned y));

    unsigned_eqb : forall x y, eqb x y = Z.eqb (unsigned x) (unsigned y);
    unsigned_ltu : forall x y, ltu x y = Z.ltb (unsigned x) (unsigned y);
    signed_lts : forall x y, lts x y = Z.ltb (signed x) (signed y);
  }.
  Arguments ok {_} _.
End word.
Notation word := word.word.
Global Coercion word.rep : word >-> Sortclass.

End Interface.

End Word.

End coqutil.

End coqutil_DOT_Word_DOT_Interface.
Require Stdlib.ZArith.ZArith.
Import Coq.ZArith.ZArith.

Class Bitwidth(width: Z): Prop := {
  width_cases: width = 32%Z \/ width = 64%Z
}.
Module Export coqutil.
Module Export Word.
Module Export Bitwidth.
End Bitwidth.
Module Export PrimitivePair.
Module pair.
  Record pair {A B} := mk { _1 : A; _2 : B _1 }.
  Arguments pair : clear implicits.
  Arguments mk {A B} _ _.

  Notation "A * B" := (pair A%type (fun _ => B%type)) : type_scope.

  Notation "( x , y , .. , z )" := (mk .. (mk x y) .. z) : core_scope.

  Notation "x '.(1)'" := (_1 x) (at level 1, left associativity) : core_scope.
  Notation "x '.(2)'" := (_2 x) (at level 1, left associativity) : core_scope.
End pair.
Module Export coqutil_DOT_Datatypes_DOT_PrimitivePair.
Module Export coqutil.
Module Export Datatypes.
Module Export PrimitivePair.
End PrimitivePair.

End Datatypes.

End coqutil.

End coqutil_DOT_Datatypes_DOT_PrimitivePair.
Module Export HList.
Import coqutil.Datatypes.PrimitivePair.
Import pair.
Local Set Universe Polymorphism.

Module Import polymorphic_list.
  Inductive list {A : Type} : Type := nil | cons (_:A) (_:list).
  Arguments list : clear implicits.

  Section WithA.
    Context {A : Type}.
Fixpoint length (l : list A) : nat.
Admitted.
  End WithA.

  Section WithElement.
    Context {A} (x : A).
    Fixpoint repeat (x : A) (n : nat) {struct n} : list A :=
      match n with
      | 0 => nil
      | S k => cons x (repeat x k)
      end.
  End WithElement.
End polymorphic_list.
Fixpoint arrows (argts : list Type) : Type -> Type.
exact (match argts with
  | nil => fun ret => ret
  | cons T argts' => fun ret => T -> arrows argts' ret
  end).
Defined.

Fixpoint hlist@{i j k} (argts : list@{j} Type@{i}) : Type@{k} :=
  match argts with
  | nil => unit
  | cons T argts' => T * hlist argts'
  end.

Module Export hlist.
  Fixpoint apply {argts : list Type} : forall {P} (f : arrows argts P) (args : hlist argts), P :=
    match argts return forall {P} (f : arrows argts P) (args : hlist argts), P with
    | nil => fun P f _ => f
    | cons T argts' => fun P f '(x, args') => apply (f x) args'
    end.

  Fixpoint foralls {argts : list Type} : forall (P : hlist argts -> Prop), Prop :=
    match argts with
    | nil => fun P => P tt
    | cons T argts' => fun P => forall x:T, foralls (fun xs' => P (x, xs'))
    end.

  Fixpoint existss {argts : list Type} : forall (P : hlist argts -> Prop), Prop :=
    match argts with
    | nil => fun P => P tt
    | cons T argts' => fun P => exists x:T, existss (fun xs' => P (x, xs'))
    end.
End hlist.

Definition tuple A n := hlist (repeat A n).
Definition ufunc A n := arrows (repeat A n).
Module Export tuple.
  Notation apply := hlist.apply.
  Definition foralls {A n} := hlist.foralls (argts:=repeat A n).
  Definition existss {A n} := hlist.existss (argts:=repeat A n).

  Import Corelib.Init.Datatypes.
  Section WithA.
    Context {A : Type}.
    Fixpoint to_list {n : nat} : tuple A n -> list A :=
      match n return tuple A n -> list A with
      | O => fun _ => nil
      | S n => fun '(pair.mk x xs') => cons x (to_list xs')
      end.
Fixpoint of_list (xs : list A) : tuple A (length xs).
exact (match xs with
      | nil => tt
      | cons x xs => pair.mk x (of_list xs)
      end).
Defined.

    Section WithF.
    End WithF.

    Section WithStep.
    End WithStep.
  End WithA.
End tuple.

End HList.
Module Export coqutil_DOT_Datatypes_DOT_HList.
Module Export coqutil.
Module Export Datatypes.
Module Export HList.
End HList.

End Datatypes.

End coqutil.

End coqutil_DOT_Datatypes_DOT_HList.
Module Export String.
Export Coq.Strings.String.

Lemma ltb_antirefl : forall k, ltb k k = false.
Admitted.

Lemma ltb_trans : forall k1 k2 k3, ltb k1 k2 = true -> ltb k2 k3 = true -> ltb k1 k3 = true.
Admitted.

Lemma ltb_total : forall k1 k2, ltb k1 k2 = false -> ltb k2 k1 = false -> k1 = k2.
Admitted.
End String.

Ltac head t :=
  lazymatch t with
  | ?f _ => head f
  | _ => t
  end.
Module Export coqutil.
Module Export Tactics.
Module Export Tactics.
End Tactics.

  Module Export coqutil_DOT_Map_DOT_Interface_WRAPPED.
Module Export Interface.
Import coqutil.Datatypes.HList.

Module Export map.
  Class map {key value} := mk {
    rep : Type;

    get: rep -> key -> option value;

    empty : rep;
    put : rep -> key -> value -> rep;
    remove : rep -> key -> rep;
    fold{R: Type}: (R -> key -> value -> R) -> R -> rep -> R;
  }.
  Arguments map : clear implicits.
  Global Coercion rep : map >-> Sortclass.

  Class ok {key value : Type} {map : map key value}: Prop := {
    map_ext : forall m1 m2, (forall k, get m1 k = get m2 k) -> m1 = m2;
    get_empty : forall k, get empty k = None;
    get_put_same : forall m k v, get (put m k v) k = Some v;
    get_put_diff : forall m k v k', k <> k' -> get (put m k' v) k = get m k;
    get_remove_same : forall m k, get (remove m k) k = None;
    get_remove_diff : forall m k k', k <> k' -> get (remove m k') k = get m k;
    fold_spec{R: Type} : forall (P: rep -> R -> Prop) (f: R -> key -> value -> R) r0,
        P empty r0 ->
        (forall k v m r, get m k = None -> P m r -> P (put m k v) (f r k v)) ->
        forall m, P m (fold f r0 m);

    fold_parametricity: forall {A B : Type} (R : A -> B -> Prop)
                               (fa: A -> key -> value -> A) (fb: B -> key -> value -> B),
        (forall a b k v, R a b -> R (fa a k v) (fb b k v)) ->
        forall a0 b0, R a0 b0 -> forall m, R (fold fa a0 m) (fold fb b0 m);

  }.
  Arguments ok {_ _} _.

  Section WithMap.
    Context {key value : Type} {map : map key value} {map_ok : ok map}.
Definition putmany: map -> map -> map.
admit.
Defined.
    Definition disjoint (a b : map) :=
      forall k v1 v2, get a k = Some v1 -> get b k = Some v2 -> False.

    Definition split m m1 m2 := m = (putmany m1 m2) /\ disjoint m1 m2.
Definition getmany_of_list (m : map) (keys : list key) : option (list value).
admit.
Defined.
Fixpoint putmany_of_list (l : list (key*value)) (init : rep) {struct l} : map.
Admitted.
Fixpoint putmany_of_list_zip (keys : list key) (values : list value) (init : rep) {struct keys} : option map.
exact (match keys, values with
      | nil, nil => Some init
      | cons k keys, cons v values =>
        putmany_of_list_zip keys values (put init k v)
      | _, _ => None
      end).
Defined.
    Definition of_list_zip keys values := putmany_of_list_zip keys values empty.

    Import coqutil.Datatypes.PrimitivePair.

    Fixpoint putmany_of_tuple {sz : nat} : tuple key sz -> tuple value sz -> map -> map :=
      match sz with
      | O => fun keys values init => init
      | S sz' => fun '(pair.mk k ks) '(pair.mk v vs) init =>
                   put (putmany_of_tuple ks vs init) k v
      end.
  End WithMap.
End map.

End Interface.
Module Export coqutil.
Module Export Map.
Module Export Interface.
Include coqutil_DOT_Map_DOT_Interface_WRAPPED.Interface.
End Interface.

End Map.

End coqutil.
Module Export SortedList.
Import coqutil.Macros.unique.
Import coqutil.Map.Interface.
Definition minimize_eq_proof{A: Type}(eq_dec: forall (x y: A), {x = y} + {x <> y}){x y: A}    (pf: x = y): x = y.
exact (match eq_dec x y with
  | left p => p
  | right n => match n pf: False with end
  end).
Defined.

Module Import parameters.
  Class parameters := {
    key : Type;
    value : Type;
    ltb : key -> key -> bool
  }.

  Class strict_order {T} {ltb : T -> T -> bool}: Prop := {
    ltb_antirefl : forall k, ltb k k = false;
    ltb_trans : forall k1 k2 k3, ltb k1 k2 = true -> ltb k2 k3 = true -> ltb k1 k3 = true;
    ltb_total : forall k1 k2, ltb k1 k2 = false -> ltb k2 k1 = false -> k1 = k2;
  }.
  Global Arguments strict_order {_} _.
End parameters.

Section SortedList.
  Context {p : unique! parameters} {ok : strict_order ltb}.

  Local Definition eqb k1 k2 := andb (negb (ltb k1 k2)) (negb (ltb k2 k1)).

  Fixpoint put m (k:key) (v:value) : list (key * value) :=
    match m with
    | nil => cons (k, v) nil
    | cons (k', v') m' =>
      match ltb k k', ltb k' k with
      |  true, _ => cons (k, v) m
      |  false, false => cons (k, v) m'
      |  false, true => cons (k', v') (put m' k v)
      end
    end.

  Fixpoint remove m (k:key) : list (key * value) :=
    match m with
    | nil => nil
    | cons (k', v') m' =>
      match ltb k k', ltb k' k with
      |  true, _ => m
      |  false, false => m'
      |  false, true => cons (k', v') (remove m' k)
      end
    end.

  Fixpoint sorted (m : list (key * value)) :=
    match m with
    | cons (k1, _) ((cons (k2, _) m'') as m') => andb (ltb k1 k2) (sorted m')
    | _ => true
    end.

  Record rep := { value : list (key * value) ; _value_ok : sorted value = true }.

  Lemma sorted_put m k v : sorted m = true -> sorted (put m k v) = true.
Admitted.

  Lemma sorted_remove m k : sorted m = true -> sorted (remove m k) = true.
Admitted.
Definition lookup(l: list (key * parameters.value))(k: key): option parameters.value.
exact (match List.find (fun p => eqb k (fst p)) l with
    | Some (_, v) => Some v
    | None => None
    end).
Defined.
Definition map : map.map key parameters.value.
exact (let wrapped_put m k v := Build_rep (put (value m) k v) (minimize_eq_proof Bool.bool_dec (sorted_put _ _ _ (_value_ok m))) in
    let wrapped_remove m k := Build_rep (remove (value m) k) (minimize_eq_proof Bool.bool_dec (sorted_remove _ _ (_value_ok m))) in
    {|
    map.rep := rep;
    map.empty := Build_rep nil eq_refl;
    map.get m k := lookup (value m) k;
    map.put := wrapped_put;
    map.remove := wrapped_remove;
    map.fold R f r0 m := List.fold_right (fun '(k, v) r => f r k v) r0 (value m);
  |}).
Defined.

  Lemma eq_value {x y : rep} : value x = value y -> x = y.
Admitted.
End SortedList.
Arguments map : clear implicits.
End SortedList.
Module Export SortedListString.

Local Instance string_strict_order: @SortedList.parameters.strict_order _ String.ltb
  := { ltb_antirefl := String.ltb_antirefl
       ; ltb_trans := String.ltb_trans
       ; ltb_total := String.ltb_total }.
Definition Build_parameters T := SortedList.parameters.Build_parameters String.string T String.ltb.
Definition map T := SortedList.map (Build_parameters T) string_strict_order.
Import Coq.ZArith.ZArith.

Local Open Scope Z_scope.

Notation byte := (Coq.Init.Byte.byte: Type).

Module Export byte.
Definition unsigned(b: byte): Z.
Admitted.
Definition of_Z(z: Z): byte.
Admitted.
Module Export LittleEndianList.
Fixpoint le_combine(l: list byte): Z.
Admitted.
Fixpoint le_split (n : nat) (w : Z) : list byte.
Admitted.
Module Export Properties.
Import coqutil.Word.Interface.
Import word.

Module Export word.
  Section WithWord.
    Context {width} {word : word width} {word_ok : word.ok word}.
    Local Hint Mode word.word - : typeclass_instances.

    Lemma unsigned_of_Z_0 : word.unsigned (word.of_Z 0) = 0.
Admitted.

    Lemma ring_theory : Ring_theory.ring_theory (of_Z 0) (of_Z 1) add mul sub opp Logic.eq.
Admi

[...]

p (fun a => cons a nil) (@app A)).
Defined.

  Section WithMap.
    Context {key value} {map : map key value} {ok : ok map}.
Definition to_sep: Tree (map -> Prop) -> map -> Prop.
exact (interp (fun x => x) sep).
Defined.

    Lemma flatten_iff1_to_sep(t : Tree.Tree (map -> Prop)):
      Lift1Prop.iff1 (seps (flatten t)) (to_sep t).
Admitted.

    Lemma iff1_to_sep_of_iff1_flatten(LHS RHS : Tree (map -> Prop)):
      Lift1Prop.iff1 (seps (flatten LHS)) (seps (flatten RHS)) ->
      Lift1Prop.iff1 (to_sep LHS) (to_sep RHS).
Admitted.

    Lemma impl1_to_sep_of_impl1_flatten(LHS RHS : Tree (map -> Prop)):
      Lift1Prop.impl1 (seps (flatten LHS)) (seps (flatten RHS)) ->
      Lift1Prop.impl1 (to_sep LHS) (to_sep RHS).
Admitted.

    Lemma flatten_to_sep_with_and(t : Tree.Tree (map -> Prop))(m: map)(C: Prop):
      seps (flatten t) m /\ C -> to_sep t m /\ C.
Admitted.
  End WithMap.

Ltac reify e :=
  lazymatch e with
  | @sep ?key ?value ?map ?a ?b =>
    let a := reify a in
    let b := reify b in
    uconstr:(@Tree.Node (@map.rep key value map -> Prop) a b)
  | ?a => uconstr:(Tree.Leaf a)
  end.

Ltac reify_goal :=
  lazymatch goal with
  | |- Lift1Prop.iff1 ?LHS ?RHS =>
    let LHS := reify LHS in
    let RHS := reify RHS in
    change (Lift1Prop.iff1 (Tree.to_sep LHS) (Tree.to_sep RHS));
    eapply Tree.iff1_to_sep_of_iff1_flatten
  | |- Lift1Prop.impl1 ?LHS ?RHS =>
    let LHS := reify LHS in
    let RHS := reify RHS in
    change (Lift1Prop.impl1 (Tree.to_sep LHS) (Tree.to_sep RHS));
    eapply Tree.impl1_to_sep_of_impl1_flatten
  end;
  cbv [Tree.flatten Tree.interp app].

Ltac flatten_seps_in H :=
  lazymatch type of H with
  | ?nested ?m =>
    let tmem := type of m in
    let E := fresh "E" in
    eassert (@iff1 tmem nested _) as E;
    [
      let stars := eval cbv [seps] in nested in
      let tree := reify stars in
      transitivity (Tree.to_sep tree); [
        cbv [seps Tree.to_sep Tree.interp]; iff1_syntactic_reflexivity
      |];

      transitivity (seps (Tree.flatten tree)); [
        exact (iff1_sym (Tree.flatten_iff1_to_sep tree))
      |];

      cbv [SeparationLogic.Tree.flatten SeparationLogic.Tree.interp SeparationLogic.app];
      iff1_syntactic_reflexivity
    | let HNew := fresh in pose proof (proj1 (E m) H) as HNew;
      move HNew before H;
      clear E H;
      rename HNew into H ]
  end.

Ltac flatten_seps_in_goal :=
  cbv [seps];
  lazymatch goal with
  | |- ?nested ?m /\ ?C =>
      let xs := reify nested in
      change (Tree.to_sep xs m /\ C);
      eapply Tree.flatten_to_sep_with_and
  | |- ?nested ?m =>
      let xs := reify nested in
      change (Tree.to_sep xs m);
      eapply Tree.flatten_iff1_to_sep
  end;
  cbv [Tree.flatten Tree.interp app].

Ltac cancel_emp_l :=
  lazymatch goal with
  | |- Lift1Prop.iff1 (@seps ?K ?V ?M ?LHS) (seps ?RHS) =>
    let i := find_constr_eq LHS constr:(@emp K V M True) in
    simple refine (cancel_emp_at_index_l i LHS RHS _ _);
    cbv [firstn skipn app hd tl];
    [syntactic_exact_deltavar (@eq_refl _ _)|]
  end.

Ltac cancel_emp_r :=
  lazymatch goal with
  | |- Lift1Prop.iff1 (seps ?LHS) (@seps ?K ?V ?M ?RHS) =>
    let j := find_constr_eq RHS constr:(@emp K V M True) in
    simple refine (cancel_emp_at_index_r j LHS RHS _ _);
    cbv [firstn skipn app hd tl];
    [syntactic_exact_deltavar (@eq_refl _ _)|]
  end.

Ltac cancel_emp_impl :=
  lazymatch goal with
  | |- Lift1Prop.impl1 (seps ?LHS) (@seps ?K ?V ?M ?RHS) =>
    let j := find_constr_eq RHS constr:(@emp K V M True) in

    simple refine (cancel_emp_at_index_impl j LHS RHS _ _);
    cbv [firstn skipn app hd tl];

    [syntactic_exact_deltavar (@eq_refl _ _)|]
  end.

Ltac cancel_seps_at_indices i j :=
  lazymatch goal with
  | |- Lift1Prop.iff1 (seps ?LHS) (seps ?RHS) =>
    simple refine (cancel_seps_at_indices i j LHS RHS _ _);
    cbv [firstn skipn app hd tl]
  end.

Ltac cancel_seps_at_indices_by_implication i j :=
  lazymatch goal with
  | |- Lift1Prop.impl1 (seps ?LHS) (seps ?RHS) =>
    simple refine (cancel_seps_at_indices_by_implication i j LHS RHS _ _);
    cbv [firstn skipn app hd tl]
  end.

Ltac find_implication xs y :=
  multimatch xs with
  | cons ?x _ => constr:(O)
  | cons _ ?xs => let i := find_implication xs y in constr:(S i)
  end.

Ltac cancel_step := once (
      let RHS := lazymatch goal with |- Lift1Prop.iff1 _ (seps ?RHS) => RHS end in
      let jy := index_and_element_of RHS in
      let j := lazymatch jy with (?i, _) => i end in
      let y := lazymatch jy with (_, ?y) => y end in
      assert_fails (has_evar y);
      let LHS := lazymatch goal with |- Lift1Prop.iff1 (seps ?LHS) _ => LHS end in
      let i := find_constr_eq LHS y in
      cancel_seps_at_indices i j; [exact eq_refl|]).

Ltac cancel_step_impl := once (
    let RHS := lazymatch goal with |- Lift1Prop.impl1 _ (seps ?RHS) => RHS end in
    let jy := index_and_element_of RHS in
    let j := lazymatch jy with (?i, _) => i end in
    let y := lazymatch jy with (_, ?y) => y end in
    assert_fails (has_evar y);
    let LHS := lazymatch goal with |- Lift1Prop.impl1 (seps ?LHS) _ => LHS end in
    let i := find_constr_eq LHS y in
    cancel_seps_at_indices_by_implication i j; [exact impl1_refl|]).

Ltac ecancel_step_at j :=
      let RHS := lazymatch goal with |- Lift1Prop.iff1 _ (seps ?RHS) => RHS end in
      let y := list_get RHS j in
      assert_fails (idtac; let y := rdelta_var y in is_evar y);
      let LHS := lazymatch goal with |- Lift1Prop.iff1 (seps ?LHS) _ => LHS end in
      let i := find_syntactic_unify_deltavar LHS y in
      cancel_seps_at_indices i j; [exact eq_refl|].

Ltac ecancel_steps_inbounds j :=
  let RHS := lazymatch goal with |- Lift1Prop.iff1 _ (seps ?RHS) => RHS end in
  let __ := list_get RHS j in
  idtac.

Ltac ecancel_steps_at j :=
   tryif (ecancel_steps_inbounds j) then (
    tryif (ecancel_step_at j)
    then (                         ecancel_steps_at j)
    else (let j := constr:(S j) in ecancel_steps_at j)
  ) else idtac.

Ltac ecancel_step_by_implication :=
      let RHS := lazymatch goal with |- Lift1Prop.impl1 _ (seps ?RHS) => RHS end in
      let jy := index_and_element_of RHS in
      let j := lazymatch jy with (?i, _) => i end in
      let y := lazymatch jy with (_, ?y) => y end in
      assert_fails (idtac; let y := rdelta_var y in is_evar y);
      let LHS := lazymatch goal with |- Lift1Prop.impl1 (seps ?LHS) _ => LHS end in
      let i := find_implication LHS y in
      cancel_seps_at_indices_by_implication i j; [solve [auto 1 with nocore ecancel_impl]|].

Ltac ecancel_done :=
  cbv [seps];
  syntactic_exact_deltavar
    (@RelationClasses.reflexivity _ _
        (@RelationClasses.Equivalence_Reflexive _ _ (@Equivalence_iff1 _)) _).

Ltac cancel_done :=
  lazymatch goal with
  | |- iff1 (seps (cons _ nil)) _ => idtac
  | |- iff1 _ (seps (cons _ nil )) => idtac
  | |- ?g => assert_fails (has_evar g)
  end;
  ecancel_done.

Ltac cancel_seps :=
  lazymatch goal with
  | |- Lift1Prop.iff1 _ _ =>
    repeat cancel_step;
    repeat cancel_emp_l;
    repeat cancel_emp_r
  | |- Lift1Prop.impl1 _ _ =>
    repeat cancel_step_impl;
    repeat cancel_emp_impl
  end;
  try solve [ cancel_done ].

Ltac cancel := reify_goal; cancel_seps.

Ltac ecancel :=
  cancel;
  lazymatch goal with
  | [|- impl1 _ _] =>
     repeat ecancel_step_by_implication;
     (solve [ cbv [seps]; exact impl1_refl ])
  | [|- iff1 _ _] =>
    ecancel_steps_at O;
    ecancel_done
  end.

Ltac ecancel_assumption :=
  multimatch goal with
  | |- _ ?m1 =>
    multimatch goal with
    | H: _ ?m2 |- _ =>
      syntactic_unify_deltavar m1 m2;
      refine (Lift1Prop.subrelation_iff1_impl1 _ _ _ _ _ H); clear H;
      solve [ecancel]
    end
  end.
Require Crypto.Arithmetic.WordByWordMontgomery.
Module Export Array.

Section Array.
  Context {value} {mem : map.map word value} {mem_ok : map.ok mem}.
  Context {T} (element : word -> T -> mem -> Prop) (size : word).
  Fixpoint array (start : word) (xs : list T) :=
    match xs with
    | nil => emp True
    | cons x xs => sep (element start x) (array (word.add start size) xs)
    end.

End Array.

Section ByteArray.
  Context {mem : map.map word byte} {mem_ok : map.ok mem}.
  Local Notation array := (array (mem:=mem) ptsto (word.of_Z 1)).

  Lemma array_1_to_anybytes bs m (a: word) :
    array a bs m -> bedrock2.Memory.anybytes a (Z.of_nat (List.length bs)) m.
Admitted.

  Lemma anybytes_to_array_1 m (addr : word) n :
      bedrock2.Memory.anybytes addr n m ->
      exists bs, array  addr bs m /\ List.length bs = Z.to_nat n.
Admitted.
End ByteArray.
Module Export Scalars.

Section Scalars.
  Context {width : Z} {BW: Bitwidth width} {word : Word.Interface.word width} {word_ok : word.ok word}.

  Context {mem : map.map word byte} {mem_ok : map.ok mem}.
  Implicit Types (m : mem).

  Definition truncated_scalar sz addr (value:Z) : mem -> Prop :=
    (le_split (bytes_per (width:=width) sz) value) $@ addr.

  Definition truncated_word sz addr (value: word) : mem -> Prop :=
    truncated_scalar sz addr (word.unsigned value).

  Notation scalar8 := ptsto (only parsing).

  Definition scalar16 := truncated_word Syntax.access_size.two.
  Definition scalar32 := truncated_word Syntax.access_size.four.
  Definition scalar := truncated_word Syntax.access_size.word.
Definition truncate_word(sz: Syntax.access_size)(w: word): word.
Admitted.

  Lemma load_one_of_sep addr value R m
    (Hsep : sep (scalar8 addr value) R m)
    : Memory.load Syntax.access_size.one m addr = Some (word.of_Z (byte.unsigned value)).
Admitted.

  Lemma load_two_of_sep addr value R m
    (Hsep : sep (scalar16 addr value) R m)
    : Memory.load Syntax.access_size.two m addr = Some (truncate_word Syntax.access_size.two value).
Admitted.

  Lemma load_four_of_sep addr value R m
    (Hsep : sep (scalar32 addr value) R m)
    : Memory.load Syntax.access_size.four m addr = Some (truncate_word Syntax.access_size.four value).
Admitted.

  Lemma load_four_of_sep_32bit(W32: width = 32) addr value R m
    (Hsep : sep (scalar32 addr value) R m)
    : Memory.load Syntax.access_size.four m addr = Some value.
Admitted.

  Lemma load_word_of_sep addr value R m
    (Hsep : sep (scalar addr value) R m)
    : Memory.load Syntax.access_size.word m addr = Some value.
Admitted.

  Lemma store_one_of_sep addr (oldvalue : byte) (value : word) R m (post:_->Prop)
    (Hsep : sep (scalar8 addr oldvalue) R m)
    (Hpost : forall m, sep (scalar8 addr (byte.of_Z (word.unsigned value))) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.one m addr value = Some m1 /\ post m1.
Admitted.

  Lemma store_two_of_sep addr (oldvalue : word) (value : word) R m (post:_->Prop)
    (Hsep : sep (scalar16 addr oldvalue) R m)
    (Hpost : forall m, sep (scalar16 addr value) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.two m addr value = Some m1 /\ post m1.
Admitted.

  Lemma store_four_of_sep addr (oldvalue : word) (value : word) R m (post:_->Prop)
    (Hsep : sep (scalar32 addr oldvalue) R m)
    (Hpost : forall m, sep (scalar32 addr value) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.four m addr value = Some m1 /\ post m1.
Admitted.

  Lemma store_word_of_sep addr (oldvalue value: word) R m (post:_->Prop)
    (Hsep : sep (scalar addr oldvalue) R m)
    (Hpost : forall m, sep (scalar addr value) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.word m addr value = Some m1 /\ post m1.
Admitted.

End Scalars.
Module Export Loops.
Import coqutil.Datatypes.PrimitivePair.
Import coqutil.Datatypes.HList.
Import coqutil.dlet.
Import bedrock2.WeakestPrecondition.

Section Loops.
  Context {width: Z} {BW: Bitwidth width} {word: word.word width} {mem: map.map word Byte.byte}.
  Context {locals: map.map String.string word}.
  Context {ext_spec: ExtSpec}.

  Context {fs : env}.
  Let call := fs.

  Local Notation "A /\ B" := (Markers.split (A /\ B)).
Definition reconstruct (variables:list String.string) (values:tuple word (length variables)) : locals.
exact (map.putmany_of_tuple (tuple.of_list variables) values map.empty).
Defined.
Fixpoint gather (variables : list String.string) (l : locals) : option (locals *  tuple word (length variables)).
exact (match variables with
    | nil => Some (l, tt)
    | cons x xs' =>
      match map.get l x with
      | None => None
      | Some v =>
        match gather xs' (map.remove l x) with
        | None => None
        | Some (l, vs') => Some (l, (pair.mk v vs'))
        end
      end
    end).
Defined.
Definition enforce (variables : list String.string) (values:tuple word (length variables)) (l:locals) : Prop.
exact (match gather variables l with
    | None => False
    | Some (remaining, r) => values = r /\ remaining = map.empty
    end).
Defined.

  Import pair.

  Lemma tailrec
    {e c t localsmap} {m : mem}
    (ghosttypes : polymorphic_list.list Type)
    (variables : list String.string)
    {l0 : tuple word (length variables)}
    {Pl : enforce variables l0 localsmap}
    {post : _->_->_-> Prop}
    {measure : Type} (spec:_->HList.arrows ghosttypes (_->_->ufunc word (length variables) (Prop*(_->_->ufunc word (length variables) Prop)))) lt
    (Hwf : well_founded lt)
    (v0 : measure)
    : hlist.foralls (fun (g0 : hlist ghosttypes) => forall
    (Hpre : (tuple.apply (hlist.apply (spec v0) g0 t m) l0).(1))
    (Hbody : forall v, hlist.foralls (fun g => forall t m, tuple.foralls (fun l =>
      @dlet _ (fun _ => Prop) (reconstruct variables l) (fun localsmap : locals =>
      match tuple.apply (hlist.apply (spec v) g t m) l with S_ =>
      S_.(1) ->
      Markers.unique (Markers.left (exists br, expr m localsmap e (eq br) /\ Markers.right (
      (word.unsigned br <> 0%Z -> cmd call c t m localsmap
        (fun t' m' localsmap' =>
          Markers.unique (Markers.left (hlist.existss (fun l' => enforce variables l' localsmap' /\ Markers.right (
          Markers.unique (Markers.left (hlist.existss (fun g' => exists v',
          match tuple.apply (hlist.apply (spec v') g' t' m') l' with S' =>
          S'.(1) /\ Markers.right (
            lt v' v /\
            forall T M, hlist.foralls (fun L => tuple.apply (S'.(2) T M) L -> tuple.apply (S_.(2) T M) L)) end))))))))) /\
      (word.unsigned br = 0%Z -> tuple.apply (S_.(2) t m) l))))end))))
    (Hpost : match (tuple.apply (hlist.apply (spec v0) g0 t m) l0).(2) with Q0 => forall t m, hlist.foralls (fun l =>  tuple.apply (Q0 t m) l -> post t m (reconstruct variables l))end)
    , cmd call (cmd.while e c) t m localsmap post ).
Admitted.
End Loops.
Import coqutil.Tactics.Tactics.
Import coqutil.Tactics.letexists.
Import coqutil.Tactics.eabstract.
Import coqutil.Tactics.reference_to_string.
Import coqutil.Tactics.ident_of_string.

Definition spec_of (procname:String.string) := Semantics.env -> Prop.
Existing Class spec_of.
Import Ltac2.Ltac2.

Local Ltac2 rec splitcmd (cmd : constr) : unit :=
  match! cmd with
    | cmd.seq ?cmd1 ?cmd2 =>
        set (cmd.seq $cmd1 $cmd2) in *; splitcmd cmd1; splitcmd cmd2
    | cmd.cond ?expr ?cmd1 ?cmd2 => set (cmd.cond $expr $cmd1 $cmd2) in *; splitcmd cmd1; splitcmd cmd2
    | cmd.while ?expr ?cmd => set (cmd.while $expr $cmd) in *; splitcmd cmd
    | _ => ()
  end.

Local Ltac2 Notation "instance_of" type(constr) :=
  lazy_match! Ltac2.Constr.pretype (preterm:(_ : $type)) with ?instance => instance end.

Local Ltac2 rec unfold_const x :=
  if Bool.neg (Constr.is_const x) then x else
    let ref := reference_to_string.reference_of_constr x in
    match! eval cbv delta [$ref] in $x with ?x => unfold_const x
  end.

Local Ltac2 function_body (proc : constr) : constr :=
  let unfolded := unfold_const proc in
  match! unfolded with (_, _, ?fbody) => fbody end.

Local Ltac2 rec callee_specs (cmd : constr) : constr list :=
  match! cmd with
    | cmd.cond _ ?c1 ?c2  => List.append (callee_specs c1) (callee_specs c2)
    | cmd.seq ?c1 ?c2 => List.append (callee_specs c1) (callee_specs c2)
    | cmd.while _ ?c => callee_specs c
    | cmd.stackalloc _ _ ?c => callee_specs c
    | cmd.call _ ?f _ => [instance_of (spec_of $f)]
    | cmd.skip => []
    | cmd.set _ _ => []
    | cmd.unset _ => []
    | cmd.store _ _ _ => []
    | cmd.interact _ _ _ => []
    | _ => Control.throw (Invalid_argument (Some (Message.concat
        (Message.of_string "Failed to recurse into the following command, consider reducing it before calling program_logic_goal_for: ")
        (Message.of_constr cmd))))
  end.

Local Ltac2 program_logic_goal_for_function (proc : constr) : unit :=
  let fname := constr_string_basename_of_constr_reference proc in
  let fname_spec := instance_of (spec_of $fname) in
  let fbody := function_body proc in
  let goal := (fun (functions : constr) =>
    List.fold_right (fun premise_spec conclusion => '(($premise_spec $functions) -> $conclusion)) (callee_specs fbody) '($fname_spec $functions)) in
  exact (forall (functions : @map.rep _ _ Semantics.env) (EnvContains : map.get functions $fname = Some $proc),
    ltac2:(let g := goal &functions in exact $g)
  ).

Set Default Proof Mode "Classic".

Definition program_logic_goal_for (_ : Syntax.func) (P : Prop) := P.

Notation "program_logic_goal_for_function! proc" := (program_logic_goal_for proc ltac2:(
   program_logic_goal_for_function (Ltac2.Constr.pretype proc)))
  (at level 10, only parsing).

Ltac normalize_body_of_function f := eval cbv in f.

Ltac bind_body_of_function f_ :=
  let f := normalize_body_of_function f_ in
  let fbody := open_constr:(_) in
  let funif := open_constr:((_, _, fbody)) in
  unify f funif;
  let go_split := ltac2:(fbody |-
    let fbody_value := Option.get (Ltac1.to_constr fbody) in
    splitcmd fbody_value) in
  change f_ with f;
  go_split fbody; intros.

Ltac enter f :=
  cbv beta delta [program_logic_goal_for];
  bind_body_of_function f;
  lazymatch goal with |- ?s ?p => let s := rdelta s in change (s p); cbv beta end.

Ltac is_context_variable H :=
  assert_succeeds (exfalso; clear -H; assert(H = H);
    let A := fresh in let B := fresh in destruct H as [A B]; pose H).

Ltac straightline_cleanup :=
  match goal with

  | x : Word.Interface.word.rep _ |- _ => clear x
  | x : Init.Byte.byte |- _ => clear x
  | x : Semantics.trace |- _ => clear x
  | x : Syntax.cmd |- _ => clear x
  | x : Syntax.expr |- _ => clear x
  | x : coqutil.Map.Interface.map.rep |- _ => clear x
  | x : BinNums.Z |- _ => clear x
  | x : unit |- _ => clear x
  | x : bool |- _ => clear x
  | x : list _ |- _ => clear x
  | x : nat |- _ => clear x

  | x := _ : Word.Interface.word.rep _ |- _ => clear x
  | x := _ : Init.Byte.byte |- _ => clear x
  | x := _ : Semantics.trace |- _ => clear x
  | x := _ : Syntax.cmd |- _ => clear x
  | x := _ : Syntax.expr |- _ => clear x
  | x := _ : coqutil.Map.Interface.map.rep |- _ => clear x
  | x := _ : BinNums.Z |- _ => clear x
  | x := _ : unit |- _ => clear x
  | x := _ : bool |- _ => clear x
  | x := _ : list _ |- _ => clear x
  | x := _ : nat |- _ => clear x
  | |- forall _, _ => intros
  | |- let _ := _ in _ => intros
  | |- dlet.dlet ?v (fun x => ?P) => change (let x := v in P); intros
  | _ => progress (cbn [Semantics.interp_binop] in * )
  | H: exists _, _ |- _ => tryif is_context_variable H then fail else destruct H
  | H: _ /\ _ |- _ => tryif is_context_variable H then fail else destruct H
  | x := ?y |- ?G => is_var y; subst x
  | H: ?x = ?y |- _ => constr_eq x y; clear H
  | H: ?x = ?y |- _ => is_var x; is_var y; assert_fails (idtac; let __ := eval cbv [x] in x in idtac); subst x
  | H: ?x = ?y |- _ => is_var x; is_var y; assert_fails (idtac; let __ := eval cbv [y] in y in idtac); subst y
  | H: ?x = ?v |- _ =>
    is_var x;
    assert_fails (idtac; let __ := eval cbv delta [x] in x in idtac);
    lazymatch v with context[x] => fail | _ => idtac end;
    let x' := fresh x in
    rename x into x';
    simple refine (let x := v in _);
    change (x' = x) in H;
    symmetry in H;
    destruct H
  end.

Ltac straightline_stackalloc :=
  match goal with Hanybytes: Memory.anybytes ?a ?n ?mStack |- _ =>
  let m := match goal with H : map.split ?mCobined ?m mStack |- _ => m end in
  let mCombined := match goal with H : map.split ?mCobined ?m mStack |- _ => mCobined end in
  let Hsplit := match goal with H : map.split ?mCobined ?m mStack |- _ => H end in
  let Hm := multimatch goal with H : _ m |- _ => H end in
  let Hm' := fresh Hm in
  let Htmp := fresh in
  let Pm := match type of Hm with ?P m => P end in
  assert_fails (assert (Separation.sep Pm (Array.array Separation.ptsto (Interface.word.of_Z (BinNums.Zpos BinNums.xH)) a _) mCombined) as _ by ecancel_assumption);
  rename Hm into Hm';
  let stack := fresh "stack" in
  let stack_length := fresh "length_" stack in
  destruct (Array.anybytes_to_array_1 mStack a n Hanybytes) as (stack&Htmp&stack_length);
  epose proof (ex_intro _ m (ex_intro _ mStack (conj Hsplit (conj Hm' Htmp)))
  : Separation.sep _ (Array.array Separation.ptsto (Interface.word.of_Z (BinNums.Zpos BinNums.xH)) a _) mCombined) as Hm;
  clear Htmp;
  try (let m' := fresh m in rename m into m'); rename mCombined into m;
  ( assert (BinInt.Z.of_nat (Datatypes.length stack) = n)
  by (rewrite stack_length; apply (ZifyInst.of_nat_to_nat_eq n))
  || fail 2 "negative stackalloc of size" n )
  end.

Ltac straightline_stackdealloc :=
  lazymatch goal with |- exists _ _, Memory.anybytes ?a ?n _ /\ map.split ?m _ _ /\ _ =>
  let Hm := multimatch goal with Hm : _ m |- _ => Hm end in
  let stack := match type of Hm with context [Array.array Separation.ptsto _ a ?stack] => stack end in
  let length_stack := match goal with H : Datatypes.length stack = _ |- _ => H end in
  let Hm' := fresh Hm in
  pose proof Hm as Hm';
  let Psep := match type of Hm with ?P _ => P end in
  let Htmp := fresh "Htmp" in
  eassert (Lift1Prop.iff1 Psep (Separation.sep _ (Array.array Separation.ptsto (Interface.word.of_Z (BinNums.Zpos BinNums.xH)) a stack))) as Htmp
  by ecancel || fail "failed to find stack frame in" Psep "using ecancel";
  eapply (fun m => proj1 (Htmp m)) in Hm;
  let m' := fresh m in
  rename m into m';
  let mStack := fresh in
  destruct Hm as (m&mStack&Hsplit&Hm&Harray1); move Hm at bottom;
  pose proof Array.array_1_to_anybytes _ _ _ Harray1 as Hanybytes;
  rewrite length_stack in Hanybytes;
  refine (ex_intro _ m (ex_intro _ mStack (conj Hanybytes (conj Hsplit _))));
  clear Htmp Hsplit mStack Harray1 Hanybytes
  end.

Ltac rename_to_different H :=
  idtac;
  let G := fresh H "'0" in
  rename H into G.
Ltac ensure_free H :=
  try rename_to_different H.

Ltac eq_uniq_step :=
  match goal with
  | |- ?x = ?y =>
      let x := rdelta x in
      let y := rdelta y in
      first [ is_evar x | is_evar y | constr_eq x y ]; exact eq_refl
  | |- ?lhs = ?rhs =>
      let lh := head lhs in
      is_constructor lh;
      let rh := head rhs in
      constr_eq lh rh;
      f_equal
  end.
Ltac eq_uniq := repeat eq_uniq_step.

Ltac fwd_uniq_step :=
  match goal with
  | |- exists x : ?T, _ =>
      let ev := open_constr:(match _ return T with x => x end) in
      eexists ev;
      let rec f :=
        tryif has_evar ev
        then fwd_uniq_step
        else idtac
      in f
  | |- _ /\ _ => split; [ solve [repeat fwd_uniq_step; eq_uniq] | ]
  | _ => solve [ eq_uniq ]
  end.

Ltac straightline :=
  match goal with
  | _ => straightline_cleanup
  | |- program_logic_goal_for ?f _ =>
    enter f; intros;
    match goal with
    | H: map.get ?functions ?fname = Some _ |- _ =>
        eapply start_func; [exact H | clear H]
    end;
    cbv match beta delta [WeakestPrecondition.func]
  | |- WeakestPrecondition.cmd _ (cmd.set ?s ?e) _ _ _ ?post =>
    unfold1_cmd_goal; cbv beta match delta [cmd_body];
    let __ := match s with String.String _ _ => idtac | String.EmptyString => idtac end in
    ident_of_constr_string_cps s ltac:(fun x =>
      ensure_free x;

      letexists _ as x; split; [solve [repeat straightline]|])
  | |- cmd _ ?c _ _ _ ?post =>
    let c := eval hnf in c in
    lazymatch c with
    | cmd.while _ _ => fail
    | cmd.cond _ _ _ => fail
    | cmd.interact _ _ _ => fail
    | _ => unfold1_cmd_goal; cbv beta match delta [cmd_body]
    end
  | |- @list_map _ _ (get _) _ _ => unfold1_list_map_goal; cbv beta match delta [list_map_body]
  | |- @list_map _ _ (expr _ _) _ _ => unfold1_list_map_goal; cbv beta match delta [list_map_body]
  | |- @list_map _ _ _ nil _ => cbv beta match fix delta [list_map list_map_body]
  | |- expr _ _ _ _ => unfold1_expr_goal; cbv beta match delta [expr_body]
  | |- dexpr _ _ _ _ => cbv beta delta [dexpr]
  | |- dexprs _ _ _ _ => cbv beta delta [dexprs]
  | |- literal _ _ => cbv beta delta [literal]
  | |- @get ?w ?W ?L ?l ?x ?P =>
      let get' := eval cbv [get] in @get in
      change (get' w W L l x P); cbv beta
  | |- load _ _ _ _ => cbv beta delta [load]
  | |- @Loops.enforce ?width ?word ?locals ?names ?values ?map =>
    let values := eval cbv in values in
    change (@Loops.enforce width word locals names values map);
    exact (conj (eq_refl values) eq_refl)
  | |- @eq (@coqutil.Map.Interface.map.rep String.string Interface.word.rep _) _ _ =>
    eapply SortedList.eq_value; exact eq_refl
  | |- @map.get String.string Interface.word.rep ?M ?m ?k = Some ?e' =>
    let e := rdelta e' in
    is_evar e;
    once (let v := multimatch goal with x := context[@map.put _ _ M _ k ?v] |- _ => v end in

          unify e v; exact (eq_refl (Some v)))
  | |- @coqutil.Map.Interface.map.get String.string Interface.word.rep _ _ _ = Some ?v =>
    let v' := rdelta v in is_evar v'; (change v with v'); exact eq_refl
  | |- ?x = ?y =>
    let y := rdelta y in is_evar y; change (x=y); exact eq_refl
  | |- ?x = ?y =>
    let x := rdelta x in is_evar x; change (x=y); exact eq_refl
  | |- ?x = ?y =>
    let x := rdelta x in let y := rdelta y in constr_eq x y; exact eq_refl
  | |- store Syntax.access_size.one _ _ _ _ =>
    eapply Scalars.store_one_of_sep; [solve[ecancel_assumption]|]
  | |- store Syntax.access_size.two _ _ _ _ =>
    eapply Scalars.store_two_of_sep; [solve[ecancel_assumption]|]
  | |- store Syntax.access_size.four _ _ _ _ =>
    eapply Scalars.store_four_of_sep; [solve[ecancel_assumption]|]
  | |- store Syntax.access_size.word _ _ _ _ =>
    eapply Scalars.store_word_of_sep; [solve[ecancel_assumption]|]
  | |- bedrock2.Memory.load Syntax.access_size.one ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_one_of_sep _ _ _ _ _ _ _ _ _ _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.two ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_two_of_sep _ _ word _ mem _ a _ _ m _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.four ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_four_of_sep_32bit _ _ word _ mem _ eq_refl a _ _ m _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.four ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_four_of_sep _ _ word _ mem _ a _ _ m _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.word ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_word_of_sep _ _ word _ mem _ a _ _ m _); ecancel_assumption
  | |- exists l', Interface.map.of_list_zip ?ks ?vs = Some l' /\ _ =>
    letexists; split; [exact eq_refl|]
  | |- exists l', Interface.map.putmany_of_list_zip ?ks ?vs ?l = Some l' /\ _ =>
    letexists; split; [exact eq_refl|]
  | _ => fwd_uniq_step
  | |- exists x, ?P /\ ?Q =>
    let x := fresh x in refine (let x := _ in ex_intro (fun x => P /\ Q) x _);
                        split; [solve [repeat straightline]|]
  | |- exists x, Markers.split (?P /\ ?Q) =>
    let x := fresh x in refine (let x := _ in ex_intro (fun x => P /\ Q) x _);
                        split; [solve [repeat straightline]|]
  | |- Markers.unique (exists x, Markers.split (?P /\ ?Q)) =>
    let x := fresh x in refine (let x := _ in ex_intro (fun x => P /\ Q) x _);
                        split; [solve [repeat straightline]|]
  | |- Markers.unique (Markers.left ?G) =>
    change G;
    unshelve (idtac; repeat match goal with
                     | |- Markers.split (?P /\ Markers.right ?Q) =>
                       split; [eabstract (repeat straightline) | change Q]
                     | |- exists _, _ => letexists
                     end); []
  | |- Markers.split ?G => change G; split
  | |- True => exact I
  | |- False \/ _ => right
  | |- _ \/ False => left
  | |- BinInt.Z.modulo ?z (Memory.bytes_per_word _) = BinInt.Z0 /\ _ =>
      lazymatch Coq.setoid_ring.InitialRing.isZcst z with
      | true => split; [exact eq_refl|]
      end
  | |- _ => straightline_stackalloc
  | |- _ => straightline_stackdealloc
  | |- context[sep (sep ?_a ?_b) ?_c] => progress (flatten_seps_in_goal; cbn [seps])
  | H : context[sep (sep ?_a ?_b) ?_c] |- _ => progress (flatten_seps_in H; cbn [seps] in H)
  end.
Import bedrock2.NotationsCustomEntry.
Local Open Scope string_scope.
Import Crypto.Arithmetic.WordByWordMontgomery.

Section WithParameters.
  Import WordByWordMontgomery.

  Context {prime: Z} (r := 64) {ri : Z}.
Instance spec_of_redc_alt : spec_of "redc_alt".
exact (fnspec! "redc_alt" Astart Bstart Sstart len / A (aval: Z) B (bval: Z) S R,
    { requires t m :=
        m =* array scalar (word.of_Z 8) Astart A *
                  array scalar (word.of_Z 8) Bstart B *
                  array scalar (word.of_Z 8) Sstart S * R /\
        word.unsigned len = Z.of_nat (List.length A)  /\
        word.unsigned len = Z.of_nat (List.length B)  /\
        word.unsigned len = Z.of_nat (List.length S) /\
        @eval r (Z.to_nat (word.unsigned len)) (List.map word.unsigned A) = aval /\
        @eval r (Z.to_nat (word.unsigned len)) (List.map word.unsigned B) = bval;
      ensures t' m' :=  t=t' /\ exists S',
          m' =*
             array scalar (word.of_Z 8) Astart A *
             array scalar (word.of_Z 8) Bstart B *
            array scalar (word.of_Z 8) Sstart S' * R /\
          ( aval * bval * ri^(word.unsigned len) ) mod prime =
            @eval r (Z.to_nat (word.unsigned len)) (List.map word.unsigned S') mod prime
    }).
Defined.
Instance spec_of_redc_step : spec_of "redc_step".
Admitted.

  Definition redc_alt :=
    func! (Astart, Bstart, Sstart, len) {
    i = $0;
    while (i < len) {
         store(Sstart + $8*i, $0);
         i = i + $1
      };
    i = $0;
    while (i < len) {
         redc_step ( load(Astart + $8*i), Bstart, Sstart, len );
          i = i + $1
      }
    }.

  Let zeros (n: Z) :=
        repeat (@word.of_Z _ word 0) (Z.to_nat n).

 Theorem redc_alt_ok :
      program_logic_goal_for_function! redc_alt.
 Proof.
   repeat straightline.

      refine ( tailrec (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ HList.polymorphic_list.nil))))))))
               ("Astart":: "Bstart" :: "Sstart" :: "len" :: "i" :: nil)
               (fun l A aval B bval S Ra Rb R t m Astart Bstart Sstart len i => PrimitivePair.pair.mk
                                    (m =* array scalar (word.of_Z 8) (word.add Sstart (word.mul (word.of_Z 8) i)) S * R /\
                                       word.unsigned len - word.unsigned i = Z.of_nat (List.length S) /\

                                    l = List.length S )
                                    (fun t' m' Astart' Bstart' Sstart' len' i' =>
                                       (
                                     t = t' /\ Astart = Astart' /\ Bstart = Bstart' /\ Sstart = Sstart' /\ len = len' /\
                                     m' =* array scalar (word.of_Z 8) (word.add Sstart (word.mul (word.of_Z 8) i)) (zeros (word.unsigned len - word.unsigned i)) * R
                                     )
                                    )
               )
               lt _ _ _ _ _ _ _ _ _ _ _ _ _);
        cbn [reconstruct map.putmany_of_list HList.tuple.to_list
         HList.hlist.foralls HList.tuple.foralls
         HList.hlist.existss HList.tuple.existss
         HList.hlist.apply  HList.tuple.apply
         HList.hlist
         List.repeat Datatypes.length
         HList.polymorphic_list.repeat HList.polymorphic_list.length
         PrimitivePair.pair._1 PrimitivePair.pair._2] in *.

      {
 repeat straightline.
}
      {
 exact Wf_nat.lt_wf.
}
      {
 repeat straightline.
        subst i.
        replace (word.add Sstart (word.mul (word.of_Z 8) (word.of_Z 0))) with (Sstart) by ring.
        repeat split; try eauto.
        -
 ecancel_assumption.
        -
 rewrite word.unsigned_of_Z_0.
Lia.lia.
}

      {
 repeat straightline.
eexists.
🛠️ Intermediate Coq File (useful for debugging if minimization did not go as far as you wanted) (truncated to 6.0KiB; full 141KiB file on GitHub Actions Artifacts under tmp.v)
(* -*- mode: coq; coq-prog-args: ("-emacs" "-q" "-w" "+implicit-core-hint-db,+implicits-in-term,+non-reversible-notation,+deprecated-intros-until-0,+deprecated-focus,+unused-intro-pattern,+variable-collision,+unexpected-implicit-declaration,+omega-is-deprecated,+deprecated-instantiate-syntax,+non-recursive,+undeclared-scope,+deprecated-hint-rewrite-without-locality,+deprecated-hint-without-locality,+deprecated-instance-without-locality,+deprecated-typeclasses-transparency-without-locality,+fragile-hint-constr,-deprecated-since-9.0,-deprecated-since-8.20,-deprecated-from-Coq" "-w" "-notation-overridden,-native-compiler-disabled,-ambiguous-paths,-masking-absolute-name" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Coqprime" "Coqprime" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Kami" "Kami" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rewriter" "Rewriter" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rupicola" "Rupicola" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Top.bug_01") -*- *)
(* File reduced by coq-bug-minimizer from original input, then from 577 lines to 117 lines, then from 131 lines to 869 lines, then from 877 lines to 453 lines, then from 468 lines to 1367 lines, then from 1372 lines to 533 lines, then from 548 lines to 1295 lines, then from 1303 lines to 616 lines, then from 631 lines to 1279 lines, then from 1286 lines to 653 lines, then from 668 lines to 953 lines, then from 961 lines to 662 lines, then from 677 lines to 1947 lines, then from 1949 lines to 996 lines, then from 1011 lines to 1284 lines, then from 1292 lines to 1026 lines, then from 1041 lines to 1079 lines, then from 1087 lines to 1042 lines, then from 1057 lines to 1205 lines, then from 1211 lines to 1085 lines, then from 1100 lines to 1221 lines, then from 1229 lines to 1123 lines, then from 1138 lines to 1177 lines, then from 1185 lines to 1151 lines, then from 1166 lines to 1480 lines, then from 1488 lines to 1182 lines, then from 1197 lines to 1464 lines, then from 1472 lines to 1195 lines, then from 1216 lines to 1089 lines, then from 1103 lines to 1492 lines, then from 1500 lines to 1101 lines, then from 1116 lines to 1306 lines, then from 1314 lines to 1114 lines, then from 1129 lines to 1859 lines, then from 1867 lines to 1133 lines, then from 1148 lines to 1714 lines, then from 1722 lines to 1326 lines, then from 1341 lines to 1990 lines, then from 1998 lines to 1486 lines, then from 1501 lines to 1869 lines, then from 1877 lines to 1526 lines, then from 1541 lines to 1966 lines, then from 1974 lines to 1564 lines, then from 1579 lines to 2023 lines, then from 2031 lines to 1594 lines, then from 1609 lines to 1995 lines, then from 2003 lines to 1621 lines, then from 1636 lines to 1925 lines, then from 1933 lines to 1639 lines, then from 1654 lines to 2735 lines, then from 2740 lines to 1705 lines, then from 1720 lines to 2134 lines, then from 2142 lines to 1716 lines, then from 1731 lines to 2049 lines, then from 2057 lines to 1876 lines, then from 1878 lines to 1549 lines, then from 1561 lines to 3345 lines *)
(* coqc version 9.3+alpha compiled with OCaml 4.14.2
   coqtop version 9.3+alpha
   Expected coqc runtime on this file: 0.000 sec
   Expected coqc peak memory usage on this file: 0.0 kb *)
Require Coq.Init.Ltac.
Module Export AdmitTactic.
Module Import LocalFalse.
Inductive False : Prop := .
End LocalFalse.
Axiom proof_admitted : False.
Import Coq.Init.Ltac.
Tactic Notation "admit" := abstract case proof_admitted.
End AdmitTactic.

Require bedrock2.Markers.
Require coqutil.Tactics.eabstract.
Require coqutil.Tactics.letexists.
Require coqutil.Tactics.ident_of_string.
Require coqutil.Tactics.reference_to_string.
Require bedrock2.NotationsCustomEntry.
Require coqutil.dlet.
Require coqutil.Word.Bitwidth.
Require coqutil.Map.SortedListString.
Import Coq.ZArith.ZArith.

Local Open Scope Z_scope.

Notation byte := (Coq.Init.Byte.byte: Type).

Module Export byte.
Definition unsigned(b: byte): Z.
Admitted.
Definition of_Z(z: Z): byte.
Admitted.
Module Export LittleEndianList.
Fixpoint le_combine(l: list byte): Z.
Admitted.
Fixpoint le_split (n : nat) (w : Z) : list byte.
Admitted.
Module Export Properties.
Import coqutil.Word.Interface.
Import word.

Module Export word.
  Section WithWord.
    Context {width} {word : word width} {word_ok : word.ok word}.
    Local Hint Mode word.word - : typeclass_instances.

    Lemma unsigned_of_Z_0 : word.unsigned (word.of_Z 0) = 0.
Admitted.

    Lemma ring_theory : Ring_theory.ring_theory (of_Z 0) (of_Z 1) add mul sub opp Logic.eq.
Admitted.
    Lemma ring_morph_add : forall x y : Z, of_Z (x + y) = add (of_Z x) (of_Z y).
Admitted.
    Lemma ring_morph_sub : forall x y : Z, of_Z (x - y) = sub (of_Z x) (of_Z y).
Admitted.
    Lemma ring_morph_mul : forall x y : Z, of_Z (x * y) = mul (of_Z x) (of_Z y).
Admitted.
    Lemma ring_morph_opp : forall x : Z, of_Z (- x) = opp (of_Z x).
Admitted.
    Lemma ring_morph :
      Ring_theory.ring_morph (of_Z 0) (of_Z 1) add   mul   sub   opp   Logic.eq
                             0        1        Z.a
🛠️ 📜 Intermediate Coq File log (useful for debugging if minimization did not go as far as you wanted)
📜 Build Log (contains the Coq error message) (truncated to last 8.0KiB; full 14MiB file on GitHub Actions Artifacts under build.log)
Util/ZUtil/Tactics/SimplifyFractionsLe.vo
src/Util/ZUtil/Tactics/SolveRange.vo
src/Util/ZUtil/Tactics/SolveTestbit.vo
src/Util/ZUtil/Tactics/SplitMinMax.vo
src/Util/ZUtil/Tactics/ZeroBounds.vo
src/Util/ZUtil/Tactics/Ztestbit.vo
src/Util/ZUtil/Testbit.vo
src/Util/ZUtil/TruncatingShiftl.vo
src/Util/ZUtil/TwosComplement.vo
src/Util/ZUtil/Z2Nat.vo
src/Util/ZUtil/ZSimplify.vo
src/Util/ZUtil/ZSimplify/Autogenerated.vo
src/Util/ZUtil/ZSimplify/Core.vo
src/Util/ZUtil/ZSimplify/Simple.vo
src/Util/ZUtil/Zselect.vo


Files Not Made:
src/Bedrock/End2End/Poly1305/Field1305.vo
src/Bedrock/End2End/X25519/EdwardsXYZT.vo
src/Bedrock/End2End/X25519/Field25519.vo
src/Bedrock/End2End/X25519/GarageDoor.vo
src/Bedrock/End2End/X25519/GarageDoorTop.vo
src/Bedrock/End2End/X25519/MontgomeryLadder.vo
src/Bedrock/End2End/X25519/MontgomeryLadderRISCV.vo
src/Bedrock/Everything.vo
src/Bedrock/Field/Stringification/Stringification.vo
src/Bedrock/Field/Synthesis/Examples/p224_64_new.vo
src/Bedrock/Field/Synthesis/New/ComputedOp.vo
src/Bedrock/Field/Synthesis/New/Signature.vo
src/Bedrock/Field/Synthesis/New/UnsaturatedSolinas.vo
src/Bedrock/Field/Synthesis/New/WordByWordMontgomery.vo
src/Bedrock/Field/Translation/Cmd.vo
src/Bedrock/Field/Translation/Func.vo
src/Bedrock/Field/Translation/Parameters/Defaults.vo
src/Bedrock/Field/Translation/Parameters/Defaults32.vo
src/Bedrock/Field/Translation/Parameters/Defaults64.vo
src/Bedrock/Field/Translation/Parameters/FE310.vo
src/Bedrock/Field/Translation/Proofs/Cmd.vo
src/Bedrock/Field/Translation/Proofs/Func.vo
src/Bedrock/Field/Translation/Proofs/ValidComputable/Cmd.vo
src/Bedrock/Field/Translation/Proofs/ValidComputable/Func.vo
src/Bedrock/Group/ScalarMult/MontgomeryLadder.vo
src/Bedrock/P256.vo
src/Bedrock/P256/Coord.vo
src/Bedrock/P256/Coord32.vo
src/Bedrock/P256/Jacobian.vo
src/Bedrock/P256/JacobianAffine.vo
src/Bedrock/P256/Platform.vo
src/Bedrock/P256/PrecomputedMultiples.vo
src/Bedrock/P256/RecodeProofs.vo
src/Bedrock/P256/Scalarmult.vo
src/Bedrock/P256/Specs.vo
src/Bedrock/Secp256k1/Addchain.vo
src/Bedrock/Secp256k1/Field256k1.vo
src/Bedrock/Secp256k1/JacobianCoZ.vo
src/Bedrock/Secp256k1/JoyeLadder.vo
src/Bedrock/Standalone/StandaloneHaskellMain.vo
src/Bedrock/Standalone/StandaloneJsOfOCamlMain.vo
src/Bedrock/Standalone/StandaloneOCamlMain.vo
src/BoundsPipeline.vo
src/CLI.vo
src/CompilersTestCases.vo
src/Curves/Montgomery/AffineInstances.vo
src/Curves/Montgomery/AffineProofs.vo
src/Curves/Montgomery/XZProofs.vo
src/Curves/Weierstrass/AffineProofs.vo
src/Curves/Weierstrass/Jacobian/CoZ.vo
src/Curves/Weierstrass/Jacobian/Jacobian.vo
src/Curves/Weierstrass/Jacobian/ScalarMult.vo
src/Curves/Weierstrass/P256.vo
src/Curves/Weierstrass/Projective.vo
src/Everything.vo
src/ExtractionJsOfOCaml/WithBedrock/fiat_crypto.vo
src/ExtractionJsOfOCaml/bedrock2_fiat_crypto.vo
src/ExtractionJsOfOCaml/fiat_crypto.vo
src/Fancy/Barrett256.vo
src/Fancy/Montgomery256.vo
src/PerfTesting/PerfTestPrint.vo
src/PerfTesting/PerfTestSearch.vo
src/PerfTesting/PerfTestSearchPattern.vo
src/PushButtonSynthesis/BarrettReduction.vo
src/PushButtonSynthesis/BaseConversion.vo
src/PushButtonSynthesis/DettmanMultiplication.vo
src/PushButtonSynthesis/FancyMontgomeryReduction.vo
src/PushButtonSynthesis/Primitives.vo
src/PushButtonSynthesis/SaturatedSolinas.vo
src/PushButtonSynthesis/SmallExamples.vo
src/PushButtonSynthesis/SolinasReduction.vo
src/PushButtonSynthesis/UnsaturatedSolinas.vo
src/PushButtonSynthesis/WordByWordMontgomery.vo
src/Rewriter/All.vo
src/Rewriter/PerfTesting/Core.vo
src/Rewriter/PerfTesting/StandaloneOCamlMain.vo
src/Rewriter/RulesGood.vo
src/SlowPrimeSynthesisExamples.vo
src/StandaloneDebuggingExamples.vo
src/StandaloneHaskellMain.vo
src/StandaloneJsOfOCamlMain.vo
src/StandaloneMonadicUtils.vo
src/StandaloneOCamlMain.vo
ROCQ compile src/Bedrock/Field/Synthesis/Examples/redc.v
MINIMIZER_DEBUG_EXTRA: coqc: /github/workspace/builds/coq/coq-failing/_install_ci/bin///rocq
MINIMIZER_DEBUG_EXTRA: original invocation: '' 
MINIMIZER_DEBUG_EXTRA: new invocation: /github/workspace/builds/coq/coq-failing/_install_ci/bin/rocq.orig compile -q -w +implicit-core-hint-db\,+implicits-in-term\,+non-reversible-notation\,+deprecated-intros-until-0\,+deprecated-focus\,+unused-intro-pattern\,+variable-collision\,+unexpected-implicit-declaration\,+omega-is-deprecated\,+deprecated-instantiate-syntax\,+non-recursive\,+undeclared-scope\,+deprecated-hint-rewrite-without-locality\,+deprecated-hint-without-locality\,+deprecated-instance-without-locality\,+deprecated-typeclasses-transparency-without-locality\,+fragile-hint-constr\,-deprecated-since-9.0\,-deprecated-since-8.20\,-deprecated-from-Coq -w -notation-overridden\,-native-compiler-disabled\,-ambiguous-paths\,-masking-absolute-name -w -deprecated-native-compiler-option -native-compiler no -R /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src Crypto src/Bedrock/Field/Synthesis/Examples/redc.v 
MINIMIZER_DEBUG_EXTRA: coqpath: 
MINIMIZER_DEBUG_EXTRA: ocamlpath: /github/workspace/builds/coq/coq-failing/_install_ci/lib:
MINIMIZER_DEBUG_EXTRA: pwd: PWD=/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto
MINIMIZER_DEBUG_EXTRA: exec: /github/workspace/builds/coq/coq-failing/_install_ci/bin/rocq.orig compile -q -w +implicit-core-hint-db\,+implicits-in-term\,+non-reversible-notation\,+deprecated-intros-until-0\,+deprecated-focus\,+unused-intro-pattern\,+variable-collision\,+unexpected-implicit-declaration\,+omega-is-deprecated\,+deprecated-instantiate-syntax\,+non-recursive\,+undeclared-scope\,+deprecated-hint-rewrite-without-locality\,+deprecated-hint-without-locality\,+deprecated-instance-without-locality\,+deprecated-typeclasses-transparency-without-locality\,+fragile-hint-constr\,-deprecated-since-9.0\,-deprecated-since-8.20\,-deprecated-from-Coq -w -notation-overridden\,-native-compiler-disabled\,-ambiguous-paths\,-masking-absolute-name -w -deprecated-native-compiler-option -native-compiler no -R /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src Crypto src/Bedrock/Field/Synthesis/Examples/redc.v 
MINIMIZER_DEBUG_EXTRA: coqlib: Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//
MINIMIZER_DEBUG: info: /tmp/tmp-coqbot-minimizer.1iLcJz2o9W
MINIMIZER_DEBUG: files:  src/Bedrock/Field/Synthesis/Examples/redc.v /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src/Bedrock/Field/Synthesis/Examples/redc.v
Warning, feedback message received but no listener to handle it!
Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]Warning, feedback message received but no listener to handle it!
Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
Warning: Deprecated environment variable COQCORELIB,
use ROCQRUNTIMELIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
File "./src/Bedrock/Field/Synthesis/Examples/redc.v", line 210, characters 29-37:
Error: Expected a single focused goal but 2 goals are focused.

Command exited with non-zero status 1
src/Bedrock/Field/Synthesis/Examples/redc.vo (real: 1.01, user: 0.85, sys: 0.16, mem: 540088 ko)
make: *** [Makefile.coq:815: src/Bedrock/Field/Synthesis/Examples/redc.vo] Error 1
make: *** [src/Bedrock/Field/Synthesis/Examples/redc.vo] Deleting file 'src/Bedrock/Field/Synthesis/Examples/redc.glob'
+ code=2
+ printf '\n%s exit code: %s\n' fiat_crypto 2
+ '[' fiat_crypto '!=' stdlib_test ']'
+ echo 'Aggregating timing log...'
Aggregating timing log...
+ echo

+ tools/make-one-time-file.py --real _build_ci/fiat_crypto.log
    Time |  Peak Mem | File Name                               
---------------------------------------------------------------
0m01.46s | 540088 ko | Total Time / Peak Mem                   
---------------------------------------------------------------
0m01.01s | 540088 ko | Bedrock/Field/Synthesis/Examples/redc.vo
0m00.45s |  34292 ko | .Makefile.coq.d                         
+ '[' '' ']'
+ exit 2
/github/workspace/builds/coq /github/workspace
::endgroup::
📜 🔎 Minimization Log (truncated to last 8.0KiB; full 36MiB file on GitHub Actions Artifacts under bug.log)
-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 668, characters 0-6:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 675, characters 0-6:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 678, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 680, characters 0-186:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 714, characters 0-94:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 771, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 774, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 776, characters 0-111:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 782, characters 0-520:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 795, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 811, characters 0-8:
Warning: Use of "Notation" keyword for abbreviations is deprecated, use
"Abbreviation" instead.
[notation-for-abbreviation,deprecated-since-9.2,deprecated,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 815, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 817, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 820, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 822, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 833, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 836, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 838, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 840, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 842, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 844, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 847, characters 71-85:
Warning: Notation Zeq_bool is deprecated since Stdlib 9.0. Use Z.eqb instead.
[deprecated-syntactic-definition-since-Stdlib-9.0,deprecated-since-Stdlib-9.0,deprecated-syntactic-definition,deprecated,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 848, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 863, characters 0-163:
Warning: Implicitly declaring Rewrite hint databases is deprecated. Please
explicitly create "rew_word_morphism"
[implicit-create-rewrite-hint-db,deprecated-since-9.2,deprecated,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 879, characters 0-6:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 882, characters 0-6:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 889, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 894, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 896, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 961, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 963, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 966, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 976, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 1072, characters 0-8:
Warning: Use of "Notation" keyword for abbreviations is deprecated, use
"Abbreviation" instead.
[notation-for-abbreviation,deprecated-since-9.2,deprecated,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 1100, characters 0-49:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 1207, characters 0-8:
Warning: Use of "Notation" keyword for abbreviations is deprecated, use
"Abbreviation" instead.
[notation-for-abbreviation,deprecated-since-9.2,deprecated,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 1243, characters 0-760:
Warning: Closed notations (i.e. starting and ending with a terminal symbol)
should usually be at level 0 (default).
[closed-notation-not-level-0,parsing,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 1243, characters 0-760:
Warning:
For backwards compatibility non left recursive notations declared at level 200
are actually at level 10, with any right-recursion being at level 200.
In the future level 200 will be treated as a normal level.
To keep the current behaviour, use "at level 10",
remove any "right associativity" annotation,
and if right recursive add "x at level 200" where "x" is the last argument.
[at-level-200-changed,deprecated-since-9.3,deprecated,default]
File "/tmp/tmpnkeot0jp/Top/bug_01.v", line 1273, characters 2-203:
Error:
In environment:
width : Z
BW : Bitwidth width
word : word.word width
mem : map word Byte.byte
locals : map string word
e : env
fname : string
fimpl : Syntax.func
t : trace
m : ?mem
args : list ?word
post : trace -> ?mem -> list ?word -> Prop
Could not find an instance for the following existential variables:
?locals : map string ?word

?ext_spec : ExtSpec

?locals0 : map string ?word

?ext_spec0 : ExtSpec

?BW : Bitwidth ?width

?word : word.word ?width

?mem : map ?word byte


�[93mIntermediate code not saved.�[0m

I will now attempt to remove unused non-instance, non-canonical structure definitions

If you have any comments on your experience of the minimizer, please share them in a reply (possibly tagging @JasonGross).
If you believe there's a bug in the bug minimizer, please report it on the bug minimizer issue tracker.

cc @JasonGross

@coqbot-app

coqbot-app Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Partially Minimized File /home/runner/work/run-coq-bug-minimizer/run-coq-bug-minimizer/builds/coq/coq-failing/_build_ci/fiat_crypto/src/Bedrock/Field/Synthesis/Examples/redc.v in 3h 58m 5s (from ci-fiat_crypto) (full log on GitHub Actions - verbose log)

We are collecting data on the user experience of the Coq Bug Minimizer.
If you haven't already filled the survey for this PR, please fill out our short survey!

⭐ 🏗️ Partially Minimized Coq File (could not inline Crypto.Arithmetic.WordByWordMontgomery, Ltac2.Array, Ltac2.Pattern, Ltac2.Ltac1, bedrock2.Markers) (truncated to first and last 32KiB; full 87KiB file on GitHub Actions Artifacts under bug.v)
(* -*- mode: coq; coq-prog-args: ("-emacs" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto") -*- *)
(* File reduced by coq-bug-minimizer from original input, then from 577 lines to 117 lines, then from 131 lines to 869 lines, then from 877 lines to 453 lines, then from 468 lines to 1367 lines, then from 1372 lines to 533 lines, then from 548 lines to 1295 lines, then from 1303 lines to 616 lines, then from 631 lines to 1279 lines, then from 1286 lines to 653 lines, then from 668 lines to 953 lines, then from 961 lines to 662 lines, then from 677 lines to 1947 lines, then from 1949 lines to 996 lines, then from 1011 lines to 1284 lines, then from 1292 lines to 1026 lines, then from 1041 lines to 1079 lines, then from 1087 lines to 1042 lines, then from 1057 lines to 1205 lines, then from 1211 lines to 1085 lines, then from 1100 lines to 1221 lines, then from 1229 lines to 1123 lines, then from 1138 lines to 1177 lines, then from 1185 lines to 1151 lines, then from 1166 lines to 1480 lines, then from 1488 lines to 1182 lines, then from 1197 lines to 1464 lines, then from 1472 lines to 1195 lines, then from 1216 lines to 1089 lines, then from 1103 lines to 1492 lines, then from 1500 lines to 1101 lines, then from 1116 lines to 1306 lines, then from 1314 lines to 1114 lines, then from 1129 lines to 1859 lines, then from 1867 lines to 1133 lines, then from 1148 lines to 1714 lines, then from 1722 lines to 1326 lines, then from 1341 lines to 1990 lines, then from 1998 lines to 1486 lines, then from 1501 lines to 1869 lines, then from 1877 lines to 1526 lines, then from 1541 lines to 1966 lines, then from 1974 lines to 1564 lines, then from 1579 lines to 2023 lines, then from 2031 lines to 1594 lines, then from 1609 lines to 1995 lines, then from 2003 lines to 1621 lines, then from 1636 lines to 1925 lines, then from 1933 lines to 1639 lines, then from 1654 lines to 2735 lines, then from 2740 lines to 1705 lines, then from 1720 lines to 2134 lines, then from 2142 lines to 1716 lines, then from 1731 lines to 2049 lines, then from 2057 lines to 1876 lines, then from 1878 lines to 1549 lines, then from 1561 lines to 1814 lines, then from 1821 lines to 1557 lines, then from 1570 lines to 2174 lines, then from 2181 lines to 1646 lines, then from 1659 lines to 2032 lines, then from 2039 lines to 1731 lines, then from 1744 lines to 4295 lines, then from 4301 lines to 1732 lines, then from 1745 lines to 2060 lines, then from 2067 lines to 1741 lines, then from 1754 lines to 2010 lines, then from 2017 lines to 1752 lines, then from 1765 lines to 2001 lines, then from 2008 lines to 1851 lines, then from 1864 lines to 1897 lines, then from 1904 lines to 1874 lines, then from 1887 lines to 2076 lines, then from 2083 lines to 1884 lines, then from 1897 lines to 2091 lines, then from 2098 lines to 1986 lines, then from 1999 lines to 2013 lines, then from 2020 lines to 2001 lines, then from 2014 lines to 2596 lines, then from 2602 lines to 2069 lines, then from 2082 lines to 2231 lines, then from 2238 lines to 2074 lines, then from 2087 lines to 2251 lines, then from 2258 lines to 2142 lines, then from 2155 lines to 2165 lines, then from 2172 lines to 2142 lines, then from 2155 lines to 2172 lines, then from 2179 lines to 2155 lines, then from 2168 lines to 2342 lines, then from 2349 lines to 2186 lines, then from 2199 lines to 2398 lines, then from 2405 lines to 2225 lines, then from 2238 lines to 2426 lines, then from 2433 lines to 2279 lines, then from 2292 lines to 2348 lines, then from 2355 lines to 2291 lines, then from 2304 lines to 2974 lines, then from 2981 lines to 2343 lines, then from 2360 lines to 2174 lines, then from 2186 lines to 2803 lines, then from 2810 lines to 2297 lines, then from 2310 lines to 3111 lines, then from 3118 lines to 2327 lines, then from 2340 lines to 2462 lines, then from 2468 lines to 2335 lines, then from 2348 lines to 2386 lines, then from 2393 lines to 2339 lines, then from 2352 lines to 2381 lines, then from 2388 lines to 2345 lines, then from 2358 lines to 2392 lines, then from 2399 lines to 2352 lines, then from 2365 lines to 2395 lines, then from 2402 lines to 2361 lines, then from 2374 lines to 2410 lines, then from 2415 lines to 2389 lines, then from 2400 lines to 2432 lines, then from 2439 lines to 2410 lines, then from 2422 lines to 2416 lines, then from 2422 lines to 2381 lines, then from 2393 lines to 2381 lines, then from 0 lines to 2381 lines *)
(* coqc version 9.3+alpha compiled with OCaml 4.14.2
   coqtop version 9.3+alpha
   Modules that could not be inlined: Crypto.Arithmetic.WordByWordMontgomery, Ltac2.Array, Ltac2.Pattern, Ltac2.Ltac1, bedrock2.Markers
   Expected coqc runtime on this file: 0.000 sec
   Expected coqc peak memory usage on this file: 0.0 kb *)
Axiom proof_admitted : False.
Tactic Notation "admit" := abstract case proof_admitted.

Require bedrock2.Markers.
Tactic Notation "eabstract" tactic3(tac) :=
  let G := match goal with |- ?G => G end in
  let pf := lazymatch constr:(ltac:(tac) : G) with ?pf => pf end in
  repeat match goal with
         | H: ?T |- _ => has_evar T;
                         clear dependent H;
                         assert_succeeds (pose pf)
         | H := ?e |- _ => has_evar e;
                         clear dependent H;
                         assert_succeeds (pose pf)
         end; admit.

Ltac expose_exists_for_letexists :=
  hnf.

Ltac letexists_ v :=
  expose_exists_for_letexists;
  lazymatch goal with
  | |- exists x, ?P =>
    let x' := fresh x in
    refine (let x' := v in ex_intro (fun x => P) x' _)
  end.
Tactic Notation "letexists" open_constr(v) :=
  letexists_ v.
Tactic Notation "letexists" :=
  letexists _.

Ltac letexists_as v x' :=
  expose_exists_for_letexists;
  lazymatch goal with
  | |- exists x, ?P =>
    refine (let x' := v in ex_intro (fun x => P) x' _)
  end.

Tactic Notation "letexists" open_constr(v) "as" ident(x) :=
  letexists_as v x.
Require Ltac2.Init.
Module Export Ident.

Import Ltac2.Init.

Ltac2 Type t := ident.

Ltac2 @ external of_string : string -> t option := "rocq-runtime.plugins.ltac2" "ident_of_string".

Ltac2 @ external to_string : t -> string := "rocq-runtime.plugins.ltac2" "ident_to_string".
Module Export String.

Ltac2 @external make : int -> char -> string := "rocq-runtime.plugins.ltac2" "string_make".
Ltac2 @external length : string -> int := "rocq-runtime.plugins.ltac2" "string_length".
Ltac2 @external get : string -> int -> char := "rocq-runtime.plugins.ltac2" "string_get".
Ltac2 @external set : string -> int -> char -> unit := "rocq-runtime.plugins.ltac2" "string_set".
Module Export Char.

Ltac2 @external of_int : int -> char := "rocq-runtime.plugins.ltac2" "char_of_int".

Ltac2 @external to_int : char -> int := "rocq-runtime.plugins.ltac2" "char_to_int".
Require Ltac2.Std.
Module Export Env.

Ltac2 @ external path : Std.reference -> ident list := "rocq-runtime.plugins.ltac2" "env_path".
Require Ltac2.Ltac1.
Module Export Option.

Ltac2 get (ov : 'a option) :=
  match ov with
  | Some v => v
  | None => Control.throw No_value
  end.
Require Ltac2.Pattern.
Module Export List.

Ltac2 rec last_opt (ls : 'a list) : 'a option :=
  match ls with
  | [] => None
  | x :: xs
    => match xs with
       | [] => Some x
       | _ :: _ => last_opt xs
       end
  end.

Ltac2 last (ls : 'a list) : 'a :=
  match last_opt ls with
  | None => Control.throw_invalid_argument "List.last"
  | Some v => v
  end.

Ltac2 rec append (ls1 : 'a list) (ls2 : 'a list) : 'a list :=
  match ls1 with
  | [] => ls2
  | x :: xs => x :: append xs ls2
  end.

Ltac2 rec fold_right (f : 'a -> 'b -> 'b) (ls : 'a list) (a : 'b) : 'b :=
  match ls with
  | [] => a
  | l :: ls => f l (fold_right f ls a)
  end.
Require Ltac2.Array.

Module Export Ltac2_DOT_Constr_WRAPPED.
Module Export Constr.

Ltac2 @ external equal : constr -> constr -> bool := "rocq-runtime.plugins.ltac2" "constr_equal".

Module Export Binder.

Ltac2 Type relevance_var.
Ltac2 Type relevance := [ Relevant | Irrelevant | RelevanceVar (relevance_var) ].

Ltac2 @ external name : binder -> ident option := "rocq-runtime.plugins.ltac2" "constr_binder_name".

End Binder.

Module Export Relevance.

  Ltac2 Type t := Binder.relevance.

End Relevance.

Module Export Unsafe.

Ltac2 Type case.

Ltac2 Type case_invert

  := [
  | NoInvert

  | CaseInvert (constr array)

].

Ltac2 Type kind := [
  | Rel (int)

  | Var (ident)

  | Meta (meta)

  | Evar (evar, constr array)

  | Sort (sort)

  | Cast (constr, cast, constr)

  | Prod (binder, constr)

  | Lambda (binder, constr)

  | LetIn (binder, constr, constr)

  | App (constr, constr array)

  | Constant (constant, instance)

  | Ind (inductive, instance)

  | Constructor (constructor, instance)

  | Case (case, (constr * Relevance.t), case_invert, constr, constr array)

  | Fix (int array, int, binder array, constr array)

  | CoFix (int, binder array, constr array)
  | Proj (projection, Relevance.t, constr)

  | Uint63 (uint63)
  | Float (float)
  | String (pstring)
  | Array (instance, constr array, constr, constr)

].

Ltac2 @ external kind : constr -> kind := "rocq-runtime.plugins.ltac2" "constr_kind".

Ltac2 @ external make : kind -> constr := "rocq-runtime.plugins.ltac2" "constr_make".

End Unsafe.

Module Export Pretype.
  Module Export Flags.
    Ltac2 Type t.

    Ltac2 @ external constr_flags : t := "rocq-runtime.plugins.ltac2" "constr_flags".

    Ltac2 @external set_allow_evars : bool -> t -> t
      := "rocq-runtime.plugins.ltac2" "pretype_flags_set_allow_evars".

    Ltac2 @external set_nf_evars : bool -> t -> t
      := "rocq-runtime.plugins.ltac2" "pretype_flags_set_nf_evars".

    Ltac2 Abbreviation open_constr_flags_with_tc :=
      set_nf_evars false (set_allow_evars true constr_flags).
  End Flags.

  Ltac2 Type expected_type.

  Ltac2 @ external expected_oftype : constr -> expected_type
    := "rocq-runtime.plugins.ltac2" "expected_oftype".

  Ltac2 @ external expected_without_type_constraint : expected_type
    := "rocq-runtime.plugins.ltac2" "expected_without_type_constraint".

  Ltac2 @ external pretype : Flags.t -> expected_type -> preterm -> constr
    := "rocq-runtime.plugins.ltac2" "constr_pretype".

End Pretype.

Ltac2 pretype (c : preterm) : constr :=
  Pretype.pretype Pretype.Flags.constr_flags Pretype.expected_without_type_constraint c.

Ltac2 is_const(c: constr) :=
  match Unsafe.kind c with
  | Unsafe.Constant _ _ => true
  | _ => false
  end.

End Constr.
Module Export Ltac2.
Module Export Constr.
Include Ltac2_DOT_Constr_WRAPPED.Constr.

Ltac2 Notation "lazy_match!" t(tactic(6)) "with" m(constr_matching) "end" : 0 :=
  Pattern.lazy_match0 t m.

Ltac2 Notation "match!" t(tactic(6)) "with" m(constr_matching) "end" : 0 :=
  Pattern.one_match0 t m.

Ltac2 default_on_concl cl :=
match cl with
| None => { Std.on_hyps := Some []; Std.on_concl := Std.AllOccurrences }
| Some cl => cl
end.

Ltac2 Notation "set" p(thunk(pose)) cl(opt(clause)) :=
  Std.set false p (default_on_concl cl).

Ltac2 Notation "eval" "red" "in" c(constr) :=
  Std.eval_red c.

Ltac2 Notation "eval" "cbv" s(strategy) "in" c(constr) :=
  Std.eval_cbv s c.

Ltac2 Notation "eval" "vm_compute" pl(opt(seq(pattern, occurrences))) "in" c(constr) :=
  Std.eval_vm pl c.

Ltac2 exact1 ev c :=
  Control.enter (fun () =>
    let c :=
      Constr.Pretype.pretype
        (if ev then Constr.Pretype.Flags.open_constr_flags_with_tc else Constr.Pretype.Flags.constr_flags)
        (Constr.Pretype.expected_oftype (Control.goal()))
        c
    in
    Std.exact_no_check c).

Ltac2 Notation "exact" c(preterm) := exact1 false c.

Ltac2 Abbreviation refine := Control.refine.
Require Stdlib.Strings.String.

Ltac2 rec length_constr_string (xs : constr) : int :=
  match kind xs with
  | App _ args =>
    match Int.equal (Array.length args) 2 with
    | true => Int.add 1 (length_constr_string (Array.get args 1))
    | _ => if equal xs 'String.EmptyString then 0 else Control.throw No_value
    end
  | Constr.Unsafe.Constructor _ _ => 0
  | _ => Control.throw No_value
  end.

Ltac2 string_of_constr_string (s : constr) : string :=
  let s := eval vm_compute in ($s : String.string) in
  let ret := String.make (length_constr_string s) (Char.of_int 0) in
  let t := constr:(true) in
  let rec fill i s :=
    match kind s with
    | App _ args =>
      if Int.equal (Array.length args) 2 then
        String.set ret i (match kind (Array.get args 0) with App _ b => Char.of_int (
            Int.add (if equal (Array.get b 0) t then 1 else 0) (
            Int.add (if equal (Array.get b 1) t then 2 else 0) (
            Int.add (if equal (Array.get b 2) t then 4 else 0) (
            Int.add (if equal (Array.get b 3) t then 8 else 0) (
            Int.add (if equal (Array.get b 4) t then 16 else 0) (
            Int.add (if equal (Array.get b 5) t then 32 else 0) (
            Int.add (if equal (Array.get b 6) t then 64 else 0) (
                    (if equal (Array.get b 7) t then 128 else 0)))))))))
          | _ => Control.throw No_value end);
        fill (Int.add i 1) (Array.get args 1)
      else ()
    | _ => ()
    end in
  fill 0 s; ret.
Ltac2 ident_of_constr_string (s : constr) := Option.get (Ident.of_string (string_of_constr_string s)).

Ltac ident_of_constr_string_cps := ltac2:(s tac |-
  Ltac1.apply tac [Ltac1.of_ident (ident_of_constr_string (Option.get (Ltac1.to_constr s)))] Ltac1.run).
Import Coq.Lists.List.
Import Coq.Strings.Ascii.
Import Stdlib.NArith.BinNat.
  Local Ltac2 rec list_constr_of_constr_list xs :=
    match! xs with cons ?x ?xs => x :: list_constr_of_constr_list xs | nil => [] end.
Local Definition f : ltac:(do 256 refine (ascii->_); exact unit).
Admitted.
Definition app : unit.
exact (ltac2:(
    let args := eval cbv in (map (fun n => ascii_of_N (N.of_nat n)) (seq 0 256)) in
    refine (make (App 'f (Array.of_list (list_constr_of_constr_list args)))))).
Defined.

Ltac2 constr_string_of_string (s : string) :=
  let asciis := match kind (eval red in app) with App _ x => x | _ => Control.throw No_value end in
  let scons := 'String.String in
  let l := String.length s in
  let rec f i :=
    if Int.equal i l then 'String.EmptyString else
    make (App scons (Array.of_list [Array.get asciis (Char.to_int (String.get s i)); f (Int.add i 1)])) in
  f 0.

Ltac2 constr_string_of_ident (i : ident) := constr_string_of_string (Ident.to_string i).
Ltac2 constr_string_of_lambda (c : constr) :=
  match kind c with
  | Lambda b _i =>
      match Binder.name b with
      | Some n => constr_string_of_ident n
      | _ => Control.throw_invalid_argument "a Lambda with unnamed binder"
      end
  | _ => Control.throw_invalid_argument "not a Lambda"
  end.
Ltac constr_string_of_lambda_cps := ltac2:( lam tac |-
  Ltac1.apply tac [Ltac1.of_constr (constr_string_of_lambda (Option.get (Ltac1.to_constr lam)))] Ltac1.run).
Module Export reference_to_string.

Ltac2 reference_of_constr c :=
  match kind c with
  | Var id => Std.VarRef id
  | Constant const _inst => Std.ConstRef const
  | Ind ind _inst => Std.IndRef ind
  | Constructor cnstr _inst => Std.ConstructRef cnstr
  | _ => Control.throw No_value
  end.

Ltac2 constr_string_basename_of_reference r :=
  constr_string_of_string (Ident.to_string (List.last (Env.path r))).

Ltac2 constr_string_basename_of_constr_reference c :=
  constr_string_basename_of_reference (reference_of_constr c).
Local Set Default Proof Mode "Classic".
Notation "'unique!' cls" := (ltac:(
  match constr:(Set) with
  | _ => let __ := constr:(_:cls) in fail 1 "unique!: already have an instance of" cls
  | _ => exact cls%type
  end))
  (at level 10, only parsing).
Global Set Default Goal Selector "!".
Module Export Syntax.

Module Import op1.
  Inductive op1 : Set := not | opp.
End op1.
Notation op1:= op1.op1.

Module Import bopname.
  Inductive bopname: Set := add | sub | mul | mulhuu | divu | remu | and | or | xor | sru | slu | srs | lts | ltu | eq.
End bopname.
Notation bopname := bopname.bopname.

Module Export access_size.
  Variant access_size: Set := one | two | four | word.
End access_size.
Notation access_size := access_size.access_size.

Module expr.
  Inductive expr: Set :=
  | literal (v: Z)
  | var (x: String.string)
  | load (_ : access_size) (addr:expr)
  | inlinetable (_ : access_size) (table: list Byte.byte) (index: expr)
  | op1 (op: op1) (e : expr)
  | op (op: bopname) (e1 e2: expr)
  | ite (c e1 e2: expr).

End expr.
Notation expr := expr.expr.

Module Export cmd.
  Inductive cmd: Set :=
  | skip
  | set (lhs : String.string) (rhs : expr)
  | unset (lhs : String.string)
  | store (_ : access_size) (address : expr) (value : expr)
  | stackalloc (lhs : String.string) (nbytes : Z) (body : cmd)

  | cond (condition : expr) (nonzero_branch zero_branch : cmd)
  | seq (s1 s2: cmd)
  | while (test : expr) (body : cmd)
  | call (binds : list String.string) (function : String.string) (args: list expr)
  | interact (binds : list String.string) (action : String.string) (args: list expr).
End cmd.
Notation cmd := cmd.cmd.

Definition func : Type := (list String.string * list String.string * cmd).
  Import Stdlib.Strings.String.
  Coercion expr.var : string >-> expr.
  Coercion expr.literal : Z >-> expr.

End Syntax.
Require Stdlib.ZArith.BinInt.

Notation "ident_to_string! x" := (
  match (fun x : Set => x) return String.string with x => ltac:(
    let lam := lazymatch goal with _ := ?lam |- _ => lam end in
    constr_string_of_lambda_cps lam ltac:(fun s => exact s))
  end) (at level 10, only parsing).
Module Export NotationsCustomEntry.
Import Coq.Strings.String.

Import bopname.
Declare Custom Entry bedrock_expr.
Notation "$ e"                := e%string%Z (in custom bedrock_expr at level 0, e constr at level 0, format "'$' e").
Notation  "( e )" := e             (in custom bedrock_expr).
Notation "x" := (ident_to_string! x) (in custom bedrock_expr, x ident, only parsing).

Infix "*"   := (expr.op mul)  (in custom bedrock_expr at level 4, left associativity).

Infix "+"   := (expr.op add)  (in custom bedrock_expr at level 6, left associativity).

Infix  "<"  := (expr.op ltu)  (in custom bedrock_expr at level 10, no associativity).
Notation  "load( a )" := (expr.load access_size.word a)
  (in custom bedrock_expr, a custom bedrock_expr, format "load( a )").
Declare Custom Entry bedrock_cmd.
Declare Scope bedrock_nontail.
Delimit Scope bedrock_nontail with bedrock_nontail.

Notation "c1 ; c2" := (seq c1%bedrock_nontail c2)
  (in custom bedrock_cmd at level 1, right associativity, format "'[v' c1 ; '/' c2 ']'").

Notation "'while' e { c }" := (while e c%bedrock_nontail)
  (in custom bedrock_cmd at level 0, e custom bedrock_expr, format "'[v' 'while'  e  {  '/  ' c '/' } ']'").

Notation "x = e" := (set (ident_to_string! x) e) (in custom bedrock_cmd, x ident, only parsing, e custom bedrock_expr).
Notation  "store( a , v )" := (store access_size.word a v)  (in custom bedrock_cmd,
  a custom bedrock_expr , v custom bedrock_expr, format "store( a ,  v )").

Declare Custom Entry bedrock_ident.
Notation "x" := (ident_to_string! x) (in custom bedrock_ident, x ident, only parsing).

Declare Custom Entry bedrock_call_lhs.
Notation "x , y , .. , z" := (@cons String.string x (@cons String.string y .. (@cons String.string z (@nil String.string)) ..))
  (in custom bedrock_call_lhs at level 0, x custom bedrock_ident, y custom bedrock_ident, z custom bedrock_ident).

Declare Custom Entry bedrock_args.
Notation "( x , y , .. , z )" := (@cons expr x (@cons expr y .. (@cons expr z (@nil expr)) ..))
  (in custom bedrock_args at level 0, x custom bedrock_expr , y custom bedrock_expr , z custom bedrock_expr ).
Notation "f args" :=  (call nil (ident_to_string! f) args) (in custom bedrock_cmd at level 0,
  f ident, args custom bedrock_args, only parsing).

Declare Scope bedrock_tail.
Delimit Scope bedrock_tail with bedrock_tail.

Declare Custom Entry bedrock_cmd_in_braces.
Notation "{ c }" := c             (in custom bedrock_cmd_in_braces, c custom bedrock_cmd).

Import Coq.Lists.List.ListNotations.
Notation "'func!' ( xs ) c" := ((xs, [], c%bedrock_tail) : func)
  (only parsing, at level 10, xs custom bedrock_call_lhs, c custom bedrock_cmd_in_braces).

End NotationsCustomEntry.
Module Export dlet.
Definition dlet {A P} (x : A) (f : forall a : A, P a) : P x.
exact (let y := x in f y).
Defined.
Notation "'dlet!' x .. y := v 'in' f" :=
  (dlet v (fun x => .. (fun y => f) .. ))
    (at level 200, x binder, y binder, f at level 200,
     format "'dlet!'  x .. y  :=  v  'in' '//' f").
Module Export coqutil.
Module Export Word.
Module Export Interface.
Import Coq.ZArith.BinInt.
Local Open Scope Z_scope.

Module Export word.
  Class word {width : Z} := {
    rep : Type;

    unsigned : rep -> Z;
    signed : rep -> Z;
    of_Z : Z -> rep;

    add : rep -> rep -> rep;
    sub : rep -> rep -> rep;
    opp : rep -> rep;

    or : rep -> rep -> rep;
    and : rep -> rep -> rep;
    xor : rep -> rep -> rep;
    not : rep -> rep;
    ndn : rep -> rep -> rep;

    mul : rep -> rep -> rep;
    mulhss : rep -> rep -> rep;
    mulhsu : rep -> rep -> rep;
    mulhuu : rep -> rep -> rep;

    divu : rep -> rep -> rep;
    divs : rep -> rep -> rep;
    modu : rep -> rep -> rep;
    mods : rep -> rep -> rep;

    slu : rep -> rep -> rep;
    sru : rep -> rep -> rep;
    srs : rep -> rep -> rep;

    eqb : rep -> rep -> bool;
    ltu : rep -> rep -> bool;
    lts : rep -> rep -> bool;

    gtu x y := ltu y x;
    gts x y := lts y x;

    swrap z := (z + 2^(width-1)) mod 2^width - 2^(width-1);

    sextend: Z -> rep -> rep;
  }.
  Arguments word : clear implicits.

  Class ok {width} {word : word width}: Prop := {
    wrap z := z mod 2^width;

    width_pos: 0 < width;

    unsigned_of_Z : forall z, unsigned (of_Z z) = wrap z;
    signed_of_Z : forall z, signed (of_Z z) = swrap z;
    of_Z_unsigned : forall x, of_Z (unsigned x) = x;

    unsigned_add : forall x y, unsigned (add x y) = wrap (Z.add (unsigned x) (unsigned y));
    unsigned_sub : forall x y, unsigned (sub x y) = wrap (Z.sub (unsigned x) (unsigned y));
    unsigned_opp : forall x, unsigned (opp x) = wrap (Z.opp (unsigned x));

    unsigned_or : forall x y, unsigned (or x y) = wrap (Z.lor (unsigned x) (unsigned y));
    unsigned_and : forall x y, unsigned (and x y) = wrap (Z.land (unsigned x) (unsigned y));
    unsigned_xor : forall x y, unsigned (xor x y) = wrap (Z.lxor (unsigned x) (unsigned y));
    unsigned_not : forall x, unsigned (not x) = wrap (Z.lnot (unsigned x));
    unsigned_ndn : forall x y, unsigned (ndn x y) = wrap (Z.ldiff (unsigned x) (unsigned y));

    unsigned_mul : forall x y, unsigned (mul x y) = wrap (Z.mul (unsigned x) (unsigned y));
    signed_mulhss : forall x y, signed (mulhss x y) = swrap (Z.mul (signed x) (signed y) / 2^width);
    signed_mulhsu : forall x y, signed (mulhsu x y) = swrap (Z.mul (signed x) (unsigned y) / 2^width);
    unsigned_mulhuu : forall x y, unsigned (mulhuu x y) = wrap (Z.mul (unsigned x) (unsigned y) / 2^width);

    unsigned_divu : forall x y, unsigned y <> 0 -> unsigned (divu x y) = wrap (Z.div (unsigned x) (unsigned y));
    signed_divs : forall x y, signed y <> 0 -> signed x <> -2^(width-1) \/ signed y <> -1 -> signed (divs x y) = swrap (Z.quot (signed x) (signed y));
    unsigned_modu : forall x y, unsigned y <> 0 -> unsigned (modu x y) = wrap (Z.modulo (unsigned x) (unsigned y));
    signed_mods : forall x y, signed y <> 0 -> signed (mods x y) = swrap (Z.rem (signed x) (signed y));

    unsigned_slu : forall x y, Z.lt (unsigned y) width -> unsigned (slu x y) = wrap (Z.shiftl (unsigned x) (unsigned y));
    unsigned_sru : forall x y, Z.lt (unsigned y) width -> unsigned (sru x y) = wrap (Z.shiftr (unsigned x) (unsigned y));
    signed_srs : forall x y, Z.lt (unsigned y) width -> signed (srs x y) = swrap (Z.shiftr (signed x) (unsigned y));

    unsigned_eqb : forall x y, eqb x y = Z.eqb (unsigned x) (unsigned y);
    unsigned_ltu : forall x y, ltu x y = Z.ltb (unsigned x) (unsigned y);
    signed_lts : forall x y, lts x y = Z.ltb (signed x) (signed y);
  }.
  Arguments ok {_} _.
End word.
Notation word := word.word.
Global Coercion word.rep : word >-> Sortclass.

End Interface.
Require Stdlib.ZArith.ZArith.
Import Coq.ZArith.ZArith.

Class Bitwidth(width: Z): Prop := {
  width_cases: width = 32%Z \/ width = 64%Z
}.
Module Export PrimitivePair.
Module pair.
  Record pair {A B} := mk { _1 : A; _2 : B _1 }.
  Arguments pair : clear implicits.
  Arguments mk {A B} _ _.

  Notation "A * B" := (pair A%type (fun _ => B%type)) : type_scope.

  Notation "( x , y , .. , z )" := (mk .. (mk x y) .. z) : core_scope.

  Notation "x '.(1)'" := (_1 x) (at level 1, left associativity) : core_scope.
  Notation "x '.(2)'" := (_2 x) (at level 1, left associativity) : core_scope.
End pair.
Module Export HList.
Import pair.
Local Set Universe Polymorphism.

Module Import polymorphic_list.
  Inductive list {A : Type} : Type := nil | cons (_:A) (_:list).
  Arguments list : clear implicits.

  Section WithA.
    Context {A : Type}.
Fixpoint length (l : list A) : nat.
Admitted.
  End WithA.

  Section WithElement.
    Context {A} (x : A).
    Fixpoint repeat (x : A) (n : nat) {struct n} : list A :=
      match n with
      | 0 => nil
      | S k => cons x (repeat x k)
      end.
  End WithElement.
End polymorphic_list.
Fixpoint arrows (argts : list Type) : Type -> Type.
exact (match argts with
  | nil => fun ret => ret
  | cons T argts' => fun ret => T -> arrows argts' ret
  end).
Defined.

Fixpoint hlist@{i j k} (argts : list@{j} Type@{i}) : Type@{k} :=
  match argts with
  | nil => unit
  | cons T argts' => T * hlist argts'
  end.

Module Export hlist.
  Fixpoint apply {argts : list Type} : forall {P} (f : arrows argts P) (args : hlist argts), P :=
    match argts return forall {P} (f : arrows argts P) (args : hlist argts), P with
    | nil => fun P f _ => f
    | cons T argts' => fun P f '(x, args') => apply (f x) args'
    end.

  Fixpoint foralls {argts : list Type} : forall (P : hlist argts -> Prop), Prop :=
    match argts with
    | nil => fun P => P tt
    | cons T argts' => fun P => forall x:T, foralls (fun xs' => P (x, xs'))
    end.

  Fixpoint existss {argts : list Type} : forall (P : hlist argts -> Prop), Prop :=
    match argts with
    | nil => fun P => P tt
    | cons T argts' => fun P => exists x:T, existss (fun xs' => P (x, xs'))
    end.
End hlist.

Definition tuple A n := hlist (repeat A n).
Definition ufunc A n := arrows (repeat A n).
Module Export tuple.
  Notation apply := hlist.apply.
  Definition foralls {A n} := hlist.foralls (argts:=repeat A n).
  Definition existss {A n} := hlist.existss (argts:=repeat A n).

  Import Corelib.Init.Datatypes.
  Section WithA.
    Context {A : Type}.
    Fixpoint to_list {n : nat} : tuple A n -> list A :=
      match n return tuple A n -> list A with
      | O => fun _ => nil
      | S n => fun '(pair.mk x xs') => cons x (to_list xs')
      end.
Fixpoint of_list (xs : list A) : tuple A (length xs).
exact (match xs with
      | nil => tt
      | cons x xs => pair.mk x (of_list xs)
      end).
Defined.

    End WithA.
End tuple.

End HList.
Module Export String.
Export Coq.Strings.String.

Lemma ltb_antirefl : forall k, ltb k k = false.
Admitted.

Lemma ltb_trans : forall k1 k2 k3, ltb k1 k2 = true -> ltb k2 k3 = true -> ltb k1 k3 = true.
Admitted.

Lemma ltb_total : forall k1 k2, ltb k1 k2 = false -> ltb k2 k1 = false -> k1 = k2.
Admitted.

Ltac head t :=
  lazymatch t with
  | ?f _ => head f
  | _ => t
  end.

  Module Export coqutil_DOT_Map_DOT_Interface_WRAPPED.
Module Export Interface.

Module Export map.
  Class map {key value} := mk {
    rep : Type;

    get: rep -> key -> option value;

    empty : rep;
    put : rep -> key -> value -> rep;
    remove : rep -> key -> rep;
    fold{R: Type}: (R -> key -> value -> R) -> R -> rep -> R;
  }.
  Arguments map : clear implicits.
  Global Coercion rep : map >-> Sortclass.

  Class ok {key value : Type} {map : map key value}: Prop := {
    map_ext : forall m1 m2, (forall k, get m1 k = get m2 k) -> m1 = m2;
    get_empty : forall k, get empty k = None;
    get_put_same : forall m k v, get (put m k v) k = Some v;
    get_put_diff : forall m k v k', k <> k' -> get (put m k' v) k = get m k;
    get_remove_same : forall m k, get (remove m k) k = None;
    get_remove_diff : forall m k k', k <> k' -> get (remove m k') k = get m k;
    fold_spec{R: Type} : forall (P: rep -> R -> Prop) (f: R -> key -> value -> R) r0,
        P empty r0 ->
        (forall k v m r, get m k = None -> P m r -> P (put m k v) (f r k v)) ->
        forall m, P m (fold f r0 m);

    fold_parametricity: forall {A B : Type} (R : A -> B -> Prop)
                               (fa: A -> key -> value -> A) (fb: B -> key -> value -> B),
        (forall a b k v, R a b -> R (fa a k v) (fb b k v)) ->
        forall a0 b0, R a0 b0 -> forall m, R (fold fa a0 m) (fold fb b0 m);

  }.
  Arguments ok {_ _} _.

  Section WithMap.
    Context {key value : Type} {map : map key value} {map_ok : ok map}.
Definition putmany: map -> map -> map.
admit.
Defined.
    Definition disjoint (a b : map) :=
      forall k v1 v2, get a k = Some v1 -> get b k = Some v2 -> False.

    Definition split m m1 m2 := m = (putmany m1 m2) /\ disjoint m1 m2.
Definition getmany_of_list (m : map) (keys : list key) : option (list value).
admit.
Defined.
Fixpoint putmany_of_list (l : list (key*value)) (init : rep) {struct l} : map.
Admitted.
Fixpoint putmany_of_list_zip (keys : list key) (values : list value) (init : rep) {struct keys} : option map.
exact (match keys, values with
      | nil, nil => Some init
      | cons k keys, cons v values =>
        putmany_of_list_zip keys values (put init k v)
      | _, _ => None
      end).
Defined.
    Definition of_list_zip keys values := putmany_of_list_zip keys values empty.

    Fixpoint putmany_of_tuple {sz : nat} : tuple key sz -> tuple value sz -> map -> map :=
      match sz with
      | O => fun keys values init => init
      | S sz' => fun '(pair.mk k ks) '(pair.mk v vs) init =>
                   put (putmany_of_tuple ks vs init) k v
      end.
  End WithMap.
End map.

End Interface.
Module Export coqutil.
Module Export Map.
Module Export Interface.
Include coqutil_DOT_Map_DOT_Interface_WRAPPED.Interface.
End Interface.
Module Export SortedList.
Definition minimize_eq_proof{A: Type}(eq_dec: forall (x y: A), {x = y} + {x <> y}){x y: A}    (pf: x = y): x = y.
exact (match eq_dec x y with
  | left p => p
  | right n => match n pf: False with end
  end).
Defined.

Module Import parameters.
  Class parameters := {
    key : Type;
    value : Type;
    ltb : key -> key -> bool
  }.

  Class strict_order {T} {ltb : T -> T -> bool}: Prop := {
    ltb_antirefl : forall k, ltb k k = false;
    ltb_trans : forall k1 k2 k3, ltb k1 k2 = true -> ltb k2 k3 = true -> ltb k1 k3 = true;
    ltb_total : forall k1 k2, ltb k1 k2 = false -> ltb k2 k1 = false -> k1 = k2;
  }.
  Global Arguments strict_order {_} _.
End parameters.

Section SortedList.
  Context {p : unique! parameters} {ok : strict_order ltb}.

  Local Definition eqb k1 k2 := andb (negb (ltb k1 k2)) (negb (ltb k2 k1)).

  Fixpoint put m (k:key) (v:value) : list (key * value) :=
    match m with
    | nil => cons (k, v) nil
    | cons (k', v') m' =>
      match ltb k k', ltb k' k with
      |  true, _ => cons (k, v) m
      |  false, false => cons (k, v) m'
      |  false, true => cons (k', v') (put m' k v)
      end
    end.

  Fixpoint remove m (k:key) : list (key * value) :=
    match m with
    | nil => nil
    | cons (k', v') m' =>
      match ltb k k', ltb k' k with
      |  true, _ => m
      |  false, false => m'
      |  false, true => cons (k', v') (remove m' k)
      end
    end.

  Fixpoint sorted (m : list (key * value)) :=
    match m with
    | cons (k1, _) ((cons (k2, _) m'') as m') => andb (ltb k1 k2) (sorted m')
    | _ => true
    end.

  Record rep := { value : list (key * value) ; _value_ok : sorted value = true }.

  Lemma sorted_put m k v : sorted m = true -> sorted (put m k v) = true.
Admitted.

  Lemma sorted_remove m k : sorted m = true -> sorted (remove m k) = true.
Admitted.
Definition lookup(l: list (key * parameters.value))(k: key): option parameters.value.
exact (match List.find (fun p => eqb k (fst p)) l with
    | Some (_, v) => Some v
    | None => None
    end).
Defined.
Definition map : map.map key parameters.value.
exact (let wrapped_put m k v := Build_rep (put (value m) k v) (minimize_eq_proof Bool.bool_dec (sorted_put _ _ _ (_value_ok m))) in
    let wrapped_remove m k := Build_rep (remove (value m) k) (minimize_eq_proof Bool.bool_dec (sorted_remove _ _ (_value_ok m))) in
    {|
    map.rep := rep;
    map

[...]

 Type :=
  | Leaf(a: A)
  | Node(left right: Tree A).
  Arguments Leaf {A} _.
  Arguments Node {A} _ _.
  Section Interp.
    Context {A B: Type}.
    Context (interp_Leaf: A -> B).
    Context (interp_Node: B -> B -> B).
Fixpoint interp(t: Tree A): B.
exact (match t with
      | Leaf a => interp_Leaf a
      | Node t1 t2 => interp_Node (interp t1) (interp t2)
      end).
Defined.
  End Interp.
Definition flatten{A: Type}: Tree A -> list A.
exact (interp (fun a => cons a nil) (@app A)).
Defined.

  Section WithMap.
    Context {key value} {map : map key value} {ok : ok map}.
Definition to_sep: Tree (map -> Prop) -> map -> Prop.
exact (interp (fun x => x) sep).
Defined.

    Lemma flatten_iff1_to_sep(t : Tree.Tree (map -> Prop)):
      Lift1Prop.iff1 (seps (flatten t)) (to_sep t).
Admitted.

    Lemma iff1_to_sep_of_iff1_flatten(LHS RHS : Tree (map -> Prop)):
      Lift1Prop.iff1 (seps (flatten LHS)) (seps (flatten RHS)) ->
      Lift1Prop.iff1 (to_sep LHS) (to_sep RHS).
Admitted.

    Lemma impl1_to_sep_of_impl1_flatten(LHS RHS : Tree (map -> Prop)):
      Lift1Prop.impl1 (seps (flatten LHS)) (seps (flatten RHS)) ->
      Lift1Prop.impl1 (to_sep LHS) (to_sep RHS).
Admitted.

    Lemma flatten_to_sep_with_and(t : Tree.Tree (map -> Prop))(m: map)(C: Prop):
      seps (flatten t) m /\ C -> to_sep t m /\ C.
Admitted.
  End WithMap.

Ltac reify e :=
  lazymatch e with
  | @sep ?key ?value ?map ?a ?b =>
    let a := reify a in
    let b := reify b in
    uconstr:(@Tree.Node (@map.rep key value map -> Prop) a b)
  | ?a => uconstr:(Tree.Leaf a)
  end.

Ltac reify_goal :=
  lazymatch goal with
  | |- Lift1Prop.iff1 ?LHS ?RHS =>
    let LHS := reify LHS in
    let RHS := reify RHS in
    change (Lift1Prop.iff1 (Tree.to_sep LHS) (Tree.to_sep RHS));
    eapply Tree.iff1_to_sep_of_iff1_flatten
  | |- Lift1Prop.impl1 ?LHS ?RHS =>
    let LHS := reify LHS in
    let RHS := reify RHS in
    change (Lift1Prop.impl1 (Tree.to_sep LHS) (Tree.to_sep RHS));
    eapply Tree.impl1_to_sep_of_impl1_flatten
  end;
  cbv [Tree.flatten Tree.interp app].

Ltac flatten_seps_in H :=
  lazymatch type of H with
  | ?nested ?m =>
    let tmem := type of m in
    let E := fresh "E" in
    eassert (@iff1 tmem nested _) as E;
    [
      let stars := eval cbv [seps] in nested in
      let tree := reify stars in
      transitivity (Tree.to_sep tree); [
        cbv [seps Tree.to_sep Tree.interp]; iff1_syntactic_reflexivity
      |];

      transitivity (seps (Tree.flatten tree)); [
        exact (iff1_sym (Tree.flatten_iff1_to_sep tree))
      |];

      cbv [SeparationLogic.Tree.flatten SeparationLogic.Tree.interp SeparationLogic.app];
      iff1_syntactic_reflexivity
    | let HNew := fresh in pose proof (proj1 (E m) H) as HNew;
      move HNew before H;
      clear E H;
      rename HNew into H ]
  end.

Ltac flatten_seps_in_goal :=
  cbv [seps];
  lazymatch goal with
  | |- ?nested ?m /\ ?C =>
      let xs := reify nested in
      change (Tree.to_sep xs m /\ C);
      eapply Tree.flatten_to_sep_with_and
  | |- ?nested ?m =>
      let xs := reify nested in
      change (Tree.to_sep xs m);
      eapply Tree.flatten_iff1_to_sep
  end;
  cbv [Tree.flatten Tree.interp app].

Ltac cancel_emp_l :=
  lazymatch goal with
  | |- Lift1Prop.iff1 (@seps ?K ?V ?M ?LHS) (seps ?RHS) =>
    let i := find_constr_eq LHS constr:(@emp K V M True) in
    simple refine (cancel_emp_at_index_l i LHS RHS _ _);
    cbv [firstn skipn app hd tl];
    [syntactic_exact_deltavar (@eq_refl _ _)|]
  end.

Ltac cancel_emp_r :=
  lazymatch goal with
  | |- Lift1Prop.iff1 (seps ?LHS) (@seps ?K ?V ?M ?RHS) =>
    let j := find_constr_eq RHS constr:(@emp K V M True) in
    simple refine (cancel_emp_at_index_r j LHS RHS _ _);
    cbv [firstn skipn app hd tl];
    [syntactic_exact_deltavar (@eq_refl _ _)|]
  end.

Ltac cancel_emp_impl :=
  lazymatch goal with
  | |- Lift1Prop.impl1 (seps ?LHS) (@seps ?K ?V ?M ?RHS) =>
    let j := find_constr_eq RHS constr:(@emp K V M True) in

    simple refine (cancel_emp_at_index_impl j LHS RHS _ _);
    cbv [firstn skipn app hd tl];

    [syntactic_exact_deltavar (@eq_refl _ _)|]
  end.

Ltac cancel_seps_at_indices i j :=
  lazymatch goal with
  | |- Lift1Prop.iff1 (seps ?LHS) (seps ?RHS) =>
    simple refine (cancel_seps_at_indices i j LHS RHS _ _);
    cbv [firstn skipn app hd tl]
  end.

Ltac cancel_seps_at_indices_by_implication i j :=
  lazymatch goal with
  | |- Lift1Prop.impl1 (seps ?LHS) (seps ?RHS) =>
    simple refine (cancel_seps_at_indices_by_implication i j LHS RHS _ _);
    cbv [firstn skipn app hd tl]
  end.

Ltac find_implication xs y :=
  multimatch xs with
  | cons ?x _ => constr:(O)
  | cons _ ?xs => let i := find_implication xs y in constr:(S i)
  end.

Ltac cancel_step := once (
      let RHS := lazymatch goal with |- Lift1Prop.iff1 _ (seps ?RHS) => RHS end in
      let jy := index_and_element_of RHS in
      let j := lazymatch jy with (?i, _) => i end in
      let y := lazymatch jy with (_, ?y) => y end in
      assert_fails (has_evar y);
      let LHS := lazymatch goal with |- Lift1Prop.iff1 (seps ?LHS) _ => LHS end in
      let i := find_constr_eq LHS y in
      cancel_seps_at_indices i j; [exact eq_refl|]).

Ltac cancel_step_impl := once (
    let RHS := lazymatch goal with |- Lift1Prop.impl1 _ (seps ?RHS) => RHS end in
    let jy := index_and_element_of RHS in
    let j := lazymatch jy with (?i, _) => i end in
    let y := lazymatch jy with (_, ?y) => y end in
    assert_fails (has_evar y);
    let LHS := lazymatch goal with |- Lift1Prop.impl1 (seps ?LHS) _ => LHS end in
    let i := find_constr_eq LHS y in
    cancel_seps_at_indices_by_implication i j; [exact impl1_refl|]).

Ltac ecancel_step_at j :=
      let RHS := lazymatch goal with |- Lift1Prop.iff1 _ (seps ?RHS) => RHS end in
      let y := list_get RHS j in
      assert_fails (idtac; let y := rdelta_var y in is_evar y);
      let LHS := lazymatch goal with |- Lift1Prop.iff1 (seps ?LHS) _ => LHS end in
      let i := find_syntactic_unify_deltavar LHS y in
      cancel_seps_at_indices i j; [exact eq_refl|].

Ltac ecancel_steps_inbounds j :=
  let RHS := lazymatch goal with |- Lift1Prop.iff1 _ (seps ?RHS) => RHS end in
  let __ := list_get RHS j in
  idtac.

Ltac ecancel_steps_at j :=
   tryif (ecancel_steps_inbounds j) then (
    tryif (ecancel_step_at j)
    then (                         ecancel_steps_at j)
    else (let j := constr:(S j) in ecancel_steps_at j)
  ) else idtac.

Ltac ecancel_step_by_implication :=
      let RHS := lazymatch goal with |- Lift1Prop.impl1 _ (seps ?RHS) => RHS end in
      let jy := index_and_element_of RHS in
      let j := lazymatch jy with (?i, _) => i end in
      let y := lazymatch jy with (_, ?y) => y end in
      assert_fails (idtac; let y := rdelta_var y in is_evar y);
      let LHS := lazymatch goal with |- Lift1Prop.impl1 (seps ?LHS) _ => LHS end in
      let i := find_implication LHS y in
      cancel_seps_at_indices_by_implication i j; [solve [auto 1 with nocore ecancel_impl]|].

Ltac ecancel_done :=
  cbv [seps];
  syntactic_exact_deltavar
    (@RelationClasses.reflexivity _ _
        (@RelationClasses.Equivalence_Reflexive _ _ (@Equivalence_iff1 _)) _).

Ltac cancel_done :=
  lazymatch goal with
  | |- iff1 (seps (cons _ nil)) _ => idtac
  | |- iff1 _ (seps (cons _ nil )) => idtac
  | |- ?g => assert_fails (has_evar g)
  end;
  ecancel_done.

Ltac cancel_seps :=
  lazymatch goal with
  | |- Lift1Prop.iff1 _ _ =>
    repeat cancel_step;
    repeat cancel_emp_l;
    repeat cancel_emp_r
  | |- Lift1Prop.impl1 _ _ =>
    repeat cancel_step_impl;
    repeat cancel_emp_impl
  end;
  try solve [ cancel_done ].

Ltac cancel := reify_goal; cancel_seps.

Ltac ecancel :=
  cancel;
  lazymatch goal with
  | [|- impl1 _ _] =>
     repeat ecancel_step_by_implication;
     (solve [ cbv [seps]; exact impl1_refl ])
  | [|- iff1 _ _] =>
    ecancel_steps_at O;
    ecancel_done
  end.

Ltac ecancel_assumption :=
  multimatch goal with
  | |- _ ?m1 =>
    multimatch goal with
    | H: _ ?m2 |- _ =>
      syntactic_unify_deltavar m1 m2;
      refine (Lift1Prop.subrelation_iff1_impl1 _ _ _ _ _ H); clear H;
      solve [ecancel]
    end
  end.
Require Crypto.Arithmetic.WordByWordMontgomery.
Module Export Array.

Section Array.
  Context {value} {mem : map.map word value} {mem_ok : map.ok mem}.
  Context {T} (element : word -> T -> mem -> Prop) (size : word).
  Fixpoint array (start : word) (xs : list T) :=
    match xs with
    | nil => emp True
    | cons x xs => sep (element start x) (array (word.add start size) xs)
    end.

End Array.

Section ByteArray.
  Local Notation array := (array (mem:=mem) ptsto (word.of_Z 1)).

  Lemma array_1_to_anybytes bs m (a: word) :
    array a bs m -> bedrock2.Memory.anybytes a (Z.of_nat (List.length bs)) m.
Admitted.

  Lemma anybytes_to_array_1 m (addr : word) n :
      bedrock2.Memory.anybytes addr n m ->
      exists bs, array  addr bs m /\ List.length bs = Z.to_nat n.
Admitted.
End ByteArray.
Module Export Scalars.

Section Scalars.
  Context {width : Z} {BW: Bitwidth width} {word : Word.Interface.word width} {word_ok : word.ok word}.

  Context {mem : map.map word byte} {mem_ok : map.ok mem}.

  Definition truncated_scalar sz addr (value:Z) : mem -> Prop :=
    (le_split (bytes_per (width:=width) sz) value) $@ addr.

  Definition truncated_word sz addr (value: word) : mem -> Prop :=
    truncated_scalar sz addr (word.unsigned value).

  Notation scalar8 := ptsto (only parsing).

  Definition scalar16 := truncated_word Syntax.access_size.two.
  Definition scalar32 := truncated_word Syntax.access_size.four.
  Definition scalar := truncated_word Syntax.access_size.word.
Definition truncate_word(sz: Syntax.access_size)(w: word): word.
Admitted.

  Lemma load_one_of_sep addr value R m
    (Hsep : sep (scalar8 addr value) R m)
    : Memory.load Syntax.access_size.one m addr = Some (word.of_Z (byte.unsigned value)).
Admitted.

  Lemma load_two_of_sep addr value R m
    (Hsep : sep (scalar16 addr value) R m)
    : Memory.load Syntax.access_size.two m addr = Some (truncate_word Syntax.access_size.two value).
Admitted.

  Lemma load_four_of_sep addr value R m
    (Hsep : sep (scalar32 addr value) R m)
    : Memory.load Syntax.access_size.four m addr = Some (truncate_word Syntax.access_size.four value).
Admitted.

  Lemma load_four_of_sep_32bit(W32: width = 32) addr value R m
    (Hsep : sep (scalar32 addr value) R m)
    : Memory.load Syntax.access_size.four m addr = Some value.
Admitted.

  Lemma load_word_of_sep addr value R m
    (Hsep : sep (scalar addr value) R m)
    : Memory.load Syntax.access_size.word m addr = Some value.
Admitted.

  Lemma store_one_of_sep addr (oldvalue : byte) (value : word) R m (post:_->Prop)
    (Hsep : sep (scalar8 addr oldvalue) R m)
    (Hpost : forall m, sep (scalar8 addr (byte.of_Z (word.unsigned value))) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.one m addr value = Some m1 /\ post m1.
Admitted.

  Lemma store_two_of_sep addr (oldvalue : word) (value : word) R m (post:_->Prop)
    (Hsep : sep (scalar16 addr oldvalue) R m)
    (Hpost : forall m, sep (scalar16 addr value) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.two m addr value = Some m1 /\ post m1.
Admitted.

  Lemma store_four_of_sep addr (oldvalue : word) (value : word) R m (post:_->Prop)
    (Hsep : sep (scalar32 addr oldvalue) R m)
    (Hpost : forall m, sep (scalar32 addr value) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.four m addr value = Some m1 /\ post m1.
Admitted.

  Lemma store_word_of_sep addr (oldvalue value: word) R m (post:_->Prop)
    (Hsep : sep (scalar addr oldvalue) R m)
    (Hpost : forall m, sep (scalar addr value) R m -> post m)
    : exists m1, Memory.store Syntax.access_size.word m addr value = Some m1 /\ post m1.
Admitted.

End Scalars.
Module Export Loops.
Import bedrock2.WeakestPrecondition.

Section Loops.
  Context {width: Z} {BW: Bitwidth width} {word: word.word width} {mem: map.map word Byte.byte}.
  Context {locals: map.map String.string word}.
  Context {ext_spec: ExtSpec}.

  Context {fs : env}.
  Let call := fs.

  Local Notation "A /\ B" := (Markers.split (A /\ B)).
Definition reconstruct (variables:list String.string) (values:tuple word (length variables)) : locals.
exact (map.putmany_of_tuple (tuple.of_list variables) values map.empty).
Defined.
Fixpoint gather (variables : list String.string) (l : locals) : option (locals *  tuple word (length variables)).
exact (match variables with
    | nil => Some (l, tt)
    | cons x xs' =>
      match map.get l x with
      | None => None
      | Some v =>
        match gather xs' (map.remove l x) with
        | None => None
        | Some (l, vs') => Some (l, (pair.mk v vs'))
        end
      end
    end).
Defined.
Definition enforce (variables : list String.string) (values:tuple word (length variables)) (l:locals) : Prop.
exact (match gather variables l with
    | None => False
    | Some (remaining, r) => values = r /\ remaining = map.empty
    end).
Defined.

  Import pair.

  Lemma tailrec
    {e c t localsmap} {m : mem}
    (ghosttypes : polymorphic_list.list Type)
    (variables : list String.string)
    {l0 : tuple word (length variables)}
    {Pl : enforce variables l0 localsmap}
    {post : _->_->_-> Prop}
    {measure : Type} (spec:_->HList.arrows ghosttypes (_->_->ufunc word (length variables) (Prop*(_->_->ufunc word (length variables) Prop)))) lt
    (Hwf : well_founded lt)
    (v0 : measure)
    : hlist.foralls (fun (g0 : hlist ghosttypes) => forall
    (Hpre : (tuple.apply (hlist.apply (spec v0) g0 t m) l0).(1))
    (Hbody : forall v, hlist.foralls (fun g => forall t m, tuple.foralls (fun l =>
      @dlet _ (fun _ => Prop) (reconstruct variables l) (fun localsmap : locals =>
      match tuple.apply (hlist.apply (spec v) g t m) l with S_ =>
      S_.(1) ->
      Markers.unique (Markers.left (exists br, expr m localsmap e (eq br) /\ Markers.right (
      (word.unsigned br <> 0%Z -> cmd call c t m localsmap
        (fun t' m' localsmap' =>
          Markers.unique (Markers.left (hlist.existss (fun l' => enforce variables l' localsmap' /\ Markers.right (
          Markers.unique (Markers.left (hlist.existss (fun g' => exists v',
          match tuple.apply (hlist.apply (spec v') g' t' m') l' with S' =>
          S'.(1) /\ Markers.right (
            lt v' v /\
            forall T M, hlist.foralls (fun L => tuple.apply (S'.(2) T M) L -> tuple.apply (S_.(2) T M) L)) end))))))))) /\
      (word.unsigned br = 0%Z -> tuple.apply (S_.(2) t m) l))))end))))
    (Hpost : match (tuple.apply (hlist.apply (spec v0) g0 t m) l0).(2) with Q0 => forall t m, hlist.foralls (fun l =>  tuple.apply (Q0 t m) l -> post t m (reconstruct variables l))end)
    , cmd call (cmd.while e c) t m localsmap post ).
Admitted.
End Loops.

Definition spec_of (procname:String.string) := Semantics.env -> Prop.
Existing Class spec_of.

Local Ltac2 rec splitcmd (cmd : constr) : unit :=
  match! cmd with
    | cmd.seq ?cmd1 ?cmd2 =>
        set (cmd.seq $cmd1 $cmd2) in *; splitcmd cmd1; splitcmd cmd2
    | cmd.cond ?expr ?cmd1 ?cmd2 => set (cmd.cond $expr $cmd1 $cmd2) in *; splitcmd cmd1; splitcmd cmd2
    | cmd.while ?expr ?cmd => set (cmd.while $expr $cmd) in *; splitcmd cmd
    | _ => ()
  end.

Local Ltac2 Notation "instance_of" type(constr) :=
  lazy_match! Ltac2.Constr.pretype (preterm:(_ : $type)) with ?instance => instance end.

Local Ltac2 rec unfold_const x :=
  if Bool.neg (Constr.is_const x) then x else
    let ref := reference_to_string.reference_of_constr x in
    match! eval cbv delta [$ref] in $x with ?x => unfold_const x
  end.

Local Ltac2 function_body (proc : constr) : constr :=
  let unfolded := unfold_const proc in
  match! unfolded with (_, _, ?fbody) => fbody end.

Local Ltac2 rec callee_specs (cmd : constr) : constr list :=
  match! cmd with
    | cmd.cond _ ?c1 ?c2  => List.append (callee_specs c1) (callee_specs c2)
    | cmd.seq ?c1 ?c2 => List.append (callee_specs c1) (callee_specs c2)
    | cmd.while _ ?c => callee_specs c
    | cmd.stackalloc _ _ ?c => callee_specs c
    | cmd.call _ ?f _ => [instance_of (spec_of $f)]
    | cmd.skip => []
    | cmd.set _ _ => []
    | cmd.unset _ => []
    | cmd.store _ _ _ => []
    | cmd.interact _ _ _ => []
    | _ => Control.throw (Invalid_argument (Some (Message.concat
        (Message.of_string "Failed to recurse into the following command, consider reducing it before calling program_logic_goal_for: ")
        (Message.of_constr cmd))))
  end.

Local Ltac2 program_logic_goal_for_function (proc : constr) : unit :=
  let fname := constr_string_basename_of_constr_reference proc in
  let fname_spec := instance_of (spec_of $fname) in
  let fbody := function_body proc in
  let goal := (fun (functions : constr) =>
    List.fold_right (fun premise_spec conclusion => '(($premise_spec $functions) -> $conclusion)) (callee_specs fbody) '($fname_spec $functions)) in
  exact (forall (functions : @map.rep _ _ Semantics.env) (EnvContains : map.get functions $fname = Some $proc),
    ltac2:(let g := goal &functions in exact $g)
  ).

Definition program_logic_goal_for (_ : Syntax.func) (P : Prop) := P.

Notation "program_logic_goal_for_function! proc" := (program_logic_goal_for proc ltac2:(
   program_logic_goal_for_function (Ltac2.Constr.pretype proc)))
  (at level 10, only parsing).

Ltac normalize_body_of_function f := eval cbv in f.

Ltac bind_body_of_function f_ :=
  let f := normalize_body_of_function f_ in
  let fbody := open_constr:(_) in
  let funif := open_constr:((_, _, fbody)) in
  unify f funif;
  let go_split := ltac2:(fbody |-
    let fbody_value := Option.get (Ltac1.to_constr fbody) in
    splitcmd fbody_value) in
  change f_ with f;
  go_split fbody; intros.

Ltac enter f :=
  cbv beta delta [program_logic_goal_for];
  bind_body_of_function f;
  lazymatch goal with |- ?s ?p => let s := rdelta s in change (s p); cbv beta end.

Ltac is_context_variable H :=
  assert_succeeds (exfalso; clear -H; assert(H = H);
    let A := fresh in let B := fresh in destruct H as [A B]; pose H).

Ltac straightline_cleanup :=
  match goal with

  | x : Word.Interface.word.rep _ |- _ => clear x
  | x : Init.Byte.byte |- _ => clear x
  | x : Semantics.trace |- _ => clear x
  | x : Syntax.cmd |- _ => clear x
  | x : Syntax.expr |- _ => clear x
  | x : coqutil.Map.Interface.map.rep |- _ => clear x
  | x : BinNums.Z |- _ => clear x
  | x : unit |- _ => clear x
  | x : bool |- _ => clear x
  | x : list _ |- _ => clear x
  | x : nat |- _ => clear x

  | x := _ : Word.Interface.word.rep _ |- _ => clear x
  | x := _ : Init.Byte.byte |- _ => clear x
  | x := _ : Semantics.trace |- _ => clear x
  | x := _ : Syntax.cmd |- _ => clear x
  | x := _ : Syntax.expr |- _ => clear x
  | x := _ : coqutil.Map.Interface.map.rep |- _ => clear x
  | x := _ : BinNums.Z |- _ => clear x
  | x := _ : unit |- _ => clear x
  | x := _ : bool |- _ => clear x
  | x := _ : list _ |- _ => clear x
  | x := _ : nat |- _ => clear x
  | |- forall _, _ => intros
  | |- let _ := _ in _ => intros
  | |- dlet.dlet ?v (fun x => ?P) => change (let x := v in P); intros
  | _ => progress (cbn [Semantics.interp_binop] in * )
  | H: exists _, _ |- _ => tryif is_context_variable H then fail else destruct H
  | H: _ /\ _ |- _ => tryif is_context_variable H then fail else destruct H
  | x := ?y |- ?G => is_var y; subst x
  | H: ?x = ?y |- _ => constr_eq x y; clear H
  | H: ?x = ?y |- _ => is_var x; is_var y; assert_fails (idtac; let __ := eval cbv [x] in x in idtac); subst x
  | H: ?x = ?y |- _ => is_var x; is_var y; assert_fails (idtac; let __ := eval cbv [y] in y in idtac); subst y
  | H: ?x = ?v |- _ =>
    is_var x;
    assert_fails (idtac; let __ := eval cbv delta [x] in x in idtac);
    lazymatch v with context[x] => fail | _ => idtac end;
    let x' := fresh x in
    rename x into x';
    simple refine (let x := v in _);
    change (x' = x) in H;
    symmetry in H;
    destruct H
  end.

Ltac straightline_stackalloc :=
  match goal with Hanybytes: Memory.anybytes ?a ?n ?mStack |- _ =>
  let m := match goal with H : map.split ?mCobined ?m mStack |- _ => m end in
  let mCombined := match goal with H : map.split ?mCobined ?m mStack |- _ => mCobined end in
  let Hsplit := match goal with H : map.split ?mCobined ?m mStack |- _ => H end in
  let Hm := multimatch goal with H : _ m |- _ => H end in
  let Hm' := fresh Hm in
  let Htmp := fresh in
  let Pm := match type of Hm with ?P m => P end in
  assert_fails (assert (Separation.sep Pm (Array.array Separation.ptsto (Interface.word.of_Z (BinNums.Zpos BinNums.xH)) a _) mCombined) as _ by ecancel_assumption);
  rename Hm into Hm';
  let stack := fresh "stack" in
  let stack_length := fresh "length_" stack in
  destruct (Array.anybytes_to_array_1 mStack a n Hanybytes) as (stack&Htmp&stack_length);
  epose proof (ex_intro _ m (ex_intro _ mStack (conj Hsplit (conj Hm' Htmp)))
  : Separation.sep _ (Array.array Separation.ptsto (Interface.word.of_Z (BinNums.Zpos BinNums.xH)) a _) mCombined) as Hm;
  clear Htmp;
  try (let m' := fresh m in rename m into m'); rename mCombined into m;
  ( assert (BinInt.Z.of_nat (Datatypes.length stack) = n)
  by (rewrite stack_length; apply (ZifyInst.of_nat_to_nat_eq n))
  || fail 2 "negative stackalloc of size" n )
  end.

Ltac straightline_stackdealloc :=
  lazymatch goal with |- exists _ _, Memory.anybytes ?a ?n _ /\ map.split ?m _ _ /\ _ =>
  let Hm := multimatch goal with Hm : _ m |- _ => Hm end in
  let stack := match type of Hm with context [Array.array Separation.ptsto _ a ?stack] => stack end in
  let length_stack := match goal with H : Datatypes.length stack = _ |- _ => H end in
  let Hm' := fresh Hm in
  pose proof Hm as Hm';
  let Psep := match type of Hm with ?P _ => P end in
  let Htmp := fresh "Htmp" in
  eassert (Lift1Prop.iff1 Psep (Separation.sep _ (Array.array Separation.ptsto (Interface.word.of_Z (BinNums.Zpos BinNums.xH)) a stack))) as Htmp
  by ecancel || fail "failed to find stack frame in" Psep "using ecancel";
  eapply (fun m => proj1 (Htmp m)) in Hm;
  let m' := fresh m in
  rename m into m';
  let mStack := fresh in
  destruct Hm as (m&mStack&Hsplit&Hm&Harray1); move Hm at bottom;
  pose proof Array.array_1_to_anybytes _ _ _ Harray1 as Hanybytes;
  rewrite length_stack in Hanybytes;
  refine (ex_intro _ m (ex_intro _ mStack (conj Hanybytes (conj Hsplit _))));
  clear Htmp Hsplit mStack Harray1 Hanybytes
  end.

Ltac rename_to_different H :=
  idtac;
  let G := fresh H "'0" in
  rename H into G.
Ltac ensure_free H :=
  try rename_to_different H.

Ltac eq_uniq_step :=
  match goal with
  | |- ?x = ?y =>
      let x := rdelta x in
      let y := rdelta y in
      first [ is_evar x | is_evar y | constr_eq x y ]; exact eq_refl
  | |- ?lhs = ?rhs =>
      let lh := head lhs in
      is_constructor lh;
      let rh := head rhs in
      constr_eq lh rh;
      f_equal
  end.
Ltac eq_uniq := repeat eq_uniq_step.

Ltac fwd_uniq_step :=
  match goal with
  | |- exists x : ?T, _ =>
      let ev := open_constr:(match _ return T with x => x end) in
      eexists ev;
      let rec f :=
        tryif has_evar ev
        then fwd_uniq_step
        else idtac
      in f
  | |- _ /\ _ => split; [ solve [repeat fwd_uniq_step; eq_uniq] | ]
  | _ => solve [ eq_uniq ]
  end.

Ltac straightline :=
  match goal with
  | _ => straightline_cleanup
  | |- program_logic_goal_for ?f _ =>
    enter f; intros;
    match goal with
    | H: map.get ?functions ?fname = Some _ |- _ =>
        eapply start_func; [exact H | clear H]
    end;
    cbv match beta delta [WeakestPrecondition.func]
  | |- WeakestPrecondition.cmd _ (cmd.set ?s ?e) _ _ _ ?post =>
    unfold1_cmd_goal; cbv beta match delta [cmd_body];
    let __ := match s with String.String _ _ => idtac | String.EmptyString => idtac end in
    ident_of_constr_string_cps s ltac:(fun x =>
      ensure_free x;

      letexists _ as x; split; [solve [repeat straightline]|])
  | |- cmd _ ?c _ _ _ ?post =>
    let c := eval hnf in c in
    lazymatch c with
    | cmd.while _ _ => fail
    | cmd.cond _ _ _ => fail
    | cmd.interact _ _ _ => fail
    | _ => unfold1_cmd_goal; cbv beta match delta [cmd_body]
    end
  | |- @list_map _ _ (get _) _ _ => unfold1_list_map_goal; cbv beta match delta [list_map_body]
  | |- @list_map _ _ (expr _ _) _ _ => unfold1_list_map_goal; cbv beta match delta [list_map_body]
  | |- @list_map _ _ _ nil _ => cbv beta match fix delta [list_map list_map_body]
  | |- expr _ _ _ _ => unfold1_expr_goal; cbv beta match delta [expr_body]
  | |- dexpr _ _ _ _ => cbv beta delta [dexpr]
  | |- dexprs _ _ _ _ => cbv beta delta [dexprs]
  | |- literal _ _ => cbv beta delta [literal]
  | |- @get ?w ?W ?L ?l ?x ?P =>
      let get' := eval cbv [get] in @get in
      change (get' w W L l x P); cbv beta
  | |- load _ _ _ _ => cbv beta delta [load]
  | |- @Loops.enforce ?width ?word ?locals ?names ?values ?map =>
    let values := eval cbv in values in
    change (@Loops.enforce width word locals names values map);
    exact (conj (eq_refl values) eq_refl)
  | |- @eq (@coqutil.Map.Interface.map.rep String.string Interface.word.rep _) _ _ =>
    eapply SortedList.eq_value; exact eq_refl
  | |- @map.get String.string Interface.word.rep ?M ?m ?k = Some ?e' =>
    let e := rdelta e' in
    is_evar e;
    once (let v := multimatch goal with x := context[@map.put _ _ M _ k ?v] |- _ => v end in

          unify e v; exact (eq_refl (Some v)))
  | |- @coqutil.Map.Interface.map.get String.string Interface.word.rep _ _ _ = Some ?v =>
    let v' := rdelta v in is_evar v'; (change v with v'); exact eq_refl
  | |- ?x = ?y =>
    let y := rdelta y in is_evar y; change (x=y); exact eq_refl
  | |- ?x = ?y =>
    let x := rdelta x in is_evar x; change (x=y); exact eq_refl
  | |- ?x = ?y =>
    let x := rdelta x in let y := rdelta y in constr_eq x y; exact eq_refl
  | |- store Syntax.access_size.one _ _ _ _ =>
    eapply Scalars.store_one_of_sep; [solve[ecancel_assumption]|]
  | |- store Syntax.access_size.two _ _ _ _ =>
    eapply Scalars.store_two_of_sep; [solve[ecancel_assumption]|]
  | |- store Syntax.access_size.four _ _ _ _ =>
    eapply Scalars.store_four_of_sep; [solve[ecancel_assumption]|]
  | |- store Syntax.access_size.word _ _ _ _ =>
    eapply Scalars.store_word_of_sep; [solve[ecancel_assumption]|]
  | |- bedrock2.Memory.load Syntax.access_size.one ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_one_of_sep _ _ _ _ _ _ _ _ _ _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.two ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_two_of_sep _ _ word _ mem _ a _ _ m _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.four ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_four_of_sep_32bit _ _ word _ mem _ eq_refl a _ _ m _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.four ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_four_of_sep _ _ word _ mem _ a _ _ m _); ecancel_assumption
  | |- @bedrock2.Memory.load _ ?word ?mem Syntax.access_size.word ?m ?a = Some ?ev =>
    try subst ev; refine (@Scalars.load_word_of_sep _ _ word _ mem _ a _ _ m _); ecancel_assumption
  | |- exists l', Interface.map.of_list_zip ?ks ?vs = Some l' /\ _ =>
    letexists; split; [exact eq_refl|]
  | |- exists l', Interface.map.putmany_of_list_zip ?ks ?vs ?l = Some l' /\ _ =>
    letexists; split; [exact eq_refl|]
  | _ => fwd_uniq_step
  | |- exists x, ?P /\ ?Q =>
    let x := fresh x in refine (let x := _ in ex_intro (fun x => P /\ Q) x _);
                        split; [solve [repeat straightline]|]
  | |- exists x, Markers.split (?P /\ ?Q) =>
    let x := fresh x in refine (let x := _ in ex_intro (fun x => P /\ Q) x _);
                        split; [solve [repeat straightline]|]
  | |- Markers.unique (exists x, Markers.split (?P /\ ?Q)) =>
    let x := fresh x in refine (let x := _ in ex_intro (fun x => P /\ Q) x _);
                        split; [solve [repeat straightline]|]
  | |- Markers.unique (Markers.left ?G) =>
    change G;
    unshelve (idtac; repeat match goal with
                     | |- Markers.split (?P /\ Markers.right ?Q) =>
                       split; [eabstract (repeat straightline) | change Q]
                     | |- exists _, _ => letexists
                     end); []
  | |- Markers.split ?G => change G; split
  | |- True => exact I
  | |- False \/ _ => right
  | |- _ \/ False => left
  | |- BinInt.Z.modulo ?z (Memory.bytes_per_word _) = BinInt.Z0 /\ _ =>
      lazymatch Coq.setoid_ring.InitialRing.isZcst z with
      | true => split; [exact eq_refl|]
      end
  | |- _ => straightline_stackalloc
  | |- _ => straightline_stackdealloc
  | |- context[sep (sep ?_a ?_b) ?_c] => progress (flatten_seps_in_goal; cbn [seps])
  | H : context[sep (sep ?_a ?_b) ?_c] |- _ => progress (flatten_seps_in H; cbn [seps] in H)
  end.
Local Open Scope string_scope.
Import Crypto.Arithmetic.WordByWordMontgomery.

Section WithParameters.
  Import WordByWordMontgomery.

  Context {prime: Z} (r := 64) {ri : Z}.
Instance spec_of_redc_alt : spec_of "redc_alt".
exact (fnspec! "redc_alt" Astart Bstart Sstart len / A (aval: Z) B (bval: Z) S R,
    { requires t m :=
        m =* array scalar (word.of_Z 8) Astart A *
                  array scalar (word.of_Z 8) Bstart B *
                  array scalar (word.of_Z 8) Sstart S * R /\
        word.unsigned len = Z.of_nat (List.length A)  /\
        word.unsigned len = Z.of_nat (List.length B)  /\
        word.unsigned len = Z.of_nat (List.length S) /\
        @eval r (Z.to_nat (word.unsigned len)) (List.map word.unsigned A) = aval /\
        @eval r (Z.to_nat (word.unsigned len)) (List.map word.unsigned B) = bval;
      ensures t' m' :=  t=t' /\ exists S',
          m' =*
             array scalar (word.of_Z 8) Astart A *
             array scalar (word.of_Z 8) Bstart B *
            array scalar (word.of_Z 8) Sstart S' * R /\
          ( aval * bval * ri^(word.unsigned len) ) mod prime =
            @eval r (Z.to_nat (word.unsigned len)) (List.map word.unsigned S') mod prime
    }).
Defined.
Instance spec_of_redc_step : spec_of "redc_step".
Admitted.

  Definition redc_alt :=
    func! (Astart, Bstart, Sstart, len) {
    i = $0;
    while (i < len) {
         store(Sstart + $8*i, $0);
         i = i + $1
      };
    i = $0;
    while (i < len) {
         redc_step ( load(Astart + $8*i), Bstart, Sstart, len );
          i = i + $1
      }
    }.

  Let zeros (n: Z) :=
        repeat (@word.of_Z _ word 0) (Z.to_nat n).

 Theorem redc_alt_ok :
      program_logic_goal_for_function! redc_alt.
 Proof.
   repeat straightline.

      refine ( tailrec (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ (HList.polymorphic_list.cons _ HList.polymorphic_list.nil))))))))
               ("Astart":: "Bstart" :: "Sstart" :: "len" :: "i" :: nil)
               (fun l A aval B bval S Ra Rb R t m Astart Bstart Sstart len i => PrimitivePair.pair.mk
                                    (m =* array scalar (word.of_Z 8) (word.add Sstart (word.mul (word.of_Z 8) i)) S * R /\
                                       word.unsigned len - word.unsigned i = Z.of_nat (List.length S) /\

                                    l = List.length S )
                                    (fun t' m' Astart' Bstart' Sstart' len' i' =>
                                       (
                                     t = t' /\ Astart = Astart' /\ Bstart = Bstart' /\ Sstart = Sstart' /\ len = len' /\
                                     m' =* array scalar (word.of_Z 8) (word.add Sstart (word.mul (word.of_Z 8) i)) (zeros (word.unsigned len - word.unsigned i)) * R
                                     )
                                    )
               )
               lt _ _ _ _ _ _ _ _ _ _ _ _ _);
        cbn [reconstruct map.putmany_of_list HList.tuple.to_list
         HList.hlist.foralls HList.tuple.foralls
         HList.hlist.existss HList.tuple.existss
         HList.hlist.apply  HList.tuple.apply
         HList.hlist
         List.repeat Datatypes.length
         HList.polymorphic_list.repeat HList.polymorphic_list.length
         PrimitivePair.pair._1 PrimitivePair.pair._2] in *.

      {
 repeat straightline.
}
      {
 exact Wf_nat.lt_wf.
}
      {
 repeat straightline.
        subst i.
        replace (word.add Sstart (word.mul (word.of_Z 8) (word.of_Z 0))) with (Sstart) by ring.
        repeat split; try eauto.
        -
 ecancel_assumption.
        -
 rewrite word.unsigned_of_Z_0.
Lia.lia.
}

      {
 repeat straightline.
eexists.
🛠️ Intermediate Coq File (useful for debugging if minimization did not go as far as you wanted) (truncated to 6.0KiB; full 91KiB file on GitHub Actions Artifacts under tmp.v)
(* -*- mode: coq; coq-prog-args: ("-emacs" "-q" "-w" "+implicit-core-hint-db,+implicits-in-term,+non-reversible-notation,+deprecated-intros-until-0,+deprecated-focus,+unused-intro-pattern,+variable-collision,+unexpected-implicit-declaration,+omega-is-deprecated,+deprecated-instantiate-syntax,+non-recursive,+undeclared-scope,+deprecated-hint-rewrite-without-locality,+deprecated-hint-without-locality,+deprecated-instance-without-locality,+deprecated-typeclasses-transparency-without-locality,+fragile-hint-constr,-deprecated-since-9.0,-deprecated-since-8.20,-deprecated-from-Coq" "-w" "-notation-overridden,-native-compiler-disabled,-ambiguous-paths,-masking-absolute-name" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Coqprime" "Coqprime" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Kami" "Kami" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rewriter" "Rewriter" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rupicola" "Rupicola" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Top.bug_01") -*- *)
(* File reduced by coq-bug-minimizer from original input, then from 577 lines to 117 lines, then from 131 lines to 869 lines, then from 877 lines to 453 lines, then from 468 lines to 1367 lines, then from 1372 lines to 533 lines, then from 548 lines to 1295 lines, then from 1303 lines to 616 lines, then from 631 lines to 1279 lines, then from 1286 lines to 653 lines, then from 668 lines to 953 lines, then from 961 lines to 662 lines, then from 677 lines to 1947 lines, then from 1949 lines to 996 lines, then from 1011 lines to 1284 lines, then from 1292 lines to 1026 lines, then from 1041 lines to 1079 lines, then from 1087 lines to 1042 lines, then from 1057 lines to 1205 lines, then from 1211 lines to 1085 lines, then from 1100 lines to 1221 lines, then from 1229 lines to 1123 lines, then from 1138 lines to 1177 lines, then from 1185 lines to 1151 lines, then from 1166 lines to 1480 lines, then from 1488 lines to 1182 lines, then from 1197 lines to 1464 lines, then from 1472 lines to 1195 lines, then from 1216 lines to 1089 lines, then from 1103 lines to 1492 lines, then from 1500 lines to 1101 lines, then from 1116 lines to 1306 lines, then from 1314 lines to 1114 lines, then from 1129 lines to 1859 lines, then from 1867 lines to 1133 lines, then from 1148 lines to 1714 lines, then from 1722 lines to 1326 lines, then from 1341 lines to 1990 lines, then from 1998 lines to 1486 lines, then from 1501 lines to 1869 lines, then from 1877 lines to 1526 lines, then from 1541 lines to 1966 lines, then from 1974 lines to 1564 lines, then from 1579 lines to 2023 lines, then from 2031 lines to 1594 lines, then from 1609 lines to 1995 lines, then from 2003 lines to 1621 lines, then from 1636 lines to 1925 lines, then from 1933 lines to 1639 lines, then from 1654 lines to 2735 lines, then from 2740 lines to 1705 lines, then from 1720 lines to 2134 lines, then from 2142 lines to 1716 lines, then from 1731 lines to 2049 lines, then from 2057 lines to 1876 lines, then from 1878 lines to 1549 lines, then from 1561 lines to 1814 lines, then from 1821 lines to 1557 lines, then from 1570 lines to 2174 lines, then from 2181 lines to 1646 lines, then from 1659 lines to 2032 lines, then from 2039 lines to 1731 lines, then from 1744 lines to 4295 lines, then from 4301 lines to 1732 lines, then from 1745 lines to 2060 lines, then from 2067 lines to 1741 lines, then from 1754 lines to 2010 lines, then from 2017 lines to 1752 lines, then from 1765 lines to 2001 lines, then from 2008 lines to 1851 lines, then from 1864 lines to 1897 lines, then from 1904 lines to 1874 lines, then from 1887 lines to 2076 lines, then from 2083 lines to 1884 lines, then from 1897 lines to 2091 lines, then from 2098 lines to 1986 lines, then from 1999 lines to 2013 lines, then from 2020 lines to 2001 lines, then from 2014 lines to 2596 lines, then from 2602 lines to 2069 lines, then from 2082 lines to 2231 lines, then from 2238 lines to 2074 lines, then from 2087 lines to 2251 lines, then from 2258 lines to 2142 lines, then from 2155 lines to 2165 lines, then from 2172 lines to 2142 lines, then from 2155 lines to 2172 lines, then from 2179 lines to 2155 lines, then from 2168 lines to 2342 lines, then from 2349 lines to 2186 lines, then from 2199 lines to 2398 lines, then from 2405 lines to 2225 lines, then from 2238 lines to 2426 lines, then from 2433 lines to 2279 lines, then from 2292 lines to 2348 lines, then from 2355 lines to 2291 lines, then from 2304 lines to 2974 lines, then from 2981 lines to 2343 lines, then from 2360 lines to 2174 lines, then from 2186 lines to 2803 lines, then from 2810 lines to 2297 lines, then from 2310 lines to 3111 lines, then from 3118 lines to 2327 lines, then from 2340 lines to 2462 lines, then from 2468 lines to 2335 lines, then from 2348 lines to 2386 lines, then from 2393 lines to 2339 lines, then from 2352 lines to 2381 lines, then from 2388 lines to 2345 lines, then from 2358 lines to 2392 lines, then from 2399 lines to 2352 lines, then from 2365 lines to 2395 lines, then from 2402 lines t
🛠️ 📜 Intermediate Coq File log (useful for debugging if minimization did not go as far as you wanted)
📜 Build Log (contains the Coq error message) (truncated to last 8.0KiB; full 14MiB file on GitHub Actions Artifacts under build.log)
Util/ZUtil/Tactics/SimplifyFractionsLe.vo
src/Util/ZUtil/Tactics/SolveRange.vo
src/Util/ZUtil/Tactics/SolveTestbit.vo
src/Util/ZUtil/Tactics/SplitMinMax.vo
src/Util/ZUtil/Tactics/ZeroBounds.vo
src/Util/ZUtil/Tactics/Ztestbit.vo
src/Util/ZUtil/Testbit.vo
src/Util/ZUtil/TruncatingShiftl.vo
src/Util/ZUtil/TwosComplement.vo
src/Util/ZUtil/Z2Nat.vo
src/Util/ZUtil/ZSimplify.vo
src/Util/ZUtil/ZSimplify/Autogenerated.vo
src/Util/ZUtil/ZSimplify/Core.vo
src/Util/ZUtil/ZSimplify/Simple.vo
src/Util/ZUtil/Zselect.vo


Files Not Made:
src/Bedrock/End2End/Poly1305/Field1305.vo
src/Bedrock/End2End/X25519/EdwardsXYZT.vo
src/Bedrock/End2End/X25519/Field25519.vo
src/Bedrock/End2End/X25519/GarageDoor.vo
src/Bedrock/End2End/X25519/GarageDoorTop.vo
src/Bedrock/End2End/X25519/MontgomeryLadder.vo
src/Bedrock/End2End/X25519/MontgomeryLadderRISCV.vo
src/Bedrock/Everything.vo
src/Bedrock/Field/Stringification/Stringification.vo
src/Bedrock/Field/Synthesis/Examples/p224_64_new.vo
src/Bedrock/Field/Synthesis/New/ComputedOp.vo
src/Bedrock/Field/Synthesis/New/Signature.vo
src/Bedrock/Field/Synthesis/New/UnsaturatedSolinas.vo
src/Bedrock/Field/Synthesis/New/WordByWordMontgomery.vo
src/Bedrock/Field/Translation/Cmd.vo
src/Bedrock/Field/Translation/Func.vo
src/Bedrock/Field/Translation/Parameters/Defaults.vo
src/Bedrock/Field/Translation/Parameters/Defaults32.vo
src/Bedrock/Field/Translation/Parameters/Defaults64.vo
src/Bedrock/Field/Translation/Parameters/FE310.vo
src/Bedrock/Field/Translation/Proofs/Cmd.vo
src/Bedrock/Field/Translation/Proofs/Func.vo
src/Bedrock/Field/Translation/Proofs/ValidComputable/Cmd.vo
src/Bedrock/Field/Translation/Proofs/ValidComputable/Func.vo
src/Bedrock/Group/ScalarMult/MontgomeryLadder.vo
src/Bedrock/P256.vo
src/Bedrock/P256/Coord.vo
src/Bedrock/P256/Coord32.vo
src/Bedrock/P256/Jacobian.vo
src/Bedrock/P256/JacobianAffine.vo
src/Bedrock/P256/Platform.vo
src/Bedrock/P256/PrecomputedMultiples.vo
src/Bedrock/P256/RecodeProofs.vo
src/Bedrock/P256/Scalarmult.vo
src/Bedrock/P256/Specs.vo
src/Bedrock/Secp256k1/Addchain.vo
src/Bedrock/Secp256k1/Field256k1.vo
src/Bedrock/Secp256k1/JacobianCoZ.vo
src/Bedrock/Secp256k1/JoyeLadder.vo
src/Bedrock/Standalone/StandaloneHaskellMain.vo
src/Bedrock/Standalone/StandaloneJsOfOCamlMain.vo
src/Bedrock/Standalone/StandaloneOCamlMain.vo
src/BoundsPipeline.vo
src/CLI.vo
src/CompilersTestCases.vo
src/Curves/Montgomery/AffineInstances.vo
src/Curves/Montgomery/AffineProofs.vo
src/Curves/Montgomery/XZProofs.vo
src/Curves/Weierstrass/AffineProofs.vo
src/Curves/Weierstrass/Jacobian/CoZ.vo
src/Curves/Weierstrass/Jacobian/Jacobian.vo
src/Curves/Weierstrass/Jacobian/ScalarMult.vo
src/Curves/Weierstrass/P256.vo
src/Curves/Weierstrass/Projective.vo
src/Everything.vo
src/ExtractionJsOfOCaml/WithBedrock/fiat_crypto.vo
src/ExtractionJsOfOCaml/bedrock2_fiat_crypto.vo
src/ExtractionJsOfOCaml/fiat_crypto.vo
src/Fancy/Barrett256.vo
src/Fancy/Montgomery256.vo
src/PerfTesting/PerfTestPrint.vo
src/PerfTesting/PerfTestSearch.vo
src/PerfTesting/PerfTestSearchPattern.vo
src/PushButtonSynthesis/BarrettReduction.vo
src/PushButtonSynthesis/BaseConversion.vo
src/PushButtonSynthesis/DettmanMultiplication.vo
src/PushButtonSynthesis/FancyMontgomeryReduction.vo
src/PushButtonSynthesis/Primitives.vo
src/PushButtonSynthesis/SaturatedSolinas.vo
src/PushButtonSynthesis/SmallExamples.vo
src/PushButtonSynthesis/SolinasReduction.vo
src/PushButtonSynthesis/UnsaturatedSolinas.vo
src/PushButtonSynthesis/WordByWordMontgomery.vo
src/Rewriter/All.vo
src/Rewriter/PerfTesting/Core.vo
src/Rewriter/PerfTesting/StandaloneOCamlMain.vo
src/Rewriter/RulesGood.vo
src/SlowPrimeSynthesisExamples.vo
src/StandaloneDebuggingExamples.vo
src/StandaloneHaskellMain.vo
src/StandaloneJsOfOCamlMain.vo
src/StandaloneMonadicUtils.vo
src/StandaloneOCamlMain.vo
ROCQ compile src/Bedrock/Field/Synthesis/Examples/redc.v
MINIMIZER_DEBUG_EXTRA: coqc: /github/workspace/builds/coq/coq-failing/_install_ci/bin///rocq
MINIMIZER_DEBUG_EXTRA: original invocation: '' 
MINIMIZER_DEBUG_EXTRA: new invocation: /github/workspace/builds/coq/coq-failing/_install_ci/bin/rocq.orig compile -q -w +implicit-core-hint-db\,+implicits-in-term\,+non-reversible-notation\,+deprecated-intros-until-0\,+deprecated-focus\,+unused-intro-pattern\,+variable-collision\,+unexpected-implicit-declaration\,+omega-is-deprecated\,+deprecated-instantiate-syntax\,+non-recursive\,+undeclared-scope\,+deprecated-hint-rewrite-without-locality\,+deprecated-hint-without-locality\,+deprecated-instance-without-locality\,+deprecated-typeclasses-transparency-without-locality\,+fragile-hint-constr\,-deprecated-since-9.0\,-deprecated-since-8.20\,-deprecated-from-Coq -w -notation-overridden\,-native-compiler-disabled\,-ambiguous-paths\,-masking-absolute-name -w -deprecated-native-compiler-option -native-compiler no -R /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src Crypto src/Bedrock/Field/Synthesis/Examples/redc.v 
MINIMIZER_DEBUG_EXTRA: coqpath: 
MINIMIZER_DEBUG_EXTRA: ocamlpath: /github/workspace/builds/coq/coq-failing/_install_ci/lib:
MINIMIZER_DEBUG_EXTRA: pwd: PWD=/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto
MINIMIZER_DEBUG_EXTRA: exec: /github/workspace/builds/coq/coq-failing/_install_ci/bin/rocq.orig compile -q -w +implicit-core-hint-db\,+implicits-in-term\,+non-reversible-notation\,+deprecated-intros-until-0\,+deprecated-focus\,+unused-intro-pattern\,+variable-collision\,+unexpected-implicit-declaration\,+omega-is-deprecated\,+deprecated-instantiate-syntax\,+non-recursive\,+undeclared-scope\,+deprecated-hint-rewrite-without-locality\,+deprecated-hint-without-locality\,+deprecated-instance-without-locality\,+deprecated-typeclasses-transparency-without-locality\,+fragile-hint-constr\,-deprecated-since-9.0\,-deprecated-since-8.20\,-deprecated-from-Coq -w -notation-overridden\,-native-compiler-disabled\,-ambiguous-paths\,-masking-absolute-name -w -deprecated-native-compiler-option -native-compiler no -R /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src Crypto src/Bedrock/Field/Synthesis/Examples/redc.v 
MINIMIZER_DEBUG_EXTRA: coqlib: Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//
MINIMIZER_DEBUG: info: /tmp/tmp-coqbot-minimizer.uzP3z48b3h
MINIMIZER_DEBUG: files:  src/Bedrock/Field/Synthesis/Examples/redc.v /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src/Bedrock/Field/Synthesis/Examples/redc.v
Warning, feedback message received but no listener to handle it!
Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]Warning, feedback message received but no listener to handle it!
Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
Warning: Deprecated environment variable COQCORELIB,
use ROCQRUNTIMELIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
File "./src/Bedrock/Field/Synthesis/Examples/redc.v", line 210, characters 29-37:
Error: Expected a single focused goal but 2 goals are focused.

Command exited with non-zero status 1
src/Bedrock/Field/Synthesis/Examples/redc.vo (real: 1.06, user: 0.89, sys: 0.16, mem: 539820 ko)
make: *** [Makefile.coq:815: src/Bedrock/Field/Synthesis/Examples/redc.vo] Error 1
make: *** [src/Bedrock/Field/Synthesis/Examples/redc.vo] Deleting file 'src/Bedrock/Field/Synthesis/Examples/redc.glob'
+ code=2
+ printf '\n%s exit code: %s\n' fiat_crypto 2
+ '[' fiat_crypto '!=' stdlib_test ']'
+ echo 'Aggregating timing log...'
Aggregating timing log...
+ echo

+ tools/make-one-time-file.py --real _build_ci/fiat_crypto.log
    Time |  Peak Mem | File Name                               
---------------------------------------------------------------
0m01.52s | 539820 ko | Total Time / Peak Mem                   
---------------------------------------------------------------
0m01.06s | 539820 ko | Bedrock/Field/Synthesis/Examples/redc.vo
0m00.46s |  34240 ko | .Makefile.coq.d                         
+ '[' '' ']'
+ exit 2
/github/workspace/builds/coq /github/workspace
::endgroup::
📜 🔎 Minimization Log (truncated to last 8.0KiB; full 90MiB file on GitHub Actions Artifacts under bug.log)
/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rewriter" "Rewriter" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rupicola" "Rupicola" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Top.bug_01" "-Q" "/tmp/tmpgwb90hdn" "" "/tmp/tmpgwb90hdn/Top/bug_01.v" "-q"

Running command (in: /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto): "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rewriter" "Rewriter" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rupicola" "Rupicola" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Top.bug_01" "-Q" "/tmp/tmpc6enuvyk" "" "/tmp/tmpc6enuvyk/Top/bug_01.v" "-q"

Running command (in: /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto): "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Rupicola" "Rupicola" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Top.bug_01" "-Q" "/tmp/tmpc986ptqv" "" "/tmp/tmpc986ptqv/Top/bug_01.v" "-q"

Running command (in: /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto): "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Top.bug_01" "-Q" "/tmp/tmpuzpy7dly" "" "/tmp/tmpuzpy7dly/Top/bug_01.v" "-q"

Running command (in: /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto): "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2" "bedrock2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Top.bug_01" "-Q" "/tmp/tmpkn75r_6a" "" "/tmp/tmpkn75r_6a/Top/bug_01.v" "-q"

Running command (in: /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto): "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/bedrock2Examples" "bedrock2Examples" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Top.bug_01" "-Q" "/tmp/tmp5ysbxvm0" "" "/tmp/tmp5ysbxvm0/Top/bug_01.v" "-q"

Running command (in: /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto): "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/compiler" "compiler" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Top.bug_01" "-Q" "/tmp/tmpmr1mqwu0" "" "/tmp/tmpmr1mqwu0/Top/bug_01.v" "-q"

Running command (in: /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto): "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/coqutil" "coqutil" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Top.bug_01" "-Q" "/tmp/tmpd1_tj5al" "" "/tmp/tmpd1_tj5al/Top/bug_01.v" "-q"

Running command (in: /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto): "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/riscv" "riscv" "-top" "Top.bug_01" "-Q" "/tmp/tmpdwo3g5zj" "" "/tmp/tmpdwo3g5zj/Top/bug_01.v" "-q"

Running command (in: /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto): "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "-top" "Top.bug_01" "-Q" "/tmp/tmpmh8egwt9" "" "/tmp/tmpmh8egwt9/Top/bug_01.v" "-q"

Running command (in: /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto): "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto/src" "Crypto" "/tmp/tmponq19wbv.v" "-q"

Running command (in: /github/workspace/builds/coq/coq-failing/_build_ci/fiat_crypto): "/github/workspace/builds/coq/coq-failing/_install_ci/bin/coqc.orig" "/tmp/tmpz_2dqdxi.v" "-q"
Updated output file with minimized arguments

If you have any comments on your experience of the minimizer, please share them in a reply (possibly tagging @JasonGross).
If you believe there's a bug in the bug minimizer, please report it on the bug minimizer issue tracker.

cc @JasonGross

@coqbot-app

coqbot-app Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor
Minimization interrupted by timeout, being automatically continued. Partially Minimized File /home/runner/work/run-coq-bug-minimizer/run-coq-bug-minimizer/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories/PCUICInductiveInversion.v in 5h 15m 6s (from ci-metarocq) (interrupted by timeout, being automatically continued) (full log on GitHub Actions - verbose log)
⭐ ⏱️ Partially Minimized Coq File (timeout) (truncated to first and last 32KiB; full 117KiB file on GitHub Actions Artifacts under bug.v)
(* -*- mode: coq; coq-prog-args: ("-emacs" "-q" "-w" "-deprecated-native-compiler-option" "-native-compiler" "no" "-coqlib" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq//" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/utils/theories" "MetaRocq.Utils" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/common/theories" "MetaRocq.Common" "-R" "/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic/theories" "MetaRocq.PCUIC" "-Q" "/github/workspace/cwd" "Top" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Equations" "Equations" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/ExtLib" "ExtLib" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Ltac2" "Ltac2" "-Q" "/github/workspace/builds/coq/coq-failing/_install_ci/lib/coq///user-contrib/Stdlib" "Stdlib" "-top" "Top.bug_01") -*- *)
(* File reduced by coq-bug-minimizer from original input, then from 4603 lines to 39 lines, then from 53 lines to 39 lines, then from 52 lines to 39 lines, then from 51 lines to 3774 lines, then from 3773 lines to 46 lines, then from 58 lines to 2403 lines, then from 2409 lines to 57 lines, then from 69 lines to 995 lines, then from 1000 lines to 81 lines, then from 93 lines to 2645 lines, then from 2646 lines to 213 lines, then from 225 lines to 90 lines, then from 104 lines to 1099 lines, then from 1098 lines to 139 lines, then from 153 lines to 1878 lines, then from 1885 lines to 430 lines, then from 444 lines to 1595 lines, then from 1601 lines to 598 lines, then from 612 lines to 2689 lines, then from 2690 lines to 619 lines, then from 633 lines to 1387 lines, then from 1388 lines to 641 lines, then from 655 lines to 3123 lines, then from 3125 lines to 716 lines, then from 730 lines to 1577 lines, then from 1582 lines to 1230 lines, then from 1240 lines to 765 lines, then from 779 lines to 2311 lines, then from 2312 lines to 795 lines, then from 809 lines to 2691 lines, then from 2694 lines to 1082 lines, then from 1096 lines to 1769 lines, then from 1775 lines to 1159 lines, then from 1173 lines to 4005 lines, then from 4004 lines to 1740 lines, then from 1760 lines to 1667 lines, then from 1679 lines to 3380 lines, then from 3385 lines to 1962 lines, then from 1974 lines to 2798 lines, then from 2802 lines to 1968 lines, then from 1979 lines to 5097 lines, then from 5063 lines to 2392 lines, then from 2404 lines to 3600 lines, then from 3603 lines to 3403 lines *)
(* coqc version 9.3+alpha compiled with OCaml 4.14.2
   coqtop version 9.3+alpha
   Expected coqc runtime on this file: 2.590 sec
   Expected coqc peak memory usage on this file: 1264540.0 kb *)









Require Corelib.Init.Hexadecimal.
Require Corelib.Program.Wf.
Require Corelib.Lists.ListDef.
Require Corelib.Floats.FloatOps.
Require Corelib.Init.Ltac.
Require Corelib.BinNums.IntDef.
Require Corelib.Numbers.BinNums.
Require Corelib.Program.Tactics.
Require Corelib.Numbers.Cyclic.Int63.PrimInt63.
Require Corelib.Strings.PrimString.
Require Corelib.Program.Basics.
Require Corelib.extraction.Extraction.
Require Corelib.BinNums.NatDef.
Require Corelib.ssr.ssrbool.
Require Corelib.Numbers.Cyclic.Int63.Uint63Axioms.
Require Corelib.Classes.Morphisms.
Require Corelib.ssr.ssreflect.
Require Corelib.Init.Nat.
Require Corelib.Init.Decimal.
Require Corelib.Numbers.Cyclic.Int63.CarryType.
Require Corelib.Strings.PrimStringAxioms.
Require Corelib.Relations.Relation_Definitions.
Require Corelib.Classes.RelationClasses.
Require Corelib.Program.Utils.
Require Corelib.Init.Byte.
Require Corelib.Classes.Morphisms_Prop.
Require Corelib.Numbers.Cyclic.Int63.Sint63Axioms.
Require Corelib.Floats.SpecFloat.
Require Corelib.Floats.PrimFloat.
Require Corelib.Init.Sumbool.
Require Corelib.Init.Wf.
Require Corelib.Setoids.Setoid.
Require Corelib.BinNums.PosDef.
Require Corelib.Classes.CRelationClasses.
Require ExtLib.Core.Any.
Require ExtLib.Structures.BinOps.
Require MetaRocq.Utils.MREquality.
Require MetaRocq.Utils.MRSquash.
Require MetaRocq.Utils.MRTactics.DestructHyps.
Require MetaRocq.Utils.MRTactics.FindHyp.
Require MetaRocq.Utils.MRTactics.Head.
Require MetaRocq.Utils.MRTactics.SpecializeBy.
Require MetaRocq.Utils.MRTactics.SplitInContext.
Require MetaRocq.Utils.MRTactics.Zeta1.
Require Stdlib.Classes.DecidableClass.
Require Stdlib.Logic.Decidable.
Require Stdlib.Logic.EqdepFacts.
Require Stdlib.Logic.FunctionalExtensionality.
Require Stdlib.Logic.HLevelsBase.
Require Stdlib.Program.Syntax.
Require Stdlib.Sets.Relations_1.
Require Stdlib.Unicode.Utf8_core.
Require Stdlib.Wellfounded.Inverse_Image.
Require Stdlib.micromega.ZifyClasses.
Require Stdlib.setoid_ring.Algebra_syntax.
Require Equations.Init.
Require ExtLib.Structures.Functor.
Require ExtLib.Structures.Monoid.
Require Ltac2.Init.
Require MetaRocq.Utils.MRTactics.UniquePose.
Require Stdlib.BinNums.IntDef.
Require Stdlib.BinNums.PosDef.
Require Stdlib.BinNums.NatDef.
Require Stdlib.Classes.CRelationClasses.
Require Stdlib.Classes.Morphisms.
Require Stdlib.Classes.Morphisms_Prop.
Require Stdlib.Classes.RelationClasses.
Require Stdlib.Floats.FloatOps.
Require Stdlib.Floats.SpecFloat.
Require Stdlib.Floats.PrimFloat.
Require Stdlib.Init.Hexadecimal.
Require Stdlib.Init.Byte.
Require Stdlib.Init.Sumbool.
Require Stdlib.Init.Decimal.
Require Stdlib.Init.Wf.
Require Stdlib.Init.Nat.
Require Stdlib.Lists.ListDef.
Require Stdlib.Logic.Eqdep.
Require Stdlib.Logic.Eqdep_dec.
Require Stdlib.Logic.ProofIrrelevanceFacts.
Require Stdlib.Numbers.BinNums.
Require Stdlib.Numbers.Cyclic.Int63.CarryType.
Require Stdlib.Numbers.Cyclic.Int63.PrimInt63.
Require Stdlib.Numbers.Cyclic.Int63.Sint63Axioms.
Require Stdlib.Numbers.Cyclic.Int63.Uint63Axioms.
Require Stdlib.Program.Basics.
Require Stdlib.Program.Tactics.
Require Stdlib.Program.Utils.
Require Stdlib.Program.Wf.
Require Stdlib.Relations.Relation_Definitions.
Require Stdlib.Setoids.Setoid.
Require Stdlib.Strings.PrimString.
Require Stdlib.Strings.PrimStringAxioms.
Require Stdlib.Unicode.Utf8.
Require Stdlib.Wellfounded.Well_Ordering.
Require Stdlib.extraction.Extraction.
Require Stdlib.ssr.ssreflect.
Require Stdlib.ssr.ssrbool.
Require Equations.Prop.SigmaNotations.
Require Equations.Signature.
Require ExtLib.Structures.Applicative.
Require Ltac2.Message.
Require Ltac2.Std.
Require MetaRocq.Utils.MRTactics.DestructHead.
Require MetaRocq.Utils.MRTactics.SpecializeAllWays.
Require Stdlib.Bool.Bool.
Require Stdlib.Logic.JMeq.
Require Stdlib.Logic.ProofIrrelevance.
Require Stdlib.Relations.Relation_Operators.
Require Stdlib.Wellfounded.Inclusion.
Require Equations.CoreTactics.
Require ExtLib.Structures.Monad.
Require Ltac2.Control.
Require MetaRocq.Utils.MRTactics.GeneralizeOverHoles.
Require Stdlib.Program.Combinators.
Require Stdlib.Relations.Operators_Properties.
Require Stdlib.Wellfounded.Disjoint_Union.
Require Stdlib.Wellfounded.Transitive_Closure.
Require ExtLib.Structures.MonadCont.
Require ExtLib.Structures.MonadExc.
Require ExtLib.Structures.MonadFix.
Require ExtLib.Structures.MonadPlus.
Require ExtLib.Structures.MonadReader.
Require ExtLib.Structures.MonadState.
Require ExtLib.Structures.MonadTrans.
Require ExtLib.Structures.MonadZero.
Require Stdlib.PArith.BinPosDef.
Require Stdlib.Relations.Relations.
Require Stdlib.Wellfounded.Union.
Require Equations.Type.Logic.
Require Ltac2.Ltac1.
Require Stdlib.Program.Equality.
Require Equations.Prop.Logic.
Require Equations.Type.Relation.
Require ExtLib.Structures.MonadWriter.
Require Stdlib.Numbers.NumPrelude.
Require Equations.Type.Relation_Properties.
Require MetaRocq.Utils.MRTactics.InHypUnderBindersDo.
Require MetaRocq.Utils.MRTactics.SpecializeUnderBindersBy.
Require Stdlib.Classes.RelationPairs.
Require Stdlib.Program.WfExtensionality.
Require Stdlib.Wellfounded.Lexicographic_Product.
Require Equations.Prop.Classes.
Require MetaRocq.Utils.MRProd.
Require Stdlib.Structures.Equalities.
Require Equations.Prop.EqDec.
Require Stdlib.Program.Subset.
Require MetaRocq.Utils.MRRelations.
Require Equations.Prop.DepElim.
Require Equations.Prop.FunctionalInduction.
Require ExtLib.Structures.Monads.
Require Stdlib.Structures.Orders.
Require ExtLib.Data.Monads.OptionMonad.
Require Equations.Prop.Constants.
Require Stdlib.Structures.OrdersTac.
Require Stdlib.Structures.OrdersFacts.
Require Stdlib.Structures.GenericMinMax.
Require Stdlib.Program.Program.
Require Stdlib.Numbers.NatInt.NZAxioms.
Require Stdlib.Numbers.NatInt.NZBase.
Require Stdlib.Numbers.NatInt.NZAdd.
Require Stdlib.Numbers.NatInt.NZMul.
Require Stdlib.Numbers.NatInt.NZOrder.
Require Stdlib.Numbers.NatInt.NZAddOrder.
Require Stdlib.Numbers.NatInt.NZMulOrder.
Require Stdlib.Numbers.NatInt.NZDiv.
Require Stdlib.Numbers.NatInt.NZGcd.
Require Stdlib.Numbers.NatInt.NZParity.
Require Stdlib.Numbers.NatInt.NZPow.
Require Stdlib.Numbers.NatInt.NZSqrt.
Require Stdlib.Numbers.NatInt.NZLog.
Require Stdlib.Numbers.NatInt.NZBits.
Require Stdlib.Numbers.Integer.Abstract.ZAxioms.
Require Stdlib.Numbers.Natural.Abstract.NAxioms.
Require Stdlib.Numbers.Integer.Abstract.ZBase.
Require Stdlib.Numbers.Natural.Abstract.NBase.
Require Stdlib.Numbers.Integer.Abstract.ZAdd.
Require Stdlib.Numbers.Natural.Abstract.NAdd.
Require Stdlib.Numbers.Integer.Abstract.ZMul.
Require Stdlib.Numbers.Natural.Abstract.NOrder.
Require Stdlib.Numbers.Integer.Abstract.ZLt.
Require Stdlib.Numbers.Natural.Abstract.NAddOrder.
Require Stdlib.Numbers.Integer.Abstract.ZAddOrder.
Require Stdlib.Numbers.Natural.Abstract.NMulOrder.
Require Stdlib.Numbers.Integer.Abstract.ZMulOrder.
Require Stdlib.Numbers.Natural.Abstract.NSub.
Require Stdlib.Numbers.Integer.Abstract.ZMaxMin.
Require Stdlib.Numbers.Integer.Abstract.ZParity.
Require Stdlib.Numbers.Integer.Abstract.ZSgnAbs.
Require Stdlib.Numbers.Natural.Abstract.NDiv.
Require Stdlib.Numbers.Natural.Abstract.NGcd.
Require Stdlib.Numbers.Natural.Abstract.NMaxMin.
Require Stdlib.Numbers.Natural.Abstract.NParity.
Require Stdlib.Numbers.Natural.Abstract.NSqrt.
Require Stdlib.Numbers.Integer.Abstract.ZDivFloor.
Require Stdlib.Numbers.Integer.Abstract.ZDivTrunc.
Require Stdlib.Numbers.Integer.Abstract.ZGcd.
Require Stdlib.Numbers.Natural.Abstract.NDiv0.
Require Stdlib.Numbers.Natural.Abstract.NPow.
Require Stdlib.Numbers.Integer.Abstract.ZPow.
Require Stdlib.Numbers.Natural.Abstract.NLcm.
Require Stdlib.Numbers.Natural.Abstract.NLog.
Require Stdlib.Numbers.Integer.Abstract.ZBits.
Require Stdlib.Numbers.Integer.Abstract.ZLcm.
Require Stdlib.Numbers.Natural.Abstract.NBits.
Require Stdlib.Numbers.Natural.Abstract.NLcm0.
Require Stdlib.Numbers.Integer.Abstract.ZProperties.
Require Stdlib.Numbers.Natural.Abstract.NProperties.
Require Stdlib.Arith.PeanoNat.
Require Stdlib.Arith.Between.
Require Stdlib.Arith.Compare_dec.
Require Stdlib.Arith.EqNat.
Require Stdlib.Arith.Factorial.
Require Stdlib.Arith.Wf_nat.
Require Stdlib.Arith.Peano_dec.
Require Stdlib.Lists.List.
Require Stdlib.Wellfounded.List_Extension.
Require Stdlib.micromega.Refl.
Require Stdlib.Sorting.Sorted.
Require Stdlib.micromega.Tauto.
Require Stdlib.Lists.ListTactics.
Require Stdlib.Sorting.SetoidList.
Require Stdlib.Structures.DecidableType.
Require Stdlib.Structures.OrderedType.
Require Stdlib.Wellfounded.Lexicographic_Exponentiation.
Require Stdlib.MSets.MSetInterface.
Require Stdlib.PArith.BinPos.
Require Stdlib.Structures.EqualitiesFacts.
Require Stdlib.Structures.OrderedTypeAlt.
Require Stdlib.Structures.OrdersAlt.
Require Stdlib.Arith.Arith_base.
Require Stdlib.FSets.FMapInterface.
Require Stdlib.PArith.POrderedType.
Require Stdlib.PArith.Pnat.
Require Stdlib.Structures.OrdersLists.
Require Stdlib.FSets.FMapList.
Require Stdlib.Vectors.Fin.
Require Stdlib.NArith.BinNatDef.
Require Stdlib.PArith.PArith.
Require Stdlib.Vectors.VectorDef.
Require Stdlib.NArith.BinNat.
Require Stdlib.setoid_ring.BinList.
Require Stdlib.MSets.MSetList.
Require Stdlib.NArith.Ndiv_def.
Require Stdlib.NArith.Ngcd_def.
Require Stdlib.NArith.Nsqrt_def.
Require Stdlib.setoid_ring.Ring_theory.
Require Stdlib.NArith.Nnat.
Require Stdlib.Wellfounded.Wellfounded.
Require Stdlib.Vectors.VectorSpec.
Require Stdlib.ZArith.BinIntDef.
Require Stdlib.Vectors.VectorEq.
Require Stdlib.Vectors.Vector.
Require Stdlib.NArith.NArith_base.
Require Stdlib.Strings.Byte.
Require MetaRocq.Utils.ByteCompare.
Require Stdlib.Strings.Ascii.
Require Stdlib.Vectors.Bvector.
Require Stdlib.Strings.String.
Require Stdlib.NArith.Ndec.
Require Stdlib.Numbers.DecimalString.
Require Stdlib.Numbers.HexadecimalString.
Require Equations.Prop.Subterm.
Require Stdlib.ZArith.BinInt.
Require Equations.Prop.Tactics.
Require Stdlib.ZArith.Int.
Require Stdlib.ZArith.Zcompare.
Require Stdlib.ZArith.Zeven.
Require Stdlib.ZArith.auxiliary.
Require Stdlib.ZArith.Zpow_def.
Require Stdlib.setoid_ring.Ncring.
Require Stdlib.Numbers.Cyclic.Abstract.DoubleType.
Require Stdlib.micromega.Env.
Require Stdlib.micromega.VarMap.
Require Stdlib.micromega.EnvRing.
Require Stdlib.setoid_ring.Ring_polynom.
Require Stdlib.setoid_ring.InitialRing.
Require Stdlib.ZArith.Znat.
Require Stdlib.ZArith.Zorder.
Require Stdlib.setoid_ring.Ncring_polynom.
Require Stdlib.setoid_ring.Ring_tac.
Require Stdlib.ZArith.Zmax.
Require Stdlib.ZArith.Zmin.
Require Stdlib.ZArith.Zminmax.
Require Stdlib.ZArith.Zmisc.
Require Stdlib.omega.OmegaLemmas.
Require Stdlib.setoid_ring.Ncring_initial.
Require Stdlib.setoid_ring.Ring_base.
Require Stdlib.micromega.ZifyInst.
Require Stdlib.setoid_ring.Ncring_tac.
Require Stdlib.setoid_ring.Ring.
Require Stdlib.ZArith.ZArith_dec.
Require Stdlib.micromega.OrderedRing.
Require Stdlib.micromega.Zify.
Require Stdlib.setoid_ring.NArithRing.
Require Stdlib.setoid_ring.ZArithRing.
Require Stdlib.ZArith.Wf_Z.
Require Stdlib.micromega.ZifyBool.
Require Stdlib.omega.PreOmega.
Require Stdlib.setoid_ring.ArithRing.
Require Stdlib.setoid_ring.Cring.
Require Stdlib.ZArith.Zbool.
Require Stdlib.setoid_ring.Integral_domain.
Require Stdlib.ZArith.Zabs.
Require Equations.Prop.NoConfusion.
Require Equations.Prop.EqDecInstances.
Require Stdlib.nsatz.NsatzTactic.
Require Equations.Prop.Loader.
Require Stdlib.NArith.NArith.
Require Stdlib.micromega.RingMicromega.
Require Equations.Prop.Telescopes.
Require Equations.Prop.Equations.
Require Stdlib.ZArith.Zhints.
Require Stdlib.Arith.Arith.
Require Stdlib.micromega.ZMicromega.
Require MetaRocq.Utils.ReflectEq.
Require Stdlib.ZArith.ZArith_base.
Require MetaRocq.Utils.MRCompare.
Require Stdlib.MSets.MSetGenTree.
Require Stdlib.MSets.MSetAVL.
Require Stdlib.ZArith.Zcomplements.
Require Stdlib.ZArith.Zdiv.
Require Stdlib.ZArith.Zpower.
Require Stdlib.micromega.Lia.
Require Stdlib.btauto.Algebra.
Require Stdlib.Structures.OrderedTypeEx.
Require Stdlib.btauto.Reflect.
Require Stdlib.btauto.Btauto.
Require Stdlib.Structures.DecidableTypeEx.
Require Stdlib.FSets.FMapFacts.
Require Stdlib.MSets.MSetFacts.
Require Stdlib.ZArith.ZNsatz.
Require Stdlib.MSets.MSetDecide.
Require Stdlib.ZArith.Zbitwise.
Require MetaRocq.Common.config.
Require Stdlib.micromega.ZArith_hints.
Require Stdlib.MSets.MSetProperties.
Require Stdlib.ZArith.Zdivisibility.
Require Stdlib.ZArith.Zcong.
Require Stdlib.ZArith.Zdiv_facts.
Require Stdlib.ZArith.ZModOffset.
Require Stdlib.ZArith.Znumtheory.
Require Stdlib.ZArith.Zgcd_alt.
Require Stdlib.ZArith.Zpow_facts.
Require Stdlib.ZArith.ZArith.
Require MetaRocq.Utils.MRArith.
Require Stdlib.Numbers.Cyclic.Abstract.CyclicAxioms.
Require Stdlib.FSets.FMapAVL.
Require Stdlib.Numbers.Cyclic.Int63.Uint63.
Require Stdlib.Numbers.Cyclic.Int63.Cyclic63.
Require Stdlib.micromega.ZifyUint63.
Require Stdlib.Numbers.Cyclic.Int63.Ring63.
Require Stdlib.Numbers.Cyclic.Int63.Sint63.
Require MetaRocq.Utils.ByteCompareSpec.
Require MetaRocq.Utils.bytestring.
Require Stdlib.Strings.PString.
Require Stdlib.FSets.FMapFullAVL.
Require MetaRocq.Utils.MRPrelude.
Require MetaRocq.Utils.MRReflect.
Require MetaRocq.Utils.MRList.
Require MetaRocq.Utils.MROption.
Require MetaRocq.Utils.MRString.
Require MetaRocq.Utils.All_Forall.
Require MetaRocq.Utils.MRMSets.
Require MetaRocq.Utils.monad_utils.
Require MetaRocq.Common.Primitive.
Require MetaRocq.Utils.Show.
Require MetaRocq.Utils.MRUtils.
Require MetaRocq.Utils.utils.
Require MetaRocq.Utils.MRFSets.
Require MetaRocq.Common.Kernames.

Module Export AdmitTactic.
Module Import LocalFalse.
Inductive False : Prop := .
End LocalFalse.
Axiom proof_admitted : False.
Import Coq.Init.Ltac.
Tactic Notation "admit" := abstract case proof_admitted.
End AdmitTactic.

Module MetaRocq_DOT_Common_DOT_BasicAst_WRAPPED.
Module Export BasicAst.

Import Stdlib.ssr.ssreflect Stdlib.Classes.Morphisms Stdlib.Structures.Orders Stdlib.Setoids.Setoid.
Import MetaRocq.Utils.utils.
Export MetaRocq.Common.Kernames.
Import Equations.Prop.Equations.


Inductive name : Set :=
| nAnon
| nNamed (_ : ident).
Derive NoConfusion EqDec for name.

Inductive relevance : Set := Relevant | Irrelevant.
Derive NoConfusion EqDec for relevance.


Record binder_annot (A : Type) := mkBindAnn { binder_name : A; binder_relevance : relevance }.


Arguments mkBindAnn {_}.
Arguments binder_name {_}.
Arguments binder_relevance {_}.

Derive NoConfusion for binder_annot.

#[global] Instance eqdec_binder_annot (A : Type) (e : Classes.EqDec A) : Classes.EqDec (binder_annot A).
Admitted.

Definition map_binder_annot {A B} (f : A -> B) (b : binder_annot A) : binder_annot B :=
  {| binder_name := f b.(binder_name); binder_relevance := b.(binder_relevance) |}.

Definition eq_binder_annot {A B} (b : binder_annot A) (b' : binder_annot B) : Prop :=
  b.(binder_relevance) = b'.(binder_relevance).


Definition aname := binder_annot name.
#[global] Instance anqme_eqdec : Classes.EqDec aname := _.

Definition eqb_binder_annot {A} (b b' : binder_annot A) : bool :=
  match Classes.eq_dec b.(binder_relevance) b'.(binder_relevance) with
  | left _ => true
  | right _ => false
  end.

Definition string_of_name (na : name) :=
  match na with
  | nAnon => "_"
  | nNamed n => n
  end.

Definition string_of_relevance (r : relevance) :=
  match r with
  | Relevant => "Relevant"
  | Irrelevant => "Irrelevant"
  end.


Inductive cast_kind : Set :=
| VmCast
| NativeCast
| Cast.
Derive NoConfusion EqDec for cast_kind.

Record case_info := mk_case_info {
  ci_ind : inductive;
  ci_npar : nat;
  
  ci_relevance : relevance }.
Derive NoConfusion EqDec for case_info.

Definition string_of_case_info ci :=
  "(" ^ string_of_inductive ci.(ci_ind) ^ "," ^
  string_of_nat ci.(ci_npar) ^ "," ^
  
  string_of_relevance ci.(ci_relevance) ^ ")".

Inductive recursivity_kind :=
  | Finite 
  | CoFinite 
  | BiFinite .
Derive NoConfusion EqDec for recursivity_kind.


Inductive conv_pb :=
  | Conv
  | Cumul.
Derive NoConfusion EqDec for conv_pb.

Definition conv_pb_leqb (pb1 pb2 : conv_pb) : bool
  := match pb1, pb2 with
     | Cumul, Conv => false
     | _, _ => true
     end.


Definition fresh_evar_id : nat.
Admitted.


Record def term := mkdef {
  dname : aname; 
  dtype : term;
  dbody : term; 
  rarg  : nat   }.

Arguments dname {term} _.
Arguments dtype {term} _.
Arguments dbody {term} _.
Arguments rarg {term} _.


Derive NoConfusion for def.
#[global] Instance def_eq_dec {A} : Classes.EqDec A -> Classes.EqDec (def A).
Admitted.

Definition string_of_def {A} (f : A -> string) (def : def A) :=
  "(" ^ string_of_name (binder_name (dname def))
      ^ "," ^ string_of_relevance (binder_relevance (dname def))
      ^ "," ^ f (dtype def)
      ^ "," ^ f (dbody def)
      ^ "," ^ string_of_nat (rarg def) ^ ")".

Definition print_def {A} (f : A -> string) (g : A -> string) (def : def A) :=
  string_of_name (binder_name (dname def)) ^ " { struct " ^ string_of_nat (rarg def) ^ " }" ^
                 " : " ^ f (dtype def) ^ " := " ^ nl ^ g (dbody def).

Definition map_def {A B} (tyf bodyf : A -> B) (d : def A) :=
  {| dname := d.(dname); dtype := tyf d.(dtype); dbody := bodyf d.(dbody); rarg := d.(rarg) |}.

Lemma map_dtype {A B} (f : A -> B) (g : A -> B) (d : def A) :
  f (dtype d) = dtype (map_def f g d).
Admitted.

Lemma map_dbody {A B} (f : A -> B) (g : A -> B) (d : def A) :
  g (dbody d) = dbody (map_def f g d).
Admitted.

Lemma map_dname {A B} (f : A -> B) (g : A -> B) (d : def A) :
  dname d = dname (map_def f g d).
Admitted.

Definition mfixpoint term := list (def term).

Definition test_def {A} (tyf bodyf : A -> bool) (d : def A) :=
  tyf d.(dtype) && bodyf d.(dbody).

Definition tFixProp {A} (P P' : A -> Type) (m : mfixpoint A) :=
  All (fun x : def A => P x.(dtype) * P' x.(dbody))%type m.

Lemma map_def_map_def {A B C} (f f' : B -> C) (g g' : A -> B) (d : def A) :
  map_def f f' (map_def g g' d) = map_def (f ∘ g) (f' ∘ g') d.
Admitted.

Lemma compose_map_def {A B C} (f f' : B -> C) (g g' : A -> B) :
  (map_def f f') ∘ (map_def g g') = map_def (f ∘ g) (f' ∘ g').
Admitted.

Lemma map_def_id {t} x : map_def (@id t) (@id t) x = id x.
Admitted.

Create Rewrite HintDb map.
#[global] Hint Rewrite @map_def_id @map_id : map.

Lemma map_def_spec {A B} (P P' : A -> Type) (f f' g g' : A -> B) (x : def A) :
  P' x.(dbody) -> P x.(dtype) -> (forall x, P x -> f x = g x) ->
  (forall x, P' x -> f' x = g' x) ->
  map_def f f' x = map_def g g' x.
Admitted.

Create HintDb all.
#[global] Hint Extern 10 (_ < _)%nat => lia : all.
#[global] Hint Extern 10 (_ <= _)%nat => lia : all.
#[global] Hint Extern 10 (@eq nat _ _) => lia : all.
#[global] Hint Extern 0 (_ = _) => progress f_equal : all.
#[global] Hint Unfold on_snd snd : all.

Lemma on_snd_eq_id_spec {A B} (f : B -> B) (x : A * B) :
  f (snd x) = snd x <->
  on_snd f x = x.
Admitted.
#[global] Hint Resolve -> on_snd_eq_id_spec : all.
#[global] Hint Resolve -> on_snd_eq_spec : all.

Lemma map_def_eq_spec {A B} (f f' g g' : A -> B) (x : def A) :
  f (dtype x) = g (dtype x) ->
  f' (dbody x) = g' (dbody x) ->
  map_def f f' x = map_def g g' x.
Admitted.
#[global] Hint Resolve map_def_eq_spec : all.

Lemma map_def_id_spec {A} (f f' : A -> A) (x : def A) :
  f (dtype x) = (dtype x) ->
  f' (dbody x) = (dbody x) ->
  map_def f f' x = x.
Admitted.
#[global] Hint Resolve map_def_id_spec : all.

Lemma tfix_map_spec {A B} {P P' : A -> Type} {l} {f f' g g' : A -> B} :
  tFixProp P P' l -> (forall x, P x -> f x = g x) ->
  (forall x, P' x -> f' x = g' x) ->
  map (map_def f f') l = map (map_def g g') l.
Admitted.

Record judgment_ {universe Term} := Judge {
  j_term : option Term;
  j_typ : Term;
  j_univ : option universe;
  j_rel : option relevance;
}.
Arguments judgment_ : clear implicits.
Arguments Judge {universe Term} _ _ _.


Definition judgment_map {univ T A} (f: T -> A) (j : judgment_ univ T) :=
  Judge (option_map f (j_term j)) (f (j_typ j)) (j_univ j) (j_rel j).

Section Contexts.
  Context {term : Type}.
  

  Record context_decl := mkdecl {
    decl_name : aname ;
    decl_body : option term ;
    decl_type : term
  }.
  Derive NoConfusion for context_decl.
End Contexts.


Arguments context_decl : clear implicits.

Abbreviation Typ typ := (Judge None typ None None).
Abbreviation TypRel typ rel := (Judge None typ None (Some rel)).
Abbreviation TermTyp tm ty := (Judge (Some tm) ty None None).
Abbreviation TermTypRel tm ty rel := (Judge (Some tm) ty None (Some rel)).
Abbreviation TermoptTyp tm typ := (Judge tm typ None None).
Abbreviation TermoptTypRel tm typ rel := (Judge tm typ None (Some rel)).
Abbreviation TypUniv ty u := (Judge None ty (Some u) None).
Abbreviation TypUnivRel ty u rel := (Judge None ty (Some u) (Some rel)).
Abbreviation TermTypUniv tm ty u := (Judge (Some tm) ty (Some u) None).

Abbreviation j_vass na ty := (TypRel ty na.(binder_relevance)).
Abbreviation j_vass_s na ty s := (TypUnivRel ty s na.(binder_relevance)).
Abbreviation j_vdef na b ty := (TermTypRel b ty na.(binder_relevance)).
Abbreviation j_decl d := (TermoptTypRel (decl_body d) (decl_type d) (decl_name d).(binder_relevance)).
Abbreviation j_decl_s d s := (Judge (decl_body d) (decl_type d) s (Some (decl_name d).(binder_relevance))).

Definition map_decl {term term'} (f : term -> term') (d : context_decl term) : context_decl term' :=
  {| decl_name := d.(decl_name);
     decl_body := option_map f d.(decl_body);
     decl_type := f d.(decl_type) |}.

Lemma compose_map_decl {term term' term''} (g : term -> term') (f : term' -> term'') x :
  map_decl f (map_decl g x) = map_decl (f ∘ g) x.
Admitted.

Lemma map_decl_ext {term term'} (f g : term -> term') x : (forall x, f x = g x) -> map_decl f x = map_decl g x.
Admitted.

#[global] Instance map_decl_proper {term term'} : Proper (`=1` ==> Logic.eq ==> Logic.eq) (@map_decl term term').
Admitted.

#[global] Instance map_decl_pointwise {term term'} : Proper (`=1` ==> `=1`) (@map_decl term term').
Admitted.


Definition map_context {term term'} (f : term -> term') (c : list (context_decl term)) :=
  List.map (map_decl f) c.

#[global] Instance map_context_proper {term term'} : Proper (`=1` ==> Logic.eq ==> Logic.eq) (@map_context term term').
Admitted.

Lemma map_context_length {term term'} (f : term -> term') l : #|map_context f l| = #|l|.
Admitted.
#[global] Hint Rewrite @map_context_length : len.

Definition test_decl {term} (f : term -> bool) (d : context_decl term) : bool :=
  option_default f d.(decl_body) true && f d.(decl_type).

#[global] Instance test_decl_proper {term} : Proper (`=1` ==> Logic.eq ==> Logic.eq) (@test_decl term).
Admitted.

Definition snoc {A} (Γ : list A) (d : A) := d :: Γ.

Notation " Γ ,, d " := (snoc Γ d) (at level 20, d at next level).

Definition app_context {A} (Γ Γ': list A) := Γ' ++ Γ.

Notation "Γ ,,, Γ'" := (app_context Γ Γ') (at level 25, Γ' at next level, left associativity).

Lemma app_context_nil_l {T} Γ : [] ,,, Γ = Γ :> list T.
Admitted.

Lemma app_context_assoc {T} Γ Γ' Γ'' : Γ ,,, (Γ' ,,, Γ'') = Γ ,,, Γ' ,,, Γ'' :> list T.
Admitted.

Lemma app_context_cons {T} Γ Γ' A : Γ ,,, (Γ' ,, A) = (Γ ,,, Γ') ,, A :> list T.
Admitted.

Lemma app_context_push {T} Γ Δ Δ' d : (Γ ,,, Δ ,,, Δ') ,, d = (Γ ,,, Δ ,,, (Δ' ,, d)) :> list T.
Admitted.

Lemma snoc_app_context {T Γ Δ d} : (Γ ,,, (d :: Δ)) =  (Γ ,,, Δ) ,,, [d] :> list T.
Admitted.

Lemma app_context_length {T} (Γ Γ' : list T) : #|Γ ,,, Γ'| = #|Γ'| + #|Γ|.
Admitted.
#[global] Hint Rewrite @app_context_length : len.

Lemma nth_error_app_context_ge {T} v Γ Γ' :
  #|Γ'| <= v -> nth_error (Γ ,,, Γ') v = nth_error Γ (v - #|Γ'|) :> option T.
Admitted.

Lemma nth_error_app_context_lt {T} v Γ Γ' :
  v < #|Γ'| -> nth_error (Γ ,,, Γ') v = nth_error Γ' v :> option T.
Admitted.

Definition ondecl {A} (P : A -> Type) (d : context_decl A) :=
  option_default P d.(decl_body) unit × P d.(decl_type).

Abbreviation onctx P := (All (ondecl P)).

Section ContextMap.
  Context {term term' : Type} (f : nat -> term -> term').

  Fixpoint mapi_context (c : list (context_decl term)) : list (context_decl term') :=
    match c with
    | d :: Γ => map_decl (f #|Γ|) d :: mapi_context Γ
    | [] => []
  end.
End ContextMap.

#[global] Instance mapi_context_proper {term term'} : Proper (`=2` ==> Logic.eq ==> Logic.eq) (@mapi_context term term').
Admitted.

Lemma mapi_context_length {term} (f : nat -> term -> term) l : #|mapi_context f l| = #|l|.
Admitted.
#[global] Hint Rewrite @mapi_context_length : len.

Section ContextTest.
  Context {term : Type} (f : term -> bool).

  Fixpoint test_context (c : list (context_decl term)) : bool :=
    match c with
    | d :: Γ => test_context Γ && test_decl f d
    | [] => true
    end.
End ContextTest.

#[global] Instance test_context_proper {term} : Proper (`=1` ==> Logic.eq ==> Logic.eq) (@test_context term).
Admitted.

Section ContextTestK.
  Context {term : Type} (f : nat -> term -> bool) (k : nat).

  Fixpoint test_context_k (c : list (context_decl term)) : bool :=
    match c with
    | d :: Γ => test_context_k Γ && test_decl (f (#|Γ| + k)) d
    | [] => true
    end.
End ContextTestK.

#[global] Instance test_context_k_proper {term} : Proper (`=1` ==> Logic.eq ==> Logic.eq ==> Logic.eq) (@test_context_k term).
Admitted.

Section Contexts.
  Context {term term' term'' : Type}.
  Abbreviation context term := (list (context_decl term)).

  Lemma test_decl_impl (f g : term -> bool) x : (forall x, f x -> g x) ->
    test_decl f x -> test_decl g x.
Admitted.

  Definition onctx_k (P : nat -> term -> Type) k (ctx : context term) :=
    Alli (fun i d => ondecl (P (Nat.pred #|ctx| - i + k)) d) 0 ctx.

  Lemma ondeclP {P : term -> Type} {p : term -> bool} {d : context_decl term} :
    (forall x, reflectT (P x) (p x)) ->
    reflectT (ondecl P d) (test_decl p d).
Admitted.

  Lemma onctxP {p : term -> bool} {ctx : context term} :
    reflectT (onctx p ctx) (test_context p ctx).
Admitted.

  Lemma map_decl_type (f : term -> term') decl : f (decl_type decl) = decl_type (map_decl f decl).
Admitted.

  Lemma map_decl_body (f : term -> term') decl : option_map f (decl_body decl) = decl_body (map_decl f decl).
Admitted.

  Lemma map_decl_id : @map_decl term term id =1 id.
Admitted.

  Lemma option_map_decl_body_map_decl (f : term -> term') x :
    option_map decl_body (option_map (map_decl f) x) =
    option_map (option_map f) (option_map decl_body x).
Admitted.

  Lemma option_map_decl_type_map_decl (f : term -> term') x :
    option_map decl_type (option_map (map_decl f) x) =
    option_map f (option_map decl_type x).
Admitted.

  Definition fold_context_k (f : nat -> term -> term') Γ :=
    List.rev (mapi (fun k' decl => map_decl (f k') decl) (List.rev Γ)).

  Arguments fold_context_k f Γ%_list_scope.

  Lemma fold_context_k_alt f Γ :
    fold_context_k f Γ =
    mapi (fun k' d => map_decl (f (Nat.pred (length Γ) - k')) d) Γ.
Admitted.

  Lemma mapi_context_fold f Γ :
    mapi_context f Γ = fold_context_k f Γ.
Admitted.

  Lemma fold_context_k_tip f d : fold_context_k f [d] = [map_decl (f 0) d].
Admitted.

  Lemma fold_context_k_length f Γ : length (fold_context_k f Γ) = length Γ.
Admitted.

  Lemma fold_context_k_snoc0 f Γ d :
    fold_context_k f (d :: Γ) = fold_context_k f Γ ,, map_decl (f (length Γ)) d.
Admitted.

  Lemma fold_context_k_app f Γ Δ :
    fold_context_k f (Δ ++ Γ)
    = fold_context_k (fun k => f (length Γ + k)) Δ ++ fold_context_k f Γ.
Admitted.

  Local Set Keyed Unification.

  Equations mapi_context_In (ctx : context term) (f : nat -> forall (x : context_decl term), In x ctx -> context_decl term) : context term :=
  mapi_context_In nil _ := nil;
  mapi_context_In (cons x xs) f := cons (f #|xs| x _) (mapi_context_In xs (fun n x H => f n x _)).

  Lemma mapi_context_In_spec (f : nat -> term -> term) (ctx : context term) :
    mapi_context_In ctx (fun n (x : context_decl term) (_ : In x ctx) => map_decl (f n) x) =
    mapi_context f ctx.
Admitted.

  Equations fold_context_In (ctx : context term) (f : context term -> forall (x : context_decl term), In x ctx -> context_decl term) : context term :=
  fold_context_In nil _ := nil;
  fold_context_In (cons x xs) f :=
    let xs' := fold_context_In xs (fun n x H => f n x _) in
    cons (f xs' x _) xs'.

  Equations fold_context (f : context term -> context_decl term -> context_decl term) (ctx : context term) : context term :=
    fold_context f nil := nil;
    fold_context f (cons x xs) :=
      let xs' := fold_context f xs in
      cons (f xs' x ) xs'.

  Lemma fold_context_length f Γ : #|fold_context f Γ| = #|Γ|.
Admitted.

  Lemma fold_context_In_spec (f : context term -> context_decl term -> context_decl term) (ctx : context term) :
    fold_context_In ctx (fun n (x : context_decl term) (_ : In x ctx) => f n x) =
    fold_context f ctx.
Admitted.

  #[global]
  Instance fold_context_Proper : Proper (`=2` ==> `=1`) fold_context.
Admitted.

  
  Definition forget_types (c : list (BasicAst.context_decl term)) : list aname :=
    map decl_name c.

End Contexts.
#[global] Hint Rewrite @fold_context_length @fold_context_k_length : len.

Section Contexts.
  Context {term term' term'' : Type}.
  Abbreviation context term := (list (context_decl term)).

  Lemma fold_context_k_id (x : context term) : fold_context_k (fun i x => x) x = x.
Admitted.

  Lemma fold_context_k_compose (f : nat -> term' -> term) (g : nat -> term'' -> term') Γ :
    fold_context_k f (fold_context_k g Γ) =
    fold_context_k (fun i => f i ∘ g i) Γ.
Admitted.

  Lemma fold_context_k_ext (f g : nat -> term' -> term) Γ :
    f =2 g ->
    fold_context_k f Γ = fold_context_k g Γ.
Admitted.

  #[global] Instance fold_context_k_proper : Proper (pointwise_relation nat (pointwise_relation _ Logic.eq) ==> Logic.eq ==> Logic.eq)
    (@fold_context_k term' term).
Admitted.

  Lemma alli_fold_context_k_prop (f : nat -> context_decl term -> bool) (g : nat -> term' -> term) ctx :
    alli f 0 (fold_context_k g ctx) =
    alli (

[...]

'
  | tProj p c => closedn k c
  | tFix mfix idx =>
    let k' := List.length mfix + k in
    List.forallb (test_def (closedn k) (closedn k')) mfix
  | tCoFix mfix idx =>
    let k' := List.length mfix + k in
    List.forallb (test_def (closedn k) (closedn k')) mfix
  | tPrim p => test_prim (closedn k) p
  | _ => true
  end.

Fixpoint noccur_between k n (t : term) : bool :=
  match t with
  | tRel i => Nat.ltb i k || Nat.leb (k + n) i
  | tEvar ev args => List.forallb (noccur_between k n) args
  | tLambda _ T M | tProd _ T M => noccur_between k n T && noccur_between (S k) n M
  | tApp u v => noccur_between k n u && noccur_between k n v
  | tLetIn na b t b' => noccur_between k n b && noccur_between k n t && noccur_between (S k) n b'
  | tCase ind p c brs =>
    let p' := test_predicate_k (fun _ => true) (fun k' => noccur_between k' n) k p in
    let brs' := test_branches_k p (fun k => noccur_between k n) k brs in
    p' && noccur_between k n c && brs'
  | tProj p c => noccur_between k n c
  | tFix mfix idx =>
    let k' := List.length mfix + k in
    List.forallb (test_def (noccur_between k n) (noccur_between k' n)) mfix
  | tCoFix mfix idx =>
    let k' := List.length mfix + k in
    List.forallb (test_def (noccur_between k n) (noccur_between k' n)) mfix
  | tPrim p => test_prim (noccur_between k n) p
  | _ => true
  end.
#[global]
Instance subst_instance_constr : UnivSubst term.
Admitted.

Module PCUICTerm <: Term.

  Definition term := term.

  Definition tRel := tRel.
  Definition tSort := tSort.
  Definition tProd := tProd.
  Definition tLambda := tLambda.
  Definition tLetIn := tLetIn.
  Definition tInd := tInd.
  Definition tProj := tProj.
  Definition mkApps := mkApps.

  Definition lift := lift.
  Definition subst := subst.
  Definition closedn := closedn.
  Definition noccur_between := noccur_between.
  Definition subst_instance_constr := subst_instance.
End PCUICTerm.

Module PCUICEnvironment := Environment PCUICTerm.
Export PCUICEnvironment.

Fixpoint destArity Γ (t : term) :=
  match t with
  | tProd na t b => destArity (Γ ,, vass na t) b
  | tLetIn na b b_ty b' => destArity (Γ ,, vdef na b b_ty) b'
  | tSort s => Some (Γ, s)
  | _ => None
  end.

Definition inds ind u (l : list one_inductive_body) :=
  let fix aux n :=
      match n with
      | 0 => []
      | S n => tInd (mkInd ind n) u :: aux n
      end
  in aux (List.length l).

Module PCUICTermUtils <: TermUtils PCUICTerm PCUICEnvironment.

Definition destArity := destArity.
Definition inds := inds.

End PCUICTermUtils.

Module PCUICEnvTyping := EnvironmentTyping.EnvTyping PCUICTerm PCUICEnvironment PCUICTermUtils.

Module PCUICConversion := EnvironmentTyping.Conversion PCUICTerm PCUICEnvironment PCUICTermUtils PCUICEnvTyping.

Module PCUICLookup := EnvironmentTyping.Lookup PCUICTerm PCUICEnvironment.
Include PCUICLookup.

Module PCUICGlobalMaps := EnvironmentTyping.GlobalMaps
  PCUICTerm
  PCUICEnvironment
  PCUICTermUtils
  PCUICEnvTyping
  PCUICConversion
  PCUICLookup
.
Include PCUICGlobalMaps.

Fixpoint decompose_app_rec (t : term) l :=
  match t with
  | tApp f a => decompose_app_rec f (a :: l)
  | _ => (t, l)
  end.

Definition decompose_app t := decompose_app_rec t [].

Definition isConstruct_app t :=
  match fst (decompose_app t) with
  | tConstruct _ _ _ => true
  | _ => false
  end.
Fixpoint decompose_prod_assum (Γ : context) (t : term) : context * term.
Admitted.

Coercion ci_ind : case_info >-> inductive.

Definition ind_predicate_context ind mdecl idecl : context :=
  let ictx := (expand_lets_ctx mdecl.(ind_params) idecl.(ind_indices)) in
  let indty := mkApps (tInd ind (abstract_instance mdecl.(ind_universes)))
    (to_extended_list (smash_context [] mdecl.(ind_params) ,,, ictx)) in
  let inddecl :=
    {| decl_name :=
      {| binder_name := nNamed (ind_name idecl); binder_relevance := idecl.(ind_relevance) |};
       decl_body := None;
       decl_type := indty |}
  in (inddecl :: ictx).

Definition inst_case_context params puinst (pctx : context) :=
  subst_context (List.rev params) 0 (subst_instance puinst pctx).

Definition inst_case_predicate_context (p : predicate term) :=
  inst_case_context p.(pparams) p.(puinst) p.(pcontext).

Definition inst_case_branch_context (p : predicate term) (br : branch term) :=
  inst_case_context p.(pparams) p.(puinst) br.(bcontext).

Definition iota_red npar p args br :=
  subst (List.rev (List.skipn npar args)) 0
    (expand_lets (inst_case_branch_context p br) (bbody br)).

Definition pre_case_predicate_context_gen ind mdecl idecl params puinst : context :=
  inst_case_context params puinst (ind_predicate_context ind mdecl idecl).

Definition case_predicate_context_gen ind mdecl idecl params puinst pctx :=
  map2 set_binder_name pctx (pre_case_predicate_context_gen ind mdecl idecl params puinst).

Definition case_predicate_context ind mdecl idecl p : context :=
  case_predicate_context_gen ind mdecl idecl p.(pparams) p.(puinst) (forget_types p.(pcontext)).

Definition cstr_branch_context ind mdecl cdecl : context :=
  expand_lets_ctx mdecl.(ind_params)
    (subst_context (inds (inductive_mind ind) (abstract_instance mdecl.(ind_universes))
       mdecl.(ind_bodies)) #|mdecl.(ind_params)|
      cdecl.(cstr_args)).

Definition pre_case_branch_context_gen ind mdecl cdecl params puinst : context :=
  inst_case_context params puinst (cstr_branch_context ind mdecl cdecl).

Definition case_branch_context_gen ind mdecl params puinst pctx cdecl :=
  map2 set_binder_name pctx (pre_case_branch_context_gen ind mdecl cdecl params puinst).

Definition case_branch_type_gen ind mdecl (idecl : one_inductive_body) params puinst bctx ptm i cdecl : context * term :=
  let cstr := tConstruct ind i puinst in
  let args := to_extended_list cdecl.(cstr_args) in
  let cstrapp := mkApps cstr (map (lift0 #|cdecl.(cstr_args)|) params ++ args) in
  let brctx := case_branch_context_gen ind mdecl params puinst bctx cdecl in
  let upars := subst_instance puinst mdecl.(ind_params) in
  let indices :=
    (map (subst (List.rev params) #|cdecl.(cstr_args)|)
      (map (expand_lets_k upars #|cdecl.(cstr_args)|)
        (map (subst (inds (inductive_mind ind) puinst mdecl.(ind_bodies))
                    (#|mdecl.(ind_params)| + #|cdecl.(cstr_args)|))
          (map (subst_instance puinst) cdecl.(cstr_indices))))) in
  let ty := mkApps (lift0 #|cdecl.(cstr_args)| ptm) (indices ++ [cstrapp]) in
  (brctx, ty).

Definition case_branch_type ind mdecl idecl p (b : branch term) ptm i cdecl : context * term :=
  case_branch_type_gen ind mdecl idecl p.(pparams) p.(puinst) (forget_types b.(bcontext)) ptm i cdecl.

Definition idecl_binder idecl :=
  {| decl_name :=
    {| binder_name := nNamed idecl.(ind_name);
        binder_relevance := idecl.(ind_relevance) |};
     decl_body := None;
     decl_type := idecl.(ind_type) |}.

Definition wf_predicate_gen mdecl idecl (pparams : list term) (pcontext : list aname) : Prop :=
  let decl := idecl_binder idecl in
  (#|pparams| = mdecl.(ind_npars)) /\
  (Forall2 (fun na decl => eq_binder_annot na decl.(decl_name))
    pcontext (decl :: idecl.(ind_indices))).

Definition wf_predicate mdecl idecl (p : predicate term) : Prop :=
  wf_predicate_gen mdecl idecl p.(pparams) (forget_types p.(pcontext)).

Definition wf_branch_gen cdecl (bctx : list aname) : Prop :=
  (Forall2 (fun na decl => eq_binder_annot na decl.(decl_name))
    bctx cdecl.(cstr_args)).

Definition wf_branch cdecl (b : branch term) : Prop :=
  wf_branch_gen cdecl (forget_types b.(bcontext)).

Definition wf_branches idecl (brs : list (branch term)) : Prop :=
  Forall2 wf_branch idecl.(ind_ctors) brs.

Definition fix_subst (l : mfixpoint term) :=
  let fix aux n :=
      match n with
      | 0 => []
      | S n => tFix l n :: aux n
      end
  in aux (List.length l).

Definition unfold_fix (mfix : mfixpoint term) (idx : nat) :=
  match List.nth_error mfix idx with
  | Some d => Some (d.(rarg), subst0 (fix_subst mfix) d.(dbody))
  | None => None
  end.

Definition cofix_subst (l : mfixpoint term) :=
  let fix aux n :=
      match n with
      | 0 => []
      | S n => tCoFix l n :: aux n
      end
  in aux (List.length l).

Definition unfold_cofix (mfix : mfixpoint term) (idx : nat) :=
  match List.nth_error mfix idx with
  | Some d => Some (d.(rarg), subst0 (cofix_subst mfix) d.(dbody))
  | None => None
  end.

Definition is_constructor n ts :=
  match List.nth_error ts n with
  | Some a => isConstruct_app a
  | None => false
  end.
Definition cmp_universe_instance (cmp_univ : Universe.t -> Universe.t -> Prop) : Instance.t -> Instance.t -> Prop.
Admitted.

Definition cmp_universe_variance (cmp_univ : conv_pb -> Universe.t -> Universe.t -> Prop) pb v u u' :=
  match v with
  | Variance.Irrelevant => True
  | Variance.Covariant => on_rel (cmp_univ pb) Universe.make' u u'
  | Variance.Invariant => on_rel (cmp_univ Conv) Universe.make' u u'
  end.

Definition cmp_universe_instance_variance cmp_univ pb v u u' :=
  Forall3 (cmp_universe_variance cmp_univ pb) v u u'.

Definition global_variance_gen lookup gr napp :=
  match gr with
  | IndRef ind =>
    match lookup_inductive_gen lookup ind with
    | Some (mdecl, idecl) =>
      match destArity [] idecl.(ind_type) with
      | Some (ctx, _) => if (context_assumptions ctx) <=? napp then
          match mdecl.(ind_variance) with
          | Some var => Variance var
          | None => AllEqual
          end
        else AllEqual
      | None => AllEqual
      end
    | None => AllEqual
    end
  | ConstructRef ind k =>
    match lookup_constructor_gen lookup ind k with
    | Some (mdecl, idecl, cdecl) =>
      if (cdecl.(cstr_arity) + mdecl.(ind_npars))%nat <=? napp then

        AllIrrelevant
      else AllEqual
    | _ => AllEqual
    end
  | _ => AllEqual
  end.

Definition cmp_opt_variance cmp_univ pb v :=
  match v with
  | AllEqual => cmp_universe_instance (cmp_univ Conv)
  | AllIrrelevant => fun l l' => #|l| = #|l'|
  | Variance v => fun u u' => cmp_universe_instance (cmp_univ Conv) u u' \/ cmp_universe_instance_variance cmp_univ pb v u u'
  end.

Definition cmp_global_instance_gen Σ cmp_universe pb gr napp :=
  cmp_opt_variance cmp_universe pb (global_variance_gen Σ gr napp).

Abbreviation cmp_global_instance Σ := (cmp_global_instance_gen (lookup_env Σ)).

Inductive eq_decl_upto_names : context_decl -> context_decl -> Type :=
  | compare_vass {na na' T} :
    eq_binder_annot na na' -> eq_decl_upto_names (vass na T) (vass na' T)
  | compare_vdef {na na' b T} :
    eq_binder_annot na na' -> eq_decl_upto_names (vdef na b T) (vdef na' b T).

Abbreviation eq_context_upto_names := (All2 eq_decl_upto_names).

Inductive context_subst : context -> list term -> list term -> Type :=
| context_subst_nil : context_subst [] [] []
| context_subst_ass Γ args s na t a :
    context_subst Γ args s ->
    context_subst (vass na t :: Γ) (args ++ [a]) (a :: s)
| context_subst_def Γ args s na b t :
    context_subst Γ args s ->
    context_subst (vdef na b t :: Γ) args (subst s 0 b :: s).
Import Stdlib.ssr.ssrbool.

Definition shiftnP k p i :=
  (i <? k) || p (i - k).
Fixpoint on_free_vars (p : nat -> bool) (t : term) : bool.
Admitted.

Definition on_free_vars_decl P d :=
  test_decl (on_free_vars P) d.

Definition on_free_vars_ctx P ctx :=
  alli (fun k => (on_free_vars_decl (shiftnP k P))) 0 (List.rev ctx).

Abbreviation is_open_term Γ := (on_free_vars (shiftnP #|Γ| xpred0)).
Abbreviation is_closed_context := (on_free_vars_ctx xpred0).
Import MetaRocq.Common.config.

Implicit Types (cf : checker_flags).

Definition cumul_predicate (cumul : context -> term -> term -> Type) cumul_universe Γ p p' :=
  All2 (cumul Γ) p.(pparams) p'.(pparams) ×
  cmp_universe_instance cumul_universe p.(puinst) p'.(puinst) ×
  eq_context_upto_names p.(pcontext) p'.(pcontext) ×
  cumul (Γ ,,, inst_case_predicate_context p) p.(preturn) p'.(preturn).

Definition cumul_branch (cumul_term : context -> term -> term -> Type) Γ p br br' :=
  eq_context_upto_names br.(bcontext) br'.(bcontext) ×
  cumul_term (Γ ,,, inst_case_branch_context p br) br.(bbody) br'.(bbody).

Definition cumul_branches cumul_term Γ p brs brs' := All2 (cumul_branch cumul_term Γ p) brs brs'.

Definition cumul_mfixpoint (cumul_term : context -> term -> term -> Type) Γ mfix mfix' :=
  All2 (fun d d' =>
    cumul_term Γ d.(dtype) d'.(dtype) ×
    cumul_term (Γ ,,, fix_context mfix) d.(dbody) d'.(dbody) ×
    d.(rarg) = d'.(rarg) ×
    eq_binder_annot d.(dname) d'.(dname)
  ) mfix mfix'.

Reserved Notation " Σ ;;; Γ ⊢ t ≤s[ pb ] u" (at level 50, Γ, t, u at next level,
  format "Σ  ;;;  Γ  ⊢  t  ≤s[ pb ]  u").

Definition cumul_Ind_univ {cf} (Σ : global_env_ext) pb i napp :=
  cmp_global_instance Σ (compare_universe Σ) pb (IndRef i) napp.

Definition cumul_Construct_univ {cf} (Σ : global_env_ext) pb  i k napp :=
  cmp_global_instance Σ (compare_universe Σ) pb (ConstructRef i k) napp.
Inductive cumulSpec0 {cf : checker_flags} (Σ : global_env_ext) Γ (pb : conv_pb) : term -> term -> Type :=

| cumul_Trans : forall t u v,
    is_closed_context Γ -> is_open_term Γ u ->
    Σ ;;; Γ ⊢ t ≤s[pb] u ->
    Σ ;;; Γ ⊢ u ≤s[pb] v ->
    Σ ;;; Γ ⊢ t ≤s[pb] v

| cumul_Sym : forall t u,
    Σ ;;; Γ ⊢ t ≤s[Conv] u ->
    Σ ;;; Γ ⊢ u ≤s[pb] t

| cumul_Refl : forall t,
    Σ ;;; Γ ⊢ t ≤s[pb] t

| cumul_Ind : forall i u u' args args',
    cumul_Ind_univ Σ pb i #|args| u u' ->
    All2 (fun t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) args args' ->
    Σ ;;; Γ ⊢ mkApps (tInd i u) args ≤s[pb] mkApps (tInd i u') args'

| cumul_Construct : forall i k u u' args args',
    cumul_Construct_univ Σ pb i k #|args| u u' ->
    All2 (fun t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) args args' ->
    Σ ;;; Γ ⊢ mkApps (tConstruct i k u) args ≤s[pb] mkApps (tConstruct i k u') args'

| cumul_Sort : forall s s',
    compare_sort Σ pb s s' ->
    Σ ;;; Γ ⊢ tSort s ≤s[pb] tSort s'

| cumul_Const : forall c u u',
    cmp_universe_instance (compare_universe Σ Conv) u u' ->
    Σ ;;; Γ ⊢ tConst c u ≤s[pb] tConst c u'

| cumul_Evar : forall e args args',
    All2 (fun t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) args args' ->
    Σ ;;; Γ ⊢ tEvar e args ≤s[pb] tEvar e args'

| cumul_App : forall t t' u u',
    Σ ;;; Γ ⊢ t ≤s[pb] t' ->
    Σ ;;; Γ ⊢ u ≤s[Conv] u' ->
    Σ ;;; Γ ⊢ tApp t u ≤s[pb] tApp t' u'

| cumul_Lambda : forall na na' ty ty' t t',
    eq_binder_annot na na' ->
    Σ ;;; Γ ⊢ ty ≤s[Conv] ty' ->
    Σ ;;; Γ ,, vass na ty ⊢ t ≤s[Conv] t' ->
    Σ ;;; Γ ⊢ tLambda na ty t ≤s[pb] tLambda na' ty' t'

| cumul_Prod : forall na na' a a' b b',
    eq_binder_annot na na' ->
    Σ ;;; Γ ⊢ a ≤s[Conv] a' ->
    Σ ;;; Γ ,, vass na a ⊢ b ≤s[pb] b' ->
    Σ ;;; Γ ⊢ tProd na a b ≤s[pb] tProd na' a' b'

| cumul_LetIn : forall na na' t t' ty ty' u u',
    eq_binder_annot na na' ->
    Σ ;;; Γ ⊢ t ≤s[Conv] t' ->
    Σ ;;; Γ ⊢ ty ≤s[Conv] ty' ->
    Σ ;;; Γ ,, vdef na t ty ⊢ u ≤s[Conv] u' ->
    Σ ;;; Γ ⊢ tLetIn na t ty u ≤s[pb] tLetIn na' t' ty' u'

| cumul_Case indn : forall p p' c c' brs brs',
    cumul_predicate (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) (compare_universe Σ Conv) Γ p p' ->
    Σ ;;; Γ ⊢ c ≤s[Conv] c' ->
    cumul_branches (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) Γ p brs brs' ->
    Σ ;;; Γ ⊢ tCase indn p c brs ≤s[pb] tCase indn p' c' brs'

| cumul_Proj : forall p c c',
    Σ ;;; Γ ⊢ c ≤s[Conv] c' ->
    Σ ;;; Γ ⊢ tProj p c ≤s[pb] tProj p c'

| cumul_Fix : forall mfix mfix' idx,
    cumul_mfixpoint (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) Γ mfix mfix' ->
    Σ ;;; Γ ⊢ tFix mfix idx ≤s[pb] tFix mfix' idx

| cumul_CoFix : forall mfix mfix' idx,
    cumul_mfixpoint (fun Γ t u => Σ ;;; Γ ⊢ t ≤s[Conv] u) Γ mfix mfix' ->
    Σ ;;; Γ ⊢ tCoFix mfix idx ≤s[pb] tCoFix mfix' idx

| cumul_Prim p p' :
  onPrims (fun x y => Σ ;;; Γ ⊢ x ≤s[Conv] y) (compare_universe Σ Conv) p p' ->
  Σ ;;; Γ ⊢ tPrim p ≤s[pb] tPrim p'

| cumul_beta : forall na t b a,
    Σ ;;; Γ ⊢ tApp (tLambda na t b) a ≤s[pb] b {0 := a}

| cumul_zeta : forall na b t b',
    Σ ;;; Γ ⊢ tLetIn na b t b' ≤s[pb] b' {0 := b}

| cumul_rel i body :
    option_map decl_body (nth_error Γ i) = Some (Some body) ->
    Σ ;;; Γ ⊢ tRel i ≤s[pb] lift0 (S i) body

| cumul_iota : forall ci c u args p brs br,
    nth_error brs c = Some br ->
    #|args| = (ci.(ci_npar) + context_assumptions br.(bcontext))%nat ->
    Σ ;;; Γ ⊢ tCase ci p (mkApps (tConstruct ci.(ci_ind) c u) args) brs  ≤s[pb] iota_red ci.(ci_npar) p args br

| cumul_fix : forall mfix idx args narg fn,
    unfold_fix mfix idx = Some (narg, fn) ->
    is_constructor narg args = true ->
    Σ ;;; Γ ⊢ mkApps (tFix mfix idx) args ≤s[pb] mkApps fn args

| cumul_cofix_case : forall ip p mfix idx args narg fn brs,
    unfold_cofix mfix idx = Some (narg, fn) ->
    Σ ;;; Γ ⊢ tCase ip p (mkApps (tCoFix mfix idx) args) brs ≤s[pb] tCase ip p (mkApps fn args) brs

| cumul_cofix_proj : forall p mfix idx args narg fn,
    unfold_cofix mfix idx = Some (narg, fn) ->
    Σ ;;; Γ ⊢ tProj p (mkApps (tCoFix mfix idx) args) ≤s[pb] tProj p (mkApps fn args)

| cumul_delta : forall c decl body (isdecl : declared_constant Σ c decl) u,
    decl.(cst_body) = Some body ->
    Σ ;;; Γ ⊢ tConst c u ≤s[pb] body@[u]

| cumul_proj : forall p args u arg,
    nth_error args (p.(proj_npars) + p.(proj_arg)) = Some arg ->
    Σ ;;; Γ ⊢ tProj p (mkApps (tConstruct p.(proj_ind) 0 u) args) ≤s[pb] arg

where " Σ ;;; Γ ⊢ t ≤s[ pb ] u " := (@cumulSpec0 _ Σ Γ pb t u) : type_scope.
Definition cumulSpec `{checker_flags} (Σ : global_env_ext) Γ := cumulSpec0 Σ Γ Cumul.

Notation " Σ ;;; Γ |- t <=s u " := (@cumulSpec _ Σ Γ t u) (at level 50, Γ, t, u at next level).

Module PCUICConversionParSpec <: EnvironmentTyping.ConversionParSig PCUICTerm PCUICEnvironment PCUICTermUtils PCUICEnvTyping.
End PCUICConversionParSpec.

Definition type_of_constructor mdecl (cdecl : constructor_body) (c : inductive * nat) (u : list Level.t) :=
  let mind := inductive_mind (fst c) in
  subst0 (inds mind u mdecl.(ind_bodies)) (subst_instance u (cstr_type cdecl)).

Include PCUICEnvTyping.

Inductive FixCoFix : Type := Fix | CoFix.

Class GuardChecker :=
{
  guard : FixCoFix -> global_env_ext -> context -> mfixpoint term -> Prop ;
}.

Axiom guard_checking : GuardChecker.
#[global]
Existing Instance guard_checking.

Definition fix_guard := guard Fix.
Definition cofix_guard := guard CoFix.

Definition destInd (t : term) :=
  match t with
  | tInd ind u => Some (ind, u)
  | _ => None
  end.

Definition isCoFinite (r : recursivity_kind) :=
  match r with
  | CoFinite => true
  | _ => false
  end.

Definition check_recursivity_kind
  (lookup: kername -> option global_decl) ind r :=
  match lookup ind with
  | Some (InductiveDecl mib) => ReflectEq.eqb mib.(ind_finite) r
  | _ => false
  end.

Definition check_one_fix d :=
  let '{| dname := na;
         dtype := ty;
         dbody := b;
         rarg := arg |} := d in
  let '(ctx, ty) := decompose_prod_assum [] ty in
  match nth_error (List.rev (smash_context [] ctx)) arg with
  | Some argd =>
    let (hd, args) := decompose_app argd.(decl_type) in
    match destInd hd with
    | Some (mkInd mind _, u) => Some mind
    | None => None
    end
  | None => None
  end.

Definition wf_fixpoint_gen
  (lookup: kername -> option global_decl) mfix :=
  forallb (isLambda ∘ dbody) mfix &&
  let checks := map check_one_fix mfix in
  match map_option_out checks with
  | Some (ind :: inds) =>

    forallb (eqb ind) inds &&
    check_recursivity_kind lookup ind Finite
  | _ => false
  end.

Definition wf_fixpoint (Σ : global_env) := wf_fixpoint_gen (lookup_env Σ).

Definition check_one_cofix d :=
  let '{| dname := na;
         dtype := ty;
         dbody := b;
         rarg := arg |} := d in
  let '(ctx, ty) := decompose_prod_assum [] ty in
  let (hd, args) := decompose_app ty in
  match destInd hd with
  | Some (mkInd ind _, u) => Some ind
  | None => None
  end.

Definition wf_cofixpoint_gen
  (lookup: kername -> option global_decl) mfix :=
  let checks := map check_one_cofix mfix in
  match map_option_out checks with
  | Some (ind :: inds) =>

    forallb (eqb ind) inds &&
    check_recursivity_kind lookup ind CoFinite
  | _ => false
  end.

Definition wf_cofixpoint (Σ : global_env) := wf_cofixpoint_gen (lookup_env Σ).

Reserved Notation "'wf_local' Σ Γ " (at level 9, Σ, Γ at next level).

Reserved Notation " Σ ;;; Γ |- t : T " (at level 50, Γ, t, T at next level).

Variant case_side_conditions `{checker_flags} wf_local_funΣ typingΣ Σ Γ ci p ps mdecl idecl indices predctx :=
| case_side_info
    (eq_npars : mdecl.(ind_npars) = ci.(ci_npar))
    (wf_pred : wf_predicate mdecl idecl p)
    (cons : consistent_instance_ext Σ (ind_universes mdecl) p.(puinst))
    (wf_pctx : wf_local_funΣ (Γ ,,, predctx))

    (conv_pctx : eq_context_upto_names p.(pcontext) (ind_predicate_context ci.(ci_ind) mdecl idecl))
    (allowed_elim : is_allowed_elimination Σ idecl.(ind_kelim) ps)
    (elim_relevance : isSortRel ps ci.(ci_relevance))
    (ind_inst : ctx_inst typingΣ Γ (p.(pparams) ++ indices)
                         (List.rev (subst_instance p.(puinst)
                                                   (ind_params mdecl ,,, ind_indices idecl : context))))
    (not_cofinite : isCoFinite mdecl.(ind_finite) = false).

Variant case_branch_typing `{checker_flags} wf_local_funΣ typingΣ Γ (ci:case_info) p ps mdecl idecl ptm  brs :=
| case_branch_info
    (wf_brs : wf_branches idecl brs)
    (brs_ty :
       All2i (fun i cdecl br =>

                eq_context_upto_names br.(bcontext) (cstr_branch_context ci mdecl cdecl) ×
                let brctxty := case_branch_type ci.(ci_ind) mdecl idecl p br ptm i cdecl in
                (wf_local_funΣ (Γ ,,, brctxty.1) ×
                ((typingΣ (Γ ,,, brctxty.1) br.(bbody) (brctxty.2)) ×
                (typingΣ (Γ ,,, brctxty.1) brctxty.2 (tSort ps)))))
             0 idecl.(ind_ctors) brs).

Variant primitive_typing_hyps `{checker_flags}
  (typingΣ : forall (Γ : context), term -> term -> Type)
  Σ Γ : prim_val term -> Type :=
| prim_int_hyps i : primitive_typing_hyps typingΣ Σ Γ (primInt; primIntModel i)
| prim_float_hyps f : primitive_typing_hyps typingΣ Σ Γ (primFloat; primFloatModel f)
| prim_string_hyps s : primitive_typing_hyps typingΣ Σ Γ (primString; primStringModel s)
| prim_array_hyps a
  (wfl : wf_universe Σ (Universe.make' a.(array_level)))
  (hty : typingΣ Γ a.(array_type) (tSort (sType (Universe.make' a.(array_level)))))
  (hdef : typingΣ Γ a.(array_default) a.(array_type))
  (hvalue : All (fun x => typingΣ Γ x a.(array_type)) a.(array_value)) :
  primitive_typing_hyps typingΣ Σ Γ (primArray; primArrayModel a).

Equations prim_type (p : prim_val term) (cst : kername) : term :=
prim_type (primInt; _) cst := tConst cst [];
prim_type (primFloat; _) cst := tConst cst [];
prim_type (primString; _) cst := tConst cst [];
prim_type (primArray; primArrayModel a) cst := tApp (tConst cst [a.(array_level)]) a.(array_type).

Inductive typing `{checker_flags} (Σ : global_env_ext) (Γ : context) : term -> term -> Type :=
| type_Rel : forall n decl,
    wf_local Σ Γ ->
    nth_error Γ n = Some decl ->
    Σ ;;; Γ |- tRel n : lift0 (S n) decl.(decl_type)

| type_Sort : forall s,
    wf_local Σ Γ ->
    wf_sort Σ s ->
    Σ ;;; Γ |- tSort s : tSort (Sort.super s)

| type_Prod : forall na A B s1 s2,
    lift_typing typing Σ Γ (j_vass_s na A s1) ->
    Σ ;;; Γ ,, vass na A |- B : tSort s2 ->
    Σ ;;; Γ |- tProd na A B : tSort (Sort.sort_of_product s1 s2)

| type_Lambda : forall na A t B,
    lift_typing typing Σ Γ (j_vass na A) ->
    Σ ;;; Γ ,, vass na A |- t : B ->
    Σ ;;; Γ |- tLambda na A t : tProd na A B

| type_LetIn : forall na b B t A,
    lift_typing typing Σ Γ (j_vdef na b B) ->
    Σ ;;; Γ ,, vdef na b B |- t : A ->
    Σ ;;; Γ |- tLetIn na b B t : tLetIn na b B A

| type_App : forall t na A B s u,

    Σ ;;; Γ |- tProd na A B : tSort s ->
    Σ ;;; Γ |- t : tProd na A B ->
    Σ ;;; Γ |- u : A ->
    Σ ;;; Γ |- tApp t u : B{0 := u}

| type_Const : forall cst u decl,
    wf_local Σ Γ ->
    declared_constant Σ cst decl ->
    consistent_instance_ext Σ decl.(cst_universes) u ->
    Σ ;;; Γ |- tConst cst u : decl.(cst_type)@[u]

| type_Ind : forall ind u mdecl idecl,
    wf_local Σ Γ ->
    declared_inductive Σ ind mdecl idecl ->
    consistent_instance_ext Σ mdecl.(ind_universes) u ->
    Σ ;;; Γ |- tInd ind u : idecl.(ind_type)@[u]

| type_Construct : forall ind i u mdecl idecl cdecl,
    wf_local Σ Γ ->
    declared_constructor Σ (ind, i) mdecl idecl cdecl ->
    consistent_instance_ext Σ mdecl.(ind_universes) u ->
    Σ ;;; Γ |- tConstruct ind i u : type_of_constructor mdecl cdecl (ind, i) u

| type_Case : forall ci p c brs indices ps mdecl idecl,
    let predctx := case_predicate_context ci.(ci_ind) mdecl idecl p in
    let ptm := it_mkLambda_or_LetIn predctx p.(preturn) in
    declared_inductive Σ ci.(ci_ind) mdecl idecl ->
    Σ ;;; Γ ,,, predctx |- p.(preturn) : tSort ps ->
    Σ ;;; Γ |- c : mkApps (tInd ci.(ci_ind) p.(puinst)) (p.(pparams) ++ indices) ->
    case_side_conditions (fun Γ => wf_local Σ Γ) (typing Σ) Σ Γ ci p ps
                         mdecl idecl indices predctx  ->
    case_branch_typing (fun Γ => wf_local Σ Γ) (typing Σ) Γ ci p ps
                        mdecl idecl ptm brs ->
    Σ ;;; Γ |- tCase ci p c brs : mkApps ptm (indices ++ [c])

| type_Proj : forall p c u mdecl idecl cdecl pdecl args,
    declared_projection Σ p mdecl idecl cdecl pdecl ->
    Σ ;;; Γ |- c : mkApps (tInd p.(proj_ind) u) args ->
    #|args| = ind_npars mdecl ->
    Σ ;;; Γ |- tProj p c : subst0 (c :: List.rev args) pdecl.(proj_type)@[u]

| type_Fix : forall mfix n decl,
    wf_local Σ Γ ->
    fix_guard Σ Γ mfix ->
    nth_error mfix n = Some decl ->
    All (on_def_type (lift_typing1 (typing Σ)) Γ) mfix ->
    All (on_def_body (lift_typing1 (typing Σ)) (fix_context mfix) Γ) mfix ->
    wf_fixpoint Σ mfix ->
    Σ ;;; Γ |- tFix mfix n : decl.(dtype)

| type_CoFix : forall mfix n decl,
    wf_local Σ Γ ->
    cofix_guard Σ Γ mfix ->
    nth_error mfix n = Some decl ->
    All (on_def_type (lift_typing1 (typing Σ)) Γ) mfix ->
    All (on_def_body (lift_typing1 (typing Σ)) (fix_context mfix) Γ) mfix ->
    wf_cofixpoint Σ mfix ->
    Σ ;;; Γ |- tCoFix mfix n : decl.(dtype)

| type_Prim p prim_ty cdecl :
    wf_local Σ Γ ->
    primitive_constant Σ (prim_val_tag p) = Some prim_ty ->
    declared_constant Σ prim_ty cdecl ->
    primitive_invariants (prim_val_tag p) cdecl ->
    primitive_typing_hyps (typing Σ) Σ Γ p ->
    Σ ;;; Γ |- tPrim p : prim_type p prim_ty

| type_Cumul : forall t A B s,
    Σ ;;; Γ |- t : A ->
    Σ ;;; Γ |- B : tSort s ->
    Σ ;;; Γ |- A <=s B ->
    Σ ;;; Γ |- t : B

where " Σ ;;; Γ |- t : T " := (typing Σ Γ t T)
and "'wf_local' Σ Γ " := (All_local_env (lift_typing1 (typing Σ)) Γ).

Module PCUICTypingDef <: EnvironmentTyping.Typing PCUICTerm PCUICEnvironment PCUICTermUtils PCUICEnvTyping PCUICConversion PCUICConversionParSpec.

End PCUICTypingDef.

Module PCUICDeclarationTyping :=
  EnvironmentTyping.DeclarationTyping
    PCUICTerm
    PCUICEnvironment
    PCUICTermUtils
    PCUICEnvTyping
    PCUICConversion
    PCUICConversionParSpec
    PCUICTypingDef
    PCUICLookup
    PCUICGlobalMaps.
Include PCUICDeclarationTyping.

Definition wf `{checker_flags} := on_global_env cumulSpec0 (lift_typing typing).
Existing Class wf.

Definition on_udecl_prop (Σ : global_env) (udecl : universes_decl)
  := let levels := levels_of_udecl udecl in
     let global_levels := global_levels Σ.(universes) in
     let all_levels := LevelSet.union levels global_levels in
     ConstraintSet.For_all (declared_cstr_levels all_levels) (constraints_of_udecl udecl).

Section ExtendsWf.
  Context {cf : checker_flags}.
  Context {Pcmp: global_env_ext -> context -> conv_pb -> term -> term -> Type}.
  Context {P: global_env_ext -> context -> judgment -> Type}.

  Let wf := on_global_env Pcmp P.

Lemma weaken_lookup_on_global_env' Σ c decl :
  wf Σ ->
  lookup_env Σ c = Some decl ->
  on_udecl_prop Σ (universes_decl_of_decl decl).
Admitted.

Definition weaken_env_prop_gen
           (R : global_env_ext -> global_env_ext -> Type)
           (P : global_env_ext -> context -> judgment -> Type) :=
  forall Σ Σ' φ, wf Σ -> wf Σ' -> R (Σ, φ) (Σ', φ) -> forall Γ j, P (Σ, φ) Γ j -> P (Σ', φ) Γ j.

Definition weaken_env_prop := weaken_env_prop_gen extends.
Definition weaken_env_decls_prop := weaken_env_prop_gen extends_decls.
Definition weaken_env_strictly_decls_prop := weaken_env_prop_gen strictly_extends_decls.

End ExtendsWf.
Arguments weaken_env_prop {cf} (Pcmp P)%_function_scope _%_function_scope.
Arguments weaken_env_strictly_decls_prop {cf} (Pcmp P)%_function_scope _%_function_scope.

#[warnings="-ambiguous-paths"]
Global Coercion weaken_env_prop_to_decls {cf Pcmp P P0} : @weaken_env_prop cf Pcmp P P0 -> @weaken_env_decls_prop cf Pcmp P P0.
Admitted.
#[warnings="-ambiguous-paths"]
Global Coercion weaken_env_prop_decls_to_strictly_decls {cf Pcmp P P0} : @weaken_env_decls_prop cf Pcmp P P0 -> @weaken_env_strictly_decls_prop cf Pcmp P P0.
Admitted.

Definition wf_ext_wk {cf : checker_flags} (Σ : global_env_ext)
  := wf Σ.1 × on_udecl_prop Σ.1 Σ.2.

Definition wf_global_ext {cf : checker_flags} Σ ext := wf_ext_wk (Σ, ext).

Lemma declared_inductive_inv `{checker_flags} {Σ P ind mdecl idecl} :
  weaken_env_strictly_decls_prop cumulSpec0 (lift_typing typing) P ->
  wf Σ -> on_global_env cumulSpec0 P Σ ->
  declared_inductive Σ ind mdecl idecl ->
  on_ind_body cumulSpec0 P (Σ, ind_universes mdecl) (inductive_mind ind) mdecl (inductive_ind ind) idecl.
Admitted.

Lemma weaken_env_prop_typing `{checker_flags} : weaken_env_prop cumulSpec0 (lift_typing typing) (lift_typing typing).
Admitted.

Lemma on_declared_constructor `{checker_flags} {Σ ref mdecl idecl cdecl}
  {wfΣ : wf Σ}
  (Hdecl : declared_constructor Σ ref mdecl idecl cdecl) :
  on_inductive cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
               (inductive_mind (fst ref)) mdecl *
  on_ind_body cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
              (inductive_mind (fst ref)) mdecl (inductive_ind (fst ref)) idecl *
  ∑ ind_ctor_sort,
    let onib := declared_inductive_inv weaken_env_prop_typing wfΣ wfΣ (let (x, _) := Hdecl in x) in
     nth_error (ind_cunivs onib) ref.2 = Some ind_ctor_sort
    ×  on_constructor cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
                 mdecl (inductive_ind (fst ref))
                 idecl idecl.(ind_indices) cdecl ind_ctor_sort.
Admitted.

Inductive subslet {cf:checker_flags} Σ (Γ : context) : list term -> context -> Type :=
| emptyslet : subslet Σ Γ [] []
| cons_let_ass Δ s na t T : subslet Σ Γ s Δ ->
              Σ ;;; Γ |- t : subst0 s T ->
             subslet Σ Γ (t :: s) (Δ ,, vass na T)
| cons_let_def Δ s na t T :
    subslet Σ Γ s Δ ->
    Σ ;;; Γ |- subst0 s t : subst0 s T ->
    subslet Σ Γ (subst0 s t :: s) (Δ ,, vdef na t T).

Record spine_subst {cf:checker_flags} Σ Γ inst s (Δ : context) := mkSpineSubst {
  spine_dom_wf : wf_local Σ Γ;
  spine_codom_wf : wf_local Σ (Γ ,,, Δ);
  inst_ctx_subst :> context_subst Δ inst s;
  inst_subslet :> subslet Σ Γ s Δ }.

Section OnConstructor.
  Context {cf:checker_flags} {Σ : global_env} {ind mdecl idecl cdecl}
    {wfΣ: wf Σ} (declc : declared_constructor Σ ind mdecl idecl cdecl).

  Lemma on_constructor_subst :
    wf_global_ext Σ (ind_universes mdecl) *
    wf_local (Σ, ind_universes mdecl)
    (arities_context (ind_bodies mdecl) ,,, ind_params mdecl ,,, cstr_args cdecl) *
    ∑ inst,
    spine_subst (Σ, ind_universes mdecl)
              (arities_context (ind_bodies mdecl) ,,, ind_params mdecl ,,,
                cstr_args cdecl)
              ((to_extended_list_k (ind_params mdecl) #|cstr_args cdecl|) ++
                (cstr_indices cdecl)) inst
            (ind_params mdecl ,,, ind_indices idecl).
  Proof using declc wfΣ.
    pose proof (on_declared_constructor declc) as [[onmind oib] [cunivs [hnth onc]]].
    pose proof (onc.(on_cargs)).
simpl in X.
    split.
split.
split.
    2:{
 eapply (weaken_lookup_on_global_env' _ _ (InductiveDecl mdecl)); tea.
        clear hnth.
unshelve eapply declared_constructor_to_gen in declc; eauto.
        exact (inductive_mind ind.1).
🛠️ Intermediate Coq File (useful for debugging if minimization did not go as far as you wanted)
🛠️ 📜 Intermediate Coq File log (useful for debugging if minimization did not go as far as you wanted)
📜 Build Log (contains the Coq error message) (truncated to last 8.0KiB; full 8.0MiB file on GitHub Actions Artifacts under build.log)
cated,default]Warning, feedback message received but no listener to handle it!
Warning: Deprecated environment variable COQLIB, use ROCQLIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
Warning: Deprecated environment variable COQCORELIB,
use ROCQRUNTIMELIB instead.
[deprecated-coq-env-var,deprecated-since-9.0,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 5, characters 0-758:
Warning:
New coercion path [weaken_env_prop_full_to_strictly_on_decls;
                   weaken_env_prop_full_strictly_on_decls_to_strictly_decls] : weaken_env_prop_full >-> weaken_env_strictly_decls_prop_full is ambiguous with existing 
[weaken_env_prop_full_to_decls; weaken_env_prop_full_decls_to_strictly_decls] : weaken_env_prop_full >-> weaken_env_strictly_decls_prop_full.
[ambiguous-paths,coercions,default]
File "./theories/PCUICInductiveInversion.v", line 5, characters 0-758:
Warning:
New coercion path [weaken_env_prop_to_strictly_on_decls;
                   weaken_env_prop_strictly_on_decls_to_strictly_decls] : weaken_env_prop >-> weaken_env_strictly_decls_prop is ambiguous with existing 
[weaken_env_prop_to_decls; weaken_env_prop_decls_to_strictly_decls] : weaken_env_prop >-> weaken_env_strictly_decls_prop.
[ambiguous-paths,coercions,default]
File "./theories/PCUICInductiveInversion.v", line 65, characters 23-30:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 79, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 80, characters 49-56:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 81, characters 56-63:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 82, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 84, characters 18-25:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 85, characters 14-21:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 99, characters 14-21:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 99, characters 26-33:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 105, characters 22-29:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 107, characters 6-13:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 108, characters 12-19:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 127, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 128, characters 43-50:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 129, characters 50-57:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 130, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 132, characters 12-19:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 133, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 147, characters 8-15:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 147, characters 20-27:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 153, characters 16-23:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 172, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 174, characters 2-9:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 201, characters 22-29:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 225, characters 22-29:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 230, characters 4-11:
Warning: The 'rewrite' tactic has been renamed 'rw'.
[rewrite-rw,deprecated-since-9.3,deprecated,default]
File "./theories/PCUICInductiveInversion.v", line 274, characters 15-35:
Error:
In environment
cf : checker_flags
Σ : global_env
ind : inductive × nat
mdecl : mutual_inductive_body
idecl : one_inductive_body
cdecl : constructor_body
wfΣ : wf Σ
declc :
  PCUICLookup.declared_constructor_gen (lookup_env Σ) ind mdecl idecl cdecl
onmind :
  on_inductive cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
    (inductive_mind ind.1) mdecl
oib :
  on_ind_body cumulSpec0 (lift_typing typing) (Σ, ind_universes mdecl)
    (inductive_mind ind.1) mdecl (inductive_ind ind.1) idecl
cunivs : constructor_univs
onc :
  on_constructor cumulSpec0 (lift_typing typing) (
    Σ, ind_universes mdecl) mdecl (inductive_ind ind.1) idecl
    (ind_indices idecl) cdecl cunivs
X :
  sorts_local_ctx (lift_typing typing) (Σ, ind_universes mdecl)
    (arities_context (ind_bodies mdecl),,, ind_params mdecl)
    (cstr_args cdecl) cunivs
The term "inductive_mind ind.1" has type "kername"
while it is expected to have type
 "lookup_env (Σ, ind_universes mdecl).1 ?c = Some (InductiveDecl mdecl)".

Command exited with non-zero status 1
theories/PCUICInductiveInversion.vo (real: 2.30, user: 2.13, sys: 0.16, mem: 847648 ko)
make[3]: *** [Makefile.rocq:815: theories/PCUICInductiveInversion.vo] Error 1
make[3]: *** [theories/PCUICInductiveInversion.vo] Deleting file 'theories/PCUICInductiveInversion.glob'
make[2]: *** [Makefile.rocq:411: all] Error 2
make[2]: Leaving directory '/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic'
make[1]: *** [Makefile:11: coq] Error 2
make[1]: Leaving directory '/github/workspace/builds/coq/coq-failing/_build_ci/metarocq/pcuic'
make: *** [Makefile:153: pcuic] Error 2
+ code=2
+ printf '\n%s exit code: %s\n' metarocq 2
+ '[' metarocq '!=' stdlib_test ']'
+ echo 'Aggregating timing log...'
Aggregating timing log...
+ echo

+ tools/make-one-time-file.py --real _build_ci/metarocq.log
    Time |  Peak Mem | File Name                 
-------------------------------------------------
0m02.30s | 847648 ko | Total Time / Peak Mem     
-------------------------------------------------
0m02.30s | 847648 ko | PCUICInductiveInversion.vo
+ '[' '' ']'
+ exit 2
/github/workspace/builds/coq /github/workspace
::endgroup::
📜 🔎 Minimization Log (truncated to last 8.0KiB; full 3.8MiB file on GitHub Actions Artifacts under bug.log)
teractive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 819, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 824, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 835, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 850, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 855, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 859, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 873, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 878, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 883, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 887, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 892, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 895, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 899, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 904, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 908, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 912, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 916, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 921, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 926, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 931, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 935, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 938, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 942, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 946, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 950, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 961, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 967, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 973, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 978, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 1009, characters 0-58:
Warning: Rewrite hint database map already exists.
[already-declared-rewrite-hint-db,automation,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 1010, characters 0-13:
Warning: Rewrite hint database map already exists.
[already-declared-rewrite-hint-db,automation,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 1012, characters 0-11:
Warning: Rewrite hint database map already exists.
[already-declared-rewrite-hint-db,automation,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 1014, characters 0-13:
Warning: Rewrite hint database map already exists.
[already-declared-rewrite-hint-db,automation,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 1016, characters 0-37:
Warning: Rewrite hint database map already exists.
[already-declared-rewrite-hint-db,automation,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 1039, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 1041, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 1043, characters 0-6:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 1046, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 1058, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 1061, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 1065, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 1067, characters 0-9:
Warning: This interactive proof is not started by the "Proof" command.
[missing-proof-command,fragile,default]
File "/tmp/tmp4p65m9ab/Top/bug_01.v", line 1071, characters 0-38:
Error: Signature components for field compare_spec do not match:
expected type
"forall x y : Level.t,
 CompareSpec (Level.eq x y) (Level.lt x y) (Level.lt y x) (Level.compare x y)"
but found type
"forall x y : Level.t,
 CompareSpec (x = y) (Level.lt x y) (Level.lt y x) (Level.compare x y)".


�[93mIntermediate code not saved.�[0m
Failed to do everything at once; trying one at a time.
Admitting definitions unsuccessful.
No successful changes.

I will now attempt to add Proof using lines
�[92m
Adding Proof using lines successful.�[0m
Failed to do everything at once; trying one at a time.
Adding Proof using lines unsuccessful.
No successful changes.

I will now attempt to export modules

If you have any comments on your experience of the minimizer, please share them in a reply (possibly tagging @JasonGross).
If you believe there's a bug in the bug minimizer, please report it on the bug minimizer issue tracker.

@SkySkimmer

Copy link
Copy Markdown
Contributor Author

I don't think the metarocq minimization is going anywhere useful so I stopped it.

The metarocq error looks like

Goal nat -> nat.
Proof.
  intros x .
  epose (_:>bool).
  unshelve eapply plus in x. (* unshelves a bool goal in master but leaves it shelved in PR *)

Note that eapply in H clears H to be able to reuse its name (IIUC).

@SkySkimmer

Copy link
Copy Markdown
Contributor Author

I tried looking at the fiat crypto error and couldn't figure it out, I guess I'll have to implement something that doesn't need to change clear.

@SkySkimmer SkySkimmer added the request: full CI Use this label when you want your next push to trigger a full CI. label Jun 12, 2026
@coqbot-app coqbot-app Bot removed the request: full CI Use this label when you want your next push to trigger a full CI. label Jun 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant