aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml23
-rw-r--r--Makefile.ci2
-rw-r--r--coq.opam2
-rw-r--r--dev/base_include3
-rwxr-xr-xdev/ci/ci-basic-overlay.sh16
-rwxr-xr-xdev/ci/ci-coq_performance_tests.sh8
-rwxr-xr-xdev/ci/ci-fiat_crypto_legacy.sh13
-rw-r--r--dev/ci/user-overlays/12372-ejgallego-proof+info.sh24
-rw-r--r--dev/ci/user-overlays/12505-ppedrot-factor-hint-flags.sh6
-rw-r--r--doc/changelog/04-tactics/12552-zify-pre-hook.rst4
-rw-r--r--doc/changelog/09-coqide/12562-coqide-lax-filename.rst4
-rw-r--r--doc/changelog/11-infrastructure-and-dependencies/12583-fix-remake.rst5
-rw-r--r--doc/plugin_tutorial/tuto1/src/g_tuto1.mlg4
-rw-r--r--doc/plugin_tutorial/tuto1/src/simple_declare.ml7
-rw-r--r--doc/sphinx/addendum/micromega.rst3
-rw-r--r--doc/sphinx/practical-tools/utilities.rst4
-rw-r--r--doc/sphinx/using/tools/coqdoc.rst2
-rw-r--r--engine/eConstr.ml5
-rw-r--r--engine/eConstr.mli3
-rw-r--r--engine/evarutil.ml22
-rw-r--r--engine/evarutil.mli2
-rw-r--r--engine/evd.ml31
-rw-r--r--engine/univSubst.ml6
-rw-r--r--ide/coqide/coqide.ml4
-rw-r--r--ide/coqide/idetop.ml2
-rw-r--r--kernel/cbytegen.ml20
-rw-r--r--kernel/environ.mli2
-rw-r--r--plugins/derive/derive.ml11
-rw-r--r--plugins/derive/derive.mli2
-rw-r--r--plugins/extraction/extract_env.ml6
-rw-r--r--plugins/firstorder/sequent.ml8
-rw-r--r--plugins/funind/functional_principles_proofs.ml14
-rw-r--r--plugins/funind/gen_principle.ml43
-rw-r--r--plugins/funind/gen_principle.mli2
-rw-r--r--plugins/funind/recdef.ml68
-rw-r--r--plugins/funind/recdef.mli2
-rw-r--r--plugins/ltac/extratactics.mlg4
-rw-r--r--plugins/ltac/g_ltac.mlg2
-rw-r--r--plugins/ltac/g_obligations.mlg8
-rw-r--r--plugins/ltac/leminv.ml2
-rw-r--r--plugins/ltac/rewrite.ml17
-rw-r--r--plugins/ltac/rewrite.mli4
-rw-r--r--pretyping/globEnv.ml24
-rw-r--r--pretyping/glob_ops.ml2
-rw-r--r--proofs/clenv.ml129
-rw-r--r--proofs/clenv.mli21
-rw-r--r--proofs/clenvtac.ml135
-rw-r--r--proofs/clenvtac.mli23
-rw-r--r--proofs/logic.ml29
-rw-r--r--proofs/logic.mli3
-rw-r--r--proofs/proof.ml2
-rw-r--r--proofs/proofs.mllib1
-rw-r--r--stm/proofBlockDelimiter.ml4
-rw-r--r--stm/stm.ml54
-rw-r--r--stm/vernac_classifier.ml2
-rw-r--r--tactics/auto.ml43
-rw-r--r--tactics/auto.mli4
-rw-r--r--tactics/autorewrite.ml69
-rw-r--r--tactics/autorewrite.mli19
-rw-r--r--tactics/class_tactics.ml112
-rw-r--r--tactics/class_tactics.mli3
-rw-r--r--tactics/eauto.ml37
-rw-r--r--tactics/equality.ml8
-rw-r--r--tactics/hints.ml110
-rw-r--r--tactics/hints.mli75
-rw-r--r--tactics/tacticals.ml10
-rw-r--r--tactics/tacticals.mli2
-rw-r--r--tactics/tactics.ml11
-rw-r--r--test-suite/Makefile9
-rw-r--r--test-suite/bugs/closed/bug_12529.v21
-rw-r--r--test-suite/bugs/closed/bug_12532.v56
-rw-r--r--test-suite/micromega/zify.v11
-rw-r--r--test-suite/output-coqtop/DependentEvars.out6
-rw-r--r--test-suite/output-coqtop/DependentEvars2.out12
-rw-r--r--test-suite/output/unification.out24
-rw-r--r--test-suite/output/unification.v26
-rw-r--r--theories/Program/Equality.v2
-rw-r--r--theories/Reals/RIneq.v22
-rw-r--r--theories/micromega/Zify.v5
-rw-r--r--tools/CoqMakefile.in2
-rw-r--r--user-contrib/Ltac2/tac2entries.ml8
-rw-r--r--vernac/classes.ml29
-rw-r--r--vernac/classes.mli2
-rw-r--r--vernac/comAssumption.ml27
-rw-r--r--vernac/comAssumption.mli4
-rw-r--r--vernac/comCoercion.ml4
-rw-r--r--vernac/comDefinition.ml12
-rw-r--r--vernac/comDefinition.mli6
-rw-r--r--vernac/comFixpoint.ml22
-rw-r--r--vernac/comFixpoint.mli8
-rw-r--r--vernac/comHints.ml2
-rw-r--r--vernac/comInductive.ml31
-rw-r--r--vernac/comInductive.mli8
-rw-r--r--vernac/comProgramFixpoint.ml17
-rw-r--r--vernac/comProgramFixpoint.mli4
-rw-r--r--vernac/declare.ml1829
-rw-r--r--vernac/declare.mli810
-rw-r--r--vernac/declareDef.ml9
-rw-r--r--vernac/g_proofs.mlg8
-rw-r--r--vernac/lemmas.ml130
-rw-r--r--vernac/lemmas.mli82
-rw-r--r--vernac/obligations.ml417
-rw-r--r--vernac/obligations.mli135
-rw-r--r--vernac/pfedit.ml19
-rw-r--r--vernac/proof_global.ml13
-rw-r--r--vernac/recLemmas.ml25
-rw-r--r--vernac/recLemmas.mli13
-rw-r--r--vernac/vernac.mllib5
-rw-r--r--vernac/vernacentries.ml131
-rw-r--r--vernac/vernacextend.ml4
-rw-r--r--vernac/vernacextend.mli4
-rw-r--r--vernac/vernacinterp.ml24
-rw-r--r--vernac/vernacinterp.mli4
-rw-r--r--vernac/vernacstate.ml56
-rw-r--r--vernac/vernacstate.mli18
116 files changed, 2674 insertions, 2795 deletions
diff --git a/.gitignore b/.gitignore
index 0c7a8f70f6..557655317c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -92,6 +92,7 @@ test-suite/coqdoc/coqdoc.css
test-suite/output/MExtraction.out
test-suite/output/*.out.real
test-suite/oUnit-anon.cache
+test-suite/redirect_test.out
test-suite/unit-tests/**/*.test
# documentation
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a6ed9be58d..9e04762d1e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -582,7 +582,7 @@ test-suite:edge:dune:dev:
# Gitlab doesn't support yet "expire_in: never" so we use the instance default
# expire_in: never
-test-suite:edge+4.11+trunk+dune:
+.test-suite:ocaml+beta+dune-template:
stage: stage-1
except:
variables:
@@ -590,11 +590,11 @@ test-suite:edge+4.11+trunk+dune:
interruptible: true
dependencies: []
script:
- - opam switch create 4.11.0 --empty
+ - opam switch create $OCAMLVER --empty
- eval $(opam env)
- opam repo add ocaml-beta https://github.com/ocaml/ocaml-beta-repository.git
- opam update
- - opam install ocaml-variants=4.11.0+trunk
+ - opam install ocaml-variants=$OCAMLVER
- opam install dune num
- eval $(opam env)
- export COQ_UNIT_TEST=noop
@@ -610,6 +610,16 @@ test-suite:edge+4.11+trunk+dune:
expire_in: 2 week
allow_failure: true
+test-suite:4.11+trunk+dune:
+ extends: .test-suite:ocaml+beta+dune-template
+ variables:
+ OCAMLVER: 4.11.0+trunk
+
+test-suite:4.12+trunk+dune:
+ extends: .test-suite:ocaml+beta+dune-template
+ variables:
+ OCAMLVER: 4.12.0+trunk
+
test-suite:base+async:
extends: .test-suite-template
dependencies:
@@ -693,6 +703,9 @@ library:ci-color:
library:ci-compcert:
extends: .ci-template-flambda
+library:ci-coq_performance_tests:
+ extends: .ci-template
+
library:ci-coq_tools:
extends: .ci-template
@@ -739,6 +752,10 @@ library:ci-fiat_crypto:
- library:ci-coqprime
- plugin:ci-rewriter
+library:ci-fiat_crypto_legacy:
+ extends: .ci-template-flambda
+ allow_failure: true # See https://github.com/coq/coq/wiki/Coq-Call-2020-06-24#adding-back-fiat-crypto-legacy
+
# We cannot use flambda due to
# https://github.com/ocaml/ocaml/issues/7842, see
# https://github.com/coq/coq/pull/11916#issuecomment-609977375
diff --git a/Makefile.ci b/Makefile.ci
index 9231fa6fed..77d8bda671 100644
--- a/Makefile.ci
+++ b/Makefile.ci
@@ -20,6 +20,7 @@ CI_TARGETS= \
ci-coquelicot \
ci-corn \
ci-cross_crypto \
+ ci-coq_performance_tests \
ci-coq_tools \
ci-coqprime \
ci-elpi \
@@ -28,6 +29,7 @@ CI_TARGETS= \
ci-equations \
ci-fcsl_pcm \
ci-fiat_crypto \
+ ci-fiat_crypto_legacy \
ci-fiat_crypto_ocaml \
ci-fiat_parsers \
ci-flocq \
diff --git a/coq.opam b/coq.opam
index e46f9def60..23cef68dce 100644
--- a/coq.opam
+++ b/coq.opam
@@ -28,6 +28,6 @@ depends: [
]
build: [
- [ "./configure" "-prefix" prefix ]
+ [ "./configure" "-prefix" prefix "-native-compiler" "no" ]
[ "dune" "build" "-p" name "-j" jobs ]
]
diff --git a/dev/base_include b/dev/base_include
index 45e79147c1..67ea3a1fa1 100644
--- a/dev/base_include
+++ b/dev/base_include
@@ -66,7 +66,6 @@ open Pretyping
open Cbv
open Coercionops
open Clenv
-open Clenvtac
open Constr_matching
open Glob_term
open Glob_ops
@@ -112,10 +111,8 @@ open Search
open Evar_refiner
open Goal
open Logic
-open Pfedit
open Proof
open Proof_using
-open Proof_global
open Redexpr
open Refiner
open Tacmach
diff --git a/dev/ci/ci-basic-overlay.sh b/dev/ci/ci-basic-overlay.sh
index cdf00f4767..4973cbb478 100755
--- a/dev/ci/ci-basic-overlay.sh
+++ b/dev/ci/ci-basic-overlay.sh
@@ -95,6 +95,13 @@
: "${flocq_CI_ARCHIVEURL:=${flocq_CI_GITURL}/-/archive}"
########################################################################
+# coq-performance-tests
+########################################################################
+: "${coq_performance_tests_CI_REF:=master}"
+: "${coq_performance_tests_CI_GITURL:=https://github.com/coq-community/coq-performance-tests}"
+: "${coq_performance_tests_CI_ARCHIVEURL:=${coq_performance_tests_CI_GITURL}/archive}"
+
+########################################################################
# coq-tools
########################################################################
: "${coq_tools_CI_REF:=master}"
@@ -172,6 +179,13 @@
: "${fiat_crypto_CI_ARCHIVEURL:=${fiat_crypto_CI_GITURL}/archive}"
########################################################################
+# fiat_crypto_legacy
+########################################################################
+: "${fiat_crypto_legacy_CI_REF:=sp2019latest}"
+: "${fiat_crypto_legacy_CI_GITURL:=https://github.com/mit-plv/fiat-crypto}"
+: "${fiat_crypto_legacy_CI_ARCHIVEURL:=${fiat_crypto_legacy_CI_GITURL}/archive}"
+
+########################################################################
# coq_dpdgraph
########################################################################
: "${coq_dpdgraph_CI_REF:=coq-master}"
@@ -349,7 +363,7 @@
########################################################################
# perennial
########################################################################
-: "${perennial_CI_REF:=master}"
+: "${perennial_CI_REF:=coq/tested}"
: "${perennial_CI_GITURL:=https://github.com/mit-pdos/perennial}"
: "${perennial_CI_ARCHIVEURL:=${perennial_CI_GITURL}/archive}"
diff --git a/dev/ci/ci-coq_performance_tests.sh b/dev/ci/ci-coq_performance_tests.sh
new file mode 100755
index 0000000000..4eb77cfb24
--- /dev/null
+++ b/dev/ci/ci-coq_performance_tests.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+ci_dir="$(dirname "$0")"
+. "${ci_dir}/ci-common.sh"
+
+git_download coq_performance_tests
+
+( cd "${CI_BUILD_DIR}/coq_performance_tests" && make coq perf && make validate && make install )
diff --git a/dev/ci/ci-fiat_crypto_legacy.sh b/dev/ci/ci-fiat_crypto_legacy.sh
new file mode 100755
index 0000000000..6d0a803401
--- /dev/null
+++ b/dev/ci/ci-fiat_crypto_legacy.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+ci_dir="$(dirname "$0")"
+. "${ci_dir}/ci-common.sh"
+
+FORCE_GIT=1
+git_download fiat_crypto_legacy
+
+fiat_crypto_legacy_CI_TARGETS1="print-old-pipeline-lite-hardcoded old-pipeline-lite-hardcoded lite-display-hardcoded"
+fiat_crypto_legacy_CI_TARGETS2="print-old-pipeline-nobigmem-hardcoded old-pipeline-nobigmem-hardcoded nonautogenerated-specific nonautogenerated-specific-display selected-specific selected-specific-display"
+
+( cd "${CI_BUILD_DIR}/fiat_crypto_legacy" && git submodule update --init --recursive && \
+ make ${fiat_crypto_legacy_CI_TARGETS1} && make -j 1 ${fiat_crypto_legacy_CI_TARGETS2} )
diff --git a/dev/ci/user-overlays/12372-ejgallego-proof+info.sh b/dev/ci/user-overlays/12372-ejgallego-proof+info.sh
new file mode 100644
index 0000000000..b9fdc338b5
--- /dev/null
+++ b/dev/ci/user-overlays/12372-ejgallego-proof+info.sh
@@ -0,0 +1,24 @@
+if [ "$CI_PULL_REQUEST" = "12372" ] || [ "$CI_BRANCH" = "proof+info" ]; then
+
+ rewriter_CI_REF=proof+info
+ rewriter_CI_GITURL=https://github.com/ejgallego/rewriter
+
+ paramcoq_CI_REF=proof+info
+ paramcoq_CI_GITURL=https://github.com/ejgallego/paramcoq
+
+ mtac2_CI_REF=proof+info
+ mtac2_CI_GITURL=https://github.com/ejgallego/Mtac2
+
+ equations_CI_REF=proof+info
+ equations_CI_GITURL=https://github.com/ejgallego/Coq-Equations
+
+ elpi_CI_REF=proof+info
+ elpi_CI_GITURL=https://github.com/ejgallego/coq-elpi
+
+ aac_tactics_CI_REF=proof+info
+ aac_tactics_CI_GITURL=https://github.com/ejgallego/aac-tactics
+
+ metacoq_CI_REF=proof+info
+ metacoq_CI_GITURL=https://github.com/ejgallego/metacoq
+
+fi
diff --git a/dev/ci/user-overlays/12505-ppedrot-factor-hint-flags.sh b/dev/ci/user-overlays/12505-ppedrot-factor-hint-flags.sh
new file mode 100644
index 0000000000..ced0d95945
--- /dev/null
+++ b/dev/ci/user-overlays/12505-ppedrot-factor-hint-flags.sh
@@ -0,0 +1,6 @@
+if [ "$CI_PULL_REQUEST" = "12505" ] || [ "$CI_BRANCH" = "factor-hint-flags" ]; then
+
+ fiat_parsers_CI_REF="factor-hint-flags"
+ fiat_parsers_CI_GITURL=https://github.com/ppedrot/fiat
+
+fi
diff --git a/doc/changelog/04-tactics/12552-zify-pre-hook.rst b/doc/changelog/04-tactics/12552-zify-pre-hook.rst
new file mode 100644
index 0000000000..975c917b19
--- /dev/null
+++ b/doc/changelog/04-tactics/12552-zify-pre-hook.rst
@@ -0,0 +1,4 @@
+- **Added:**
+ Thhe :tacn:`zify` tactic can now be extended by redefining the `zify_pre_hook`
+ tactic. (`#12552 <https://github.com/coq/coq/pull/12552>`_,
+ by Kazuhiko Sakaguchi).
diff --git a/doc/changelog/09-coqide/12562-coqide-lax-filename.rst b/doc/changelog/09-coqide/12562-coqide-lax-filename.rst
new file mode 100644
index 0000000000..ef3160dd99
--- /dev/null
+++ b/doc/changelog/09-coqide/12562-coqide-lax-filename.rst
@@ -0,0 +1,4 @@
+- **Fixed:** CoqIDE no longer exits when trying to open a file whose name is not a valid identifier
+ (`#12562 <https://github.com/coq/coq/pull/12562>`_,
+ fixes `#10988 <https://github.com/coq/coq/issues/10988>`_,
+ by Vincent Laporte).
diff --git a/doc/changelog/11-infrastructure-and-dependencies/12583-fix-remake.rst b/doc/changelog/11-infrastructure-and-dependencies/12583-fix-remake.rst
new file mode 100644
index 0000000000..d9c8b634d6
--- /dev/null
+++ b/doc/changelog/11-infrastructure-and-dependencies/12583-fix-remake.rst
@@ -0,0 +1,5 @@
+- **Fixed:**
+ Running ``make`` in ``test-suite/`` twice (or more) in a row will no longer
+ rebuild the ``modules/`` tests on subsequent runs, if they have not been
+ modified in the meantime (`#12583 <https://github.com/coq/coq/pull/12583>`_,
+ fixes `#12582 <https://github.com/coq/coq/issues/12582>`_, by Jason Gross).
diff --git a/doc/plugin_tutorial/tuto1/src/g_tuto1.mlg b/doc/plugin_tutorial/tuto1/src/g_tuto1.mlg
index 8c2090f3be..d24d968c01 100644
--- a/doc/plugin_tutorial/tuto1/src/g_tuto1.mlg
+++ b/doc/plugin_tutorial/tuto1/src/g_tuto1.mlg
@@ -286,8 +286,8 @@ END
VERNAC COMMAND EXTEND ExploreProof CLASSIFIED AS QUERY
| ![ proof_query ] [ "ExploreProof" ] ->
{ fun ~pstate ->
- let sigma, env = Declare.get_current_context pstate in
- let pprf = Proof.partial_proof (Declare.Proof.get_proof pstate) in
+ let sigma, env = Declare.Proof.get_current_context pstate in
+ let pprf = Proof.partial_proof (Declare.Proof.get pstate) in
Feedback.msg_notice
(Pp.prlist_with_sep Pp.fnl (Printer.pr_econstr_env env sigma) pprf)
}
diff --git a/doc/plugin_tutorial/tuto1/src/simple_declare.ml b/doc/plugin_tutorial/tuto1/src/simple_declare.ml
index e9e866c5fb..4d0105ea9d 100644
--- a/doc/plugin_tutorial/tuto1/src/simple_declare.ml
+++ b/doc/plugin_tutorial/tuto1/src/simple_declare.ml
@@ -1,6 +1,7 @@
let declare_definition ~poly name sigma body =
let udecl = UState.default_univ_decl in
- let scope = Declare.Global Declare.ImportDefaultBehavior in
+ let scope = Locality.Global Locality.ImportDefaultBehavior in
let kind = Decls.(IsDefinition Definition) in
- Declare.declare_definition ~name ~scope ~kind ~impargs:[] ~udecl
- ~opaque:false ~poly ~types:None ~body sigma
+ let cinfo = Declare.CInfo.make ~name ~typ:None () in
+ let info = Declare.Info.make ~scope ~kind ~udecl ~poly () in
+ Declare.declare_definition ~info ~cinfo ~opaque:false ~body sigma
diff --git a/doc/sphinx/addendum/micromega.rst b/doc/sphinx/addendum/micromega.rst
index c4947e6b3a..c01e6a5aa6 100644
--- a/doc/sphinx/addendum/micromega.rst
+++ b/doc/sphinx/addendum/micromega.rst
@@ -278,7 +278,8 @@ obtain :math:`-1`. By Theorem :ref:`Psatz <psatz_thm>`, the goal is valid.
This tactic is internally called by :tacn:`lia` to support additional types e.g., :g:`nat`, :g:`positive` and :g:`N`.
By requiring the module ``ZifyBool``, the boolean type :g:`bool` and some comparison operators are also supported.
- :tacn:`zify` can also be extended by rebinding the tactic `Zify.zify_post_hook` that is run immediately after :tacn:`zify`.
+ :tacn:`zify` can also be extended by rebinding the tactics `Zify.zify_pre_hook` and `Zify.zify_post_hook` that are
+ respectively run in the first and the last steps of :tacn:`zify`.
+ To support :g:`Z.div` and :g:`Z.modulo`: ``Ltac Zify.zify_post_hook ::= Z.div_mod_to_equations``.
+ To support :g:`Z.quot` and :g:`Z.rem`: ``Ltac Zify.zify_post_hook ::= Z.quot_rem_to_equations``.
diff --git a/doc/sphinx/practical-tools/utilities.rst b/doc/sphinx/practical-tools/utilities.rst
index 33ebbce640..d9992029ba 100644
--- a/doc/sphinx/practical-tools/utilities.rst
+++ b/doc/sphinx/practical-tools/utilities.rst
@@ -74,8 +74,8 @@ to literally pass an argument ``foo`` to ``coqc``: in the
example, this allows to pass the two-word option ``-w all`` (see
:ref:`command line options <command-line-options>`).
-Currently, both |CoqIDE| and Proof-General (version ≥ ``4.3pre``)
-understand ``_CoqProject`` files and invoke |Coq| with the desired options.
+|CoqIDE|, Proof-General and VSCoq all
+understand ``_CoqProject`` files and can be used to invoke |Coq| with the desired options.
The ``coq_makefile`` utility can be used to set up a build infrastructure
for the |Coq| project based on makefiles. The recommended way of
diff --git a/doc/sphinx/using/tools/coqdoc.rst b/doc/sphinx/using/tools/coqdoc.rst
index f872c1b2e3..9ac3d2adda 100644
--- a/doc/sphinx/using/tools/coqdoc.rst
+++ b/doc/sphinx/using/tools/coqdoc.rst
@@ -1,3 +1,5 @@
+.. index:: coqdoc
+
.. _coqdoc:
Documenting |Coq| files with coqdoc
diff --git a/engine/eConstr.ml b/engine/eConstr.ml
index ca681e58f8..42c9359ff0 100644
--- a/engine/eConstr.ml
+++ b/engine/eConstr.ml
@@ -733,6 +733,11 @@ let map_rel_context_in_env f env sign =
in
aux env [] (List.rev sign)
+let match_named_context_val :
+ named_context_val -> (named_declaration * lazy_val * named_context_val) option =
+ match unsafe_eq with
+ | Refl -> match_named_context_val
+
let fresh_global ?loc ?rigid ?names env sigma reference =
let (evd,t) = Evd.fresh_global ?loc ?rigid ?names env sigma reference in
evd, t
diff --git a/engine/eConstr.mli b/engine/eConstr.mli
index 9a73c3e3f5..aea441b90b 100644
--- a/engine/eConstr.mli
+++ b/engine/eConstr.mli
@@ -322,6 +322,9 @@ val lookup_named_val : variable -> named_context_val -> named_declaration
val map_rel_context_in_env :
(env -> constr -> constr) -> env -> rel_context -> rel_context
+val match_named_context_val :
+ named_context_val -> (named_declaration * lazy_val * named_context_val) option
+
(* XXX Missing Sigma proxy *)
val fresh_global :
?loc:Loc.t -> ?rigid:Evd.rigid -> ?names:Univ.Instance.t -> Environ.env ->
diff --git a/engine/evarutil.ml b/engine/evarutil.ml
index 5fcadfcef7..eea7e38f87 100644
--- a/engine/evarutil.ml
+++ b/engine/evarutil.ml
@@ -287,7 +287,7 @@ let csubst_subst { csubst_len = k; csubst_var = v; csubst_rel = s } c =
EConstr.of_constr c
type ext_named_context =
- csubst * Id.Set.t * EConstr.named_context
+ csubst * Id.Set.t * named_context_val
let push_var id { csubst_len = n; csubst_var = v; csubst_rel = s; csubst_rev = r } =
let s = Int.Map.add n (Constr.mkVar id) s in
@@ -325,22 +325,22 @@ type naming_mode =
let push_rel_decl_to_named_context
?(hypnaming=KeepUserNameAndRenameExistingButSectionNames)
- sigma decl (subst, avoid, nc) =
+ sigma decl ((subst, avoid, nc) : ext_named_context) =
let open EConstr in
let open Vars in
let map_decl f d =
NamedDecl.map_constr f d
in
- let rec replace_var_named_declaration id0 id = function
- | [] -> []
- | decl :: nc ->
+ let rec replace_var_named_declaration id0 id nc = match match_named_context_val nc with
+ | None -> empty_named_context_val
+ | Some (decl, _, nc) ->
if Id.equal id0 (NamedDecl.get_id decl) then
(* Stop here, the variable cannot occur before its definition *)
- (NamedDecl.set_id id decl) :: nc
+ push_named_context_val (NamedDecl.set_id id decl) nc
else
let nc = replace_var_named_declaration id0 id nc in
let vsubst = [id0 , mkVar id] in
- map_decl (fun c -> replace_vars vsubst c) decl :: nc
+ push_named_context_val (map_decl (fun c -> replace_vars vsubst c) decl) nc
in
let extract_if_neq id = function
| Anonymous -> None
@@ -372,7 +372,7 @@ let push_rel_decl_to_named_context
let subst = update_var id0 id subst in
let d = decl |> NamedDecl.of_rel_decl (fun _ -> id0) |> map_decl (csubst_subst subst) in
let nc = replace_var_named_declaration id0 id nc in
- (push_var id0 subst, Id.Set.add id avoid, d :: nc)
+ (push_var id0 subst, Id.Set.add id avoid, push_named_context_val d nc)
| Some id0 when hypnaming = FailIfConflict ->
user_err Pp.(Id.print id0 ++ str " is already used.")
| _ ->
@@ -381,7 +381,7 @@ let push_rel_decl_to_named_context
the new binder has name [id]. Which amounts to the same
behaviour than when [id=id0]. *)
let d = decl |> NamedDecl.of_rel_decl (fun _ -> id) |> map_decl (csubst_subst subst) in
- (push_var id subst, Id.Set.add id avoid, d :: nc)
+ (push_var id subst, Id.Set.add id avoid, push_named_context_val d nc)
let push_rel_context_to_named_context ?hypnaming env sigma typ =
(* compute the instances relative to the named context and rel_context *)
@@ -399,8 +399,8 @@ let push_rel_context_to_named_context ?hypnaming env sigma typ =
(* We do keep the instances corresponding to local definition (see above) *)
let (subst, _, env) =
Context.Rel.fold_outside (fun d acc -> push_rel_decl_to_named_context ?hypnaming sigma d acc)
- (rel_context env) ~init:(empty_csubst, avoid, named_context env) in
- (val_of_named_context env, csubst_subst subst typ, inst_rels@inst_vars, subst)
+ (rel_context env) ~init:(empty_csubst, avoid, named_context_val env) in
+ (env, csubst_subst subst typ, inst_rels@inst_vars, subst)
(*------------------------------------*
* Entry points to define new evars *
diff --git a/engine/evarutil.mli b/engine/evarutil.mli
index b5c7ccb283..b3c94e6b3b 100644
--- a/engine/evarutil.mli
+++ b/engine/evarutil.mli
@@ -268,7 +268,7 @@ val empty_csubst : csubst
val csubst_subst : csubst -> constr -> constr
type ext_named_context =
- csubst * Id.Set.t * named_context
+ csubst * Id.Set.t * named_context_val
val push_rel_decl_to_named_context : ?hypnaming:naming_mode ->
evar_map -> rel_declaration -> ext_named_context -> ext_named_context
diff --git a/engine/evd.ml b/engine/evd.ml
index ff13676818..f0ee8ae68f 100644
--- a/engine/evd.ml
+++ b/engine/evd.ml
@@ -1174,12 +1174,34 @@ let meta_declare mv v ?(name=Anonymous) evd =
let metas = Metamap.add mv (Cltyp(name,mk_freelisted v)) evd.metas in
set_metas evd metas
+(* If the meta is defined then forget its name *)
+let meta_name evd mv =
+ try fst (clb_name (Metamap.find mv evd.metas)) with Not_found -> Anonymous
+
+let evar_source_of_meta mv evd =
+ match meta_name evd mv with
+ | Anonymous -> Loc.tag Evar_kinds.GoalEvar
+ | Name id -> Loc.tag @@ Evar_kinds.VarInstance id
+
+let use_meta_source evd mv v =
+ match Constr.kind v with
+ | Evar (evk,_) ->
+ let f = function
+ | None -> None
+ | Some evi as x ->
+ match evi.evar_source with
+ | None, Evar_kinds.GoalEvar -> Some { evi with evar_source = evar_source_of_meta mv evd }
+ | _ -> x in
+ { evd with undf_evars = EvMap.update evk f evd.undf_evars }
+ | _ -> evd
+
let meta_assign mv (v, pb) evd =
let modify _ = function
| Cltyp (na, ty) -> Clval (na, (mk_freelisted v, pb), ty)
| _ -> anomaly ~label:"meta_assign" (Pp.str "already defined.")
in
let metas = Metamap.modify mv modify evd.metas in
+ let evd = use_meta_source evd mv v in
set_metas evd metas
let meta_reassign mv (v, pb) evd =
@@ -1190,10 +1212,6 @@ let meta_reassign mv (v, pb) evd =
let metas = Metamap.modify mv modify evd.metas in
set_metas evd metas
-(* If the meta is defined then forget its name *)
-let meta_name evd mv =
- try fst (clb_name (Metamap.find mv evd.metas)) with Not_found -> Anonymous
-
let clear_metas evd = {evd with metas = Metamap.empty}
let meta_merge ?(with_univs = true) evd1 evd2 =
@@ -1217,11 +1235,6 @@ let retract_coercible_metas evd =
let metas = Metamap.Smart.mapi map evd.metas in
!mc, set_metas evd metas
-let evar_source_of_meta mv evd =
- match meta_name evd mv with
- | Anonymous -> Loc.tag Evar_kinds.GoalEvar
- | Name id -> Loc.tag @@ Evar_kinds.VarInstance id
-
let dependent_evar_ident ev evd =
let evi = find evd ev in
match evi.evar_source with
diff --git a/engine/univSubst.ml b/engine/univSubst.ml
index a691239ee2..92211d5f3d 100644
--- a/engine/univSubst.ml
+++ b/engine/univSubst.ml
@@ -131,9 +131,9 @@ let nf_evars_and_universes_opt_subst f subst =
let rec aux c =
match kind c with
| Evar (evk, args) ->
- let args = List.map aux args in
- (match try f (evk, args) with Not_found -> None with
- | None -> mkEvar (evk, args)
+ let args' = List.Smart.map aux args in
+ (match try f (evk, args') with Not_found -> None with
+ | None -> if args == args' then c else mkEvar (evk, args')
| Some c -> aux c)
| Const pu ->
let pu' = subst_univs_fn_puniverses lsubst pu in
diff --git a/ide/coqide/coqide.ml b/ide/coqide/coqide.ml
index ab2a17798e..b66da11e7b 100644
--- a/ide/coqide/coqide.ml
+++ b/ide/coqide/coqide.ml
@@ -114,8 +114,10 @@ let make_coqtop_args fname =
(* We basically copy the code of Names.check_valid since it is not exported *)
(* to coqide. This is to prevent a possible failure of parsing "-topfile" *)
(* at initialization of coqtop (see #10286) *)
+ (* If the file name is a valid identifier, use it as toplevel name; *)
+ (* otherwise the default “Top” will be used. *)
match Unicode.ident_refutation (Filename.chop_extension (Filename.basename fname)) with
- | Some (_,x) -> output_string stderr (x^"\n"); exit 1
+ | Some _ -> args
| None -> "-topfile"::fname::args
in
proj, args
diff --git a/ide/coqide/idetop.ml b/ide/coqide/idetop.ml
index bd99cbed1b..2adc35ae3e 100644
--- a/ide/coqide/idetop.ml
+++ b/ide/coqide/idetop.ml
@@ -343,7 +343,7 @@ let search flags =
let pstate = Vernacstate.Declare.get_pstate () in
let sigma, env = match pstate with
| None -> let env = Global.env () in Evd.(from_env env, env)
- | Some p -> Declare.get_goal_context p 1 in
+ | Some p -> Declare.Proof.get_goal_context p 1 in
List.map export_coq_object (Search.interface_search env sigma (
List.map (fun (c, b) -> (import_search_constraint c, b)) flags)
)
diff --git a/kernel/cbytegen.ml b/kernel/cbytegen.ml
index b3a4bd7471..59ae8c0745 100644
--- a/kernel/cbytegen.ml
+++ b/kernel/cbytegen.ml
@@ -130,7 +130,7 @@ type comp_env = {
nb_uni_stack : int ; (* number of universes on the stack, *)
(* universes are always at the bottom. *)
nb_stack : int; (* number of variables on the stack *)
- in_stack : int list; (* position in the stack *)
+ in_stack : int Range.t; (* position in the stack *)
nb_rec : int; (* number of mutually recursive functions *)
pos_rec : instruction list; (* instruction d'acces pour les variables *)
(* de point fix ou de cofix *)
@@ -158,7 +158,7 @@ let empty_comp_env ()=
{ arity = 0;
nb_uni_stack = 0;
nb_stack = 0;
- in_stack = [];
+ in_stack = Range.empty;
nb_rec = 0;
pos_rec = [];
offset = 0;
@@ -188,13 +188,13 @@ let ensure_stack_capacity f x =
(*i Creation functions for comp_env *)
let rec add_param n sz l =
- if Int.equal n 0 then l else add_param (n - 1) sz (n+sz::l)
+ if Int.equal n 0 then l else add_param (n - 1) sz (Range.cons (n+sz) l)
let comp_env_fun ?(univs=0) arity =
{ arity;
nb_uni_stack = univs ;
nb_stack = arity;
- in_stack = add_param arity 0 [];
+ in_stack = add_param arity 0 Range.empty;
nb_rec = 0;
pos_rec = [];
offset = 1;
@@ -206,7 +206,7 @@ let comp_env_fix_type rfv =
{ arity = 0;
nb_uni_stack = 0;
nb_stack = 0;
- in_stack = [];
+ in_stack = Range.empty;
nb_rec = 0;
pos_rec = [];
offset = 1;
@@ -221,7 +221,7 @@ let comp_env_fix ndef curr_pos arity rfv =
{ arity;
nb_uni_stack = 0;
nb_stack = arity;
- in_stack = add_param arity 0 [];
+ in_stack = add_param arity 0 Range.empty;
nb_rec = ndef;
pos_rec = !prec;
offset = 2 * (ndef - curr_pos - 1)+1;
@@ -232,7 +232,7 @@ let comp_env_cofix_type ndef rfv =
{ arity = 0;
nb_uni_stack = 0;
nb_stack = 0;
- in_stack = [];
+ in_stack = Range.empty;
nb_rec = 0;
pos_rec = [];
offset = 1+ndef;
@@ -247,7 +247,7 @@ let comp_env_cofix ndef arity rfv =
{ arity;
nb_uni_stack = 0;
nb_stack = arity;
- in_stack = add_param arity 0 [];
+ in_stack = add_param arity 0 Range.empty;
nb_rec = ndef;
pos_rec = !prec;
offset = ndef+1;
@@ -264,7 +264,7 @@ let push_param n sz r =
let push_local sz r =
{ r with
nb_stack = r.nb_stack + 1;
- in_stack = (sz + 1) :: r.in_stack }
+ in_stack = Range.cons (sz + 1) r.in_stack }
(*i Compilation of variables *)
let find_at fv env = FvMap.find fv env.fv_fwd
@@ -280,7 +280,7 @@ let pos_named id r =
let pos_rel i r sz =
if i <= r.nb_stack then
- Kacc(sz - (List.nth r.in_stack (i-1)))
+ Kacc(sz - (Range.get r.in_stack (i-1)))
else
let i = i - r.nb_stack in
if i <= r.nb_rec then
diff --git a/kernel/environ.mli b/kernel/environ.mli
index 79e632daa0..f489b13a3b 100644
--- a/kernel/environ.mli
+++ b/kernel/environ.mli
@@ -176,6 +176,8 @@ val named_body : variable -> env -> constr option
val fold_named_context :
(env -> Constr.named_declaration -> 'a -> 'a) -> env -> init:'a -> 'a
+val match_named_context_val : named_context_val -> (named_declaration * lazy_val * named_context_val) option
+
(** Recurrence on [named_context] starting from younger decl *)
val fold_named_context_reverse :
('a -> Constr.named_declaration -> 'a) -> init:'a -> env -> 'a
diff --git a/plugins/derive/derive.ml b/plugins/derive/derive.ml
index e5665c59b8..027064b75f 100644
--- a/plugins/derive/derive.ml
+++ b/plugins/derive/derive.ml
@@ -15,7 +15,7 @@ open Context.Named.Declaration
(which can contain references to [f]) in the context extended by
[f:=?x]. When the proof ends, [f] is defined as the value of [?x]
and [lemma] as the proof. *)
-let start_deriving f suchthat name : Lemmas.t =
+let start_deriving f suchthat name : Declare.Proof.t =
let env = Global.env () in
let sigma = Evd.from_env env in
@@ -40,8 +40,7 @@ let start_deriving f suchthat name : Lemmas.t =
TNil sigma))))))
in
- let info = Lemmas.Info.make ~proof_ending:(Declare.Proof_ending.(End_derive {f; name})) ~kind () in
- let lemma = Lemmas.start_dependent_lemma ~name ~poly ~info goals in
- Lemmas.pf_map (Declare.Proof.map_proof begin fun p ->
- Util.pi1 @@ Proof.run_tactic env Proofview.(tclFOCUS 1 2 shelve) p
- end) lemma
+ let info = Declare.Info.make ~poly ~kind () in
+ let lemma = Declare.Proof.start_derive ~name ~f ~info goals in
+ Declare.Proof.map lemma ~f:(fun p ->
+ Util.pi1 @@ Proof.run_tactic env Proofview.(tclFOCUS 1 2 shelve) p)
diff --git a/plugins/derive/derive.mli b/plugins/derive/derive.mli
index ef94c7e78f..06e7dacd36 100644
--- a/plugins/derive/derive.mli
+++ b/plugins/derive/derive.mli
@@ -16,4 +16,4 @@ val start_deriving
: Names.Id.t
-> Constrexpr.constr_expr
-> Names.Id.t
- -> Lemmas.t
+ -> Declare.Proof.t
diff --git a/plugins/extraction/extract_env.ml b/plugins/extraction/extract_env.ml
index a0627dbe63..af43c0517e 100644
--- a/plugins/extraction/extract_env.ml
+++ b/plugins/extraction/extract_env.ml
@@ -729,13 +729,13 @@ let extract_and_compile l =
(* Show the extraction of the current ongoing proof *)
let show_extraction ~pstate =
init ~inner:true false false;
- let prf = Declare.Proof.get_proof pstate in
- let sigma, env = Declare.get_current_context pstate in
+ let prf = Declare.Proof.get pstate in
+ let sigma, env = Declare.Proof.get_current_context pstate in
let trms = Proof.partial_proof prf in
let extr_term t =
let ast, ty = extract_constr env sigma t in
let mp = Lib.current_mp () in
- let l = Label.of_id (Declare.Proof.get_proof_name pstate) in
+ let l = Label.of_id (Declare.Proof.get_name pstate) in
let fake_ref = GlobRef.ConstRef (Constant.make2 mp l) in
let decl = Dterm (fake_ref, ast, ty) in
print_one_decl [] mp decl
diff --git a/plugins/firstorder/sequent.ml b/plugins/firstorder/sequent.ml
index 3dd5059e5d..db3631daa4 100644
--- a/plugins/firstorder/sequent.ml
+++ b/plugins/firstorder/sequent.ml
@@ -205,10 +205,10 @@ open Hints
let extend_with_auto_hints env sigma l seq =
let f (seq,sigma) p_a_t =
- match repr_hint p_a_t.code with
- | Res_pf (c,_) | Give_exact (c,_)
- | Res_pf_THEN_trivial_fail (c,_) ->
- let (c, _, _) = c in
+ match FullHint.repr p_a_t with
+ | Res_pf c | Give_exact c
+ | Res_pf_THEN_trivial_fail c ->
+ let c = c.hint_term in
(match EConstr.destRef sigma c with
| exception Constr.DestKO -> seq, sigma
| gr, _ ->
diff --git a/plugins/funind/functional_principles_proofs.ml b/plugins/funind/functional_principles_proofs.ml
index b864b18887..2151ad7873 100644
--- a/plugins/funind/functional_principles_proofs.ml
+++ b/plugins/funind/functional_principles_proofs.ml
@@ -853,12 +853,16 @@ let generate_equation_lemma evd fnames f fun_num nb_params nb_args rec_args_num
(*i The next call to mk_equation_id is valid since we are
constructing the lemma Ensures by: obvious i*)
- let lemma =
- Lemmas.start_lemma ~name:(mk_equation_id f_id) ~poly:false evd lemma_type
+ let info = Declare.Info.make () in
+ let cinfo =
+ Declare.CInfo.make ~name:(mk_equation_id f_id) ~typ:lemma_type ()
+ in
+ let lemma = Declare.Proof.start ~cinfo ~info evd in
+ let lemma, _ =
+ Declare.Proof.by (Proofview.V82.tactic prove_replacement) lemma
in
- let lemma, _ = Lemmas.by (Proofview.V82.tactic prove_replacement) lemma in
- let () =
- Lemmas.save_lemma_proved ~lemma ~opaque:Declare.Transparent ~idopt:None
+ let (_ : _ list) =
+ Declare.Proof.save ~proof:lemma ~opaque:Vernacexpr.Transparent ~idopt:None
in
evd
diff --git a/plugins/funind/gen_principle.ml b/plugins/funind/gen_principle.ml
index 608155eb71..167cf37026 100644
--- a/plugins/funind/gen_principle.ml
+++ b/plugins/funind/gen_principle.ml
@@ -319,7 +319,7 @@ let generate_functional_principle (evd : Evd.evar_map ref) old_princ_type sorts
let entry = Declare.definition_entry ~univs ?types body in
let (_ : Names.GlobRef.t) =
Declare.declare_entry ~name:new_princ_name ~hook
- ~scope:(Declare.Global Declare.ImportDefaultBehavior)
+ ~scope:(Locality.Global Locality.ImportDefaultBehavior)
~kind:Decls.(IsProof Theorem)
~impargs:[] ~uctx entry
in
@@ -400,7 +400,7 @@ let register_struct is_rec fixpoint_exprl =
Pp.(str "Body of Function must be given")
in
ComDefinition.do_definition ~name:fname.CAst.v ~poly:false
- ~scope:(Declare.Global Declare.ImportDefaultBehavior)
+ ~scope:(Locality.Global Locality.ImportDefaultBehavior)
~kind:Decls.Definition univs binders None body (Some rtype);
let evd, rev_pconstants =
List.fold_left
@@ -419,7 +419,7 @@ let register_struct is_rec fixpoint_exprl =
(None, evd, List.rev rev_pconstants)
| _ ->
ComFixpoint.do_fixpoint
- ~scope:(Declare.Global Declare.ImportDefaultBehavior) ~poly:false
+ ~scope:(Locality.Global Locality.ImportDefaultBehavior) ~poly:false
fixpoint_exprl;
let evd, rev_pconstants =
List.fold_left
@@ -1370,12 +1370,12 @@ let make_scheme evd (fas : (Constr.pconstant * Sorts.family) list) : _ list =
| None -> raise Not_found
| Some finfos -> finfos
in
- let open Declare in
match finfos.equation_lemma with
- | None -> Transparent (* non recursive definition *)
+ | None -> Vernacexpr.Transparent (* non recursive definition *)
| Some equation ->
- if Declareops.is_opaque (Global.lookup_constant equation) then Opaque
- else Transparent
+ if Declareops.is_opaque (Global.lookup_constant equation) then
+ Vernacexpr.Opaque
+ else Vernacexpr.Transparent
in
let body, typ, univs, _hook, sigma0 =
try
@@ -1518,12 +1518,14 @@ let derive_correctness (funs : Constr.pconstant list) (graphs : inductive list)
i*)
let lem_id = mk_correct_id f_id in
let typ, _ = lemmas_types_infos.(i) in
- let lemma = Lemmas.start_lemma ~name:lem_id ~poly:false !evd typ in
+ let info = Declare.Info.make () in
+ let cinfo = Declare.CInfo.make ~name:lem_id ~typ () in
+ let lemma = Declare.Proof.start ~cinfo ~info !evd in
let lemma =
- fst @@ Lemmas.by (Proofview.V82.tactic (proving_tac i)) lemma
+ fst @@ Declare.Proof.by (Proofview.V82.tactic (proving_tac i)) lemma
in
- let () =
- Lemmas.save_lemma_proved ~lemma ~opaque:Declare.Transparent
+ let (_ : GlobRef.t list) =
+ Declare.Proof.save ~proof:lemma ~opaque:Vernacexpr.Transparent
~idopt:None
in
let finfo =
@@ -1580,21 +1582,22 @@ let derive_correctness (funs : Constr.pconstant list) (graphs : inductive list)
Ensures by: obvious
i*)
let lem_id = mk_complete_id f_id in
- let lemma =
- Lemmas.start_lemma ~name:lem_id ~poly:false sigma
- (fst lemmas_types_infos.(i))
+ let info = Declare.Info.make () in
+ let cinfo =
+ Declare.CInfo.make ~name:lem_id ~typ:(fst lemmas_types_infos.(i)) ()
in
+ let lemma = Declare.Proof.start ~cinfo sigma ~info in
let lemma =
fst
- (Lemmas.by
+ (Declare.Proof.by
(Proofview.V82.tactic
(observe_tac
("prove completeness (" ^ Id.to_string f_id ^ ")")
(proving_tac i)))
lemma)
in
- let () =
- Lemmas.save_lemma_proved ~lemma ~opaque:Declare.Transparent
+ let (_ : _ list) =
+ Declare.Proof.save ~proof:lemma ~opaque:Vernacexpr.Transparent
~idopt:None
in
let finfo =
@@ -1769,7 +1772,7 @@ let register_mes interactive_proof fname rec_impls wf_mes_expr wf_rel_expr_opt
using_lemmas args ret_type body
let do_generate_principle_aux pconstants on_error register_built
- interactive_proof fixpoint_exprl : Lemmas.t option =
+ interactive_proof fixpoint_exprl : Declare.Proof.t option =
List.iter
(fun {Vernacexpr.notations} ->
if not (List.is_empty notations) then
@@ -2155,7 +2158,7 @@ let make_graph (f_ref : GlobRef.t) =
(* *************** statically typed entrypoints ************************* *)
-let do_generate_principle_interactive fixl : Lemmas.t =
+let do_generate_principle_interactive fixl : Declare.Proof.t =
match do_generate_principle_aux [] warning_error true true fixl with
| Some lemma -> lemma
| None ->
@@ -2199,7 +2202,7 @@ let build_scheme fas =
List.iter2
(fun (princ_id, _, _) (body, types, univs, opaque) ->
let (_ : Constant.t) =
- let opaque = if opaque = Declare.Opaque then true else false in
+ let opaque = if opaque = Vernacexpr.Opaque then true else false in
let def_entry = Declare.definition_entry ~univs ~opaque ?types body in
Declare.declare_constant ~name:princ_id
~kind:Decls.(IsProof Theorem)
diff --git a/plugins/funind/gen_principle.mli b/plugins/funind/gen_principle.mli
index 3c04d6cb7d..28751c4501 100644
--- a/plugins/funind/gen_principle.mli
+++ b/plugins/funind/gen_principle.mli
@@ -12,7 +12,7 @@ val warn_cannot_define_graph : ?loc:Loc.t -> Pp.t * Pp.t -> unit
val warn_cannot_define_principle : ?loc:Loc.t -> Pp.t * Pp.t -> unit
val do_generate_principle_interactive :
- Vernacexpr.fixpoint_expr list -> Lemmas.t
+ Vernacexpr.fixpoint_expr list -> Declare.Proof.t
val do_generate_principle : Vernacexpr.fixpoint_expr list -> unit
val make_graph : Names.GlobRef.t -> unit
diff --git a/plugins/funind/recdef.ml b/plugins/funind/recdef.ml
index 9b2d9c4815..884792cc15 100644
--- a/plugins/funind/recdef.ml
+++ b/plugins/funind/recdef.ml
@@ -58,7 +58,10 @@ let declare_fun name kind ?univs value =
(Declare.declare_constant ~name ~kind (Declare.DefinitionEntry ce))
let defined lemma =
- Lemmas.save_lemma_proved ~lemma ~opaque:Declare.Transparent ~idopt:None
+ let (_ : _ list) =
+ Declare.Proof.save ~proof:lemma ~opaque:Vernacexpr.Transparent ~idopt:None
+ in
+ ()
let def_of_const t =
match Constr.kind t with
@@ -1343,7 +1346,7 @@ let whole_start concl_tac nb_args is_mes func input_type relation rec_arg_num :
g
let get_current_subgoals_types pstate =
- let p = Declare.Proof.get_proof pstate in
+ let p = Declare.Proof.get pstate in
let Proof.{goals = sgs; sigma; _} = Proof.data p in
(sigma, List.map (Goal.V82.abstract_type sigma) sgs)
@@ -1405,7 +1408,7 @@ let clear_goals sigma =
List.map clear_goal
let build_new_goal_type lemma =
- let sigma, sub_gls_types = Lemmas.pf_fold get_current_subgoals_types lemma in
+ let sigma, sub_gls_types = get_current_subgoals_types lemma in
(* Pp.msgnl (str "sub_gls_types1 := " ++ Util.prlist_with_sep (fun () -> Pp.fnl () ++ Pp.fnl ()) Printer.pr_lconstr sub_gls_types); *)
let sub_gls_types = clear_goals sigma sub_gls_types in
(* Pp.msgnl (str "sub_gls_types2 := " ++ Pp.prlist_with_sep (fun () -> Pp.fnl () ++ Pp.fnl ()) Printer.pr_lconstr sub_gls_types); *)
@@ -1414,16 +1417,17 @@ let build_new_goal_type lemma =
let is_opaque_constant c =
let cb = Global.lookup_constant c in
+ let open Vernacexpr in
match cb.Declarations.const_body with
- | Declarations.OpaqueDef _ -> Declare.Opaque
- | Declarations.Undef _ -> Declare.Opaque
- | Declarations.Def _ -> Declare.Transparent
- | Declarations.Primitive _ -> Declare.Opaque
+ | Declarations.OpaqueDef _ -> Opaque
+ | Declarations.Undef _ -> Opaque
+ | Declarations.Def _ -> Transparent
+ | Declarations.Primitive _ -> Opaque
let open_new_goal ~lemma build_proof sigma using_lemmas ref_ goal_name
(gls_type, decompose_and_tac, nb_goal) =
(* Pp.msgnl (str "gls_type := " ++ Printer.pr_lconstr gls_type); *)
- let current_proof_name = Lemmas.pf_fold Declare.Proof.get_proof_name lemma in
+ let current_proof_name = Declare.Proof.get_name lemma in
let name =
match goal_name with
| Some s -> s
@@ -1488,18 +1492,20 @@ let open_new_goal ~lemma build_proof sigma using_lemmas ref_ goal_name
[Hints.Hint_db.empty TransparentState.empty false] ]))
in
let lemma = build_proof env (Evd.from_env env) start_tac end_tac in
- Lemmas.save_lemma_proved ~lemma ~opaque:opacity ~idopt:None
- in
- let info = Lemmas.Info.make ~hook:(Declare.Hook.make hook) () in
- let lemma =
- Lemmas.start_lemma ~name:na ~poly:false (* FIXME *) ~info sigma gls_type
+ let (_ : _ list) =
+ Declare.Proof.save ~proof:lemma ~opaque:opacity ~idopt:None
+ in
+ ()
in
+ let info = Declare.Info.make ~hook:(Declare.Hook.make hook) () in
+ let cinfo = Declare.CInfo.make ~name:na ~typ:gls_type () in
+ let lemma = Declare.Proof.start ~cinfo ~info sigma in
let lemma =
if Indfun_common.is_strict_tcc () then
- fst @@ Lemmas.by (Proofview.V82.tactic tclIDTAC) lemma
+ fst @@ Declare.Proof.by (Proofview.V82.tactic tclIDTAC) lemma
else
fst
- @@ Lemmas.by
+ @@ Declare.Proof.by
(Proofview.V82.tactic (fun g ->
tclTHEN decompose_and_tac
(tclORELSE
@@ -1521,27 +1527,28 @@ let open_new_goal ~lemma build_proof sigma using_lemmas ref_ goal_name
g))
lemma
in
- if Lemmas.(pf_fold Declare.Proof.get_open_goals) lemma = 0 then (
- defined lemma; None )
+ if Declare.Proof.get_open_goals lemma = 0 then (defined lemma; None)
else Some lemma
let com_terminate interactive_proof tcc_lemma_name tcc_lemma_ref is_mes
fonctional_ref input_type relation rec_arg_num thm_name using_lemmas nb_args
ctx hook =
let start_proof env ctx tac_start tac_end =
- let info = Lemmas.Info.make ~hook () in
- let lemma =
- Lemmas.start_lemma ~name:thm_name ~poly:false (*FIXME*) ~info ctx
- (EConstr.of_constr (compute_terminate_type nb_args fonctional_ref))
+ let cinfo =
+ Declare.CInfo.make ~name:thm_name
+ ~typ:(EConstr.of_constr (compute_terminate_type nb_args fonctional_ref))
+ ()
in
+ let info = Declare.Info.make ~hook () in
+ let lemma = Declare.Proof.start ~cinfo ~info ctx in
let lemma =
fst
- @@ Lemmas.by
+ @@ Declare.Proof.by
(New.observe_tac (fun _ _ -> str "starting_tac") tac_start)
lemma
in
fst
- @@ Lemmas.by
+ @@ Declare.Proof.by
(Proofview.V82.tactic
(observe_tac
(fun _ _ -> str "whole_start")
@@ -1602,13 +1609,16 @@ let com_eqn uctx nb_arg eq_name functional_ref f_ref terminate_ref
let evd = Evd.from_ctx uctx in
let f_constr = constr_of_monomorphic_global f_ref in
let equation_lemma_type = subst1 f_constr equation_lemma_type in
- let lemma =
- Lemmas.start_lemma ~name:eq_name ~poly:false evd
- (EConstr.of_constr equation_lemma_type)
+ let info = Declare.Info.make () in
+ let cinfo =
+ Declare.CInfo.make ~name:eq_name
+ ~typ:(EConstr.of_constr equation_lemma_type)
+ ()
in
+ let lemma = Declare.Proof.start ~cinfo evd ~info in
let lemma =
fst
- @@ Lemmas.by
+ @@ Declare.Proof.by
(Proofview.V82.tactic
(start_equation f_ref terminate_ref (fun x ->
prove_eq
@@ -1642,7 +1652,7 @@ let com_eqn uctx nb_arg eq_name functional_ref f_ref terminate_ref
in
let _ =
Flags.silently
- (fun () -> Lemmas.save_lemma_proved ~lemma ~opaque:opacity ~idopt:None)
+ (fun () -> Declare.Proof.save ~proof:lemma ~opaque:opacity ~idopt:None)
()
in
()
@@ -1651,7 +1661,7 @@ let com_eqn uctx nb_arg eq_name functional_ref f_ref terminate_ref
let recursive_definition ~interactive_proof ~is_mes function_name rec_impls
type_of_f r rec_arg_num eq generate_induction_principle using_lemmas :
- Lemmas.t option =
+ Declare.Proof.t option =
let open Term in
let open Constr in
let open CVars in
diff --git a/plugins/funind/recdef.mli b/plugins/funind/recdef.mli
index 4e5146e37c..2612f2b63e 100644
--- a/plugins/funind/recdef.mli
+++ b/plugins/funind/recdef.mli
@@ -25,4 +25,4 @@ val recursive_definition :
-> EConstr.constr
-> unit)
-> Constrexpr.constr_expr list
- -> Lemmas.t option
+ -> Declare.Proof.t option
diff --git a/plugins/ltac/extratactics.mlg b/plugins/ltac/extratactics.mlg
index ffb597d4cb..40c64a1c26 100644
--- a/plugins/ltac/extratactics.mlg
+++ b/plugins/ltac/extratactics.mlg
@@ -918,7 +918,7 @@ END
VERNAC COMMAND EXTEND GrabEvars STATE proof
| [ "Grab" "Existential" "Variables" ]
=> { classify_as_proofstep }
- -> { fun ~pstate -> Declare.Proof.map_proof (fun p -> Proof.V82.grab_evars p) pstate }
+ -> { fun ~pstate -> Declare.Proof.map ~f:(fun p -> Proof.V82.grab_evars p) pstate }
END
(* Shelves all the goals under focus. *)
@@ -950,7 +950,7 @@ END
VERNAC COMMAND EXTEND Unshelve STATE proof
| [ "Unshelve" ]
=> { classify_as_proofstep }
- -> { fun ~pstate -> Declare.Proof.map_proof (fun p -> Proof.unshelve p) pstate }
+ -> { fun ~pstate -> Declare.Proof.map ~f:(fun p -> Proof.unshelve p) pstate }
END
(* Gives up on the goals under focus: the goals are considered solved,
diff --git a/plugins/ltac/g_ltac.mlg b/plugins/ltac/g_ltac.mlg
index 996f6b3eb3..114acaa412 100644
--- a/plugins/ltac/g_ltac.mlg
+++ b/plugins/ltac/g_ltac.mlg
@@ -363,7 +363,7 @@ let print_info_trace =
let vernac_solve ~pstate n info tcom b =
let open Goal_select in
- let pstate, status = Declare.Proof.map_fold_proof_endline (fun etac p ->
+ let pstate, status = Declare.Proof.map_fold_endline ~f:(fun etac p ->
let with_end_tac = if b then Some etac else None in
let global = match n with SelectAll | SelectList _ -> true | _ -> false in
let info = Option.append info (print_info_trace ()) in
diff --git a/plugins/ltac/g_obligations.mlg b/plugins/ltac/g_obligations.mlg
index 498b33d1a8..81ee6ed5bb 100644
--- a/plugins/ltac/g_obligations.mlg
+++ b/plugins/ltac/g_obligations.mlg
@@ -28,7 +28,7 @@ let () =
let tac = Proofview.tclBIND (Proofview.tclUNIT ()) begin fun () ->
snd (get_default_tactic ())
end in
- Obligations.default_tactic := tac
+ Declare.Obls.default_tactic := tac
let with_tac f tac =
let env = Genintern.empty_glob_sign (Global.env ()) in
@@ -78,10 +78,10 @@ GRAMMAR EXTEND Gram
{
-open Obligations
+open Declare.Obls
-let obligation obl tac = with_tac (fun t -> Obligations.obligation obl t) tac
-let next_obligation obl tac = with_tac (fun t -> Obligations.next_obligation obl t) tac
+let obligation obl tac = with_tac (fun t -> obligation obl t) tac
+let next_obligation obl tac = with_tac (fun t -> next_obligation obl t) tac
let classify_obbl _ = Vernacextend.(VtStartProof (Doesn'tGuaranteeOpacity,[]))
diff --git a/plugins/ltac/leminv.ml b/plugins/ltac/leminv.ml
index 5a8ec404ee..0024d1a4ba 100644
--- a/plugins/ltac/leminv.ml
+++ b/plugins/ltac/leminv.ml
@@ -261,7 +261,7 @@ let lemInv id c =
try
let clause = mk_clenv_from_env (pf_env gls) (project gls) None (c, pf_get_type_of gls c) in
let clause = clenv_constrain_last_binding (EConstr.mkVar id) clause in
- Clenvtac.res_pf clause ~flags:(Unification.elim_flags ()) ~with_evars:false
+ Clenv.res_pf clause ~flags:(Unification.elim_flags ()) ~with_evars:false
with
| NoSuchBinding ->
user_err
diff --git a/plugins/ltac/rewrite.ml b/plugins/ltac/rewrite.ml
index 4bc8d61258..f16d0717df 100644
--- a/plugins/ltac/rewrite.ml
+++ b/plugins/ltac/rewrite.ml
@@ -1900,10 +1900,12 @@ let declare_projection name instance_id r =
in it_mkProd_or_LetIn ccl ctx
in
let types = Some (it_mkProd_or_LetIn typ ctx) in
- let kind, opaque, scope = Decls.(IsDefinition Definition), false, Declare.Global Declare.ImportDefaultBehavior in
+ let kind, opaque, scope = Decls.(IsDefinition Definition), false, Locality.Global Locality.ImportDefaultBehavior in
let impargs, udecl = [], UState.default_univ_decl in
+ let cinfo = Declare.CInfo.make ~name ~impargs ~typ:types () in
+ let info = Declare.Info.make ~scope ~kind ~udecl ~poly () in
let _r : GlobRef.t =
- Declare.declare_definition ~name ~scope ~kind ~opaque ~impargs ~udecl ~poly ~types ~body sigma
+ Declare.declare_definition ~cinfo ~info ~opaque ~body sigma
in ()
let build_morphism_signature env sigma m =
@@ -1967,7 +1969,7 @@ let add_morphism_as_parameter atts m n : unit =
let env = Global.env () in
let evd = Evd.from_env env in
let poly = atts.polymorphic in
- let kind, opaque, scope = Decls.(IsAssumption Logical), false, Declare.Global Declare.ImportDefaultBehavior in
+ let kind, opaque, scope = Decls.(IsAssumption Logical), false, Locality.Global Locality.ImportDefaultBehavior in
let impargs, udecl = [], UState.default_univ_decl in
let evd, types = build_morphism_signature env evd m in
let evd, pe = Declare.prepare_parameter ~poly ~udecl ~types evd in
@@ -1978,7 +1980,7 @@ let add_morphism_as_parameter atts m n : unit =
(PropGlobal.proper_class env evd) Hints.empty_hint_info atts.global cst);
declare_projection n instance_id cst
-let add_morphism_interactive atts m n : Lemmas.t =
+let add_morphism_interactive atts m n : Declare.Proof.t =
init_setoid ();
let instance_id = add_suffix n "_Proper" in
let env = Global.env () in
@@ -1996,11 +1998,12 @@ let add_morphism_interactive atts m n : Lemmas.t =
| _ -> assert false
in
let hook = Declare.Hook.make hook in
- let info = Lemmas.Info.make ~hook ~kind () in
Flags.silently
(fun () ->
- let lemma = Lemmas.start_lemma ~name:instance_id ~poly ~info evd morph in
- fst (Lemmas.by (Tacinterp.interp tac) lemma)) ()
+ let cinfo = Declare.CInfo.make ~name:instance_id ~typ:morph () in
+ let info = Declare.Info.make ~poly ~hook ~kind () in
+ let lemma = Declare.Proof.start ~cinfo ~info evd in
+ fst (Declare.Proof.by (Tacinterp.interp tac) lemma)) ()
let add_morphism atts binders m s n =
init_setoid ();
diff --git a/plugins/ltac/rewrite.mli b/plugins/ltac/rewrite.mli
index 1161c84e6a..60a66dd861 100644
--- a/plugins/ltac/rewrite.mli
+++ b/plugins/ltac/rewrite.mli
@@ -101,7 +101,7 @@ val add_setoid
-> Id.t
-> unit
-val add_morphism_interactive : rewrite_attributes -> constr_expr -> Id.t -> Lemmas.t
+val add_morphism_interactive : rewrite_attributes -> constr_expr -> Id.t -> Declare.Proof.t
val add_morphism_as_parameter : rewrite_attributes -> constr_expr -> Id.t -> unit
val add_morphism
@@ -110,7 +110,7 @@ val add_morphism
-> constr_expr
-> constr_expr
-> Id.t
- -> Lemmas.t
+ -> Declare.Proof.t
val get_reflexive_proof : env -> evar_map -> constr -> constr -> evar_map * constr
diff --git a/pretyping/globEnv.ml b/pretyping/globEnv.ml
index fad41614b4..05abb86f46 100644
--- a/pretyping/globEnv.ml
+++ b/pretyping/globEnv.ml
@@ -33,6 +33,8 @@ type t = {
(** For locating indices *)
renamed_env : env;
(** For name management *)
+ renamed_vars : EConstr.t list Lazy.t;
+ (** Identity instance of named_context of renamed_env, to maximize sharing *)
extra : ext_named_context Lazy.t;
(** Delay the computation of the evar extended environment *)
lvar : ltac_var_map;
@@ -42,10 +44,12 @@ let make ~hypnaming env sigma lvar =
let get_extra env sigma =
let avoid = Environ.ids_of_named_context_val (Environ.named_context_val env) in
Context.Rel.fold_outside (fun d acc -> push_rel_decl_to_named_context ~hypnaming sigma d acc)
- (rel_context env) ~init:(empty_csubst, avoid, named_context env) in
+ (rel_context env) ~init:(empty_csubst, avoid, named_context_val env) in
+ let open Context.Named.Declaration in
{
static_env = env;
renamed_env = env;
+ renamed_vars = lazy (List.map (get_id %> mkVar) (named_context env));
extra = lazy (get_extra env sigma);
lvar = lvar;
}
@@ -67,10 +71,12 @@ let ltac_interp_id { ltac_idents ; ltac_genargs } id =
let ltac_interp_name lvar = Nameops.Name.map (ltac_interp_id lvar)
let push_rel ~hypnaming sigma d env =
- let d' = Context.Rel.Declaration.map_name (ltac_interp_name env.lvar) d in
+ let open Context.Rel.Declaration in
+ let d' = map_name (ltac_interp_name env.lvar) d in
let env = {
static_env = push_rel d env.static_env;
renamed_env = push_rel d' env.renamed_env;
+ renamed_vars = env.renamed_vars;
extra = lazy (push_rel_decl_to_named_context ~hypnaming:hypnaming sigma d' (Lazy.force env.extra));
lvar = env.lvar;
} in
@@ -83,6 +89,7 @@ let push_rel_context ~hypnaming ?(force_names=false) sigma ctx env =
let env = {
static_env = push_rel_context ctx env.static_env;
renamed_env = push_rel_context ctx' env.renamed_env;
+ renamed_vars = env.renamed_vars;
extra = lazy (List.fold_right (fun d acc -> push_rel_decl_to_named_context ~hypnaming:hypnaming sigma d acc) ctx' (Lazy.force env.extra));
lvar = env.lvar;
} in
@@ -95,13 +102,14 @@ let push_rec_types ~hypnaming sigma (lna,typarray) env =
Array.map get_annot ctx, env
let new_evar env sigma ?src ?naming typ =
- let open Context.Named.Declaration in
- let inst_vars = List.map (get_id %> mkVar) (named_context env.renamed_env) in
- let inst_rels = List.rev (rel_list 0 (nb_rel env.renamed_env)) in
- let (subst, _, nc) = Lazy.force env.extra in
+ let lazy inst_vars = env.renamed_vars in
+ let rec rel_list n accu =
+ if n <= 0 then accu
+ else rel_list (n - 1) (mkRel n :: accu)
+ in
+ let instance = rel_list (nb_rel env.renamed_env) inst_vars in
+ let (subst, _, sign) = Lazy.force env.extra in
let typ' = csubst_subst subst typ in
- let instance = inst_rels @ inst_vars in
- let sign = val_of_named_context nc in
new_evar_instance sign sigma typ' ?src ?naming instance
let new_type_evar env sigma ~src =
diff --git a/pretyping/glob_ops.ml b/pretyping/glob_ops.ml
index cb868e0480..342175a512 100644
--- a/pretyping/glob_ops.ml
+++ b/pretyping/glob_ops.ml
@@ -55,7 +55,7 @@ exception ComplexSort
let glob_sort_family = let open Sorts in function
| UAnonymous {rigid=true} -> InType
- | UNamed [GSProp,0] -> InProp
+ | UNamed [GSProp,0] -> InSProp
| UNamed [GProp,0] -> InProp
| UNamed [GSet,0] -> InSet
| _ -> raise ComplexSort
diff --git a/proofs/clenv.ml b/proofs/clenv.ml
index 87b4255b88..7fb3a21813 100644
--- a/proofs/clenv.ml
+++ b/proofs/clenv.ml
@@ -28,6 +28,7 @@ open Pretype_errors
open Evarutil
open Unification
open Tactypes
+open Logic
(******************************************************************)
(* Clausal environments *)
@@ -41,7 +42,6 @@ type clausenv = {
let cl_env ce = ce.env
let cl_sigma ce = ce.evd
-let clenv_nf_meta clenv c = nf_meta clenv.env clenv.evd c
let clenv_term clenv c = meta_instance clenv.env clenv.evd c
let clenv_meta_type clenv mv = Typing.meta_type clenv.env clenv.evd mv
let clenv_value clenv = meta_instance clenv.env clenv.evd clenv.templval
@@ -376,21 +376,21 @@ let adjust_meta_source evd mv = function
*)
let clenv_pose_metas_as_evars clenv dep_mvs =
- let rec fold clenv evs = function
- | [] -> clenv, evs
+ let rec fold clenv = function
+ | [] -> clenv
| mv::mvs ->
let ty = clenv_meta_type clenv mv in
(* Postpone the evar-ization if dependent on another meta *)
(* This assumes no cycle in the dependencies - is it correct ? *)
- if occur_meta clenv.evd ty then fold clenv evs (mvs@[mv])
+ if occur_meta clenv.evd ty then fold clenv (mvs@[mv])
else
let src = evar_source_of_meta mv clenv.evd in
let src = adjust_meta_source clenv.evd mv src in
let evd = clenv.evd in
let (evd, evar) = new_evar (cl_env clenv) evd ~src ty in
let clenv = clenv_assign mv evar {clenv with evd=evd} in
- fold clenv (fst (destEvar evd evar) :: evs) mvs in
- fold clenv [] dep_mvs
+ fold clenv mvs in
+ fold clenv dep_mvs
(******************************************************************)
@@ -444,8 +444,6 @@ let clenv_fchain ?with_univs ?(flags=fchain_flags ()) mv clenv nextclenv =
(***************************************************************)
(* Bindings *)
-type arg_bindings = constr explicit_bindings
-
(* [clenv_independent clenv]
* returns a list of metavariables which appear in the term cval,
* and which are not dependent. That is, they do not appear in
@@ -598,6 +596,121 @@ let clenv_constrain_dep_args hyps_only bl clenv =
else
error_not_right_number_missing_arguments (List.length occlist)
+
+(* This function put casts around metavariables whose type could not be
+ * inferred by the refiner, that is head of applications, predicates and
+ * subject of Cases.
+ * Does check that the casted type is closed. Anyway, the refiner would
+ * fail in this case... *)
+
+let clenv_cast_meta clenv =
+ let rec crec u =
+ match EConstr.kind clenv.evd u with
+ | App _ | Case _ -> crec_hd u
+ | Cast (c,_,_) when isMeta clenv.evd c -> u
+ | Proj (p, c) -> mkProj (p, crec_hd c)
+ | _ -> EConstr.map clenv.evd crec u
+
+ and crec_hd u =
+ match EConstr.kind clenv.evd (strip_outer_cast clenv.evd u) with
+ | Meta mv ->
+ (try
+ let b = Typing.meta_type clenv.env clenv.evd mv in
+ assert (not (occur_meta clenv.evd b));
+ if occur_meta clenv.evd b then u
+ else mkCast (mkMeta mv, DEFAULTcast, b)
+ with Not_found -> u)
+ | App(f,args) -> mkApp (crec_hd f, Array.map crec args)
+ | Case(ci,p,c,br) ->
+ mkCase (ci, crec_hd p, crec_hd c, Array.map crec br)
+ | Proj (p, c) -> mkProj (p, crec_hd c)
+ | _ -> u
+ in
+ crec
+
+let clenv_value_cast_meta clenv =
+ clenv_cast_meta clenv (clenv_value clenv)
+
+let clenv_pose_dependent_evars ?(with_evars=false) clenv =
+ let dep_mvs = clenv_dependent clenv in
+ let env, sigma = clenv.env, clenv.evd in
+ if not (List.is_empty dep_mvs) && not with_evars then
+ raise
+ (RefinerError (env, sigma, UnresolvedBindings (List.map (meta_name clenv.evd) dep_mvs)));
+ clenv_pose_metas_as_evars clenv dep_mvs
+
+let clenv_refine ?(with_evars=false) ?(with_classes=true) clenv =
+ Proofview.Goal.enter begin fun gl ->
+ let clenv = clenv_pose_dependent_evars ~with_evars clenv in
+ let evd' =
+ if with_classes then
+ let evd' =
+ Typeclasses.resolve_typeclasses ~filter:Typeclasses.all_evars
+ ~fail:(not with_evars) clenv.env clenv.evd
+ in
+ (* After an apply, all the subgoals including those dependent shelved ones are in
+ the hands of the user and resolution won't be called implicitely on them. *)
+ Typeclasses.make_unresolvables (fun x -> true) evd'
+ else clenv.evd
+ in
+ let clenv = { clenv with evd = evd' } in
+ Proofview.tclTHEN
+ (Proofview.Unsafe.tclEVARS (Evd.clear_metas evd'))
+ (refiner ~check:false EConstr.Unsafe.(to_constr (clenv_cast_meta clenv (clenv_value clenv))))
+ end
+
+open Unification
+
+let dft = default_unify_flags
+
+let res_pf ?with_evars ?(with_classes=true) ?(flags=dft ()) clenv =
+ Proofview.Goal.enter begin fun gl ->
+ let clenv = clenv_unique_resolver ~flags clenv gl in
+ clenv_refine ?with_evars ~with_classes clenv
+ end
+
+(* [unifyTerms] et [unify] ne semble pas gérer les Meta, en
+ particulier ne semblent pas vérifier que des instances différentes
+ d'une même Meta sont compatibles. D'ailleurs le "fst" jette les metas
+ provenant de w_Unify. (Utilisé seulement dans prolog.ml) *)
+
+let fail_quick_core_unif_flags = {
+ modulo_conv_on_closed_terms = Some TransparentState.full;
+ use_metas_eagerly_in_conv_on_closed_terms = false;
+ use_evars_eagerly_in_conv_on_closed_terms = false;
+ modulo_delta = TransparentState.empty;
+ modulo_delta_types = TransparentState.full;
+ check_applied_meta_types = false;
+ use_pattern_unification = false;
+ use_meta_bound_pattern_unification = true; (* ? *)
+ allowed_evars = AllowAll;
+ restrict_conv_on_strict_subterms = false; (* ? *)
+ modulo_betaiota = false;
+ modulo_eta = true;
+}
+
+let fail_quick_unif_flags = {
+ core_unify_flags = fail_quick_core_unif_flags;
+ merge_unify_flags = fail_quick_core_unif_flags;
+ subterm_unify_flags = fail_quick_core_unif_flags;
+ allow_K_in_toplevel_higher_order_unification = false;
+ resolve_evars = false
+}
+
+(* let unifyTerms m n = walking (fun wc -> fst (w_Unify CONV m n [] wc)) *)
+let unify ?(flags=fail_quick_unif_flags) m =
+ Proofview.Goal.enter begin fun gl ->
+ let env = Tacmach.New.pf_env gl in
+ let n = Tacmach.New.pf_concl gl in
+ let evd = clear_metas (Tacmach.New.project gl) in
+ try
+ let evd' = w_unify env evd CONV ~flags m n in
+ Proofview.Unsafe.tclEVARSADVANCE evd'
+ with e when CErrors.noncritical e ->
+ let info = Exninfo.reify () in
+ Proofview.tclZERO ~info e
+ end
+
(****************************************************************)
(* Clausal environment for an application *)
diff --git a/proofs/clenv.mli b/proofs/clenv.mli
index 4279ab4768..fd1e2fe593 100644
--- a/proofs/clenv.mli
+++ b/proofs/clenv.mli
@@ -37,9 +37,6 @@ val clenv_value : clausenv -> constr
(** type of clenv (instantiated) *)
val clenv_type : clausenv -> types
-(** substitute resolved metas *)
-val clenv_nf_meta : clausenv -> EConstr.constr -> EConstr.constr
-
(** type of a meta in clenv context *)
val clenv_meta_type : clausenv -> metavariable -> types
@@ -62,18 +59,8 @@ val clenv_fchain :
val clenv_unify :
?flags:unify_flags -> conv_pb -> constr -> constr -> clausenv -> clausenv
-(** unifies the concl of the goal with the type of the clenv *)
-val clenv_unique_resolver :
- ?flags:unify_flags -> clausenv -> Proofview.Goal.t -> clausenv
-
-val clenv_dependent : clausenv -> metavariable list
-
-val clenv_pose_metas_as_evars : clausenv -> metavariable list -> clausenv * Evar.t list
-
(** {6 Bindings } *)
-type arg_bindings = constr explicit_bindings
-
(** bindings where the key is the position in the template of the
clenv (dependent or not). Positions can be negative meaning to
start from the rightmost argument of the template. *)
@@ -109,6 +96,14 @@ val make_clenv_binding :
exception NotExtensibleClause
val clenv_push_prod : clausenv -> clausenv
+(** {6 Clenv tactics} *)
+
+val unify : ?flags:unify_flags -> constr -> unit Proofview.tactic
+val res_pf : ?with_evars:bool -> ?with_classes:bool -> ?flags:unify_flags -> clausenv -> unit Proofview.tactic
+
+val clenv_pose_dependent_evars : ?with_evars:bool -> clausenv -> clausenv
+val clenv_value_cast_meta : clausenv -> constr
+
(** {6 Pretty-print (debug only) } *)
val pr_clenv : clausenv -> Pp.t
diff --git a/proofs/clenvtac.ml b/proofs/clenvtac.ml
deleted file mode 100644
index 007d53f911..0000000000
--- a/proofs/clenvtac.ml
+++ /dev/null
@@ -1,135 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * Copyright INRIA, CNRS and contributors *)
-(* <O___,, * (see version control and CREDITS file for authors & dates) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-open Util
-open Constr
-open Termops
-open Evd
-open EConstr
-open Logic
-open Reduction
-open Clenv
-
-(* This function put casts around metavariables whose type could not be
- * inferred by the refiner, that is head of applications, predicates and
- * subject of Cases.
- * Does check that the casted type is closed. Anyway, the refiner would
- * fail in this case... *)
-
-let clenv_cast_meta clenv =
- let rec crec u =
- match EConstr.kind clenv.evd u with
- | App _ | Case _ -> crec_hd u
- | Cast (c,_,_) when isMeta clenv.evd c -> u
- | Proj (p, c) -> mkProj (p, crec_hd c)
- | _ -> EConstr.map clenv.evd crec u
-
- and crec_hd u =
- match EConstr.kind clenv.evd (strip_outer_cast clenv.evd u) with
- | Meta mv ->
- (try
- let b = Typing.meta_type clenv.env clenv.evd mv in
- assert (not (occur_meta clenv.evd b));
- if occur_meta clenv.evd b then u
- else mkCast (mkMeta mv, DEFAULTcast, b)
- with Not_found -> u)
- | App(f,args) -> mkApp (crec_hd f, Array.map crec args)
- | Case(ci,p,c,br) ->
- mkCase (ci, crec_hd p, crec_hd c, Array.map crec br)
- | Proj (p, c) -> mkProj (p, crec_hd c)
- | _ -> u
- in
- crec
-
-let clenv_value_cast_meta clenv =
- clenv_cast_meta clenv (clenv_value clenv)
-
-let clenv_pose_dependent_evars ?(with_evars=false) clenv =
- let dep_mvs = clenv_dependent clenv in
- let env, sigma = clenv.env, clenv.evd in
- if not (List.is_empty dep_mvs) && not with_evars then
- raise
- (RefinerError (env, sigma, UnresolvedBindings (List.map (meta_name clenv.evd) dep_mvs)));
- clenv_pose_metas_as_evars clenv dep_mvs
-
-let clenv_refine ?(with_evars=false) ?(with_classes=true) clenv =
- Proofview.Goal.enter begin fun gl ->
- let clenv, evars = clenv_pose_dependent_evars ~with_evars clenv in
- let evd' =
- if with_classes then
- let evd' =
- Typeclasses.resolve_typeclasses ~filter:Typeclasses.all_evars
- ~fail:(not with_evars) clenv.env clenv.evd
- in
- (* After an apply, all the subgoals including those dependent shelved ones are in
- the hands of the user and resolution won't be called implicitely on them. *)
- Typeclasses.make_unresolvables (fun x -> true) evd'
- else clenv.evd
- in
- let clenv = { clenv with evd = evd' } in
- Proofview.tclTHEN
- (Proofview.Unsafe.tclEVARS (Evd.clear_metas evd'))
- (refiner ~check:false EConstr.Unsafe.(to_constr (clenv_cast_meta clenv (clenv_value clenv))))
- end
-
-let clenv_pose_dependent_evars ?(with_evars=false) clenv =
- fst (clenv_pose_dependent_evars ~with_evars clenv)
-
-open Unification
-
-let dft = default_unify_flags
-
-let res_pf ?with_evars ?(with_classes=true) ?(flags=dft ()) clenv =
- Proofview.Goal.enter begin fun gl ->
- let clenv = clenv_unique_resolver ~flags clenv gl in
- clenv_refine ?with_evars ~with_classes clenv
- end
-
-(* [unifyTerms] et [unify] ne semble pas gérer les Meta, en
- particulier ne semblent pas vérifier que des instances différentes
- d'une même Meta sont compatibles. D'ailleurs le "fst" jette les metas
- provenant de w_Unify. (Utilisé seulement dans prolog.ml) *)
-
-let fail_quick_core_unif_flags = {
- modulo_conv_on_closed_terms = Some TransparentState.full;
- use_metas_eagerly_in_conv_on_closed_terms = false;
- use_evars_eagerly_in_conv_on_closed_terms = false;
- modulo_delta = TransparentState.empty;
- modulo_delta_types = TransparentState.full;
- check_applied_meta_types = false;
- use_pattern_unification = false;
- use_meta_bound_pattern_unification = true; (* ? *)
- allowed_evars = AllowAll;
- restrict_conv_on_strict_subterms = false; (* ? *)
- modulo_betaiota = false;
- modulo_eta = true;
-}
-
-let fail_quick_unif_flags = {
- core_unify_flags = fail_quick_core_unif_flags;
- merge_unify_flags = fail_quick_core_unif_flags;
- subterm_unify_flags = fail_quick_core_unif_flags;
- allow_K_in_toplevel_higher_order_unification = false;
- resolve_evars = false
-}
-
-(* let unifyTerms m n = walking (fun wc -> fst (w_Unify CONV m n [] wc)) *)
-let unify ?(flags=fail_quick_unif_flags) m =
- Proofview.Goal.enter begin fun gl ->
- let env = Tacmach.New.pf_env gl in
- let n = Tacmach.New.pf_concl gl in
- let evd = clear_metas (Tacmach.New.project gl) in
- try
- let evd' = w_unify env evd CONV ~flags m n in
- Proofview.Unsafe.tclEVARSADVANCE evd'
- with e when CErrors.noncritical e ->
- let info = Exninfo.reify () in
- Proofview.tclZERO ~info e
- end
diff --git a/proofs/clenvtac.mli b/proofs/clenvtac.mli
deleted file mode 100644
index 6eafca359b..0000000000
--- a/proofs/clenvtac.mli
+++ /dev/null
@@ -1,23 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * Copyright INRIA, CNRS and contributors *)
-(* <O___,, * (see version control and CREDITS file for authors & dates) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-(** Legacy components of the previous proof engine. *)
-
-open Clenv
-open EConstr
-open Unification
-
-(** Tactics *)
-val unify : ?flags:unify_flags -> constr -> unit Proofview.tactic
-val clenv_refine : ?with_evars:bool -> ?with_classes:bool -> clausenv -> unit Proofview.tactic
-val res_pf : ?with_evars:bool -> ?with_classes:bool -> ?flags:unify_flags -> clausenv -> unit Proofview.tactic
-
-val clenv_pose_dependent_evars : ?with_evars:bool -> clausenv -> clausenv
-val clenv_value_cast_meta : clausenv -> constr
diff --git a/proofs/logic.ml b/proofs/logic.ml
index c7a1c32e7c..07ea2ea572 100644
--- a/proofs/logic.ml
+++ b/proofs/logic.ml
@@ -20,7 +20,6 @@ open Environ
open Reductionops
open Inductiveops
open Typing
-open Type_errors
open Retyping
module NamedDecl = Context.Named.Declaration
@@ -40,34 +39,6 @@ type refiner_error =
exception RefinerError of Environ.env * Evd.evar_map * refiner_error
-open Pretype_errors
-
-(** FIXME: this is quite brittle. Why not accept any PretypeError? *)
-let is_typing_error = function
-| UnexpectedType (_, _) | NotProduct _
-| VarNotFound _ | TypingError _ -> true
-| _ -> false
-
-let is_unification_error = function
-| CannotUnify _ | CannotUnifyLocal _| CannotGeneralize _
-| NoOccurrenceFound _ | CannotUnifyBindingType _
-| ActualTypeNotCoercible _ | UnifOccurCheck _
-| CannotFindWellTypedAbstraction _ | WrongAbstractionType _
-| UnsolvableImplicit _| AbstractionOverMeta _
-| UnsatisfiableConstraints _ -> true
-| _ -> false
-
-let catchable_exception = function
- | CErrors.UserError _ | TypeError _
- | Proof.OpenProof _
- (* abstract will call close_proof inside a tactic *)
- | RefinerError _ | Indrec.RecursionSchemeError _
- | Nametab.GlobalizationError _
- (* reduction errors *)
- | Tacred.ReductionTacticError _ -> true
- (* unification and typing errors *)
- | PretypeError(_,_, e) -> is_unification_error e || is_typing_error e
- | _ -> false
let error_no_such_hypothesis env sigma id = raise (RefinerError (env, sigma, NoSuchHyp id))
diff --git a/proofs/logic.mli b/proofs/logic.mli
index 9dc75000a1..21757e47dc 100644
--- a/proofs/logic.mli
+++ b/proofs/logic.mli
@@ -47,9 +47,6 @@ exception RefinerError of Environ.env * evar_map * refiner_error
val error_no_such_hypothesis : Environ.env -> evar_map -> Id.t -> 'a
-val catchable_exception : exn -> bool
-[@@ocaml.deprecated "This function does not scale in the presence of dynamically added exceptions. Use instead CErrors.noncritical, or the exact name of the exception that matters in the corresponding case."]
-
(** Move destination for hypothesis *)
type 'id move_location =
diff --git a/proofs/proof.ml b/proofs/proof.ml
index 175c487958..a183fa7797 100644
--- a/proofs/proof.ml
+++ b/proofs/proof.ml
@@ -120,7 +120,7 @@ type t =
; name : Names.Id.t
(** the name of the theorem whose proof is being constructed *)
; poly : bool
- (** Locality, polymorphism, and "kind" [Coercion, Definition, etc...] *)
+ (** polymorphism *)
}
(*** General proof functions ***)
diff --git a/proofs/proofs.mllib b/proofs/proofs.mllib
index 756fef0511..790a9dd2cc 100644
--- a/proofs/proofs.mllib
+++ b/proofs/proofs.mllib
@@ -9,4 +9,3 @@ Proof_bullet
Refiner
Tacmach
Clenv
-Clenvtac
diff --git a/stm/proofBlockDelimiter.ml b/stm/proofBlockDelimiter.ml
index 2ff76e69f8..3d892fa5ca 100644
--- a/stm/proofBlockDelimiter.ml
+++ b/stm/proofBlockDelimiter.ml
@@ -49,8 +49,8 @@ let is_focused_goal_simple ~doc id =
match state_of_id ~doc id with
| `Expired | `Error _ | `Valid None -> `Not
| `Valid (Some { Vernacstate.lemmas }) ->
- Option.cata (Vernacstate.LemmaStack.with_top_pstate ~f:(fun proof ->
- let proof = Declare.Proof.get_proof proof in
+ Option.cata (Vernacstate.LemmaStack.with_top ~f:(fun proof ->
+ let proof = Declare.Proof.get proof in
let Proof.{ goals=focused; stack=r1; shelf=r2; given_up=r3; sigma } = Proof.data proof in
let rest = List.(flatten (map (fun (x,y) -> x @ y) r1)) @ r2 @ r3 in
if List.for_all (fun x -> simple_goal sigma x rest) focused
diff --git a/stm/stm.ml b/stm/stm.ml
index b72cee7a9d..652d064b83 100644
--- a/stm/stm.ml
+++ b/stm/stm.ml
@@ -147,7 +147,7 @@ let update_global_env () =
PG_compat.update_global_env ()
module Vcs_ = Vcs.Make(Stateid.Self)
-type future_proof = Declare.closed_proof_output Future.computation
+type future_proof = Declare.Proof.closed_proof_output Future.computation
type depth = int
type branch_type =
@@ -1047,9 +1047,9 @@ end = struct (* {{{ *)
end (* }}} *)
(* Wrapper for the proof-closing special path for Qed *)
-let stm_qed_delay_proof ?route ~proof ~info ~id ~st ~loc ~control pending : Vernacstate.t =
+let stm_qed_delay_proof ?route ~proof ~pinfo ~id ~st ~loc ~control pending : Vernacstate.t =
set_id_for_feedback ?route dummy_doc id;
- Vernacinterp.interp_qed_delayed_proof ~proof ~info ~st ~control (CAst.make ?loc pending)
+ Vernacinterp.interp_qed_delayed_proof ~proof ~pinfo ~st ~control (CAst.make ?loc pending)
(* Wrapper for Vernacentries.interp to set the feedback id *)
(* It is currently called 19 times, this number should be certainly
@@ -1157,7 +1157,8 @@ end = struct (* {{{ *)
let get_proof ~doc id =
match state_of_id ~doc id with
- | `Valid (Some vstate) -> Option.map (Vernacstate.LemmaStack.with_top_pstate ~f:Declare.Proof.get_proof) vstate.Vernacstate.lemmas
+ | `Valid (Some vstate) ->
+ Option.map (Vernacstate.LemmaStack.with_top ~f:Declare.Proof.get) vstate.Vernacstate.lemmas
| _ -> None
let undo_vernac_classifier v ~doc =
@@ -1351,7 +1352,7 @@ module rec ProofTask : sig
t_stop : Stateid.t;
t_drop : bool;
t_states : competence;
- t_assign : Declare.closed_proof_output Future.assignment -> unit;
+ t_assign : Declare.Proof.closed_proof_output Future.assignment -> unit;
t_loc : Loc.t option;
t_uuid : Future.UUID.t;
t_name : string }
@@ -1374,7 +1375,7 @@ module rec ProofTask : sig
?loc:Loc.t ->
drop_pt:bool ->
Stateid.t * Stateid.t -> Stateid.t ->
- Declare.closed_proof_output Future.computation
+ Declare.Proof.closed_proof_output Future.computation
(* If set, only tasks overlapping with this list are processed *)
val set_perspective : Stateid.t list -> unit
@@ -1390,7 +1391,7 @@ end = struct (* {{{ *)
t_stop : Stateid.t;
t_drop : bool;
t_states : competence;
- t_assign : Declare.closed_proof_output Future.assignment -> unit;
+ t_assign : Declare.Proof.closed_proof_output Future.assignment -> unit;
t_loc : Loc.t option;
t_uuid : Future.UUID.t;
t_name : string }
@@ -1412,7 +1413,7 @@ end = struct (* {{{ *)
e_safe_states : Stateid.t list }
type response =
- | RespBuiltProof of Declare.closed_proof_output * float
+ | RespBuiltProof of Declare.Proof.closed_proof_output * float
| RespError of error
| RespStates of (Stateid.t * State.partial_state) list
@@ -1522,11 +1523,12 @@ end = struct (* {{{ *)
PG_compat.close_future_proof ~feedback_id:stop (Future.from_val proof) in
let st = Vernacstate.freeze_interp_state ~marshallable:false in
- let opaque = Declare.Opaque in
+ let opaque = Opaque in
try
let _pstate =
+ let pinfo = Declare.Proof.Proof_info.default () in
stm_qed_delay_proof ~st ~id:stop
- ~proof:pobject ~info:(Lemmas.Info.make ()) ~loc ~control:[] (Proved (opaque,None)) in
+ ~proof:pobject ~pinfo ~loc ~control:[] (Proved (opaque,None)) in
()
with exn ->
(* If [stm_qed_delay_proof] fails above we need to use the
@@ -1666,13 +1668,13 @@ end = struct (* {{{ *)
let _proof = PG_compat.return_partial_proof () in
`OK_ADMITTED
else begin
- let opaque = Declare.Opaque in
+ let opaque = Opaque in
(* The original terminator, a hook, has not been saved in the .vio*)
let proof, _info =
PG_compat.close_proof ~opaque ~keep_body_ucst_separate:true in
- let info = Lemmas.Info.make () in
+ let pinfo = Declare.Proof.Proof_info.default () in
(* We jump at the beginning since the kernel handles side effects by also
* looking at the ones that happen to be present in the current env *)
@@ -1685,9 +1687,9 @@ end = struct (* {{{ *)
*)
(* STATE We use the state resulting from reaching start. *)
let st = Vernacstate.freeze_interp_state ~marshallable:false in
- ignore(stm_qed_delay_proof ~id:stop ~st ~proof ~info ~loc ~control:[] (Proved (opaque,None)));
+ ignore(stm_qed_delay_proof ~id:stop ~st ~proof ~pinfo ~loc ~control:[] (Proved (opaque,None)));
(* Is this name the same than the one in scope? *)
- let name = Declare.get_po_name proof in
+ let name = Declare.Proof.get_po_name proof in
`OK name
end
with e ->
@@ -1932,8 +1934,7 @@ end = struct (* {{{ *)
List.for_all (Context.Named.Declaration.for_all is_ground)
Evd.(evar_context g))
then
- CErrors.user_err ~hdr:"STM" Pp.(strbrk("the par: goal selector supports ground "^
- "goals only"))
+ CErrors.user_err ~hdr:"STM" Pp.(strbrk("The par: goal selector does not support goals with existential variables"))
else begin
let (i, ast) = r_ast in
PG_compat.map_proof (fun p -> Proof.focus focus_cond () i p);
@@ -1950,10 +1951,15 @@ end = struct (* {{{ *)
| Evd.Evar_empty -> RespNoProgress
| Evd.Evar_defined t ->
let t = Evarutil.nf_evar sigma t in
- if Evarutil.is_ground_term sigma t then
+ let evars = Evarutil.undefined_evars_of_term sigma t in
+ if Evar.Set.is_empty evars then
let t = EConstr.Unsafe.to_constr t in
RespBuiltSubProof (t, Evd.evar_universe_context sigma)
- else CErrors.user_err ~hdr:"STM" Pp.(str"The solution is not ground")
+ else
+ CErrors.user_err ~hdr:"STM"
+ Pp.(str"The par: selector requires a tactic that makes no progress or fully" ++
+ str" solves the goal and leaves no unresolved existential variables. The following" ++
+ str" existentials remain unsolved: " ++ prlist (Termops.pr_existential_key sigma) (Evar.Set.elements evars))
end) ()
with e when CErrors.noncritical e -> RespError (CErrors.print e)
@@ -2157,7 +2163,7 @@ let collect_proof keep cur hd brkind id =
| id :: _ -> Names.Id.to_string id in
let loc = (snd cur).expr.CAst.loc in
let is_defined_expr = function
- | VernacEndProof (Proved (Declare.Transparent,_)) -> true
+ | VernacEndProof (Proved (Transparent,_)) -> true
| _ -> false in
let is_defined = function
| _, { expr = e } -> is_defined_expr e.CAst.v.expr
@@ -2492,13 +2498,13 @@ let known_state ~doc ?(redefine_qed=false) ~cache id =
| VtKeepDefined ->
CErrors.anomaly (Pp.str "Cannot delegate transparent proofs, this is a bug in the STM.")
in
- let proof, info =
+ let proof, pinfo =
PG_compat.close_future_proof ~feedback_id:id fp in
if not delegate then ignore(Future.compute fp);
reach view.next;
let st = Vernacstate.freeze_interp_state ~marshallable:false in
let control, pe = extract_pe x in
- ignore(stm_qed_delay_proof ~id ~st ~proof ~info ~loc ~control pe);
+ ignore(stm_qed_delay_proof ~id ~st ~proof ~pinfo ~loc ~control pe);
feedback ~id:id Incomplete
| { VCS.kind = `Master }, _ -> assert false
end;
@@ -2522,7 +2528,7 @@ let known_state ~doc ?(redefine_qed=false) ~cache id =
| VtKeep VtKeepAxiom ->
qed.fproof <- Some (None, ref false); None
| VtKeep opaque ->
- let opaque = let open Declare in match opaque with
+ let opaque = match opaque with
| VtKeepOpaque -> Opaque | VtKeepDefined -> Transparent
| VtKeepAxiom -> assert false
in
@@ -2537,9 +2543,9 @@ let known_state ~doc ?(redefine_qed=false) ~cache id =
let st = Vernacstate.freeze_interp_state ~marshallable:false in
let _st = match proof with
| None -> stm_vernac_interp id st x
- | Some (proof, info) ->
+ | Some (proof, pinfo) ->
let control, pe = extract_pe x in
- stm_qed_delay_proof ~id ~st ~proof ~info ~loc ~control pe
+ stm_qed_delay_proof ~id ~st ~proof ~pinfo ~loc ~control pe
in
let wall_clock3 = Unix.gettimeofday () in
Aux_file.record_in_aux_at ?loc:x.expr.CAst.loc "proof_check_time"
diff --git a/stm/vernac_classifier.ml b/stm/vernac_classifier.ml
index cf127648b4..a957f7354f 100644
--- a/stm/vernac_classifier.ml
+++ b/stm/vernac_classifier.ml
@@ -37,7 +37,7 @@ let string_of_vernac_classification = function
| VtMeta -> "Meta "
| VtProofMode _ -> "Proof Mode"
-let vtkeep_of_opaque = let open Declare in function
+let vtkeep_of_opaque = function
| Opaque -> VtKeepOpaque
| Transparent -> VtKeepDefined
diff --git a/tactics/auto.ml b/tactics/auto.ml
index 681c4e910f..3287c1c354 100644
--- a/tactics/auto.ml
+++ b/tactics/auto.ml
@@ -29,7 +29,7 @@ open Hints
(* tactics with a trace mechanism for automatic search *)
(**************************************************************************)
-let priority l = List.filter (fun (_, hint) -> Int.equal hint.pri 0) l
+let priority l = List.filter (fun (_, hint) -> Int.equal (FullHint.priority hint) 0) l
let compute_secvars gl =
let hyps = Proofview.Goal.hyps gl in
@@ -69,7 +69,8 @@ let auto_unif_flags =
(* Try unification with the precompiled clause, then use registered Apply *)
-let connect_hint_clenv ~poly (c, _, ctx) clenv gl =
+let connect_hint_clenv h gl =
+ let { hint_term = c; hint_uctx = ctx; hint_clnv = clenv } = h in
(* [clenv] has been generated by a hint-making function, so the only relevant
data in its evarmap is the set of metas. The [evar_reset_evd] function
below just replaces the metas of sigma by those coming from the clenv. *)
@@ -77,7 +78,7 @@ let connect_hint_clenv ~poly (c, _, ctx) clenv gl =
let evd = Evd.evars_reset_evd ~with_conv_pbs:true ~with_univs:false sigma clenv.evd in
(* Still, we need to update the universes *)
let clenv, c =
- if poly then
+ if h.hint_poly then
(* Refresh the instance of the hint *)
let (subst, ctx) = UnivGen.fresh_universe_context_set_instance ctx in
let emap c = Vars.subst_univs_level_constr subst c in
@@ -95,22 +96,21 @@ let connect_hint_clenv ~poly (c, _, ctx) clenv gl =
{ clenv with evd = evd ; env = Proofview.Goal.env gl }, c
in clenv, c
-let unify_resolve ~poly flags ((c : raw_hint), clenv) =
+let unify_resolve flags (h : hint) =
Proofview.Goal.enter begin fun gl ->
- let clenv, c = connect_hint_clenv ~poly c clenv gl in
- let clenv = clenv_unique_resolver ~flags clenv gl in
- Clenvtac.clenv_refine clenv
+ let clenv, c = connect_hint_clenv h gl in
+ Clenv.res_pf ~flags clenv
end
-let unify_resolve_nodelta poly h = unify_resolve ~poly auto_unif_flags h
+let unify_resolve_nodelta h = unify_resolve auto_unif_flags h
-let unify_resolve_gen ~poly = function
- | None -> unify_resolve_nodelta poly
- | Some flags -> unify_resolve ~poly flags
+let unify_resolve_gen = function
+ | None -> unify_resolve_nodelta
+ | Some flags -> unify_resolve flags
-let exact poly (c,clenv) =
+let exact h =
Proofview.Goal.enter begin fun gl ->
- let clenv', c = connect_hint_clenv ~poly c clenv gl in
+ let clenv', c = connect_hint_clenv h gl in
Tacticals.New.tclTHEN
(Proofview.Unsafe.tclEVARUNIVCONTEXT (Evd.evar_universe_context clenv'.evd))
(exact_check c)
@@ -381,16 +381,16 @@ and my_find_search_delta sigma db_list local_db secvars hdc concl =
in List.map (fun x -> (Some flags,x)) l)
(local_db::db_list)
-and tac_of_hint dbg db_list local_db concl (flags, ({pat=p; code=t;poly=poly;db=dbname})) =
+and tac_of_hint dbg db_list local_db concl (flags, h) =
let tactic = function
- | Res_pf (c,cl) -> unify_resolve_gen ~poly flags (c,cl)
+ | Res_pf h -> unify_resolve_gen flags h
| ERes_pf _ -> Proofview.Goal.enter (fun gl ->
let info = Exninfo.reify () in
Tacticals.New.tclZEROMSG ~info (str "eres_pf"))
- | Give_exact (c, cl) -> exact poly (c, cl)
- | Res_pf_THEN_trivial_fail (c,cl) ->
+ | Give_exact h -> exact h
+ | Res_pf_THEN_trivial_fail h ->
Tacticals.New.tclTHEN
- (unify_resolve_gen ~poly flags (c,cl))
+ (unify_resolve_gen flags h)
(* With "(debug) trivial", we shouldn't end here, and
with "debug auto" we don't display the details of inner trivial *)
(trivial_fail_db (no_dbg dbg) (not (Option.is_empty flags)) db_list local_db)
@@ -403,16 +403,17 @@ and tac_of_hint dbg db_list local_db concl (flags, ({pat=p; code=t;poly=poly;db=
Tacticals.New.tclFAIL ~info 0 (str"Unbound reference")
end
| Extern tacast ->
+ let p = FullHint.pattern h in
conclPattern concl p tacast
in
let pr_hint env sigma =
- let origin = match dbname with
+ let origin = match FullHint.database h with
| None -> mt ()
| Some n -> str " (in " ++ str n ++ str ")"
in
- pr_hint env sigma t ++ origin
+ FullHint.print env sigma h ++ origin
in
- tclLOG dbg pr_hint (run_hint t tactic)
+ tclLOG dbg pr_hint (FullHint.run h tactic)
and trivial_resolve sigma dbg mod_delta db_list local_db secvars cl =
try
diff --git a/tactics/auto.mli b/tactics/auto.mli
index 33deefd0bd..903da143d2 100644
--- a/tactics/auto.mli
+++ b/tactics/auto.mli
@@ -24,10 +24,10 @@ val default_search_depth : int ref
val auto_flags_of_state : TransparentState.t -> Unification.unify_flags
val connect_hint_clenv
- : poly:bool -> raw_hint -> clausenv -> Proofview.Goal.t -> clausenv * constr
+ : hint -> Proofview.Goal.t -> clausenv * constr
(** Try unification with the precompiled clause, then use registered Apply *)
-val unify_resolve : poly:bool -> Unification.unify_flags -> (raw_hint * clausenv) -> unit Proofview.tactic
+val unify_resolve : Unification.unify_flags -> hint -> unit Proofview.tactic
(** [ConclPattern concl pat tacast]:
if the term concl matches the pattern pat, (in sense of
diff --git a/tactics/autorewrite.ml b/tactics/autorewrite.ml
index eaefa2947a..cc56de066d 100644
--- a/tactics/autorewrite.ml
+++ b/tactics/autorewrite.ml
@@ -212,60 +212,37 @@ let inHintRewrite : string * HintDN.t -> Libobject.obj =
~cache:cache_hintrewrite
~subst:(Some subst_hintrewrite)
-open Clenv
-
type hypinfo = {
- hyp_cl : clausenv;
- hyp_prf : constr;
- hyp_ty : types;
- hyp_car : constr;
- hyp_rel : constr;
- hyp_l2r : bool;
- hyp_left : constr;
- hyp_right : constr;
+ hyp_ty : EConstr.types;
+ hyp_pat : EConstr.constr;
}
-let decompose_applied_relation metas env sigma c ctype left2right =
+let decompose_applied_relation env sigma c ctype left2right =
let find_rel ty =
- let eqclause = Clenv.mk_clenv_from_env env sigma None (EConstr.of_constr c,ty) in
- let eqclause =
- if metas then eqclause
- else fst (clenv_pose_metas_as_evars eqclause (Evd.undefined_metas eqclause.evd))
- in
- let (equiv, args) = EConstr.decompose_app sigma (Clenv.clenv_type eqclause) in
- let rec split_last_two = function
- | [c1;c2] -> [],(c1, c2)
- | x::y::z ->
- let l,res = split_last_two (y::z) in x::l, res
- | _ -> raise Not_found
- in
- try
- let others,(c1,c2) = split_last_two args in
- let ty1, ty2 = Retyping.get_type_of env eqclause.evd c1, Retyping.get_type_of env eqclause.evd c2 in
- (* XXX: It looks like mk_clenv_from_env should be fixed instead? *)
- let open EConstr in
- let hyp_ty = Unsafe.to_constr ty in
- let hyp_car = Unsafe.to_constr ty1 in
- let hyp_prf = Unsafe.to_constr @@ Clenv.clenv_value eqclause in
- let hyp_rel = Unsafe.to_constr @@ mkApp (equiv, Array.of_list others) in
- let hyp_left = Unsafe.to_constr @@ c1 in
- let hyp_right = Unsafe.to_constr @@ c2 in
-(* if not (evd_convertible env eqclause.evd ty1 ty2) then None *)
-(* else *)
- Some { hyp_cl=eqclause; hyp_prf; hyp_ty; hyp_car; hyp_rel; hyp_l2r=left2right; hyp_left; hyp_right; }
- with Not_found -> None
+ (* FIXME: this is nonsense, we generate evars and then we drop the
+ corresponding evarmap. This sometimes works because [Term_dnet] performs
+ evar surgery via [Termops.filtering]. *)
+ let sigma, ty = Clenv.make_evar_clause env sigma ty in
+ let (_, args) = Termops.decompose_app_vect sigma ty.Clenv.cl_concl in
+ let len = Array.length args in
+ if 2 <= len then
+ let c1 = args.(len - 2) in
+ let c2 = args.(len - 1) in
+ Some (if left2right then c1 else c2)
+ else None
in
match find_rel ctype with
- | Some c -> Some c
+ | Some c -> Some { hyp_pat = c; hyp_ty = ctype }
| None ->
let ctx,t' = Reductionops.splay_prod_assum env sigma ctype in (* Search for underlying eq *)
- match find_rel (it_mkProd_or_LetIn t' ctx) with
- | Some c -> Some c
+ let ctype = it_mkProd_or_LetIn t' ctx in
+ match find_rel ctype with
+ | Some c -> Some { hyp_pat = c; hyp_ty = ctype }
| None -> None
-let find_applied_relation ?loc metas env sigma c left2right =
+let find_applied_relation ?loc env sigma c left2right =
let ctype = Retyping.get_type_of env sigma (EConstr.of_constr c) in
- match decompose_applied_relation metas env sigma c ctype left2right with
+ match decompose_applied_relation env sigma c ctype left2right with
| Some c -> c
| None ->
user_err ?loc ~hdr:"decompose_applied_relation"
@@ -283,9 +260,9 @@ let add_rew_rules base lrul =
List.fold_left
(fun dn {CAst.loc;v=((c,ctx),b,t)} ->
let sigma = Evd.merge_context_set Evd.univ_rigid sigma ctx in
- let info = find_applied_relation ?loc false env sigma c b in
- let pat = if b then info.hyp_left else info.hyp_right in
- let rul = { rew_lemma = c; rew_type = info.hyp_ty;
+ let info = find_applied_relation ?loc env sigma c b in
+ let pat = EConstr.Unsafe.to_constr info.hyp_pat in
+ let rul = { rew_lemma = c; rew_type = EConstr.Unsafe.to_constr info.hyp_ty;
rew_pat = pat; rew_ctx = ctx; rew_l2r = b;
rew_tac = Option.map intern t}
in incr counter;
diff --git a/tactics/autorewrite.mli b/tactics/autorewrite.mli
index 8f7a1c8fcf..974aef8e8f 100644
--- a/tactics/autorewrite.mli
+++ b/tactics/autorewrite.mli
@@ -43,22 +43,3 @@ val auto_multi_rewrite : ?conds:conditions -> string list -> Locus.clause -> uni
val auto_multi_rewrite_with : ?conds:conditions -> unit Proofview.tactic -> string list -> Locus.clause -> unit Proofview.tactic
val print_rewrite_hintdb : string -> Pp.t
-
-open Clenv
-
-
-type hypinfo = {
- hyp_cl : clausenv;
- hyp_prf : constr;
- hyp_ty : types;
- hyp_car : constr;
- hyp_rel : constr;
- hyp_l2r : bool;
- hyp_left : constr;
- hyp_right : constr;
-}
-
-val find_applied_relation :
- ?loc:Loc.t -> bool ->
- Environ.env -> Evd.evar_map -> constr -> bool -> hypinfo
-
diff --git a/tactics/class_tactics.ml b/tactics/class_tactics.ml
index 195073d7aa..4156d5f0ee 100644
--- a/tactics/class_tactics.ml
+++ b/tactics/class_tactics.ml
@@ -14,7 +14,6 @@
*)
open Pp
-open CErrors
open Util
open Names
open Term
@@ -144,13 +143,13 @@ let auto_unif_flags ?(allowed_evars = AllowAll) st =
resolve_evars = false
}
-let e_give_exact flags poly (c,clenv) =
+let e_give_exact flags h =
+ let { hint_term = c; hint_clnv = clenv } = h in
let open Tacmach.New in
Proofview.Goal.enter begin fun gl ->
let sigma = project gl in
- let (c, _, _) = c in
let c, sigma =
- if poly then
+ if h.hint_poly then
let clenv', subst = Clenv.refresh_undefined_univs clenv in
let evd = evars_reset_evd ~with_conv_pbs:true sigma clenv'.evd in
let c = Vars.subst_univs_level_constr subst c in
@@ -159,37 +158,28 @@ let e_give_exact flags poly (c,clenv) =
in
let (sigma, t1) = Typing.type_of (pf_env gl) sigma c in
Proofview.Unsafe.tclEVARS sigma <*>
- Clenvtac.unify ~flags t1 <*> exact_no_check c
+ Clenv.unify ~flags t1 <*> exact_no_check c
end
-let clenv_unique_resolver_tac with_evars ~flags clenv' =
- Proofview.Goal.enter begin fun gls ->
- let resolve =
- try Proofview.tclUNIT (clenv_unique_resolver ~flags clenv' gls)
- with e when noncritical e ->
- let _, info = Exninfo.capture e in
- Proofview.tclZERO ~info e
- in resolve >>= fun clenv' ->
- Clenvtac.clenv_refine ~with_evars ~with_classes:false clenv'
+let unify_e_resolve flags = begin fun gls (h, _) ->
+ let clenv', c = connect_hint_clenv h gls in
+ Clenv.res_pf ~with_evars:true ~with_classes:false ~flags clenv'
end
-let unify_e_resolve poly flags = begin fun gls (c,_,clenv) ->
- let clenv', c = connect_hint_clenv ~poly c clenv gls in
- clenv_unique_resolver_tac true ~flags clenv' end
-
-let unify_resolve poly flags = begin fun gls (c,_,clenv) ->
- let clenv', _ = connect_hint_clenv ~poly c clenv gls in
- clenv_unique_resolver_tac false ~flags clenv'
+let unify_resolve flags = begin fun gls (h, _) ->
+ let clenv', _ = connect_hint_clenv h gls in
+ Clenv.res_pf ~with_evars:false ~with_classes:false ~flags clenv'
end
(** Application of a lemma using [refine] instead of the old [w_unify] *)
-let unify_resolve_refine poly flags gls ((c, t, ctx),n,clenv) =
+let unify_resolve_refine flags gls (h, n) =
+ let { hint_term = c; hint_type = t; hint_uctx = ctx; hint_clnv = clenv } = h in
let open Clenv in
let env = Proofview.Goal.env gls in
let concl = Proofview.Goal.concl gls in
Refine.refine ~typecheck:false begin fun sigma ->
let sigma, term, ty =
- if poly then
+ if h.hint_poly then
let (subst, ctx) = UnivGen.fresh_universe_context_set_instance ctx in
let map c = Vars.subst_univs_level_constr subst c in
let sigma = Evd.merge_context_set Evd.univ_flexible sigma ctx in
@@ -206,9 +196,9 @@ let unify_resolve_refine poly flags gls ((c, t, ctx),n,clenv) =
env sigma' cl.cl_concl concl)
in (sigma', term) end
-let unify_resolve_refine poly flags gl clenv =
+let unify_resolve_refine flags gl clenv =
Proofview.tclORELSE
- (unify_resolve_refine poly flags gl clenv)
+ (unify_resolve_refine flags gl clenv)
(fun (exn,info) ->
match exn with
| Evarconv.UnableToUnify _ ->
@@ -221,8 +211,8 @@ let unify_resolve_refine poly flags gl clenv =
(** Dealing with goals of the form A -> B and hints of the form
C -> A -> B.
*)
-let clenv_of_prods poly nprods (c, clenv) gl =
- let (c, _, _) = c in
+let clenv_of_prods nprods h gl =
+ let { hint_term = c; hint_clnv = clenv; hint_poly = poly } = h in
if poly || Int.equal nprods 0 then Some (None, clenv)
else
let sigma = Tacmach.New.project gl in
@@ -234,20 +224,22 @@ let clenv_of_prods poly nprods (c, clenv) gl =
mk_clenv_from_n gl (Some diff) (c,ty))
else None
-let with_prods nprods poly (c, clenv) f =
+let with_prods nprods h f =
if get_typeclasses_limit_intros () then
Proofview.Goal.enter begin fun gl ->
- try match clenv_of_prods poly nprods (c, clenv) gl with
+ try match clenv_of_prods nprods h gl with
| None ->
let info = Exninfo.reify () in
Tacticals.New.tclZEROMSG ~info (str"Not enough premisses")
- | Some (diff, clenv') -> f gl (c, diff, clenv')
+ | Some (diff, clenv') ->
+ let h = { h with hint_clnv = clenv' } in
+ f gl (h, diff)
with e when CErrors.noncritical e ->
let e, info = Exninfo.capture e in
Tacticals.New.tclZEROMSG ~info (CErrors.print e) end
else Proofview.Goal.enter
begin fun gl ->
- if Int.equal nprods 0 then f gl (c, None, clenv)
+ if Int.equal nprods 0 then f gl (h, None)
else Tacticals.New.tclZEROMSG (str"Not enough premisses") end
let matches_pattern concl pat =
@@ -346,44 +338,47 @@ and e_my_find_search db_list local_db secvars hdc complete only_classes env sigm
with e when CErrors.noncritical e -> AllowAll
in
let tac_of_hint =
- fun (flags, {pri = b; pat = p; poly = poly; code = t; secvars; name = name}) ->
+ fun (flags, h) ->
+ let b = FullHint.priority h in
+ let p = FullHint.pattern h in
+ let name = FullHint.name h in
let tac = function
- | Res_pf (term,cl) ->
+ | Res_pf h ->
if get_typeclasses_filtered_unification () then
let tac =
- with_prods nprods poly (term,cl)
+ with_prods nprods h
(fun gl clenv ->
matches_pattern concl p <*>
- unify_resolve_refine poly flags gl clenv)
+ unify_resolve_refine flags gl clenv)
in Tacticals.New.tclTHEN tac Proofview.shelve_unifiable
else
let tac =
- with_prods nprods poly (term,cl) (unify_resolve poly flags) in
+ with_prods nprods h (unify_resolve flags) in
Proofview.tclBIND (Proofview.with_shelf tac)
(fun (gls, ()) -> shelve_dependencies gls)
- | ERes_pf (term,cl) ->
+ | ERes_pf h ->
if get_typeclasses_filtered_unification () then
- let tac = (with_prods nprods poly (term,cl)
+ let tac = (with_prods nprods h
(fun gl clenv ->
matches_pattern concl p <*>
- unify_resolve_refine poly flags gl clenv)) in
+ unify_resolve_refine flags gl clenv)) in
Tacticals.New.tclTHEN tac Proofview.shelve_unifiable
else
let tac =
- with_prods nprods poly (term,cl) (unify_e_resolve poly flags) in
+ with_prods nprods h (unify_e_resolve flags) in
Proofview.tclBIND (Proofview.with_shelf tac)
(fun (gls, ()) -> shelve_dependencies gls)
- | Give_exact (c,clenv) ->
+ | Give_exact h ->
if get_typeclasses_filtered_unification () then
let tac =
matches_pattern concl p <*>
Proofview.Goal.enter
- (fun gl -> unify_resolve_refine poly flags gl (c,None,clenv)) in
+ (fun gl -> unify_resolve_refine flags gl (h, None)) in
Tacticals.New.tclTHEN tac Proofview.shelve_unifiable
else
- e_give_exact flags poly (c,clenv)
- | Res_pf_THEN_trivial_fail (term,cl) ->
- let fst = with_prods nprods poly (term,cl) (unify_e_resolve poly flags) in
+ e_give_exact flags h
+ | Res_pf_THEN_trivial_fail h ->
+ let fst = with_prods nprods h (unify_e_resolve flags) in
let snd = if complete then Tacticals.New.tclIDTAC
else e_trivial_fail_db only_classes db_list local_db secvars in
Tacticals.New.tclTHEN fst snd
@@ -391,7 +386,7 @@ and e_my_find_search db_list local_db secvars hdc complete only_classes env sigm
Proofview.tclPROGRESS (unfold_in_concl [AllOccurrences,c])
| Extern tacast -> conclPattern concl p tacast
in
- let tac = run_hint t tac in
+ let tac = FullHint.run h tac in
let tac = if complete then Tacticals.New.tclCOMPLETE tac else tac in
let pp =
match p with
@@ -399,9 +394,9 @@ and e_my_find_search db_list local_db secvars hdc complete only_classes env sigm
str " with pattern " ++ Printer.pr_constr_pattern_env env sigma pat
| _ -> mt ()
in
- match repr_hint t with
- | Extern _ -> (tac, b, true, name, lazy (pr_hint env sigma t ++ pp))
- | _ -> (tac, b, false, name, lazy (pr_hint env sigma t ++ pp))
+ match FullHint.repr h with
+ | Extern _ -> (tac, b, true, name, lazy (FullHint.print env sigma h ++ pp))
+ | _ -> (tac, b, false, name, lazy (FullHint.print env sigma h ++ pp))
in
let hint_of_db = hintmap_of sigma hdc secvars concl in
let hintl = List.map_filter (fun db -> match hint_of_db db with
@@ -440,10 +435,6 @@ let e_possible_resolve db_list local_db secvars only_classes env sigma concl =
let cut_of_hints h =
List.fold_left (fun cut db -> PathOr (Hint_db.cut db, cut)) PathEmpty h
-let catchable = function
- | Refiner.FailError _ -> true
- | e -> Logic.catchable_exception e [@@ocaml.warning "-3"]
-
let pr_depth l =
let rec fmt elts =
match elts with
@@ -499,7 +490,7 @@ let evars_to_goals p evm =
else Some (goals, nongoals)
(** Making local hints *)
-let make_resolve_hyp env sigma st flags only_classes pri decl =
+let make_resolve_hyp env sigma st only_classes pri decl =
let id = NamedDecl.get_id decl in
let cty = Evarutil.nf_evar sigma (NamedDecl.get_type decl) in
let rec iscl env ty =
@@ -524,13 +515,11 @@ let make_resolve_hyp env sigma st flags only_classes pri decl =
(List.map_append
(fun (path,info,c) ->
let h = IsConstr (EConstr.of_constr c,Univ.ContextSet.empty) [@ocaml.warning "-3"] in
- make_resolves env sigma ~name:(PathHints path)
- (true,false,not !Flags.quiet) info ~check:true ~poly:false
- h)
+ make_resolves env sigma ~name:(PathHints path) info ~check:true ~poly:false h)
hints)
else []
in
- (hints @ make_resolves env sigma flags pri ~name ~check:false ~poly:false (IsGlobRef id))
+ (hints @ make_resolves env sigma pri ~name ~check:false ~poly:false (IsGlobRef id))
else []
let make_hints g (modes,st) only_classes sign =
@@ -546,7 +535,7 @@ let make_hints g (modes,st) only_classes sign =
in
if consider then
let hint =
- pf_apply make_resolve_hyp g st (true,false,false) only_classes empty_hint_info hyp
+ pf_apply make_resolve_hyp g st only_classes empty_hint_info hyp
in hint @ hints
else hints)
([]) sign
@@ -793,7 +782,7 @@ module Search = struct
let decl = Tacmach.New.pf_last_hyp gl in
let hint =
make_resolve_hyp env sigma (Hint_db.transparent_state info.search_hints)
- (true,false,false) info.search_only_classes empty_hint_info decl in
+ info.search_only_classes empty_hint_info decl in
let ldb = Hint_db.add_list env sigma hint info.search_hints in
let info' =
{ info with search_hints = ldb; last_tac = lazy (str"intro");
@@ -1246,7 +1235,8 @@ let autoapply c i =
(Hints.Hint_db.transparent_state hintdb) in
let cty = Tacmach.New.pf_get_type_of gl c in
let ce = mk_clenv_from gl (c,cty) in
- unify_e_resolve false flags gl ((c,cty,Univ.ContextSet.empty),0,ce) <*>
+ let h = { hint_term = c; hint_type = cty; hint_uctx = Univ.ContextSet.empty; hint_clnv = ce; hint_poly = false } in
+ unify_e_resolve flags gl (h, 0) <*>
Proofview.tclEVARMAP >>= (fun sigma ->
let sigma = Typeclasses.make_unresolvables
(fun ev -> Typeclasses.all_goals ev (Lazy.from_val (snd (Evd.find sigma ev).evar_source))) sigma in
diff --git a/tactics/class_tactics.mli b/tactics/class_tactics.mli
index b97b90d777..381f68f14f 100644
--- a/tactics/class_tactics.mli
+++ b/tactics/class_tactics.mli
@@ -15,9 +15,6 @@ open EConstr
val typeclasses_db : string
-val catchable : exn -> bool
-[@@ocaml.deprecated "Use instead CErrors.noncritical, or the exact name of the exception that matters in the corresponding case."]
-
val set_typeclasses_debug : bool -> unit
val set_typeclasses_depth : int option -> unit
diff --git a/tactics/eauto.ml b/tactics/eauto.ml
index c2eabffd44..d275e15255 100644
--- a/tactics/eauto.ml
+++ b/tactics/eauto.ml
@@ -37,7 +37,7 @@ let e_give_exact ?(flags=eauto_unif_flags) c =
if occur_existential sigma t1 || occur_existential sigma t2 then
Tacticals.New.tclTHENLIST
[Proofview.Unsafe.tclEVARS sigma;
- Clenvtac.unify ~flags t1;
+ Clenv.unify ~flags t1;
exact_no_check c]
else exact_check c
end
@@ -65,13 +65,10 @@ open Auto
(* A tactic similar to Auto, but using EApply, Assumption and e_give_exact *)
(***************************************************************************)
-let unify_e_resolve poly flags (c,clenv) =
+let unify_e_resolve flags h =
Proofview.Goal.enter begin fun gl ->
- let clenv', c = connect_hint_clenv ~poly c clenv gl in
- let clenv' = clenv_unique_resolver ~flags clenv' gl in
- Proofview.tclTHEN
- (Proofview.Unsafe.tclEVARUNIVCONTEXT (Evd.evar_universe_context clenv'.evd))
- (Tactics.Simple.eapply c)
+ let clenv', c = connect_hint_clenv h gl in
+ Clenv.res_pf ~with_evars:true ~with_classes:true ~flags clenv'
end
let hintmap_of sigma secvars concl =
@@ -88,9 +85,9 @@ let hintmap_of sigma secvars concl =
else (fun db -> Hint_db.map_auto sigma ~secvars hdc concl db)
(* FIXME: should be (Hint_db.map_eauto hdc concl db) *)
-let e_exact poly flags (c,clenv) =
+let e_exact flags h =
Proofview.Goal.enter begin fun gl ->
- let clenv', c = connect_hint_clenv ~poly c clenv gl in
+ let clenv', c = connect_hint_clenv h gl in
Tacticals.New.tclTHEN
(Proofview.Unsafe.tclEVARUNIVCONTEXT (Evd.evar_universe_context clenv'.evd))
(e_give_exact c)
@@ -120,23 +117,23 @@ and e_my_find_search env sigma db_list local_db secvars concl =
List.map (fun x -> flags, x) (hint_of_db db)) (local_db::db_list)
in
let tac_of_hint =
- fun (st, {pri = b; pat = p; code = t; poly = poly}) ->
- let b = match Hints.repr_hint t with
+ fun (st, h) ->
+ let b = match FullHint.repr h with
| Unfold_nth _ -> 1
- | _ -> b
+ | _ -> FullHint.priority h
in
let tac = function
- | Res_pf (term,cl) -> unify_resolve ~poly st (term,cl)
- | ERes_pf (term,cl) -> unify_e_resolve poly st (term,cl)
- | Give_exact (c,cl) -> e_exact poly st (c,cl)
- | Res_pf_THEN_trivial_fail (term,cl) ->
- Tacticals.New.tclTHEN (unify_e_resolve poly st (term,cl))
+ | Res_pf h -> unify_resolve st h
+ | ERes_pf h -> unify_e_resolve st h
+ | Give_exact h -> e_exact st h
+ | Res_pf_THEN_trivial_fail h ->
+ Tacticals.New.tclTHEN (unify_e_resolve st h)
(e_trivial_fail_db db_list local_db)
| Unfold_nth c -> reduce (Unfold [AllOccurrences,c]) onConcl
- | Extern tacast -> conclPattern concl p tacast
+ | Extern tacast -> conclPattern concl (FullHint.pattern h) tacast
in
- let tac = run_hint t tac in
- (tac, b, lazy (pr_hint env sigma t))
+ let tac = FullHint.run h tac in
+ (tac, b, lazy (FullHint.print env sigma h))
in
List.map tac_of_hint hintl
diff --git a/tactics/equality.ml b/tactics/equality.ml
index 79b6dfe920..39017c946f 100644
--- a/tactics/equality.ml
+++ b/tactics/equality.ml
@@ -154,7 +154,7 @@ let instantiate_lemma_all frzevars gl c ty l l2r concl =
let c1 = args.(arglen - 2) in
let c2 = args.(arglen - 1) in
let try_occ (evd', c') =
- Clenvtac.clenv_pose_dependent_evars ~with_evars:true {eqclause with evd = evd'}
+ Clenv.clenv_pose_dependent_evars ~with_evars:true {eqclause with evd = evd'}
in
let flags = make_flags frzevars (Tacmach.New.project gl) rewrite_unif_flags eqclause in
let occs =
@@ -1045,7 +1045,7 @@ let discr_positions env sigma (lbeq,eqn,(t,t1,t2)) eq_clause cpath dirn =
discrimination_pf e (t,t1,t2) discriminator lbeq false_kind >>= fun pf ->
let pf_ty = mkArrow eqn Sorts.Relevant false_0 in
let absurd_clause = apply_on_clause (pf,pf_ty) eq_clause in
- let pf = Clenvtac.clenv_value_cast_meta absurd_clause in
+ let pf = Clenv.clenv_value_cast_meta absurd_clause in
tclTHENS (assert_after Anonymous false_0)
[onLastHypId gen_absurdity; (Refiner.refiner ~check:true EConstr.Unsafe.(to_constr pf))]
@@ -1067,7 +1067,7 @@ let onEquality with_evars tac (c,lbindc) =
let t = pf_get_type_of gl c in
let t' = try snd (reduce_to_quantified_ind t) with UserError _ -> t in
let eq_clause = pf_apply make_clenv_binding gl (c,t') lbindc in
- let eq_clause' = Clenvtac.clenv_pose_dependent_evars ~with_evars eq_clause in
+ let eq_clause' = Clenv.clenv_pose_dependent_evars ~with_evars eq_clause in
let eqn = clenv_type eq_clause' in
(* FIXME evar leak *)
let (eq,u,eq_args) = pf_apply find_this_eq_data_decompose gl eqn in
@@ -1397,7 +1397,7 @@ let inject_at_positions env sigma l2r (eq,_,(t,t1,t2)) eq_clause posns tac =
let pf = applist(congr,[t;resty;injfun;t1;t2]) in
let sigma, pf_typ = Typing.type_of env sigma pf in
let inj_clause = apply_on_clause (pf,pf_typ) eq_clause in
- let pf = Clenvtac.clenv_value_cast_meta inj_clause in
+ let pf = Clenv.clenv_value_cast_meta inj_clause in
let ty = simplify_args env sigma (clenv_type inj_clause) in
evdref := sigma;
Some (pf, ty)
diff --git a/tactics/hints.ml b/tactics/hints.ml
index 0c23532e12..7a5615dd8e 100644
--- a/tactics/hints.ml
+++ b/tactics/hints.ml
@@ -135,15 +135,20 @@ type 'a with_uid = {
uid : KerName.t;
}
-type raw_hint = constr * types * Univ.ContextSet.t
-
-type hint = (raw_hint * clausenv) hint_ast with_uid
+type raw_hint = constr * types * Univ.ContextSet.t * bool (* poly *)
+
+type hint = {
+ hint_term : constr;
+ hint_type : types;
+ hint_uctx : Univ.ContextSet.t;
+ hint_clnv : clausenv;
+ hint_poly : bool;
+ (** Is the hint polymorpic and hence should be refreshed at each application *)
+}
type 'a with_metadata =
{ pri : int
(** A number lower is higher priority *)
- ; poly : bool
- (** Is the hint polymorpic and hence should be refreshed at each application *)
; pat : constr_pattern option
(** A pattern for the concl of the Goal *)
; name : hints_path_atom
@@ -156,7 +161,7 @@ type 'a with_metadata =
(** the tactic to apply when the concl matches pat *)
}
-type full_hint = hint with_metadata
+type full_hint = hint hint_ast with_uid with_metadata
type hint_entry = GlobRef.t option *
raw_hint hint_ast with_uid with_metadata
@@ -300,19 +305,21 @@ let strip_params env sigma c =
| _ -> c
let instantiate_hint env sigma p =
- let mk_clenv (c, cty, ctx) =
+ let mk_clenv (c, cty, ctx, poly) =
let sigma = Evd.merge_context_set univ_flexible sigma ctx in
let cl = mk_clenv_from_env env sigma None (c,cty) in
- {cl with templval =
+ let cl = {cl with templval =
{ cl.templval with rebus = strip_params env sigma cl.templval.rebus };
env = empty_env}
+ in
+ { hint_term = c; hint_type = cty; hint_uctx = ctx; hint_clnv = cl; hint_poly = poly }
in
let code = match p.code.obj with
- | Res_pf c -> Res_pf (c, mk_clenv c)
- | ERes_pf c -> ERes_pf (c, mk_clenv c)
+ | Res_pf c -> Res_pf (mk_clenv c)
+ | ERes_pf c -> ERes_pf (mk_clenv c)
| Res_pf_THEN_trivial_fail c ->
- Res_pf_THEN_trivial_fail (c, mk_clenv c)
- | Give_exact c -> Give_exact (c, mk_clenv c)
+ Res_pf_THEN_trivial_fail (mk_clenv c)
+ | Give_exact c -> Give_exact (mk_clenv c)
| Unfold_nth e -> Unfold_nth e
| Extern t -> Extern t
in
@@ -489,7 +496,6 @@ module Hint_db :
sig
type t
val empty : ?name:hint_db_name -> TransparentState.t -> bool -> t
-val find : GlobRef.t -> t -> search_entry
val map_none : secvars:Id.Pred.t -> t -> full_hint list
val map_all : secvars:Id.Pred.t -> GlobRef.t -> t -> full_hint list
val map_existential : evar_map -> secvars:Id.Pred.t ->
@@ -800,9 +806,9 @@ let make_exact_entry env sigma info ~poly ?(name=PathAny) (c, cty, ctx) =
| None -> pat
in
(Some hd,
- { pri; poly; pat = Some pat; name;
+ { pri; pat = Some pat; name;
db = None; secvars;
- code = with_uid (Give_exact (c, cty, ctx)); })
+ code = with_uid (Give_exact (c, cty, ctx, poly)); })
let make_apply_entry env sigma (eapply,hnf,verbose) info ~poly ?(name=PathAny) (c, cty, ctx) =
let cty = if hnf then hnf_constr env sigma cty else cty in
@@ -824,10 +830,10 @@ let make_apply_entry env sigma (eapply,hnf,verbose) info ~poly ?(name=PathAny) (
in
if Int.equal nmiss 0 then
(Some hd,
- { pri; poly; pat = Some pat; name;
+ { pri; pat = Some pat; name;
db = None;
secvars;
- code = with_uid (Res_pf(c,cty,ctx)); })
+ code = with_uid (Res_pf(c,cty,ctx,poly)); })
else begin
if not eapply then failwith "make_apply_entry";
if verbose then begin
@@ -843,9 +849,9 @@ let make_apply_entry env sigma (eapply,hnf,verbose) info ~poly ?(name=PathAny) (
)
end;
(Some hd,
- { pri; poly; pat = Some pat; name;
+ { pri; pat = Some pat; name;
db = None; secvars;
- code = with_uid (ERes_pf(c,cty,ctx)); })
+ code = with_uid (ERes_pf(c,cty,ctx,poly)); })
end
| _ -> failwith "make_apply_entry"
@@ -916,7 +922,6 @@ let make_unfold eref =
let g = global_of_evaluable_reference eref in
(Some g,
{ pri = 4;
- poly = false;
pat = None;
name = PathHints [g];
db = None;
@@ -927,7 +932,6 @@ let make_extern pri pat tacast =
let hdconstr = Option.map try_head_pattern pat in
(hdconstr,
{ pri = pri;
- poly = false;
pat = pat;
name = PathAny;
db = None;
@@ -954,12 +958,11 @@ let make_trivial env sigma poly ?(name=PathAny) r =
let ce = mk_clenv_from_env env sigma None (c,t) in
(Some hd,
{ pri=1;
- poly = poly;
pat = Some (Patternops.pattern_of_constr env ce.evd (EConstr.to_constr sigma (clenv_type ce)));
name = name;
db = None;
secvars = secvars_of_constr env sigma c;
- code= with_uid (Res_pf_THEN_trivial_fail(c,t,ctx)) })
+ code= with_uid (Res_pf_THEN_trivial_fail(c,t,ctx,poly)) })
@@ -1070,29 +1073,30 @@ let subst_autohint (subst, obj) =
(try head_constr_bound Evd.empty (EConstr.of_constr t.Univ.univ_abstracted_value)
with Bound -> gr')
in
+ let subst_mps subst c = EConstr.of_constr (subst_mps subst (EConstr.Unsafe.to_constr c)) in
+ let subst_aux ((c, t, ctx, poly) as h) =
+ let c' = subst_mps subst c in
+ let t' = subst_mps subst t in
+ if c==c' && t'==t then h else (c', t', ctx, poly)
+ in
let subst_hint (k,data as hint) =
let k' = Option.Smart.map subst_key k in
let env = Global.env () in
let sigma = Evd.from_env env in
let pat' = Option.Smart.map (subst_pattern env sigma subst) data.pat in
- let subst_mps subst c = EConstr.of_constr (subst_mps subst (EConstr.Unsafe.to_constr c)) in
let code' = match data.code.obj with
- | Res_pf (c,t,ctx) ->
- let c' = subst_mps subst c in
- let t' = subst_mps subst t in
- if c==c' && t'==t then data.code.obj else Res_pf (c', t',ctx)
- | ERes_pf (c,t,ctx) ->
- let c' = subst_mps subst c in
- let t' = subst_mps subst t in
- if c==c' && t'==t then data.code.obj else ERes_pf (c',t',ctx)
- | Give_exact (c,t,ctx) ->
- let c' = subst_mps subst c in
- let t' = subst_mps subst t in
- if c==c' && t'== t then data.code.obj else Give_exact (c',t',ctx)
- | Res_pf_THEN_trivial_fail (c,t,ctx) ->
- let c' = subst_mps subst c in
- let t' = subst_mps subst t in
- if c==c' && t==t' then data.code.obj else Res_pf_THEN_trivial_fail (c',t',ctx)
+ | Res_pf h ->
+ let h' = subst_aux h in
+ if h == h' then data.code.obj else Res_pf h'
+ | ERes_pf h ->
+ let h' = subst_aux h in
+ if h == h' then data.code.obj else ERes_pf h'
+ | Give_exact h ->
+ let h' = subst_aux h in
+ if h == h' then data.code.obj else Give_exact h'
+ | Res_pf_THEN_trivial_fail h ->
+ let h' = subst_aux h in
+ if h == h' then data.code.obj else Res_pf_THEN_trivial_fail h'
| Unfold_nth ref ->
let ref' = subst_evaluable_reference subst ref in
if ref==ref' then data.code.obj else Unfold_nth ref'
@@ -1336,6 +1340,9 @@ let constructor_hints env sigma eapply lems =
List.map_append (fun (poly, lem) ->
make_resolves env sigma (eapply,true,false) empty_hint_info ~check:true ~poly lem) lems
+let make_resolves env sigma info ~check ~poly ?name hint =
+ make_resolves env sigma (true, false, false) info ~check ~poly ?name hint
+
let make_local_hint_db env sigma ts eapply lems =
let map c = c env sigma in
let lems = List.map map lems in
@@ -1365,13 +1372,13 @@ let make_db_list dbnames =
(* Functions for printing the hints *)
(**************************************************************************)
-let pr_hint_elt env sigma (c, _, _) = pr_econstr_env env sigma c
+let pr_hint_elt env sigma h = pr_econstr_env env sigma h.hint_term
let pr_hint env sigma h = match h.obj with
- | Res_pf (c, _) -> (str"simple apply " ++ pr_hint_elt env sigma c)
- | ERes_pf (c, _) -> (str"simple eapply " ++ pr_hint_elt env sigma c)
- | Give_exact (c, _) -> (str"exact " ++ pr_hint_elt env sigma c)
- | Res_pf_THEN_trivial_fail (c, _) ->
+ | Res_pf c -> (str"simple apply " ++ pr_hint_elt env sigma c)
+ | ERes_pf c -> (str"simple eapply " ++ pr_hint_elt env sigma c)
+ | Give_exact c -> (str"exact " ++ pr_hint_elt env sigma c)
+ | Res_pf_THEN_trivial_fail c ->
(str"simple apply " ++ pr_hint_elt env sigma c ++ str" ; trivial")
| Unfold_nth c ->
str"unfold " ++ pr_evaluable_reference c
@@ -1574,4 +1581,15 @@ let run_hint tac k = match warn_hint () with
let info = Exninfo.reify () in
Proofview.tclZERO ~info (UserError (None, (str "Tactic failure.")))
-let repr_hint h = h.obj
+module FullHint =
+struct
+ type t = full_hint
+ let priority (h : t) = h.pri
+ let pattern (h : t) = h.pat
+ let database (h : t) = h.db
+ let run (h : t) k = run_hint h.code k
+ let print env sigma (h : t) = pr_hint env sigma h.code
+ let name (h : t) = h.name
+
+ let repr (h : t) = h.code.obj
+end
diff --git a/tactics/hints.mli b/tactics/hints.mli
index 6c8b7fed75..8243716624 100644
--- a/tactics/hints.mli
+++ b/tactics/hints.mli
@@ -15,7 +15,6 @@ open Environ
open Evd
open Tactypes
open Clenv
-open Pattern
open Typeclasses
(** {6 General functions. } *)
@@ -40,8 +39,13 @@ type 'a hint_ast =
| Unfold_nth of evaluable_global_reference (* Hint Unfold *)
| Extern of Genarg.glob_generic_argument (* Hint Extern *)
-type hint
-type raw_hint = constr * types * Univ.ContextSet.t
+type hint = {
+ hint_term : constr;
+ hint_type : types;
+ hint_uctx : Univ.ContextSet.t;
+ hint_clnv : clausenv;
+ hint_poly : bool;
+}
type 'a hints_path_atom_gen =
| PathHints of 'a list
@@ -51,26 +55,20 @@ type 'a hints_path_atom_gen =
type hints_path_atom = GlobRef.t hints_path_atom_gen
type hint_db_name = string
-type 'a with_metadata = private
- { pri : int
- (** A number lower is higher priority *)
- ; poly : bool
- (** Is the hint polymorpic and hence should be refreshed at each application *)
- ; pat : constr_pattern option
- (** A pattern for the concl of the Goal *)
- ; name : hints_path_atom
- (** A potential name to refer to the hint *)
- ; db : string option
- (** The database from which the hint comes *)
- ; secvars : Id.Pred.t
- (** The set of section variables the hint depends on *)
- ; code : 'a
- (** the tactic to apply when the concl matches pat *)
- }
-
-type full_hint = hint with_metadata
-
-type search_entry
+module FullHint :
+sig
+ type t
+ val priority : t -> int
+ val pattern : t -> Pattern.constr_pattern option
+ val database : t -> string option
+ val run : t -> (hint hint_ast -> 'r Proofview.tactic) -> 'r Proofview.tactic
+ val name : t -> hints_path_atom
+ val print : env -> evar_map -> t -> Pp.t
+
+ (** This function is for backward compatibility only, not to use in newly
+ written code. *)
+ val repr : t -> hint hint_ast
+end
(** The head may not be bound. *)
@@ -117,42 +115,41 @@ module Hint_db :
sig
type t
val empty : ?name:hint_db_name -> TransparentState.t -> bool -> t
- val find : GlobRef.t -> t -> search_entry
(** All hints which have no pattern.
* [secvars] represent the set of section variables that
* can be used in the hint. *)
- val map_none : secvars:Id.Pred.t -> t -> full_hint list
+ val map_none : secvars:Id.Pred.t -> t -> FullHint.t list
(** All hints associated to the reference *)
- val map_all : secvars:Id.Pred.t -> GlobRef.t -> t -> full_hint list
+ val map_all : secvars:Id.Pred.t -> GlobRef.t -> t -> FullHint.t list
(** All hints associated to the reference, respecting modes if evars appear in the
arguments, _not_ using the discrimination net.
Returns a [ModeMismatch] if there are declared modes and none matches.
*)
val map_existential : evar_map -> secvars:Id.Pred.t ->
- (GlobRef.t * constr array) -> constr -> t -> full_hint list with_mode
+ (GlobRef.t * constr array) -> constr -> t -> FullHint.t list with_mode
(** All hints associated to the reference, respecting modes if evars appear in the
arguments and using the discrimination net.
Returns a [ModeMismatch] if there are declared modes and none matches. *)
- val map_eauto : evar_map -> secvars:Id.Pred.t -> (GlobRef.t * constr array) -> constr -> t -> full_hint list with_mode
+ val map_eauto : evar_map -> secvars:Id.Pred.t -> (GlobRef.t * constr array) -> constr -> t -> FullHint.t list with_mode
(** All hints associated to the reference.
Precondition: no evars should appear in the arguments, so no modes
are checked. *)
val map_auto : evar_map -> secvars:Id.Pred.t ->
- (GlobRef.t * constr array) -> constr -> t -> full_hint list
+ (GlobRef.t * constr array) -> constr -> t -> FullHint.t list
val add_one : env -> evar_map -> hint_entry -> t -> t
val add_list : env -> evar_map -> hint_entry list -> t -> t
val remove_one : GlobRef.t -> t -> t
val remove_list : GlobRef.t list -> t -> t
val iter : (GlobRef.t option ->
- hint_mode array list -> full_hint list -> unit) -> t -> unit
+ hint_mode array list -> FullHint.t list -> unit) -> t -> unit
- val fold : (GlobRef.t option -> hint_mode array list -> full_hint list -> 'a -> 'a) -> t -> 'a -> 'a
+ val fold : (GlobRef.t option -> hint_mode array list -> FullHint.t list -> 'a -> 'a) -> t -> 'a -> 'a
val use_dn : t -> bool
val transparent_state : t -> TransparentState.t
@@ -214,7 +211,7 @@ val prepare_hint : bool (* Check no remaining evars *) ->
has missing arguments. *)
val make_resolves :
- env -> evar_map -> bool * bool * bool -> hint_info -> check:bool -> poly:bool -> ?name:hints_path_atom ->
+ env -> evar_map -> hint_info -> check:bool -> poly:bool -> ?name:hints_path_atom ->
hint_term -> hint_entry list
(** [make_resolve_hyp hname htyp].
@@ -225,19 +222,6 @@ val make_resolves :
val make_resolve_hyp :
env -> evar_map -> named_declaration -> hint_entry list
-(** [make_extern pri pattern tactic_expr] *)
-
-val make_extern :
- int -> constr_pattern option -> Genarg.glob_generic_argument
- -> hint_entry
-
-val run_hint : hint ->
- ((raw_hint * clausenv) hint_ast -> 'r Proofview.tactic) -> 'r Proofview.tactic
-
-(** This function is for backward compatibility only, not to use in newly
- written code. *)
-val repr_hint : hint -> (raw_hint * clausenv) hint_ast
-
(** Create a Hint database from the pairs (name, constr).
Useful to take the current goal hypotheses as hints;
Boolean tells if lemmas with evars are allowed *)
@@ -262,4 +246,3 @@ val pr_applicable_hint : Proof.t -> Pp.t
val pr_hint_ref : env -> evar_map -> GlobRef.t -> Pp.t
val pr_hint_db_by_name : env -> evar_map -> hint_db_name -> Pp.t
val pr_hint_db_env : env -> evar_map -> Hint_db.t -> Pp.t
-val pr_hint : env -> evar_map -> hint -> Pp.t
diff --git a/tactics/tacticals.ml b/tactics/tacticals.ml
index a4d306c497..22c5bbe73f 100644
--- a/tactics/tacticals.ml
+++ b/tactics/tacticals.ml
@@ -140,9 +140,7 @@ let ifOnHyp pred tac1 tac2 id gl =
type branch_args = {
ity : pinductive; (* the type we were eliminating on *)
- largs : constr list; (* its arguments *)
branchnum : int; (* the branch number *)
- pred : constr; (* the predicate we used *)
nassums : int; (* number of assumptions/letin to be introduced *)
branchsign : bool list; (* the signature of the branch.
true=assumption, false=let-in *)
@@ -686,22 +684,18 @@ module New = struct
| None -> elimclause'
| Some p -> clenv_unify ~flags Reduction.CONV (mkMeta pmv) p elimclause'
in
- let clenv' = clenv_unique_resolver ~flags elimclause' gl in
let after_tac i =
- let (hd,largs) = decompose_app clenv'.evd clenv'.templtyp.Evd.rebus in
let ba = { branchsign = branchsigns.(i);
branchnames = brnames.(i);
nassums = List.length branchsigns.(i);
branchnum = i+1;
- ity = ind;
- largs = List.map (clenv_nf_meta clenv') largs;
- pred = clenv_nf_meta clenv' hd }
+ ity = ind; }
in
tac ba
in
let branchtacs = List.init (Array.length branchsigns) after_tac in
Proofview.tclTHEN
- (Clenvtac.clenv_refine clenv')
+ (Clenv.res_pf ~flags elimclause')
(Proofview.tclEXTEND [] tclIDTAC branchtacs)
end) end
diff --git a/tactics/tacticals.mli b/tactics/tacticals.mli
index eebe702259..88419af836 100644
--- a/tactics/tacticals.mli
+++ b/tactics/tacticals.mli
@@ -89,9 +89,7 @@ val onClauseLR : (Id.t option -> tactic) -> clause -> tactic
type branch_args = private {
ity : pinductive; (** the type we were eliminating on *)
- largs : constr list; (** its arguments *)
branchnum : int; (** the branch number *)
- pred : constr; (** the predicate we used *)
nassums : int; (** number of assumptions/letin to be introduced *)
branchsign : bool list; (** the signature of the branch.
true=assumption, false=let-in *)
diff --git a/tactics/tactics.ml b/tactics/tactics.ml
index 65f79b6a51..3133f9be1e 100644
--- a/tactics/tactics.ml
+++ b/tactics/tactics.ml
@@ -1373,7 +1373,7 @@ let do_replace id = function
[id] is replaced by P using the proof given by [tac] *)
let clenv_refine_in ?err with_evars targetid id sigma0 clenv tac =
- let clenv = Clenvtac.clenv_pose_dependent_evars ~with_evars clenv in
+ let clenv = Clenv.clenv_pose_dependent_evars ~with_evars clenv in
let clenv =
{ clenv with evd = Typeclasses.resolve_typeclasses
~fail:(not with_evars) clenv.env clenv.evd }
@@ -1475,7 +1475,7 @@ let general_elim_clause with_evars flags where indclause elim =
match where with
| None ->
let elimclause = clenv_fchain ~flags indmv elimclause indclause in
- Clenvtac.res_pf elimclause ~with_evars ~with_classes:true ~flags
+ Clenv.res_pf elimclause ~with_evars ~with_classes:true ~flags
| Some id ->
let hypmv =
match List.remove Int.equal indmv (clenv_independent elimclause) with
@@ -1737,7 +1737,7 @@ let general_apply ?(respect_opaque=false) with_delta with_destruct with_evars
let n = nb_prod_modulo_zeta sigma thm_ty - nprod in
if n<0 then error "Applied theorem does not have enough premises.";
let clause = make_clenv_binding_apply env sigma (Some n) (c,thm_ty) lbind in
- Clenvtac.res_pf clause ~with_evars ~flags
+ Clenv.res_pf clause ~with_evars ~flags
with exn when noncritical exn ->
let exn, info = Exninfo.capture exn in
Proofview.tclZERO ~info exn
@@ -4371,8 +4371,7 @@ let induction_tac with_evars params indvars elim =
(* elimclause' is built from elimclause by instantiating all args and params. *)
let elimclause' = recolle_clenv i params indvars elimclause gl in
(* one last resolution (useless?) *)
- let resolved = clenv_unique_resolver ~flags:(elim_flags ()) elimclause' gl in
- Clenvtac.clenv_refine ~with_evars resolved
+ Clenv.res_pf ~with_evars ~flags:(elim_flags ()) elimclause'
end
(* Apply induction "in place" taking into account dependent
@@ -4813,7 +4812,7 @@ let elim_scheme_type elim t =
(* t is inductive, then CUMUL or CONV is irrelevant *)
clenv_unify ~flags:(elim_flags ()) Reduction.CUMUL t
(clenv_meta_type clause mv) clause in
- Clenvtac.res_pf clause' ~flags:(elim_flags ()) ~with_evars:false
+ Clenv.res_pf clause' ~flags:(elim_flags ()) ~with_evars:false
| _ -> anomaly (Pp.str "elim_scheme_type.")
end
diff --git a/test-suite/Makefile b/test-suite/Makefile
index d4ad438d61..59cc3e5a38 100644
--- a/test-suite/Makefile
+++ b/test-suite/Makefile
@@ -629,7 +629,14 @@ $(addsuffix .log,$(wildcard ideal-features/*.v)): %.v.log: %.v $(PREREQUISITELOG
} > "$@"
# Additional dependencies for module tests
-$(addsuffix .log,$(wildcard modules/*.v)): %.v.log: modules/Nat.vo modules/plik.vo
+COMMON_MODULE_DEPENDENCIES := modules/plik.v modules/Nat.v
+# We exclude Nat.v.log and plik.v.log because these log files do not
+# depend on having the corresponding .vo files built first, and we end
+# up with pseudo-cyclic build rules if we don't exclude them (See
+# COQBUG(https://github.com/coq/coq/issues/12582)). Additionally, we
+# impose order-only dependencies to ensure that we won't rebuild the
+# .vo files in the .log target after we've already built them.
+$(addsuffix .log,$(filter-out $(COMMON_MODULE_DEPENDENCIES),$(wildcard modules/*.v))): %.v.log: $(COMMON_MODULE_DEPENDENCIES:.v=.vo) | $(COMMON_MODULE_DEPENDENCIES:.v=.v.log)
modules/%.vo: modules/%.v
$(HIDE)$(coqc) -R modules Mods $<
diff --git a/test-suite/bugs/closed/bug_12529.v b/test-suite/bugs/closed/bug_12529.v
new file mode 100644
index 0000000000..bc3c9a28bd
--- /dev/null
+++ b/test-suite/bugs/closed/bug_12529.v
@@ -0,0 +1,21 @@
+Goal SProp.
+match goal with |- SProp => idtac end.
+Fail match goal with |- Prop => idtac end.
+Abort.
+
+Goal Prop.
+Fail match goal with |- SProp => idtac end.
+match goal with |- Prop => idtac end.
+Abort.
+
+Class F A := f : A.
+
+Inductive pFalse : Prop := .
+Inductive sFalse : SProp := .
+
+Hint Extern 0 (F Prop) => exact pFalse : typeclass_instances.
+Definition pf := f : Prop.
+
+Hint Extern 0 (F SProp) => exact sFalse : typeclass_instances.
+Definition sf := (f : SProp).
+Definition pf' := (f : Prop).
diff --git a/test-suite/bugs/closed/bug_12532.v b/test-suite/bugs/closed/bug_12532.v
new file mode 100644
index 0000000000..665f6643e6
--- /dev/null
+++ b/test-suite/bugs/closed/bug_12532.v
@@ -0,0 +1,56 @@
+(** This is a change of behaviour introduced by PR #12532. It is not clear
+ whether it is a legit behaviour but it is worth having it in the test
+ suite. *)
+
+Module Foo.
+
+Axiom whatever : Type.
+Axiom name : Type.
+Axiom nw : forall (P : Type), name -> P.
+Axiom raft_data : Type.
+Axiom In : raft_data -> Prop.
+
+Axiom foo : forall st st', In st -> In st'.
+
+Definition params := prod whatever raft_data.
+
+Goal forall
+ (d : raft_data),
+ (forall (h : name), In (@snd whatever raft_data (@nw params h))) ->
+ In d.
+Proof.
+intros.
+eapply foo.
+solve [debug eauto].
+Abort.
+
+End Foo.
+
+Module Bar.
+
+Axiom whatever : Type.
+Axiom AppendEntries : whatever -> Prop.
+Axiom name : Type.
+Axiom nw : forall (P : Type), name -> P.
+Axiom raft_data : Type.
+Axiom In : raft_data -> Prop.
+
+Axiom foo :
+ forall st st' lid,
+ (AppendEntries lid -> In st) -> AppendEntries lid -> In st'.
+
+Definition params := prod whatever raft_data.
+
+Goal forall
+ (d : raft_data),
+ (forall (h : name) (w : whatever),
+ AppendEntries w -> In (@snd whatever raft_data (@nw params h))) ->
+ In d.
+Proof.
+intros.
+eapply foo.
+intros.
+solve [debug eauto].
+Abort.
+
+End Bar.
diff --git a/test-suite/micromega/zify.v b/test-suite/micromega/zify.v
index 8fd7398638..a12623c3c0 100644
--- a/test-suite/micromega/zify.v
+++ b/test-suite/micromega/zify.v
@@ -159,7 +159,7 @@ Require Import ZifyClasses.
Require Import ZifyInst.
Instance Zero : CstOp (@zero znat : nat) := Op_O.
-Add CstOp Zero.
+Add Zify CstOp Zero.
Goal @zero znat = 0%nat.
@@ -227,3 +227,12 @@ Goal forall (f : Z -> bool), negb (negb (f 0)) = f 0.
Proof.
intros. lia.
Qed.
+
+Ltac Zify.zify_pre_hook ::= unfold is_true in *.
+
+Goal forall x y : nat, is_true (Nat.eqb x 1) ->
+ is_true (Nat.eqb y 0) ->
+ is_true (Nat.eqb (x + y) 1).
+Proof.
+lia.
+Qed.
diff --git a/test-suite/output-coqtop/DependentEvars.out b/test-suite/output-coqtop/DependentEvars.out
index 9ca3fa3357..2e69b94505 100644
--- a/test-suite/output-coqtop/DependentEvars.out
+++ b/test-suite/output-coqtop/DependentEvars.out
@@ -77,14 +77,14 @@ p14 < 3 focused subgoals
p123 : (P1 -> P2) -> P3
p34 : P3 -> P4
============================
- ?P -> (?Goal2 -> P4) /\ ?Goal2
+ ?P -> (?P0 -> P4) /\ ?P0
subgoal 2 is:
- ?P -> (?Goal2 -> P4) /\ ?Goal2
+ ?P -> (?P0 -> P4) /\ ?P0
subgoal 3 is:
?P
-(dependent evars: ?X4:?P, ?X5 using ?X10 ?X11, ?X10 using ?X11, ?X11:?Goal2; in current goal: ?X4 ?X5 ?X10 ?X11)
+(dependent evars: ?X4:?P, ?X5 using ?X10 ?X11, ?X10 using ?X11, ?X11:?P0; in current goal: ?X4 ?X5 ?X10 ?X11)
p14 <
Coq <
diff --git a/test-suite/output-coqtop/DependentEvars2.out b/test-suite/output-coqtop/DependentEvars2.out
index 29ebba7c86..63bfafa88d 100644
--- a/test-suite/output-coqtop/DependentEvars2.out
+++ b/test-suite/output-coqtop/DependentEvars2.out
@@ -90,13 +90,13 @@ Try unfocusing with "}".
(shelved: 2)
subgoal 1 is:
- ?P -> (?Goal2 -> P4) /\ ?Goal2
+ ?P -> (?P0 -> P4) /\ ?P0
subgoal 2 is:
- ?P -> (?Goal2 -> P4) /\ ?Goal2
+ ?P -> (?P0 -> P4) /\ ?P0
subgoal 3 is:
?P
-(dependent evars: ?X4:?P, ?X5 using ?X10 ?X11, ?X10 using ?X11, ?X11:?Goal2; in current goal:)
+(dependent evars: ?X4:?P, ?X5 using ?X10 ?X11, ?X10 using ?X11, ?X11:?P0; in current goal:)
p14 < 3 focused subgoals
(shelved: 2)
@@ -106,14 +106,14 @@ p14 < 3 focused subgoals
p123 : (P1 -> P2) -> P3
p34 : P3 -> P4
============================
- ?P -> (?Goal2 -> P4) /\ ?Goal2
+ ?P -> (?P0 -> P4) /\ ?P0
subgoal 2 is:
- ?P -> (?Goal2 -> P4) /\ ?Goal2
+ ?P -> (?P0 -> P4) /\ ?P0
subgoal 3 is:
?P
-(dependent evars: ?X4:?P, ?X5 using ?X10 ?X11, ?X10 using ?X11, ?X11:?Goal2; in current goal: ?X4 ?X5 ?X10 ?X11)
+(dependent evars: ?X4:?P, ?X5 using ?X10 ?X11, ?X10 using ?X11, ?X11:?P0; in current goal: ?X4 ?X5 ?X10 ?X11)
p14 <
Coq <
diff --git a/test-suite/output/unification.out b/test-suite/output/unification.out
index dfd755da61..cf31871e5a 100644
--- a/test-suite/output/unification.out
+++ b/test-suite/output/unification.out
@@ -9,3 +9,27 @@ Unable to unify "T" with "?X@{x0:=x; x:=C a}" (cannot instantiate
The command has indeed failed with message:
The term "id" has type "ID" while it is expected to have type
"Type -> ?T" (cannot instantiate "?T" because "A" is not in its scope).
+1 focused subgoal
+(shelved: 1)
+
+ H : forall x : nat, S (S (S x)) = x
+ ============================
+ ?x = 0
+1 focused subgoal
+(shelved: 1)
+
+ H : forall x : nat, S (S (S x)) = x
+ ============================
+ ?x = 0
+1 focused subgoal
+(shelved: 1)
+
+ H : forall x : nat, S (S (S x)) = x
+ ============================
+ ?x = 0
+1 focused subgoal
+(shelved: 1)
+
+ H : forall x : nat, S x = x
+ ============================
+ ?y = 0
diff --git a/test-suite/output/unification.v b/test-suite/output/unification.v
index ff99f2e23c..fe7366a97d 100644
--- a/test-suite/output/unification.v
+++ b/test-suite/output/unification.v
@@ -10,3 +10,29 @@ Fail Check fun x => match x return ?[X] with C a => a end.
Fail Check (id:Type -> _).
End A.
+
+(* Choice of evar names *)
+
+Goal (forall x, S (S (S x)) = x) -> exists x, S x = 0.
+eexists.
+rewrite H.
+Show.
+Undo 2.
+eexists ?[x].
+rewrite H.
+Show.
+Undo 2.
+eexists ?[y].
+rewrite H.
+Show.
+reflexivity.
+Qed.
+
+(* Preserve the name if there is one *)
+
+Goal (forall x, S x = x) -> exists x, S x = 0.
+eexists ?[y].
+rewrite H.
+Show.
+reflexivity.
+Qed.
diff --git a/theories/Program/Equality.v b/theories/Program/Equality.v
index b46ddaa32b..5862a08838 100644
--- a/theories/Program/Equality.v
+++ b/theories/Program/Equality.v
@@ -264,7 +264,7 @@ Class DependentEliminationPackage (A : Type) :=
Ltac elim_tac tac p :=
let ty := type of p in
- let eliminator := eval simpl in (@elim (_ : DependentEliminationPackage ty)) in
+ let eliminator := eval simpl in (@elim _ (_ : DependentEliminationPackage ty)) in
tac p eliminator.
(** Specialization to do case analysis or induction.
diff --git a/theories/Reals/RIneq.v b/theories/Reals/RIneq.v
index 33e40a115b..4fa8b3216a 100644
--- a/theories/Reals/RIneq.v
+++ b/theories/Reals/RIneq.v
@@ -1774,6 +1774,28 @@ Proof.
now rewrite <- INR_IPR, SuccNat2Pos.id_succ.
Qed.
+Lemma IZR_NEG : forall p, IZR (Zneg p) = Ropp (IZR (Zpos p)).
+Proof.
+ reflexivity.
+Qed.
+
+(** The three following lemmas map the default form of numerical
+ constants to their representation in terms of the axioms of
+ [R]. This can be a useful intermediate representation for reifying
+ to another axiomatics of the reals. It is however generally more
+ convenient to keep constants represented under an [IZR z] form when
+ working within [R]. *)
+
+Lemma IZR_POS_xO : forall p, IZR (Zpos (xO p)) = (1+1) * (IZR (Zpos p)).
+Proof.
+ intro. unfold IZR, IPR. destruct p; simpl; trivial. rewrite Rmult_1_r. trivial.
+Qed.
+
+Lemma IZR_POS_xI : forall p, IZR (Zpos (xI p)) = 1 + (1+1) * IZR (Zpos p).
+Proof.
+ intro. unfold IZR, IPR. destruct p; simpl; trivial. rewrite Rmult_1_r. trivial.
+Qed.
+
Lemma plus_IZR_NEG_POS :
forall p q:positive, IZR (Zpos p + Zneg q) = IZR (Zpos p) + IZR (Zneg q).
Proof.
diff --git a/theories/micromega/Zify.v b/theories/micromega/Zify.v
index 2df3c57d32..183fd6a914 100644
--- a/theories/micromega/Zify.v
+++ b/theories/micromega/Zify.v
@@ -11,12 +11,15 @@
Require Import ZifyClasses ZifyInst.
Declare ML Module "zify_plugin".
-(** [zify_post_hook] is there to be redefined. *)
+(** [zify_pre_hook] and [zify_post_hook] are there to be redefined. *)
+Ltac zify_pre_hook := idtac.
+
Ltac zify_post_hook := idtac.
Ltac iter_specs := zify_iter_specs.
Ltac zify := intros;
+ zify_pre_hook ;
zify_elim_let ;
zify_op ;
(zify_iter_specs) ;
diff --git a/tools/CoqMakefile.in b/tools/CoqMakefile.in
index 1436da30fa..9097195721 100644
--- a/tools/CoqMakefile.in
+++ b/tools/CoqMakefile.in
@@ -104,7 +104,7 @@ BEFORE ?=
AFTER ?=
# FIXME this should be generated by Coq (modules already linked by Coq)
-CAMLDONTLINK=unix,str
+CAMLDONTLINK=num,str,unix,dynlink,threads
# OCaml binaries
CAMLC ?= "$(OCAMLFIND)" ocamlc -c
diff --git a/user-contrib/Ltac2/tac2entries.ml b/user-contrib/Ltac2/tac2entries.ml
index 987cd8c1b8..0a6e976db8 100644
--- a/user-contrib/Ltac2/tac2entries.ml
+++ b/user-contrib/Ltac2/tac2entries.ml
@@ -808,7 +808,7 @@ let perform_eval ~pstate e =
Goal_select.SelectAll, Proof.start ~name ~poly sigma []
| Some pstate ->
Goal_select.get_default_goal_selector (),
- Declare.Proof.get_proof pstate
+ Declare.Proof.get pstate
in
let v = match selector with
| Goal_select.SelectNth i -> Proofview.tclFOCUS i i v
@@ -912,15 +912,15 @@ let print_ltac qid =
(** Calling tactics *)
let solve ~pstate default tac =
- let pstate, status = Declare.Proof.map_fold_proof_endline begin fun etac p ->
+ let pstate, status = Declare.Proof.map_fold_endline pstate ~f:(fun etac p ->
let with_end_tac = if default then Some etac else None in
let g = Goal_select.get_default_goal_selector () in
let (p, status) = Proof.solve g None tac ?with_end_tac p in
(* in case a strict subtree was completed,
go back to the top of the prooftree *)
let p = Proof.maximal_unfocus Vernacentries.command_focus p in
- p, status
- end pstate in
+ p, status)
+ in
if not status then Feedback.feedback Feedback.AddedAxiom;
pstate
diff --git a/vernac/classes.ml b/vernac/classes.ml
index 21e2afe6a9..ba08aa2b94 100644
--- a/vernac/classes.ml
+++ b/vernac/classes.ml
@@ -311,12 +311,13 @@ let instance_hook info global ?hook cst =
declare_instance env sigma (Some info) (not global) cst;
(match hook with Some h -> h cst | None -> ())
-let declare_instance_constant info global impargs ?hook name udecl poly sigma term termtype =
+let declare_instance_constant iinfo global impargs ?hook name udecl poly sigma term termtype =
let kind = Decls.(IsDefinition Instance) in
- let scope = Declare.Global Declare.ImportDefaultBehavior in
- let kn = Declare.declare_definition ~name ~kind ~scope ~impargs
- ~opaque:false ~poly sigma ~udecl ~types:(Some termtype) ~body:term in
- instance_hook info global ?hook kn
+ let scope = Locality.Global Locality.ImportDefaultBehavior in
+ let cinfo = Declare.CInfo.make ~name ~impargs ~typ:(Some termtype) () in
+ let info = Declare.Info.make ~kind ~scope ~poly ~udecl () in
+ let kn = Declare.declare_definition ~cinfo ~info ~opaque:false ~body:term sigma in
+ instance_hook iinfo global ?hook kn
let do_declare_instance sigma ~global ~poly k u ctx ctx' pri udecl impargs subst name =
let subst = List.fold_left2
@@ -344,9 +345,12 @@ let declare_instance_program env sigma ~global ~poly name pri impargs udecl term
let obls, _, term, typ = RetrieveObl.retrieve_obligations env name sigma 0 term termtype in
let hook = Declare.Hook.make hook in
let uctx = Evd.evar_universe_context sigma in
- let scope, kind = Declare.Global Declare.ImportDefaultBehavior, Decls.Instance in
+ let scope, kind = Locality.Global Locality.ImportDefaultBehavior,
+ Decls.IsDefinition Decls.Instance in
+ let cinfo = Declare.CInfo.make ~name ~typ ~impargs () in
+ let info = Declare.Info.make ~udecl ~scope ~poly ~kind ~hook () in
let _ : Declare.Obls.progress =
- Obligations.add_definition ~name ~term ~udecl ~scope ~poly ~kind ~hook ~impargs ~uctx typ obls
+ Declare.Obls.add_definition ~cinfo ~info ~term ~uctx obls
in ()
let declare_instance_open sigma ?hook ~tac ~global ~poly id pri impargs udecl ids term termtype =
@@ -358,11 +362,12 @@ let declare_instance_open sigma ?hook ~tac ~global ~poly id pri impargs udecl id
let sigma = Evd.reset_future_goals sigma in
let kind = Decls.(IsDefinition Instance) in
let hook = Declare.Hook.(make (fun { S.dref ; _ } -> instance_hook pri global ?hook dref)) in
- let info = Lemmas.Info.make ~hook ~kind () in
+ let info = Declare.Info.make ~hook ~kind ~udecl ~poly () in
(* XXX: We need to normalize the type, otherwise Admitted / Qed will fails!
This is due to a bug in proof_global :( *)
let termtype = Evarutil.nf_evar sigma termtype in
- let lemma = Lemmas.start_lemma ~name:id ~poly ~udecl ~info ~impargs sigma termtype in
+ let cinfo = Declare.CInfo.make ~name:id ~impargs ~typ:termtype () in
+ let lemma = Declare.Proof.start ~cinfo ~info sigma in
(* spiwack: I don't know what to do with the status here. *)
let lemma =
match term with
@@ -374,15 +379,15 @@ let declare_instance_open sigma ?hook ~tac ~global ~poly id pri impargs udecl id
Tactics.New.reduce_after_refine;
]
in
- let lemma, _ = Lemmas.by init_refine lemma in
+ let lemma, _ = Declare.Proof.by init_refine lemma in
lemma
| None ->
- let lemma, _ = Lemmas.by (Tactics.auto_intros_tac ids) lemma in
+ let lemma, _ = Declare.Proof.by (Tactics.auto_intros_tac ids) lemma in
lemma
in
match tac with
| Some tac ->
- let lemma, _ = Lemmas.by tac lemma in
+ let lemma, _ = Declare.Proof.by tac lemma in
lemma
| None ->
lemma
diff --git a/vernac/classes.mli b/vernac/classes.mli
index 1b6deb3b28..07695b5bef 100644
--- a/vernac/classes.mli
+++ b/vernac/classes.mli
@@ -36,7 +36,7 @@ val new_instance_interactive
-> ?hook:(GlobRef.t -> unit)
-> Vernacexpr.hint_info_expr
-> (bool * constr_expr) option
- -> Id.t * Lemmas.t
+ -> Id.t * Declare.Proof.t
val new_instance
: ?global:bool (** Not global by default. *)
diff --git a/vernac/comAssumption.ml b/vernac/comAssumption.ml
index 44c30598aa..d8475126ca 100644
--- a/vernac/comAssumption.ml
+++ b/vernac/comAssumption.ml
@@ -61,8 +61,8 @@ let declare_axiom is_coe ~poly ~local ~kind typ (univs, pl) imps nl {CAst.v=name
let sigma = Evd.from_env env in
let () = if do_instance then Classes.declare_instance env sigma None false gr in
let local = match local with
- | Declare.ImportNeedQualified -> true
- | Declare.ImportDefaultBehavior -> false
+ | Locality.ImportNeedQualified -> true
+ | Locality.ImportDefaultBehavior -> false
in
let () = if is_coe then ComCoercion.try_add_new_coercion gr ~local ~poly in
let inst = instance_of_univ_entry univs in
@@ -86,11 +86,11 @@ let context_set_of_entry = function
| Monomorphic_entry uctx -> uctx
let declare_assumptions ~poly ~scope ~kind univs nl l =
- let () = let open Declare in match scope with
- | Discharge ->
+ let () = match scope with
+ | Locality.Discharge ->
(* declare universes separately for variables *)
DeclareUctx.declare_universe_context ~poly (context_set_of_entry (fst univs))
- | Global _ -> ()
+ | Locality.Global _ -> ()
in
let _, _ = List.fold_left (fun (subst,univs) ((is_coe,idl),typ,imps) ->
(* NB: here univs are ignored when scope=Discharge *)
@@ -98,10 +98,10 @@ let declare_assumptions ~poly ~scope ~kind univs nl l =
let univs,subst' =
List.fold_left_map (fun univs id ->
let refu = match scope with
- | Declare.Discharge ->
+ | Locality.Discharge ->
declare_variable is_coe ~kind typ imps Glob_term.Explicit id;
GlobRef.VarRef id.CAst.v, Univ.Instance.empty
- | Declare.Global local ->
+ | Locality.Global local ->
declare_axiom is_coe ~local ~poly ~kind typ univs imps nl id
in
next_univs univs, (id.CAst.v, Constr.mkRef refu))
@@ -128,9 +128,8 @@ let process_assumptions_udecls ~scope l =
udecl, id
| (_, ([], _))::_ | [] -> assert false
in
- let open Declare in
let () = match scope, udecl with
- | Discharge, Some _ ->
+ | Locality.Discharge, Some _ ->
let loc = first_id.CAst.loc in
let msg = Pp.str "Section variables cannot be polymorphic." in
user_err ?loc msg
@@ -174,7 +173,7 @@ let do_assumptions ~program_mode ~poly ~scope ~kind nl l =
uvars, (coe,t,imps))
Univ.LSet.empty l
in
- (* XXX: Using `DeclareDef.prepare_parameter` here directly is not
+ (* XXX: Using `Declare.prepare_parameter` here directly is not
possible as we indeed declare several parameters; however,
restrict_universe_context should be called in a centralized place
IMO, thus I think we should adapt `prepare_parameter` to handle
@@ -202,11 +201,11 @@ let context_insection sigma ~poly ctx =
else Monomorphic_entry Univ.ContextSet.empty
in
let entry = Declare.definition_entry ~univs ~types:t b in
- (* XXX Fixme: Use DeclareDef.prepare_definition *)
+ (* XXX Fixme: Use Declare.prepare_definition *)
let uctx = Evd.evar_universe_context sigma in
let kind = Decls.(IsDefinition Definition) in
let _ : GlobRef.t =
- Declare.declare_entry ~name ~scope:Declare.Discharge
+ Declare.declare_entry ~name ~scope:Locality.Discharge
~kind ~impargs:[] ~uctx entry
in
()
@@ -237,8 +236,8 @@ let context_nosection sigma ~poly ctx =
let entry = Declare.definition_entry ~univs ~types:t b in
Declare.DefinitionEntry entry
in
- let local = if Lib.is_modtype () then Declare.ImportDefaultBehavior
- else Declare.ImportNeedQualified
+ let local = if Lib.is_modtype () then Locality.ImportDefaultBehavior
+ else Locality.ImportNeedQualified
in
let cst = Declare.declare_constant ~name ~kind ~local decl in
let () = Declare.assumption_message name in
diff --git a/vernac/comAssumption.mli b/vernac/comAssumption.mli
index 989015a9f3..3d425ad768 100644
--- a/vernac/comAssumption.mli
+++ b/vernac/comAssumption.mli
@@ -17,7 +17,7 @@ open Constrexpr
val do_assumptions
: program_mode:bool
-> poly:bool
- -> scope:Declare.locality
+ -> scope:Locality.locality
-> kind:Decls.assumption_object_kind
-> Declaremods.inline
-> (ident_decl list * constr_expr) with_coercion list
@@ -35,7 +35,7 @@ val declare_variable
val declare_axiom
: coercion_flag
-> poly:bool
- -> local:Declare.import_status
+ -> local:Locality.import_status
-> kind:Decls.assumption_object_kind
-> Constr.types
-> Entries.universes_entry * UnivNames.universe_binders
diff --git a/vernac/comCoercion.ml b/vernac/comCoercion.ml
index 3cc5dd65af..15d8ebc4b5 100644
--- a/vernac/comCoercion.ml
+++ b/vernac/comCoercion.ml
@@ -354,7 +354,7 @@ let try_add_new_coercion_with_source ref ~local ~poly ~source =
try_add_new_coercion_core ref ~local poly (Some source) None false
let add_coercion_hook poly { Declare.Hook.S.scope; dref; _ } =
- let open Declare in
+ let open Locality in
let local = match scope with
| Discharge -> assert false (* Local Coercion in section behaves like Local Definition *)
| Global ImportNeedQualified -> true
@@ -367,7 +367,7 @@ let add_coercion_hook poly { Declare.Hook.S.scope; dref; _ } =
let add_coercion_hook ~poly = Declare.Hook.make (add_coercion_hook poly)
let add_subclass_hook ~poly { Declare.Hook.S.scope; dref; _ } =
- let open Declare in
+ let open Locality in
let stre = match scope with
| Discharge -> assert false (* Local Subclass in section behaves like Local Definition *)
| Global ImportNeedQualified -> true
diff --git a/vernac/comDefinition.ml b/vernac/comDefinition.ml
index d56917271c..f9b2d8b1d1 100644
--- a/vernac/comDefinition.ml
+++ b/vernac/comDefinition.ml
@@ -116,9 +116,10 @@ let do_definition ?hook ~name ~scope ~poly ~kind udecl bl red_option c ctypopt =
interp_definition ~program_mode udecl bl ~poly red_option c ctypopt
in
let kind = Decls.IsDefinition kind in
+ let cinfo = Declare.CInfo.make ~name ~impargs ~typ:types () in
+ let info = Declare.Info.make ~scope ~kind ?hook ~udecl ~poly () in
let _ : Names.GlobRef.t =
- Declare.declare_definition ~name ~scope ~kind ?hook ~impargs
- ~opaque:false ~poly evd ~udecl ~types ~body
+ Declare.declare_definition ~info ~cinfo ~opaque:false ~body evd
in ()
let do_definition_program ?hook ~name ~scope ~poly ~kind udecl bl red_option c ctypopt =
@@ -126,8 +127,9 @@ let do_definition_program ?hook ~name ~scope ~poly ~kind udecl bl red_option c c
let (body, types), evd, udecl, impargs =
interp_definition ~program_mode udecl bl ~poly red_option c ctypopt
in
- let term, ty, uctx, obls = Declare.prepare_obligation ~name ~body ~types evd in
+ let term, typ, uctx, obls = Declare.Obls.prepare_obligation ~name ~body ~types evd in
let _ : Declare.Obls.progress =
- Obligations.add_definition
- ~name ~term ty ~uctx ~udecl ~impargs ~scope ~poly ~kind ?hook obls
+ let cinfo = Declare.CInfo.make ~name ~typ ~impargs () in
+ let info = Declare.Info.make ~udecl ~scope ~poly ~kind ?hook () in
+ Declare.Obls.add_definition ~cinfo ~info ~term ~uctx obls
in ()
diff --git a/vernac/comDefinition.mli b/vernac/comDefinition.mli
index 2e8fe16252..e3417d0062 100644
--- a/vernac/comDefinition.mli
+++ b/vernac/comDefinition.mli
@@ -17,7 +17,7 @@ open Constrexpr
val do_definition
: ?hook:Declare.Hook.t
-> name:Id.t
- -> scope:Declare.locality
+ -> scope:Locality.locality
-> poly:bool
-> kind:Decls.definition_object_kind
-> universe_decl_expr option
@@ -30,9 +30,9 @@ val do_definition
val do_definition_program
: ?hook:Declare.Hook.t
-> name:Id.t
- -> scope:Declare.locality
+ -> scope:Locality.locality
-> poly:bool
- -> kind:Decls.definition_object_kind
+ -> kind:Decls.logical_kind
-> universe_decl_expr option
-> local_binder_expr list
-> red_expr option
diff --git a/vernac/comFixpoint.ml b/vernac/comFixpoint.ml
index 0b75e7f410..0f34adf1c7 100644
--- a/vernac/comFixpoint.ml
+++ b/vernac/comFixpoint.ml
@@ -257,11 +257,9 @@ let build_recthms ~indexes fixnames fixtypes fiximps =
in
let thms =
List.map3 (fun name typ (ctx,impargs,_) ->
- { Declare.Recthm.name
- ; typ
- ; args = List.map Context.Rel.Declaration.get_name ctx
- ; impargs})
- fixnames fixtypes fiximps
+ let args = List.map Context.Rel.Declaration.get_name ctx in
+ Declare.CInfo.make ~name ~typ ~args ~impargs ()
+ ) fixnames fixtypes fiximps
in
fix_kind, cofix, thms
@@ -270,9 +268,10 @@ let declare_fixpoint_interactive_generic ?indexes ~scope ~poly ((fixnames,_fixrs
let indexes = Option.default [] indexes in
let init_terms = Some fixdefs in
let evd = Evd.from_ctx ctx in
+ let info = Declare.Info.make ~poly ~scope ~kind:(Decls.IsDefinition fix_kind) ~udecl () in
let lemma =
- Lemmas.start_lemma_with_initialization ~poly ~scope ~kind:(Decls.IsDefinition fix_kind) ~udecl
- evd (Some(cofix,indexes,init_terms)) thms None in
+ Declare.Proof.start_mutual_with_initialization ~info
+ evd ~mutual_info:(cofix,indexes,init_terms) ~cinfo:thms None in
(* Declare notations *)
List.iter (Metasyntax.add_notation_interpretation (Global.env())) ntns;
lemma
@@ -283,10 +282,11 @@ let declare_fixpoint_generic ?indexes ~scope ~poly ((fixnames,fixrs,fixdefs,fixt
let fixdefs = List.map Option.get fixdefs in
let rec_declaration = prepare_recursive_declaration fixnames fixrs fixtypes fixdefs in
let fix_kind = Decls.IsDefinition fix_kind in
+ let info = Declare.Info.make ~scope ~kind:fix_kind ~poly ~udecl () in
+ let cinfo = fixitems in
let _ : GlobRef.t list =
- Declare.declare_mutually_recursive ~scope ~opaque:false ~kind:fix_kind ~poly ~uctx
- ~possible_indexes:indexes ~udecl ~ntns ~rec_declaration
- fixitems
+ Declare.declare_mutually_recursive ~cinfo ~info ~opaque:false ~uctx
+ ~possible_indexes:indexes ~ntns ~rec_declaration
in
()
@@ -322,7 +322,7 @@ let do_fixpoint_common (fixl : Vernacexpr.fixpoint_expr list) =
let (_, _, _, info as fix) = interp_fixpoint ~cofix:false fixl in
fixl, ntns, fix, List.map compute_possible_guardness_evidences info
-let do_fixpoint_interactive ~scope ~poly l : Lemmas.t =
+let do_fixpoint_interactive ~scope ~poly l : Declare.Proof.t =
let fixl, ntns, fix, possible_indexes = do_fixpoint_common l in
let lemma = declare_fixpoint_interactive_generic ~indexes:possible_indexes ~scope ~poly fix ntns in
lemma
diff --git a/vernac/comFixpoint.mli b/vernac/comFixpoint.mli
index 62a9d10bae..aa5446205c 100644
--- a/vernac/comFixpoint.mli
+++ b/vernac/comFixpoint.mli
@@ -16,16 +16,16 @@ open Vernacexpr
(** Entry points for the vernacular commands Fixpoint and CoFixpoint *)
val do_fixpoint_interactive :
- scope:Declare.locality -> poly:bool -> fixpoint_expr list -> Lemmas.t
+ scope:Locality.locality -> poly:bool -> fixpoint_expr list -> Declare.Proof.t
val do_fixpoint :
- scope:Declare.locality -> poly:bool -> fixpoint_expr list -> unit
+ scope:Locality.locality -> poly:bool -> fixpoint_expr list -> unit
val do_cofixpoint_interactive :
- scope:Declare.locality -> poly:bool -> cofixpoint_expr list -> Lemmas.t
+ scope:Locality.locality -> poly:bool -> cofixpoint_expr list -> Declare.Proof.t
val do_cofixpoint :
- scope:Declare.locality -> poly:bool -> cofixpoint_expr list -> unit
+ scope:Locality.locality -> poly:bool -> cofixpoint_expr list -> unit
(************************************************************************)
(** Internal API *)
diff --git a/vernac/comHints.ml b/vernac/comHints.ml
index ec37ec7fa8..b05bf9a675 100644
--- a/vernac/comHints.ml
+++ b/vernac/comHints.ml
@@ -56,7 +56,7 @@ let project_hint ~poly pri l2r r =
Declare.(DefinitionEntry (definition_entry ~univs:ctx ~opaque:false c))
in
let c =
- Declare.declare_constant ~local:Declare.ImportDefaultBehavior ~name
+ Declare.declare_constant ~local:Locality.ImportDefaultBehavior ~name
~kind:Decls.(IsDefinition Definition)
cb
in
diff --git a/vernac/comInductive.ml b/vernac/comInductive.ml
index 95489c9132..673124296d 100644
--- a/vernac/comInductive.ml
+++ b/vernac/comInductive.ml
@@ -60,23 +60,28 @@ type structured_one_inductive_expr = {
ind_lc : (Id.t * constr_expr) list
}
+exception Same of Id.t
+
let check_all_names_different indl =
+ let rec elements = function
+ | [] -> Id.Set.empty
+ | id :: l ->
+ let s = elements l in
+ if Id.Set.mem id s then raise (Same id) else Id.Set.add id s
+ in
let ind_names = List.map (fun ind -> ind.ind_name) indl in
let cstr_names = List.map_append (fun ind -> List.map fst ind.ind_lc) indl in
- let l = List.duplicates Id.equal ind_names in
- let () = match l with
- | [] -> ()
- | t :: _ -> raise (InductiveError (SameNamesTypes t))
+ let ind_names = match elements ind_names with
+ | s -> s
+ | exception (Same t) -> raise (InductiveError (SameNamesTypes t))
in
- let l = List.duplicates Id.equal cstr_names in
- let () = match l with
- | [] -> ()
- | c :: _ -> raise (InductiveError (SameNamesConstructors (List.hd l)))
+ let cstr_names = match elements cstr_names with
+ | s -> s
+ | exception (Same c) -> raise (InductiveError (SameNamesConstructors c))
in
- let l = List.intersect Id.equal ind_names cstr_names in
- match l with
- | [] -> ()
- | _ -> raise (InductiveError (SameNamesOverlap l))
+ let l = Id.Set.inter ind_names cstr_names in
+ if not (Id.Set.is_empty l) then
+ raise (InductiveError (SameNamesOverlap (Id.Set.elements l)))
(** Make the arity conclusion flexible to avoid generating an upper bound universe now,
only if the universe does not appear anywhere else.
@@ -652,5 +657,3 @@ let make_cases ind =
let consref = GlobRef.ConstructRef (ith_constructor_of_inductive ind (i + 1)) in
(Libnames.string_of_qualid (Nametab.shortest_qualid_of_global Id.Set.empty consref) :: al') :: l)
mip.mind_nf_lc []
-
-let declare_mutual_inductive_with_eliminations = DeclareInd.declare_mutual_inductive_with_eliminations
diff --git a/vernac/comInductive.mli b/vernac/comInductive.mli
index 984581152a..9c876787a3 100644
--- a/vernac/comInductive.mli
+++ b/vernac/comInductive.mli
@@ -41,14 +41,6 @@ val do_mutual_inductive
val make_cases : Names.inductive -> string list list
-val declare_mutual_inductive_with_eliminations
- : ?primitive_expected:bool
- -> Entries.mutual_inductive_entry
- -> UnivNames.universe_binders
- -> DeclareInd.one_inductive_impls list
- -> Names.MutInd.t
- [@@ocaml.deprecated "Please use DeclareInd.declare_mutual_inductive_with_eliminations"]
-
val interp_mutual_inductive_constr
: sigma:Evd.evar_map
-> template:bool option
diff --git a/vernac/comProgramFixpoint.ml b/vernac/comProgramFixpoint.ml
index 4aa46e0a86..37615fa09c 100644
--- a/vernac/comProgramFixpoint.ml
+++ b/vernac/comProgramFixpoint.ml
@@ -260,8 +260,11 @@ let build_wellfounded (recname,pl,bl,arityc,body) poly r measure notation =
RetrieveObl.retrieve_obligations env recname sigma 0 def typ
in
let uctx = Evd.evar_universe_context sigma in
- ignore(Obligations.add_definition ~name:recname ~term:evars_def ~udecl
- ~poly evars_typ ~uctx evars ~hook)
+ let cinfo = Declare.CInfo.make ~name:recname ~typ:evars_typ () in
+ let info = Declare.Info.make ~udecl ~poly ~hook () in
+ let _ : Declare.Obls.progress =
+ Declare.Obls.add_definition ~cinfo ~info ~term:evars_def ~uctx evars in
+ ()
let out_def = function
| Some def -> def
@@ -290,7 +293,8 @@ let do_program_recursive ~scope ~poly fixkind fixl =
let evars, _, def, typ =
RetrieveObl.retrieve_obligations env name evm
(List.length rec_sign) def typ in
- ({ Declare.Recthm.name; typ; impargs; args = [] }, def, evars)
+ let cinfo = Declare.CInfo.make ~name ~typ ~impargs () in
+ (cinfo, def, evars)
in
let (fixnames,fixrs,fixdefs,fixtypes) = fix in
let fiximps = List.map pi2 info in
@@ -314,11 +318,12 @@ let do_program_recursive ~scope ~poly fixkind fixl =
end in
let uctx = Evd.evar_universe_context evd in
let kind = match fixkind with
- | Declare.Obls.IsFixpoint _ -> Decls.Fixpoint
- | Declare.Obls.IsCoFixpoint -> Decls.CoFixpoint
+ | Declare.Obls.IsFixpoint _ -> Decls.(IsDefinition Fixpoint)
+ | Declare.Obls.IsCoFixpoint -> Decls.(IsDefinition CoFixpoint)
in
let ntns = List.map_append (fun { Vernacexpr.notations } -> notations ) fixl in
- Obligations.add_mutual_definitions defs ~poly ~scope ~kind ~udecl ~uctx ntns fixkind
+ let info = Declare.Info.make ~poly ~scope ~kind ~udecl () in
+ Declare.Obls.add_mutual_definitions defs ~info ~uctx ~ntns fixkind
let do_fixpoint ~scope ~poly l =
let g = List.map (fun { Vernacexpr.rec_order } -> rec_order) l in
diff --git a/vernac/comProgramFixpoint.mli b/vernac/comProgramFixpoint.mli
index 8b1fa6c202..e39f62c348 100644
--- a/vernac/comProgramFixpoint.mli
+++ b/vernac/comProgramFixpoint.mli
@@ -14,8 +14,8 @@ open Vernacexpr
val do_fixpoint :
(* When [false], assume guarded. *)
- scope:Declare.locality -> poly:bool -> fixpoint_expr list -> unit
+ scope:Locality.locality -> poly:bool -> fixpoint_expr list -> unit
val do_cofixpoint :
(* When [false], assume guarded. *)
- scope:Declare.locality -> poly:bool -> cofixpoint_expr list -> unit
+ scope:Locality.locality -> poly:bool -> cofixpoint_expr list -> unit
diff --git a/vernac/declare.ml b/vernac/declare.ml
index 59922c662a..6326a22e83 100644
--- a/vernac/declare.ml
+++ b/vernac/declare.ml
@@ -16,111 +16,76 @@ open Names
open Safe_typing
module NamedDecl = Context.Named.Declaration
-type opacity_flag = Vernacexpr.opacity_flag = Opaque | Transparent
+(* Hooks naturally belong here as they apply to both definitions and lemmas *)
+module Hook = struct
+ module S = struct
+ type t =
+ { uctx : UState.t
+ (** [ustate]: universe constraints obtained when the term was closed *)
+ ; obls : (Names.Id.t * Constr.t) list
+ (** [(n1,t1),...(nm,tm)]: association list between obligation
+ name and the corresponding defined term (might be a constant,
+ but also an arbitrary term in the Expand case of obligations) *)
+ ; scope : Locality.locality
+ (** [locality]: Locality of the original declaration *)
+ ; dref : Names.GlobRef.t
+ (** [ref]: identifier of the original declaration *)
+ }
+ end
-type t =
- { endline_tactic : Genarg.glob_generic_argument option
- ; section_vars : Id.Set.t option
- ; proof : Proof.t
- ; udecl: UState.universe_decl
- (** Initial universe declarations *)
- ; initial_euctx : UState.t
- (** The initial universe context (for the statement) *)
- }
+ type t = (S.t -> unit) CEphemeron.key
-(*** Proof Global manipulation ***)
+ let make hook = CEphemeron.create hook
-let get_proof ps = ps.proof
-let get_proof_name ps = (Proof.data ps.proof).Proof.name
+ let call ?hook x = Option.iter (fun hook -> CEphemeron.get hook x) hook
-let get_initial_euctx ps = ps.initial_euctx
+end
-let map_proof f p = { p with proof = f p.proof }
-let map_fold_proof f p = let proof, res = f p.proof in { p with proof }, res
+module CInfo = struct
-let map_fold_proof_endline f ps =
- let et =
- match ps.endline_tactic with
- | None -> Proofview.tclUNIT ()
- | Some tac ->
- let open Geninterp in
- let {Proof.poly} = Proof.data ps.proof in
- let ist = { lfun = Id.Map.empty; poly; extra = TacStore.empty } in
- let Genarg.GenArg (Genarg.Glbwit tag, tac) = tac in
- let tac = Geninterp.interp tag ist tac in
- Ftactic.run tac (fun _ -> Proofview.tclUNIT ())
- in
- let (newpr,ret) = f et ps.proof in
- let ps = { ps with proof = newpr } in
- ps, ret
+ type 'constr t =
+ { name : Id.t
+ (** Name of theorem *)
+ ; typ : 'constr
+ (** Type of theorem *)
+ ; args : Name.t list
+ (** Names to pre-introduce *)
+ ; impargs : Impargs.manual_implicits
+ (** Explicitily declared implicit arguments *)
+ }
-let compact_the_proof pf = map_proof Proof.compact pf
-(* Sets the tactic to be used when a tactic line is closed with [...] *)
-let set_endline_tactic tac ps =
- { ps with endline_tactic = Some tac }
+ let make ~name ~typ ?(args=[]) ?(impargs=[]) () =
+ { name; typ; args; impargs }
-(** [start_proof ~name ~udecl ~poly sigma goals] starts a proof of
- name [name] with goals [goals] (a list of pairs of environment and
- conclusion). The proof is started in the evar map [sigma] (which
- can typically contain universe constraints), and with universe
- bindings [udecl]. *)
-let start_proof ~name ~udecl ~poly sigma goals =
- let proof = Proof.start ~name ~poly sigma goals in
- let initial_euctx = Evd.evar_universe_context Proof.((data proof).sigma) in
- { proof
- ; endline_tactic = None
- ; section_vars = None
- ; udecl
- ; initial_euctx
- }
+ let to_constr sigma thm = { thm with typ = EConstr.to_constr sigma thm.typ }
-let start_dependent_proof ~name ~udecl ~poly goals =
- let proof = Proof.dependent_start ~name ~poly goals in
- let initial_euctx = Evd.evar_universe_context Proof.((data proof).sigma) in
- { proof
- ; endline_tactic = None
- ; section_vars = None
- ; udecl
- ; initial_euctx
- }
+ let get_typ { typ; _ } = typ
+ let get_name { name; _ } = name
-let get_used_variables pf = pf.section_vars
-let get_universe_decl pf = pf.udecl
+end
-let set_used_variables ps l =
- let open Context.Named.Declaration in
- let env = Global.env () in
- let ids = List.fold_right Id.Set.add l Id.Set.empty in
- let ctx = Environ.keep_hyps env ids in
- let ctx_set =
- List.fold_right Id.Set.add (List.map NamedDecl.get_id ctx) Id.Set.empty in
- let vars_of = Environ.global_vars_set in
- let aux env entry (ctx, all_safe as orig) =
- match entry with
- | LocalAssum ({Context.binder_name=x},_) ->
- if Id.Set.mem x all_safe then orig
- else (ctx, all_safe)
- | LocalDef ({Context.binder_name=x},bo, ty) as decl ->
- if Id.Set.mem x all_safe then orig else
- let vars = Id.Set.union (vars_of env bo) (vars_of env ty) in
- if Id.Set.subset vars all_safe
- then (decl :: ctx, Id.Set.add x all_safe)
- else (ctx, all_safe) in
- let ctx, _ =
- Environ.fold_named_context aux env ~init:(ctx,ctx_set) in
- if not (Option.is_empty ps.section_vars) then
- CErrors.user_err Pp.(str "Used section variables can be declared only once");
- ctx, { ps with section_vars = Some (Context.Named.to_vars ctx) }
+(** Information for a declaration, interactive or not, includes
+ parameters shared by mutual constants *)
+module Info = struct
-let get_open_goals ps =
- let Proof.{ goals; stack; shelf } = Proof.data ps.proof in
- List.length goals +
- List.fold_left (+) 0
- (List.map (fun (l1,l2) -> List.length l1 + List.length l2) stack) +
- List.length shelf
+ type t =
+ { poly : bool
+ ; inline : bool
+ ; kind : Decls.logical_kind
+ ; udecl : UState.universe_decl
+ ; scope : Locality.locality
+ ; hook : Hook.t option
+ }
+
+ (** Note that [opaque] doesn't appear here as it is not known at the
+ start of the proof in the interactive case. *)
+ let make ?(poly=false) ?(inline=false) ?(kind=Decls.(IsDefinition Definition))
+ ?(udecl=UState.default_univ_decl) ?(scope=Locality.Global Locality.ImportDefaultBehavior)
+ ?hook () =
+ { poly; inline; kind; udecl; scope; hook }
-type import_status = Locality.import_status = ImportDefaultBehavior | ImportNeedQualified
+end
(** Declaration of constants and parameters *)
@@ -153,117 +118,6 @@ let definition_entry_core ?(opaque=false) ?(inline=false) ?feedback_id ?section_
let definition_entry =
definition_entry_core ?eff:None ?univsbody:None ?feedback_id:None ?section_vars:None
-type proof_object =
- { name : Names.Id.t
- (* [name] only used in the STM *)
- ; entries : Evd.side_effects proof_entry list
- ; uctx: UState.t
- }
-
-let get_po_name { name } = name
-
-let private_poly_univs =
- Goptions.declare_bool_option_and_ref
- ~depr:false
- ~key:["Private";"Polymorphic";"Universes"]
- ~value:true
-
-(* XXX: This is still separate from close_proof below due to drop_pt in the STM *)
-(* XXX: Unsafe_typ:true is needed by vio files, see bf0499bc507d5a39c3d5e3bf1f69191339270729 *)
-let prepare_proof ~unsafe_typ { proof } =
- let Proof.{name=pid;entry;poly} = Proof.data proof in
- let initial_goals = Proofview.initial_goals entry in
- let evd = Proof.return ~pid proof in
- let eff = Evd.eval_side_effects evd in
- let evd = Evd.minimize_universes evd in
- let to_constr_body c =
- match EConstr.to_constr_opt evd c with
- | Some p ->
- Vars.universes_of_constr p, p
- | None ->
- CErrors.user_err Pp.(str "Some unresolved existential variables remain")
- in
- let to_constr_typ t =
- if unsafe_typ
- then
- let t = EConstr.Unsafe.to_constr t in
- Vars.universes_of_constr t, t
- else to_constr_body t
- in
- (* ppedrot: FIXME, this is surely wrong. There is no reason to duplicate
- side-effects... This may explain why one need to uniquize side-effects
- thereafter... *)
- (* EJGA: actually side-effects de-duplication and this codepath is
- unrelated. Duplicated side-effects arise from incorrect scheme
- generation code, the main bulk of it was mostly fixed by #9836
- but duplication can still happen because of rewriting schemes I
- think; however the code below is mostly untested, the only
- code-paths that generate several proof entries are derive and
- equations and so far there is no code in the CI that will
- actually call those and do a side-effect, TTBOMK *)
- (* EJGA: likely the right solution is to attach side effects to the first constant only? *)
- let proofs = List.map (fun (body, typ) -> (to_constr_body body, eff), to_constr_typ typ) initial_goals in
- proofs, Evd.evar_universe_context evd
-
-let make_univs_deferred ~poly ~initial_euctx ~uctx ~udecl
- (used_univs_typ, typ) (used_univs_body, body) =
- let used_univs = Univ.LSet.union used_univs_body used_univs_typ in
- let utyp = UState.univ_entry ~poly initial_euctx in
- let uctx = UState.constrain_variables (fst (UState.context_set initial_euctx)) uctx in
- (* For vi2vo compilation proofs are computed now but we need to
- complement the univ constraints of the typ with the ones of
- the body. So we keep the two sets distinct. *)
- let uctx_body = UState.restrict uctx used_univs in
- let ubody = UState.check_mono_univ_decl uctx_body udecl in
- utyp, ubody
-
-let make_univs_private_poly ~poly ~uctx ~udecl (used_univs_typ, typ) (used_univs_body, body) =
- let used_univs = Univ.LSet.union used_univs_body used_univs_typ in
- let universes = UState.restrict uctx used_univs in
- let typus = UState.restrict universes used_univs_typ in
- let utyp = UState.check_univ_decl ~poly typus udecl in
- let ubody = Univ.ContextSet.diff
- (UState.context_set universes)
- (UState.context_set typus)
- in
- utyp, ubody
-
-let make_univs ~poly ~uctx ~udecl (used_univs_typ, typ) (used_univs_body, body) =
- let used_univs = Univ.LSet.union used_univs_body used_univs_typ in
- (* Since the proof is computed now, we can simply have 1 set of
- constraints in which we merge the ones for the body and the ones
- for the typ. We recheck the declaration after restricting with
- the actually used universes.
- TODO: check if restrict is really necessary now. *)
- let ctx = UState.restrict uctx used_univs in
- let utyp = UState.check_univ_decl ~poly ctx udecl in
- utyp, Univ.ContextSet.empty
-
-let close_proof ~opaque ~keep_body_ucst_separate ps =
-
- let { section_vars; proof; udecl; initial_euctx } = ps in
- let { Proof.name; poly } = Proof.data proof in
- let unsafe_typ = keep_body_ucst_separate && not poly in
- let elist, uctx = prepare_proof ~unsafe_typ ps in
- let opaque = match opaque with Opaque -> true | Transparent -> false in
-
- let make_entry ((((_ub, body) as b), eff), ((_ut, typ) as t)) =
- let utyp, ubody =
- (* allow_deferred case *)
- if not poly &&
- (keep_body_ucst_separate
- || not (Safe_typing.is_empty_private_constants eff.Evd.seff_private))
- then make_univs_deferred ~initial_euctx ~poly ~uctx ~udecl t b
- (* private_poly_univs case *)
- else if poly && opaque && private_poly_univs ()
- then make_univs_private_poly ~poly ~uctx ~udecl t b
- else make_univs ~poly ~uctx ~udecl t b
- in
- definition_entry_core ~opaque ?section_vars ~univs:utyp ~univsbody:ubody ~types:typ ~eff body
- in
- let entries = CList.map make_entry elist in
- { name; entries; uctx }
-
type 'a constant_entry =
| DefinitionEntry of 'a proof_entry
| ParameterEntry of Entries.parameter_entry
@@ -271,7 +125,7 @@ type 'a constant_entry =
type constant_obj = {
cst_kind : Decls.logical_kind;
- cst_locl : import_status;
+ cst_locl : Locality.import_status;
}
let load_constant i ((sp,kn), obj) =
@@ -285,8 +139,8 @@ let load_constant i ((sp,kn), obj) =
let open_constant f i ((sp,kn), obj) =
(* Never open a local definition *)
match obj.cst_locl with
- | ImportNeedQualified -> ()
- | ImportDefaultBehavior ->
+ | Locality.ImportNeedQualified -> ()
+ | Locality.ImportDefaultBehavior ->
let con = Global.constant_of_delta_kn kn in
if Libobject.in_filter_ref (GlobRef.ConstRef con) f then
Nametab.push (Nametab.Exactly i) sp (GlobRef.ConstRef con)
@@ -340,7 +194,7 @@ let register_constant kn kind local =
update_tables kn
let register_side_effect (c, role) =
- let () = register_constant c Decls.(IsProof Theorem) ImportDefaultBehavior in
+ let () = register_constant c Decls.(IsProof Theorem) Locality.ImportDefaultBehavior in
match role with
| None -> ()
| Some (Evd.Schema (ind, kind)) -> DeclareScheme.declare_scheme kind [|ind,c|]
@@ -497,14 +351,14 @@ let define_constant ~name cd =
if unsafe || is_unsafe_typing_flags() then feedback_axiom();
kn
-let declare_constant ?(local = ImportDefaultBehavior) ~name ~kind cd =
+let declare_constant ?(local = Locality.ImportDefaultBehavior) ~name ~kind cd =
let () = check_exists name in
let kn = define_constant ~name cd in
(* Register the libobjects attached to the constants *)
let () = register_constant kn kind local in
kn
-let declare_private_constant ?role ?(local = ImportDefaultBehavior) ~name ~kind de =
+let declare_private_constant ?role ?(local = Locality.ImportDefaultBehavior) ~name ~kind de =
let kn, eff =
let de =
if not de.proof_entry_opaque then
@@ -684,180 +538,6 @@ module Internal = struct
let objConstant = objConstant
end
-(*** Proof Global Environment ***)
-
-type closed_proof_output = (Constr.t * Evd.side_effects) list * UState.t
-
-let close_proof_delayed ~feedback_id ps (fpl : closed_proof_output Future.computation) =
- let { section_vars; proof; udecl; initial_euctx } = ps in
- let { Proof.name; poly; entry; sigma } = Proof.data proof in
-
- (* We don't allow poly = true in this path *)
- if poly then
- CErrors.anomaly (Pp.str "Cannot delay universe-polymorphic constants.");
-
- let fpl, uctx = Future.split2 fpl in
- (* Because of dependent subgoals at the beginning of proofs, we could
- have existential variables in the initial types of goals, we need to
- normalise them for the kernel. *)
- let subst_evar k = Evd.existential_opt_value0 sigma k in
- let nf = UnivSubst.nf_evars_and_universes_opt_subst subst_evar (UState.subst initial_euctx) in
-
- (* We only support opaque proofs, this will be enforced by using
- different entries soon *)
- let opaque = true in
- let make_entry p (_, types) =
- (* Already checked the univ_decl for the type universes when starting the proof. *)
- let univs = UState.univ_entry ~poly:false initial_euctx in
- let types = nf (EConstr.Unsafe.to_constr types) in
-
- Future.chain p (fun (pt,eff) ->
- (* Deferred proof, we already checked the universe declaration with
- the initial universes, ensure that the final universes respect
- the declaration as well. If the declaration is non-extensible,
- this will prevent the body from adding universes and constraints. *)
- let uctx = Future.force uctx in
- let uctx = UState.constrain_variables (fst (UState.context_set initial_euctx)) uctx in
- let used_univs = Univ.LSet.union
- (Vars.universes_of_constr types)
- (Vars.universes_of_constr pt)
- in
- let univs = UState.restrict uctx used_univs in
- let univs = UState.check_mono_univ_decl univs udecl in
- (pt,univs),eff)
- |> delayed_definition_entry ~opaque ~feedback_id ~section_vars ~univs ~types
- in
- let entries = Future.map2 make_entry fpl (Proofview.initial_goals entry) in
- { name; entries; uctx = initial_euctx }
-
-let close_future_proof = close_proof_delayed
-
-let return_partial_proof { proof } =
- let proofs = Proof.partial_proof proof in
- let Proof.{sigma=evd} = Proof.data proof in
- let eff = Evd.eval_side_effects evd in
- (* ppedrot: FIXME, this is surely wrong. There is no reason to duplicate
- side-effects... This may explain why one need to uniquize side-effects
- thereafter... *)
- let proofs = List.map (fun c -> EConstr.Unsafe.to_constr c, eff) proofs in
- proofs, Evd.evar_universe_context evd
-
-let return_proof ps =
- let p, uctx = prepare_proof ~unsafe_typ:false ps in
- List.map (fun (((_ub, body),eff),_) -> (body,eff)) p, uctx
-
-let update_global_env =
- map_proof (fun p ->
- let { Proof.sigma } = Proof.data p in
- let tac = Proofview.Unsafe.tclEVARS (Evd.update_sigma_env sigma (Global.env ())) in
- let p, (status,info), _ = Proof.run_tactic (Global.env ()) tac p in
- p)
-
-let next = let n = ref 0 in fun () -> incr n; !n
-
-let by tac = map_fold_proof (Proof.solve (Goal_select.SelectNth 1) None tac)
-
-let build_constant_by_tactic ~name ?(opaque=Transparent) ~uctx ~sign ~poly typ tac =
- let evd = Evd.from_ctx uctx in
- let goals = [ (Global.env_of_context sign , typ) ] in
- let pf = start_proof ~name ~poly ~udecl:UState.default_univ_decl evd goals in
- let pf, status = by tac pf in
- let { entries; uctx } = close_proof ~opaque ~keep_body_ucst_separate:false pf in
- match entries with
- | [entry] ->
- entry, status, uctx
- | _ ->
- CErrors.anomaly Pp.(str "[build_constant_by_tactic] close_proof returned more than one proof term")
-
-let build_by_tactic ?(side_eff=true) env ~uctx ~poly ~typ tac =
- let name = Id.of_string ("temporary_proof"^string_of_int (next())) in
- let sign = Environ.(val_of_named_context (named_context env)) in
- let ce, status, uctx = build_constant_by_tactic ~name ~uctx ~sign ~poly typ tac in
- let cb, uctx =
- if side_eff then inline_private_constants ~uctx env ce
- else
- (* GG: side effects won't get reset: no need to treat their universes specially *)
- let (cb, ctx), _eff = Future.force ce.proof_entry_body in
- cb, UState.merge ~sideff:false Evd.univ_rigid uctx ctx
- in
- cb, ce.proof_entry_type, ce.proof_entry_universes, status, uctx
-
-let declare_abstract ~name ~poly ~kind ~sign ~secsign ~opaque ~solve_tac sigma concl =
- (* EJGA: flush_and_check_evars is only used in abstract, could we
- use a different API? *)
- let concl =
- try Evarutil.flush_and_check_evars sigma concl
- with Evarutil.Uninstantiated_evar _ ->
- CErrors.user_err Pp.(str "\"abstract\" cannot handle existentials.")
- in
- let sigma, concl =
- (* FIXME: should be done only if the tactic succeeds *)
- let sigma = Evd.minimize_universes sigma in
- sigma, Evarutil.nf_evars_universes sigma concl
- in
- let concl = EConstr.of_constr concl in
- let uctx = Evd.evar_universe_context sigma in
- let (const, safe, uctx) =
- try build_constant_by_tactic ~name ~opaque:Transparent ~poly ~uctx ~sign:secsign concl solve_tac
- with Logic_monad.TacticFailure e as src ->
- (* if the tactic [tac] fails, it reports a [TacticFailure e],
- which is an error irrelevant to the proof system (in fact it
- means that [e] comes from [tac] failing to yield enough
- success). Hence it reraises [e]. *)
- let (_, info) = Exninfo.capture src in
- Exninfo.iraise (e, info)
- in
- let sigma = Evd.set_universe_context sigma uctx in
- let body, effs = Future.force const.proof_entry_body in
- (* We drop the side-effects from the entry, they already exist in the ambient environment *)
- let const = Internal.map_entry_body const ~f:(fun _ -> body, ()) in
- (* EJGA: Hack related to the above call to
- `build_constant_by_tactic` with `~opaque:Transparent`. Even if
- the abstracted term is destined to be opaque, if we trigger the
- `if poly && opaque && private_poly_univs ()` in `Proof_global`
- kernel will boom. This deserves more investigation. *)
- let const = Internal.set_opacity ~opaque const in
- let const, args = Internal.shrink_entry sign const in
- let cst () =
- (* do not compute the implicit arguments, it may be costly *)
- let () = Impargs.make_implicit_args false in
- (* ppedrot: seems legit to have abstracted subproofs as local*)
- declare_private_constant ~local:ImportNeedQualified ~name ~kind const
- in
- let cst, eff = Impargs.with_implicit_protection cst () in
- let inst = match const.proof_entry_universes with
- | Entries.Monomorphic_entry _ -> EConstr.EInstance.empty
- | Entries.Polymorphic_entry (_, ctx) ->
- (* We mimic what the kernel does, that is ensuring that no additional
- constraints appear in the body of polymorphic constants. Ideally this
- should be enforced statically. *)
- let (_, body_uctx), _ = Future.force const.proof_entry_body in
- let () = assert (Univ.ContextSet.is_empty body_uctx) in
- EConstr.EInstance.make (Univ.UContext.instance ctx)
- in
- let args = List.map EConstr.of_constr args in
- let lem = EConstr.mkConstU (cst, inst) in
- let effs = Evd.concat_side_effects eff effs in
- effs, sigma, lem, args, safe
-
-let get_goal_context pf i =
- let p = get_proof pf in
- Proof.get_goal_context_gen p i
-
-let get_current_goal_context pf =
- let p = get_proof pf in
- try Proof.get_goal_context_gen p 1
- with
- | Proof.NoSuchGoal _ ->
- (* spiwack: returning empty evar_map, since if there is no goal,
- under focus, there is no accessible evar either. EJGA: this
- seems strange, as we have pf *)
- let env = Global.env () in
- Evd.from_env env, env
-
-let get_current_context pf =
- let p = get_proof pf in
- Proof.get_proof_context p
let declare_definition_scheme ~internal ~univs ~role ~name c =
let kind = Decls.(IsDefinition Scheme) in
@@ -866,38 +546,6 @@ let declare_definition_scheme ~internal ~univs ~role ~name c =
let () = if internal then () else definition_message name in
kn, eff
-let _ = Ind_tables.declare_definition_scheme := declare_definition_scheme
-let _ = Abstract.declare_abstract := declare_abstract
-
-let declare_universe_context = DeclareUctx.declare_universe_context
-
-type locality = Locality.locality = | Discharge | Global of import_status
-
-(* Hooks naturally belong here as they apply to both definitions and lemmas *)
-module Hook = struct
- module S = struct
- type t =
- { uctx : UState.t
- (** [ustate]: universe constraints obtained when the term was closed *)
- ; obls : (Names.Id.t * Constr.t) list
- (** [(n1,t1),...(nm,tm)]: association list between obligation
- name and the corresponding defined term (might be a constant,
- but also an arbitrary term in the Expand case of obligations) *)
- ; scope : locality
- (** [locality]: Locality of the original declaration *)
- ; dref : Names.GlobRef.t
- (** [ref]: identifier of the original declaration *)
- }
- end
-
- type t = (S.t -> unit) CEphemeron.key
-
- let make hook = CEphemeron.create hook
-
- let call ?hook x = Option.iter (fun hook -> CEphemeron.get hook x) hook
-
-end
-
(* Locality stuff *)
let declare_entry_core ~name ~scope ~kind ?hook ~obls ~impargs ~uctx entry =
let should_suggest =
@@ -907,11 +555,11 @@ let declare_entry_core ~name ~scope ~kind ?hook ~obls ~impargs ~uctx entry =
in
let ubind = UState.universe_binders uctx in
let dref = match scope with
- | Discharge ->
+ | Locality.Discharge ->
let () = declare_variable_core ~name ~kind (SectionLocalDef entry) in
if should_suggest then Proof_using.suggest_variable (Global.env ()) name;
Names.GlobRef.VarRef name
- | Global local ->
+ | Locality.Global local ->
let kn = declare_constant ~name ~local ~kind (DefinitionEntry entry) in
let gr = Names.GlobRef.ConstRef kn in
if should_suggest then Proof_using.suggest_constant (Global.env ()) kn;
@@ -920,7 +568,7 @@ let declare_entry_core ~name ~scope ~kind ?hook ~obls ~impargs ~uctx entry =
in
let () = Impargs.maybe_declare_manual_implicits false dref impargs in
let () = definition_message name in
- Option.iter (fun hook -> Hook.call ~hook { Hook.S.uctx; obls; scope; dref }) hook;
+ Hook.call ?hook { Hook.S.uctx; obls; scope; dref };
dref
let declare_entry = declare_entry_core ~obls:[]
@@ -938,22 +586,10 @@ let mutual_make_bodies ~fixitems ~rec_declaration ~possible_indexes =
let vars = Vars.universes_of_constr (List.hd fixdecls) in
vars, fixdecls, None
-module Recthm = struct
- type t =
- { name : Names.Id.t
- (** Name of theorem *)
- ; typ : Constr.t
- (** Type of theorem *)
- ; args : Names.Name.t list
- (** Names to pre-introduce *)
- ; impargs : Impargs.manual_implicits
- (** Explicitily declared implicit arguments *)
- }
-end
-
-let declare_mutually_recursive_core ~opaque ~scope ~kind ~poly ~uctx ~udecl ~ntns ~rec_declaration ~possible_indexes ?(restrict_ucontext=true) fixitems =
+let declare_mutually_recursive_core ~info ~cinfo ~opaque ~ntns ~uctx ~rec_declaration ~possible_indexes ?(restrict_ucontext=true) () =
+ let { Info.poly; udecl; scope; kind; _ } = info in
let vars, fixdecls, indexes =
- mutual_make_bodies ~fixitems ~rec_declaration ~possible_indexes in
+ mutual_make_bodies ~fixitems:cinfo ~rec_declaration ~possible_indexes in
let uctx, univs =
(* XXX: Obligations don't do this, this seems like a bug? *)
if restrict_ucontext
@@ -966,18 +602,18 @@ let declare_mutually_recursive_core ~opaque ~scope ~kind ~poly ~uctx ~udecl ~ntn
uctx, univs
in
let csts = CList.map2
- (fun Recthm.{ name; typ; impargs } body ->
+ (fun CInfo.{ name; typ; impargs } body ->
let entry = definition_entry ~opaque ~types:typ ~univs body in
declare_entry ~name ~scope ~kind ~impargs ~uctx entry)
- fixitems fixdecls
+ cinfo fixdecls
in
let isfix = Option.has_some possible_indexes in
- let fixnames = List.map (fun { Recthm.name } -> name) fixitems in
+ let fixnames = List.map (fun { CInfo.name } -> name) cinfo in
recursive_message isfix indexes fixnames;
List.iter (Metasyntax.add_notation_interpretation (Global.env())) ntns;
csts
-let declare_mutually_recursive = declare_mutually_recursive_core ~restrict_ucontext:true
+let declare_mutually_recursive = declare_mutually_recursive_core ~restrict_ucontext:true ()
let warn_let_as_axiom =
CWarnings.create ~name:"let-as-axiom" ~category:"vernacular"
@@ -986,8 +622,8 @@ let warn_let_as_axiom =
let declare_assumption ~name ~scope ~hook ~impargs ~uctx pe =
let local = match scope with
- | Discharge -> warn_let_as_axiom name; ImportNeedQualified
- | Global local -> local
+ | Locality.Discharge -> warn_let_as_axiom name; Locality.ImportNeedQualified
+ | Locality.Global local -> local
in
let kind = Decls.(IsAssumption Conjectural) in
let decl = ParameterEntry pe in
@@ -1001,20 +637,22 @@ let declare_assumption ~name ~scope ~hook ~impargs ~uctx pe =
(* Preparing proof entries *)
-let prepare_definition ?opaque ?inline ~poly ~udecl ~types ~body sigma =
+let prepare_definition ~info ~opaque ~body ~typ sigma =
+ let { Info.poly; udecl; inline; _ } = info in
let env = Global.env () in
Pretyping.check_evars_are_solved ~program_mode:false env sigma;
let sigma, (body, types) = Evarutil.finalize ~abort_on_undefined_evars:true
- sigma (fun nf -> nf body, Option.map nf types)
+ sigma (fun nf -> nf body, Option.map nf typ)
in
let univs = Evd.check_univ_decl ~poly sigma udecl in
- let entry = definition_entry ?opaque ?inline ?types ~univs body in
+ let entry = definition_entry ~opaque ~inline ?types ~univs body in
let uctx = Evd.evar_universe_context sigma in
entry, uctx
-let declare_definition_core ~name ~scope ~kind ~opaque ~impargs ~udecl ?hook
- ~obls ~poly ?inline ~types ~body sigma =
- let entry, uctx = prepare_definition ~opaque ~poly ~udecl ~types ~body ?inline sigma in
+let declare_definition_core ~info ~cinfo ~opaque ~obls ~body sigma =
+ let { CInfo.name; impargs; typ; _ } = cinfo in
+ let entry, uctx = prepare_definition ~info ~opaque ~body ~typ sigma in
+ let { Info.scope; kind; hook; _ } = info in
declare_entry_core ~name ~scope ~kind ~impargs ~obls ?hook ~uctx entry
let declare_definition = declare_definition_core ~obls:[]
@@ -1043,10 +681,17 @@ let prepare_parameter ~poly ~udecl ~types sigma =
let univs = Evd.check_univ_decl ~poly sigma udecl in
sigma, (None(*proof using*), (typ, univs), None(*inline*))
-(* Compat: will remove *)
-exception AlreadyDeclared = DeclareUniv.AlreadyDeclared
+type progress = Remain of int | Dependent | Defined of GlobRef.t
-module Obls = struct
+type obligation_resolver =
+ Id.t option
+ -> Int.Set.t
+ -> unit Proofview.tactic option
+ -> progress
+
+type obligation_qed_info = {name : Id.t; num : int; auto : obligation_resolver}
+
+module Obls_ = struct
open Constr
@@ -1070,37 +715,32 @@ type obligations = {obls : Obligation.t array; remaining : int}
type fixpoint_kind = IsFixpoint of lident option list | IsCoFixpoint
module ProgramDecl = struct
+
type t =
- { prg_name : Id.t
+ { prg_cinfo : constr CInfo.t
+ ; prg_info : Info.t
+ ; prg_opaque : bool
; prg_body : constr
- ; prg_type : constr
- ; prg_ctx : UState.t
- ; prg_univdecl : UState.universe_decl
+ ; prg_uctx : UState.t
; prg_obligations : obligations
; prg_deps : Id.t list
; prg_fixkind : fixpoint_kind option
- ; prg_implicits : Impargs.manual_implicits
; prg_notations : Vernacexpr.decl_notation list
- ; prg_poly : bool
- ; prg_scope : locality
- ; prg_kind : Decls.definition_object_kind
; prg_reduce : constr -> constr
- ; prg_hook : Hook.t option
- ; prg_opaque : bool }
+ }
open Obligation
- let make ?(opaque = false) ?hook n ~udecl ~uctx ~impargs ~poly ~scope ~kind b
- t deps fixkind notations obls reduce =
- let obls', b =
- match b with
+ let make ~info ~cinfo ~opaque ~ntns ~reduce ~deps ~uctx ~body ~fixpoint_kind obls =
+ let obls', body =
+ match body with
| None ->
assert (Int.equal (Array.length obls) 0);
- let n = Nameops.add_suffix n "_obligation" in
+ let n = Nameops.add_suffix cinfo.CInfo.name "_obligation" in
( [| { obl_name = n
; obl_body = None
; obl_location = Loc.tag Evar_kinds.InternalHole
- ; obl_type = t
+ ; obl_type = cinfo.CInfo.typ
; obl_status = (false, Evar_kinds.Expand)
; obl_deps = Int.Set.empty
; obl_tac = None } |]
@@ -1118,25 +758,34 @@ module ProgramDecl = struct
obls
, b )
in
- let ctx = UState.make_flexible_nonalgebraic uctx in
- { prg_name = n
- ; prg_body = b
- ; prg_type = reduce t
- ; prg_ctx = ctx
- ; prg_univdecl = udecl
+ let prg_uctx = UState.make_flexible_nonalgebraic uctx in
+ { prg_cinfo = { cinfo with CInfo.typ = reduce cinfo.CInfo.typ }
+ ; prg_info = info
+ ; prg_opaque = opaque
+ ; prg_body = body
+ ; prg_uctx
; prg_obligations = {obls = obls'; remaining = Array.length obls'}
; prg_deps = deps
- ; prg_fixkind = fixkind
- ; prg_notations = notations
- ; prg_implicits = impargs
- ; prg_poly = poly
- ; prg_scope = scope
- ; prg_kind = kind
- ; prg_reduce = reduce
- ; prg_hook = hook
- ; prg_opaque = opaque }
-
- let set_uctx ~uctx prg = {prg with prg_ctx = uctx}
+ ; prg_fixkind = fixpoint_kind
+ ; prg_notations = ntns
+ ; prg_reduce = reduce }
+
+ let show prg =
+ let { CInfo.name; typ; _ } = prg.prg_cinfo in
+ let env = Global.env () in
+ let sigma = Evd.from_env env in
+ Id.print name ++ spc () ++ str ":" ++ spc ()
+ ++ Printer.pr_constr_env env sigma typ
+ ++ spc () ++ str ":=" ++ fnl ()
+ ++ Printer.pr_constr_env env sigma prg.prg_body
+
+ module Internal = struct
+ let get_name prg = prg.prg_cinfo.CInfo.name
+ let get_uctx prg = prg.prg_uctx
+ let set_uctx ~uctx prg = {prg with prg_uctx = uctx}
+ let get_poly prg = prg.prg_info.Info.poly
+ let get_obligations prg = prg.prg_obligations
+ end
end
open Obligation
@@ -1213,7 +862,7 @@ let unfold_entry cst = Hints.HintsUnfoldEntry [EvalConstRef cst]
let add_hint local prg cst =
let locality = if local then Goptions.OptLocal else Goptions.OptExport in
- Hints.add_hints ~locality [Id.to_string prg.prg_name] (unfold_entry cst)
+ Hints.add_hints ~locality [Id.to_string prg.prg_cinfo.CInfo.name] (unfold_entry cst)
(* true = hide obligations *)
let get_hide_obligations =
@@ -1223,14 +872,16 @@ let get_hide_obligations =
~value:false
let declare_obligation prg obl ~uctx ~types ~body =
- let univs = UState.univ_entry ~poly:prg.prg_poly uctx in
+ let poly = prg.prg_info.Info.poly in
+ let univs = UState.univ_entry ~poly uctx in
let body = prg.prg_reduce body in
let types = Option.map prg.prg_reduce types in
match obl.obl_status with
- | _, Evar_kinds.Expand -> (false, {obl with obl_body = Some (TermObl body)})
+ | _, Evar_kinds.Expand ->
+ (false, {obl with obl_body = Some (TermObl body)}, [])
| force, Evar_kinds.Define opaque ->
let opaque = (not force) && opaque in
- let poly = prg.prg_poly in
+ let poly = prg.prg_info.Info.poly in
let ctx, body, ty, args =
if not poly then shrink_body body types
else ([], body, types, [||])
@@ -1239,7 +890,7 @@ let declare_obligation prg obl ~uctx ~types ~body =
(* ppedrot: seems legit to have obligations as local *)
let constant =
declare_constant ~name:obl.obl_name
- ~local:ImportNeedQualified
+ ~local:Locality.ImportNeedQualified
~kind:Decls.(IsProof Property)
(DefinitionEntry ce)
in
@@ -1257,7 +908,7 @@ let declare_obligation prg obl ~uctx ~types ~body =
(mkApp (mkConst constant, args))
ctx))
in
- (true, {obl with obl_body = body})
+ (true, {obl with obl_body = body}, [GlobRef.ConstRef constant])
(* Updating the obligation meta-info on close *)
@@ -1323,7 +974,6 @@ module State = struct
let prg_ref, prg_tag =
Summary.ref_tag ProgMap.empty ~name:"program-tcc-table"
- let num_pending () = num_pending !prg_ref
let first_pending () = first_pending !prg_ref
let get_unique_open_prog id = get_unique_open_prog !prg_ref id
let add id prg = prg_ref := add !prg_ref id prg
@@ -1349,8 +999,8 @@ let check_solved_obligations ~what_for : unit =
++ str "unsolved obligations" )
let map_replace k v m = ProgMap.add k (CEphemeron.create v) (ProgMap.remove k m)
-let progmap_remove pm prg = ProgMap.remove prg.prg_name pm
-let progmap_replace prg' pm = map_replace prg'.prg_name prg' pm
+let progmap_remove pm prg = ProgMap.remove prg.prg_cinfo.CInfo.name pm
+let progmap_replace prg' pm = map_replace prg'.prg_cinfo.CInfo.name prg' pm
let obligations_solved prg = Int.equal prg.prg_obligations.remaining 0
let obligations_message rem =
@@ -1359,8 +1009,6 @@ let obligations_message rem =
(CString.plural rem "obligation")
|> Pp.str |> Flags.if_verbose Feedback.msg_info
-type progress = Remain of int | Dependent | Defined of GlobRef.t
-
let get_obligation_body expand obl =
match obl.obl_body with
| None -> None
@@ -1430,33 +1078,22 @@ let replace_appvars subst =
let subst_prog subst prg =
if get_hide_obligations () then
( replace_appvars subst prg.prg_body
- , replace_appvars subst (* Termops.refresh_universes *) prg.prg_type )
+ , replace_appvars subst (* Termops.refresh_universes *) prg.prg_cinfo.CInfo.typ )
else
let subst' = List.map (fun (n, (_, b)) -> (n, b)) subst in
( Vars.replace_vars subst' prg.prg_body
- , Vars.replace_vars subst' (* Termops.refresh_universes *) prg.prg_type )
+ , Vars.replace_vars subst' (* Termops.refresh_universes *) prg.prg_cinfo.CInfo.typ )
let declare_definition prg =
let varsubst = obligation_substitution true prg in
- let sigma = Evd.from_ctx prg.prg_ctx in
+ let sigma = Evd.from_ctx prg.prg_uctx in
let body, types = subst_prog varsubst prg in
let body, types = EConstr.(of_constr body, Some (of_constr types)) in
- (* All these should be grouped into a struct a some point *)
- let opaque, poly, udecl, hook =
- (prg.prg_opaque, prg.prg_poly, prg.prg_univdecl, prg.prg_hook)
- in
- let name, scope, kind, impargs =
- ( prg.prg_name
- , prg.prg_scope
- , Decls.(IsDefinition prg.prg_kind)
- , prg.prg_implicits )
- in
+ let cinfo = { prg.prg_cinfo with CInfo.typ = types } in
+ let name, info, opaque = prg.prg_cinfo.CInfo.name, prg.prg_info, prg.prg_opaque in
let obls = List.map (fun (id, (_, c)) -> (id, c)) varsubst in
(* XXX: This is doing normalization twice *)
- let kn =
- declare_definition_core ~name ~scope ~kind ~impargs ?hook ~obls
- ~opaque ~poly ~udecl ~types ~body sigma
- in
+ let kn = declare_definition_core ~cinfo ~info ~obls ~body ~opaque sigma in
let pm = progmap_remove !State.prg_ref prg in
State.prg_ref := pm;
kn
@@ -1487,7 +1124,7 @@ let declare_mutual_definition l =
let oblsubst = obligation_substitution true x in
let subs, typ = subst_prog oblsubst x in
let env = Global.env () in
- let sigma = Evd.from_ctx x.prg_ctx in
+ let sigma = Evd.from_ctx x.prg_uctx in
let r = Retyping.relevance_of_type env sigma (EConstr.of_constr typ) in
let term =
snd (Reductionops.splay_lam_n env sigma len (EConstr.of_constr subs))
@@ -1497,7 +1134,7 @@ let declare_mutual_definition l =
in
let term = EConstr.to_constr sigma term in
let typ = EConstr.to_constr sigma typ in
- let def = (x.prg_reduce term, r, x.prg_reduce typ, x.prg_implicits) in
+ let def = (x.prg_reduce term, r, x.prg_reduce typ, x.prg_cinfo.CInfo.impargs) in
let oblsubst = List.map (fun (id, (_, c)) -> (id, c)) oblsubst in
(def, oblsubst)
in
@@ -1515,13 +1152,13 @@ let declare_mutual_definition l =
( d :: a1
, r :: a2
, typ :: a3
- , Recthm.{name; typ; impargs; args = []} :: a4 ))
+ , CInfo.{name; typ; impargs; args = []} :: a4 ))
defs first.prg_deps ([], [], [], [])
in
let fixkind = Option.get first.prg_fixkind in
let arrrec, recvec = (Array.of_list fixtypes, Array.of_list fixdefs) in
let rvec = Array.of_list fixrs in
- let namevec = Array.of_list (List.map (fun x -> Name x.prg_name) l) in
+ let namevec = Array.of_list (List.map (fun x -> Name x.prg_cinfo.CInfo.name) l) in
let rec_declaration = (Array.map2 Context.make_annot namevec rvec, arrrec, recvec) in
let possible_indexes =
match fixkind with
@@ -1530,24 +1167,22 @@ let declare_mutual_definition l =
| IsCoFixpoint -> None
in
(* In the future we will pack all this in a proper record *)
- let poly, scope, ntns, opaque =
- (first.prg_poly, first.prg_scope, first.prg_notations, first.prg_opaque)
- in
- let kind =
+ (* XXX: info refactoring *)
+ let _kind =
if fixkind != IsCoFixpoint then Decls.(IsDefinition Fixpoint)
else Decls.(IsDefinition CoFixpoint)
in
+ let scope = first.prg_info.Info.scope in
(* Declare the recursive definitions *)
- let udecl = UState.default_univ_decl in
let kns =
- declare_mutually_recursive_core ~scope ~opaque ~kind ~udecl ~ntns
- ~uctx:first.prg_ctx ~rec_declaration ~possible_indexes ~poly
- ~restrict_ucontext:false fixitems
+ declare_mutually_recursive_core ~info:first.prg_info ~ntns:first.prg_notations
+ ~uctx:first.prg_uctx ~rec_declaration ~possible_indexes ~opaque:first.prg_opaque
+ ~restrict_ucontext:false ~cinfo:fixitems ()
in
(* Only for the first constant *)
let dref = List.hd kns in
Hook.(
- call ?hook:first.prg_hook {S.uctx = first.prg_ctx; obls; scope; dref});
+ call ?hook:first.prg_info.Info.hook {S.uctx = first.prg_uctx; obls; scope; dref});
let pm = List.fold_left progmap_remove !State.prg_ref l in
State.prg_ref := pm;
dref
@@ -1587,74 +1222,60 @@ let dependencies obls n =
let update_program_decl_on_defined prg obls num obl ~uctx rem ~auto =
let obls = Array.copy obls in
let () = obls.(num) <- obl in
- let prg = {prg with prg_ctx = uctx} in
+ let prg = {prg with prg_uctx = uctx} in
let _progress = update_obls prg obls (pred rem) in
let () =
if pred rem > 0 then
let deps = dependencies obls num in
if not (Int.Set.is_empty deps) then
- let _progress = auto (Some prg.prg_name) deps None in
+ let _progress = auto (Some prg.prg_cinfo.CInfo.name) deps None in
()
else ()
else ()
in
()
-type obligation_resolver =
- Id.t option
- -> Int.Set.t
- -> unit Proofview.tactic option
- -> progress
-
-type obligation_qed_info = {name : Id.t; num : int; auto : obligation_resolver}
-
-let obligation_terminator entries uctx {name; num; auto} =
- match entries with
- | [entry] ->
- let env = Global.env () in
- let ty = entry.proof_entry_type in
- let body, uctx = inline_private_constants ~uctx env entry in
- let sigma = Evd.from_ctx uctx in
- Inductiveops.control_only_guard (Global.env ()) sigma
- (EConstr.of_constr body);
- (* Declare the obligation ourselves and drop the hook *)
- let prg = Option.get (State.find name) in
- let {obls; remaining = rem} = prg.prg_obligations in
- let obl = obls.(num) in
- let status =
- match (obl.obl_status, entry.proof_entry_opaque) with
- | (_, Evar_kinds.Expand), true -> err_not_transp ()
- | (true, _), true -> err_not_transp ()
- | (false, _), true -> Evar_kinds.Define true
- | (_, Evar_kinds.Define true), false -> Evar_kinds.Define false
- | (_, status), false -> status
- in
- let obl = {obl with obl_status = (false, status)} in
- let uctx = if prg.prg_poly then uctx else UState.union prg.prg_ctx uctx in
- let defined, obl = declare_obligation prg obl ~body ~types:ty ~uctx in
- let prg_ctx =
- if prg.prg_poly then
- (* Polymorphic *)
- (* We merge the new universes and constraints of the
- polymorphic obligation with the existing ones *)
- UState.union prg.prg_ctx uctx
- else if
- (* The first obligation, if defined,
- declares the univs of the constant,
- each subsequent obligation declares its own additional
- universes and constraints if any *)
- defined
- then
- UState.from_env (Global.env ())
- else uctx
- in
- update_program_decl_on_defined prg obls num obl ~uctx:prg_ctx rem ~auto
- | _ ->
- CErrors.anomaly
- Pp.(
- str
- "[obligation_terminator] close_proof returned more than one proof \
- term")
+let obligation_terminator ~entry ~uctx ~oinfo:{name; num; auto} =
+ let env = Global.env () in
+ let ty = entry.proof_entry_type in
+ let body, uctx = inline_private_constants ~uctx env entry in
+ let sigma = Evd.from_ctx uctx in
+ Inductiveops.control_only_guard (Global.env ()) sigma
+ (EConstr.of_constr body);
+ (* Declare the obligation ourselves and drop the hook *)
+ let prg = Option.get (State.find name) in
+ let {obls; remaining = rem} = prg.prg_obligations in
+ let obl = obls.(num) in
+ let status =
+ match (obl.obl_status, entry.proof_entry_opaque) with
+ | (_, Evar_kinds.Expand), true -> err_not_transp ()
+ | (true, _), true -> err_not_transp ()
+ | (false, _), true -> Evar_kinds.Define true
+ | (_, Evar_kinds.Define true), false -> Evar_kinds.Define false
+ | (_, status), false -> status
+ in
+ let obl = {obl with obl_status = (false, status)} in
+ let poly = prg.prg_info.Info.poly in
+ let uctx = if poly then uctx else UState.union prg.prg_uctx uctx in
+ let defined, obl, cst = declare_obligation prg obl ~body ~types:ty ~uctx in
+ let prg_ctx =
+ if poly then
+ (* Polymorphic *)
+ (* We merge the new universes and constraints of the
+ polymorphic obligation with the existing ones *)
+ UState.union prg.prg_uctx uctx
+ else if
+ (* The first obligation, if defined,
+ declares the univs of the constant,
+ each subsequent obligation declares its own additional
+ universes and constraints if any *)
+ defined
+ then
+ UState.from_env (Global.env ())
+ else uctx
+ in
+ update_program_decl_on_defined prg obls num obl ~uctx:prg_ctx rem ~auto;
+ cst
(* Similar to the terminator but for the admitted path; this assumes
the admitted constant was already declared.
@@ -1674,7 +1295,7 @@ let obligation_admitted_terminator {name; num; auto} ctx' dref =
| _ -> ()
in
let inst, ctx' =
- if not prg.prg_poly (* Not polymorphic *) then
+ if not prg.prg_info.Info.poly (* Not polymorphic *) then
(* The universe context was declared globally, we continue
from the new global environment. *)
let ctx = UState.from_env (Global.env ()) in
@@ -1692,16 +1313,16 @@ let obligation_admitted_terminator {name; num; auto} ctx' dref =
end
(************************************************************************)
-(* Commom constant saving path, for both Qed and Admitted *)
+(* Handling of interactive proofs *)
(************************************************************************)
-(* Support for mutually proved theorems *)
+type lemma_possible_guards = int list list
module Proof_ending = struct
type t =
| Regular
- | End_obligation of Obls.obligation_qed_info
+ | End_obligation of obligation_qed_info
| End_derive of { f : Id.t; name : Id.t }
| End_equations of
{ hook : Constant.t list -> Evd.evar_map -> unit
@@ -1712,58 +1333,533 @@ module Proof_ending = struct
end
-type lemma_possible_guards = int list list
+(* Alias *)
+module Proof_ = Proof
+module Proof = struct
-module Info = struct
+module Proof_info = struct
type t =
- { hook : Hook.t option
+ { cinfo : Constr.t CInfo.t list
+ (** cinfo contains each individual constant info in a mutual decl *)
+ ; info : Info.t
; proof_ending : Proof_ending.t CEphemeron.key
(* This could be improved and the CEphemeron removed *)
- ; scope : locality
- ; kind : Decls.logical_kind
- (* thms and compute guard are specific only to start_lemma_with_initialization + regular terminator *)
- ; thms : Recthm.t list
; compute_guard : lemma_possible_guards
+ (** thms and compute guard are specific only to
+ start_lemma_with_initialization + regular terminator, so we
+ could make this per-proof kind *)
}
- let make ?hook ?(proof_ending=Proof_ending.Regular) ?(scope=Global ImportDefaultBehavior)
- ?(kind=Decls.(IsProof Lemma)) ?(compute_guard=[]) ?(thms=[]) () =
- { hook
+ let make ~cinfo ~info ?(compute_guard=[]) ?(proof_ending=Proof_ending.Regular) () =
+ { cinfo
+ ; info
; compute_guard
; proof_ending = CEphemeron.create proof_ending
- ; thms
- ; scope
- ; kind
}
(* This is used due to a deficiency on the API, should fix *)
- let add_first_thm ~info ~name ~typ ~impargs =
- let thms =
- { Recthm.name
- ; impargs
- ; typ = EConstr.Unsafe.to_constr typ
- ; args = [] } :: info.thms
- in
- { info with thms }
+ let add_first_thm ~pinfo ~name ~typ ~impargs =
+ let cinfo : Constr.t CInfo.t = CInfo.make ~name ~impargs ~typ:(EConstr.Unsafe.to_constr typ) () in
+ { pinfo with cinfo = cinfo :: pinfo.cinfo }
+ (* This is called by the STM, and we have to fixup cinfo later as
+ indeed it will not be correct *)
+ let default () = make ~cinfo:[] ~info:(Info.make ()) ()
end
+type t =
+ { endline_tactic : Genarg.glob_generic_argument option
+ ; section_vars : Id.Set.t option
+ ; proof : Proof.t
+ ; initial_euctx : UState.t
+ (** The initial universe context (for the statement) *)
+ ; pinfo : Proof_info.t
+ }
+
+(*** Proof Global manipulation ***)
+
+let info { pinfo } = pinfo
+let get ps = ps.proof
+let get_name ps = (Proof.data ps.proof).Proof.name
+let get_initial_euctx ps = ps.initial_euctx
+
+let fold ~f p = f p.proof
+let map ~f p = { p with proof = f p.proof }
+let map_fold ~f p = let proof, res = f p.proof in { p with proof }, res
+
+let map_fold_endline ~f ps =
+ let et =
+ match ps.endline_tactic with
+ | None -> Proofview.tclUNIT ()
+ | Some tac ->
+ let open Geninterp in
+ let {Proof.poly} = Proof.data ps.proof in
+ let ist = { lfun = Id.Map.empty; poly; extra = TacStore.empty } in
+ let Genarg.GenArg (Genarg.Glbwit tag, tac) = tac in
+ let tac = Geninterp.interp tag ist tac in
+ Ftactic.run tac (fun _ -> Proofview.tclUNIT ())
+ in
+ let (newpr,ret) = f et ps.proof in
+ let ps = { ps with proof = newpr } in
+ ps, ret
+
+let compact pf = map ~f:Proof.compact pf
+
+(* Sets the tactic to be used when a tactic line is closed with [...] *)
+let set_endline_tactic tac ps =
+ { ps with endline_tactic = Some tac }
+
+let initialize_named_context_for_proof () =
+ let sign = Global.named_context () in
+ List.fold_right
+ (fun d signv ->
+ let id = NamedDecl.get_id d in
+ let d = if Decls.variable_opacity id then NamedDecl.drop_body d else d in
+ Environ.push_named_context_val d signv) sign Environ.empty_named_context_val
+
+let start_proof_core ~name ~typ ~pinfo ?(sign=initialize_named_context_for_proof ()) sigma =
+ (* In ?sign, we remove the bodies of variables in the named context
+ marked "opaque", this is a hack tho, see #10446, and
+ build_constant_by_tactic uses a different method that would break
+ program_inference_hook *)
+ let { Proof_info.info = { Info.poly; _ }; _ } = pinfo in
+ let goals = [Global.env_of_context sign, typ] in
+ let proof = Proof.start ~name ~poly sigma goals in
+ let initial_euctx = Evd.evar_universe_context Proof.((data proof).sigma) in
+ { proof
+ ; endline_tactic = None
+ ; section_vars = None
+ ; initial_euctx
+ ; pinfo
+ }
+
+(** [start_proof ~info ~cinfo sigma] starts a proof of [cinfo].
+ The proof is started in the evar map [sigma] (which
+ can typically contain universe constraints) *)
+let start_core ~info ~cinfo ?proof_ending sigma =
+ let { CInfo.name; typ; _ } = cinfo in
+ let cinfo = [{ cinfo with CInfo.typ = EConstr.Unsafe.to_constr cinfo.CInfo.typ }] in
+ let pinfo = Proof_info.make ~cinfo ~info ?proof_ending () in
+ start_proof_core ~name ~typ ~pinfo ?sign:None sigma
+
+let start = start_core ?proof_ending:None
+
+let start_dependent ~info ~name ~proof_ending goals =
+ let proof = Proof.dependent_start ~name ~poly:info.Info.poly goals in
+ let initial_euctx = Evd.evar_universe_context Proof.((data proof).sigma) in
+ let cinfo = [] in
+ let pinfo = Proof_info.make ~info ~cinfo ~proof_ending () in
+ { proof
+ ; endline_tactic = None
+ ; section_vars = None
+ ; initial_euctx
+ ; pinfo
+ }
+
+let start_derive ~f ~name ~info goals =
+ let proof_ending = Proof_ending.End_derive {f; name} in
+ start_dependent ~info ~name ~proof_ending goals
+
+let start_equations ~name ~info ~hook ~types sigma goals =
+ let proof_ending = Proof_ending.End_equations {hook; i=name; types; sigma} in
+ start_dependent ~name ~info ~proof_ending goals
+
+let rec_tac_initializer finite guard thms snl =
+ if finite then
+ match List.map (fun { CInfo.name; typ } -> name, (EConstr.of_constr typ)) thms with
+ | (id,_)::l -> Tactics.mutual_cofix id l 0
+ | _ -> assert false
+ else
+ (* nl is dummy: it will be recomputed at Qed-time *)
+ let nl = match snl with
+ | None -> List.map succ (List.map List.last guard)
+ | Some nl -> nl
+ in match List.map2 (fun { CInfo.name; typ } n -> (name, n, (EConstr.of_constr typ))) thms nl with
+ | (id,n,_)::l -> Tactics.mutual_fix id n l 0
+ | _ -> assert false
+
+let start_with_initialization ~info ~cinfo sigma =
+ let { CInfo.name; typ; args } = cinfo in
+ let init_tac = Tactics.auto_intros_tac args in
+ let pinfo = Proof_info.make ~cinfo:[cinfo] ~info () in
+ let lemma = start_proof_core ~name ~typ:(EConstr.of_constr typ) ~pinfo ?sign:None sigma in
+ map lemma ~f:(fun p ->
+ pi1 @@ Proof.run_tactic Global.(env ()) init_tac p)
+
+type mutual_info = (bool * lemma_possible_guards * Constr.t option list option)
+
+let start_mutual_with_initialization ~info ~cinfo ~mutual_info sigma snl =
+ let intro_tac { CInfo.args; _ } = Tactics.auto_intros_tac args in
+ let init_tac, compute_guard =
+ let (finite,guard,init_terms) = mutual_info in
+ let rec_tac = rec_tac_initializer finite guard cinfo snl in
+ let term_tac =
+ match init_terms with
+ | None ->
+ List.map intro_tac cinfo
+ | Some init_terms ->
+ (* This is the case for hybrid proof mode / definition
+ fixpoint, where terms for some constants are given with := *)
+ let tacl = List.map (Option.cata (EConstr.of_constr %> Tactics.exact_no_check) Tacticals.New.tclIDTAC) init_terms in
+ List.map2 (fun tac thm -> Tacticals.New.tclTHEN tac (intro_tac thm)) tacl cinfo
+ in
+ Tacticals.New.tclTHENS rec_tac term_tac, guard
+ in
+ match cinfo with
+ | [] -> CErrors.anomaly (Pp.str "No proof to start.")
+ | { CInfo.name; typ; impargs; _} :: thms ->
+ let pinfo = Proof_info.make ~cinfo ~info ~compute_guard () in
+ (* start_lemma has the responsibility to add (name, impargs, typ)
+ to thms, once Info.t is more refined this won't be necessary *)
+ let typ = EConstr.of_constr typ in
+ let lemma = start_proof_core ~name ~typ ~pinfo sigma in
+ map lemma ~f:(fun p ->
+ pi1 @@ Proof.run_tactic Global.(env ()) init_tac p)
+
+let get_used_variables pf = pf.section_vars
+let get_universe_decl pf = pf.pinfo.Proof_info.info.Info.udecl
+
+let set_used_variables ps l =
+ let open Context.Named.Declaration in
+ let env = Global.env () in
+ let ids = List.fold_right Id.Set.add l Id.Set.empty in
+ let ctx = Environ.keep_hyps env ids in
+ let ctx_set =
+ List.fold_right Id.Set.add (List.map NamedDecl.get_id ctx) Id.Set.empty in
+ let vars_of = Environ.global_vars_set in
+ let aux env entry (ctx, all_safe as orig) =
+ match entry with
+ | LocalAssum ({Context.binder_name=x},_) ->
+ if Id.Set.mem x all_safe then orig
+ else (ctx, all_safe)
+ | LocalDef ({Context.binder_name=x},bo, ty) as decl ->
+ if Id.Set.mem x all_safe then orig else
+ let vars = Id.Set.union (vars_of env bo) (vars_of env ty) in
+ if Id.Set.subset vars all_safe
+ then (decl :: ctx, Id.Set.add x all_safe)
+ else (ctx, all_safe) in
+ let ctx, _ =
+ Environ.fold_named_context aux env ~init:(ctx,ctx_set) in
+ if not (Option.is_empty ps.section_vars) then
+ CErrors.user_err Pp.(str "Used section variables can be declared only once");
+ ctx, { ps with section_vars = Some (Context.Named.to_vars ctx) }
+
+let get_open_goals ps =
+ let Proof.{ goals; stack; shelf } = Proof.data ps.proof in
+ List.length goals +
+ List.fold_left (+) 0
+ (List.map (fun (l1,l2) -> List.length l1 + List.length l2) stack) +
+ List.length shelf
+
+type proof_object =
+ { name : Names.Id.t
+ (* [name] only used in the STM *)
+ ; entries : Evd.side_effects proof_entry list
+ ; uctx: UState.t
+ }
+
+let get_po_name { name } = name
+
+let private_poly_univs =
+ Goptions.declare_bool_option_and_ref
+ ~depr:false
+ ~key:["Private";"Polymorphic";"Universes"]
+ ~value:true
+
+(* XXX: This is still separate from close_proof below due to drop_pt in the STM *)
+(* XXX: Unsafe_typ:true is needed by vio files, see bf0499bc507d5a39c3d5e3bf1f69191339270729 *)
+let prepare_proof ~unsafe_typ { proof } =
+ let Proof.{name=pid;entry;poly} = Proof.data proof in
+ let initial_goals = Proofview.initial_goals entry in
+ let evd = Proof.return ~pid proof in
+ let eff = Evd.eval_side_effects evd in
+ let evd = Evd.minimize_universes evd in
+ let to_constr_body c =
+ match EConstr.to_constr_opt evd c with
+ | Some p ->
+ Vars.universes_of_constr p, p
+ | None ->
+ CErrors.user_err Pp.(str "Some unresolved existential variables remain")
+ in
+ let to_constr_typ t =
+ if unsafe_typ
+ then
+ let t = EConstr.Unsafe.to_constr t in
+ Vars.universes_of_constr t, t
+ else to_constr_body t
+ in
+ (* ppedrot: FIXME, this is surely wrong. There is no reason to duplicate
+ side-effects... This may explain why one need to uniquize side-effects
+ thereafter... *)
+ (* EJGA: actually side-effects de-duplication and this codepath is
+ unrelated. Duplicated side-effects arise from incorrect scheme
+ generation code, the main bulk of it was mostly fixed by #9836
+ but duplication can still happen because of rewriting schemes I
+ think; however the code below is mostly untested, the only
+ code-paths that generate several proof entries are derive and
+ equations and so far there is no code in the CI that will
+ actually call those and do a side-effect, TTBOMK *)
+ (* EJGA: likely the right solution is to attach side effects to the first constant only? *)
+ let proofs = List.map (fun (body, typ) -> (to_constr_body body, eff), to_constr_typ typ) initial_goals in
+ proofs, Evd.evar_universe_context evd
+
+let make_univs_deferred ~poly ~initial_euctx ~uctx ~udecl
+ (used_univs_typ, typ) (used_univs_body, body) =
+ let used_univs = Univ.LSet.union used_univs_body used_univs_typ in
+ let utyp = UState.univ_entry ~poly initial_euctx in
+ let uctx = UState.constrain_variables (fst (UState.context_set initial_euctx)) uctx in
+ (* For vi2vo compilation proofs are computed now but we need to
+ complement the univ constraints of the typ with the ones of
+ the body. So we keep the two sets distinct. *)
+ let uctx_body = UState.restrict uctx used_univs in
+ let ubody = UState.check_mono_univ_decl uctx_body udecl in
+ utyp, ubody
+
+let make_univs_private_poly ~poly ~uctx ~udecl (used_univs_typ, typ) (used_univs_body, body) =
+ let used_univs = Univ.LSet.union used_univs_body used_univs_typ in
+ let universes = UState.restrict uctx used_univs in
+ let typus = UState.restrict universes used_univs_typ in
+ let utyp = UState.check_univ_decl ~poly typus udecl in
+ let ubody = Univ.ContextSet.diff
+ (UState.context_set universes)
+ (UState.context_set typus)
+ in
+ utyp, ubody
+
+let make_univs ~poly ~uctx ~udecl (used_univs_typ, typ) (used_univs_body, body) =
+ let used_univs = Univ.LSet.union used_univs_body used_univs_typ in
+ (* Since the proof is computed now, we can simply have 1 set of
+ constraints in which we merge the ones for the body and the ones
+ for the typ. We recheck the declaration after restricting with
+ the actually used universes.
+ TODO: check if restrict is really necessary now. *)
+ let ctx = UState.restrict uctx used_univs in
+ let utyp = UState.check_univ_decl ~poly ctx udecl in
+ utyp, Univ.ContextSet.empty
+
+let close_proof ~opaque ~keep_body_ucst_separate ps =
+
+ let { section_vars; proof; initial_euctx; pinfo } = ps in
+ let { Proof_info.info = { Info.udecl } } = pinfo in
+ let { Proof.name; poly } = Proof.data proof in
+ let unsafe_typ = keep_body_ucst_separate && not poly in
+ let elist, uctx = prepare_proof ~unsafe_typ ps in
+ let opaque = match opaque with
+ | Vernacexpr.Opaque -> true
+ | Vernacexpr.Transparent -> false in
+
+ let make_entry ((((_ub, body) as b), eff), ((_ut, typ) as t)) =
+ let utyp, ubody =
+ (* allow_deferred case *)
+ if not poly &&
+ (keep_body_ucst_separate
+ || not (Safe_typing.is_empty_private_constants eff.Evd.seff_private))
+ then make_univs_deferred ~initial_euctx ~poly ~uctx ~udecl t b
+ (* private_poly_univs case *)
+ else if poly && opaque && private_poly_univs ()
+ then make_univs_private_poly ~poly ~uctx ~udecl t b
+ else make_univs ~poly ~uctx ~udecl t b
+ in
+ definition_entry_core ~opaque ?section_vars ~univs:utyp ~univsbody:ubody ~types:typ ~eff body
+ in
+ let entries = CList.map make_entry elist in
+ { name; entries; uctx }
+
+type closed_proof_output = (Constr.t * Evd.side_effects) list * UState.t
+
+let close_proof_delayed ~feedback_id ps (fpl : closed_proof_output Future.computation) =
+ let { section_vars; proof; initial_euctx; pinfo } = ps in
+ let { Proof_info.info = { Info.udecl } } = pinfo in
+ let { Proof.name; poly; entry; sigma } = Proof.data proof in
+
+ (* We don't allow poly = true in this path *)
+ if poly then
+ CErrors.anomaly (Pp.str "Cannot delay universe-polymorphic constants.");
+
+ let fpl, uctx = Future.split2 fpl in
+ (* Because of dependent subgoals at the beginning of proofs, we could
+ have existential variables in the initial types of goals, we need to
+ normalise them for the kernel. *)
+ let subst_evar k = Evd.existential_opt_value0 sigma k in
+ let nf = UnivSubst.nf_evars_and_universes_opt_subst subst_evar (UState.subst initial_euctx) in
+
+ (* We only support opaque proofs, this will be enforced by using
+ different entries soon *)
+ let opaque = true in
+ let make_entry p (_, types) =
+ (* Already checked the univ_decl for the type universes when starting the proof. *)
+ let univs = UState.univ_entry ~poly:false initial_euctx in
+ let types = nf (EConstr.Unsafe.to_constr types) in
+
+ Future.chain p (fun (pt,eff) ->
+ (* Deferred proof, we already checked the universe declaration with
+ the initial universes, ensure that the final universes respect
+ the declaration as well. If the declaration is non-extensible,
+ this will prevent the body from adding universes and constraints. *)
+ let uctx = Future.force uctx in
+ let uctx = UState.constrain_variables (fst (UState.context_set initial_euctx)) uctx in
+ let used_univs = Univ.LSet.union
+ (Vars.universes_of_constr types)
+ (Vars.universes_of_constr pt)
+ in
+ let univs = UState.restrict uctx used_univs in
+ let univs = UState.check_mono_univ_decl univs udecl in
+ (pt,univs),eff)
+ |> delayed_definition_entry ~opaque ~feedback_id ~section_vars ~univs ~types
+ in
+ let entries = Future.map2 make_entry fpl (Proofview.initial_goals entry) in
+ { name; entries; uctx = initial_euctx }
+
+let close_future_proof = close_proof_delayed
+
+let return_partial_proof { proof } =
+ let proofs = Proof.partial_proof proof in
+ let Proof.{sigma=evd} = Proof.data proof in
+ let eff = Evd.eval_side_effects evd in
+ (* ppedrot: FIXME, this is surely wrong. There is no reason to duplicate
+ side-effects... This may explain why one need to uniquize side-effects
+ thereafter... *)
+ let proofs = List.map (fun c -> EConstr.Unsafe.to_constr c, eff) proofs in
+ proofs, Evd.evar_universe_context evd
+
+let return_proof ps =
+ let p, uctx = prepare_proof ~unsafe_typ:false ps in
+ List.map (fun (((_ub, body),eff),_) -> (body,eff)) p, uctx
+
+let update_global_env =
+ map ~f:(fun p ->
+ let { Proof.sigma } = Proof.data p in
+ let tac = Proofview.Unsafe.tclEVARS (Evd.update_sigma_env sigma (Global.env ())) in
+ let p, (status,info), _ = Proof.run_tactic (Global.env ()) tac p in
+ p)
+
+let next = let n = ref 0 in fun () -> incr n; !n
+
+let by tac = map_fold ~f:(Proof.solve (Goal_select.SelectNth 1) None tac)
+
+let build_constant_by_tactic ~name ?(opaque=Vernacexpr.Transparent) ~uctx ~sign ~poly (typ : EConstr.t) tac =
+ let evd = Evd.from_ctx uctx in
+ let typ_ = EConstr.Unsafe.to_constr typ in
+ let cinfo = [CInfo.make ~name ~typ:typ_ ()] in
+ let info = Info.make ~poly () in
+ let pinfo = Proof_info.make ~cinfo ~info () in
+ let pf = start_proof_core ~name ~typ ~pinfo ~sign evd in
+ let pf, status = by tac pf in
+ let { entries; uctx } = close_proof ~opaque ~keep_body_ucst_separate:false pf in
+ match entries with
+ | [entry] ->
+ entry, status, uctx
+ | _ ->
+ CErrors.anomaly Pp.(str "[build_constant_by_tactic] close_proof returned more than one proof term")
+
+let build_by_tactic ?(side_eff=true) env ~uctx ~poly ~typ tac =
+ let name = Id.of_string ("temporary_proof"^string_of_int (next())) in
+ let sign = Environ.(val_of_named_context (named_context env)) in
+ let ce, status, uctx = build_constant_by_tactic ~name ~uctx ~sign ~poly typ tac in
+ let cb, uctx =
+ if side_eff then inline_private_constants ~uctx env ce
+ else
+ (* GG: side effects won't get reset: no need to treat their universes specially *)
+ let (cb, ctx), _eff = Future.force ce.proof_entry_body in
+ cb, UState.merge ~sideff:false Evd.univ_rigid uctx ctx
+ in
+ cb, ce.proof_entry_type, ce.proof_entry_universes, status, uctx
+
+let declare_abstract ~name ~poly ~kind ~sign ~secsign ~opaque ~solve_tac sigma concl =
+ (* EJGA: flush_and_check_evars is only used in abstract, could we
+ use a different API? *)
+ let concl =
+ try Evarutil.flush_and_check_evars sigma concl
+ with Evarutil.Uninstantiated_evar _ ->
+ CErrors.user_err Pp.(str "\"abstract\" cannot handle existentials.")
+ in
+ let sigma, concl =
+ (* FIXME: should be done only if the tactic succeeds *)
+ let sigma = Evd.minimize_universes sigma in
+ sigma, Evarutil.nf_evars_universes sigma concl
+ in
+ let concl = EConstr.of_constr concl in
+ let uctx = Evd.evar_universe_context sigma in
+ let (const, safe, uctx) =
+ try build_constant_by_tactic ~name ~opaque:Vernacexpr.Transparent ~poly ~uctx ~sign:secsign concl solve_tac
+ with Logic_monad.TacticFailure e as src ->
+ (* if the tactic [tac] fails, it reports a [TacticFailure e],
+ which is an error irrelevant to the proof system (in fact it
+ means that [e] comes from [tac] failing to yield enough
+ success). Hence it reraises [e]. *)
+ let (_, info) = Exninfo.capture src in
+ Exninfo.iraise (e, info)
+ in
+ let sigma = Evd.set_universe_context sigma uctx in
+ let body, effs = Future.force const.proof_entry_body in
+ (* We drop the side-effects from the entry, they already exist in the ambient environment *)
+ let const = Internal.map_entry_body const ~f:(fun _ -> body, ()) in
+ (* EJGA: Hack related to the above call to
+ `build_constant_by_tactic` with `~opaque:Transparent`. Even if
+ the abstracted term is destined to be opaque, if we trigger the
+ `if poly && opaque && private_poly_univs ()` in `close_proof`
+ kernel will boom. This deserves more investigation. *)
+ let const = Internal.set_opacity ~opaque const in
+ let const, args = Internal.shrink_entry sign const in
+ let cst () =
+ (* do not compute the implicit arguments, it may be costly *)
+ let () = Impargs.make_implicit_args false in
+ (* ppedrot: seems legit to have abstracted subproofs as local*)
+ declare_private_constant ~local:Locality.ImportNeedQualified ~name ~kind const
+ in
+ let cst, eff = Impargs.with_implicit_protection cst () in
+ let inst = match const.proof_entry_universes with
+ | Entries.Monomorphic_entry _ -> EConstr.EInstance.empty
+ | Entries.Polymorphic_entry (_, ctx) ->
+ (* We mimic what the kernel does, that is ensuring that no additional
+ constraints appear in the body of polymorphic constants. Ideally this
+ should be enforced statically. *)
+ let (_, body_uctx), _ = Future.force const.proof_entry_body in
+ let () = assert (Univ.ContextSet.is_empty body_uctx) in
+ EConstr.EInstance.make (Univ.UContext.instance ctx)
+ in
+ let args = List.map EConstr.of_constr args in
+ let lem = EConstr.mkConstU (cst, inst) in
+ let effs = Evd.concat_side_effects eff effs in
+ effs, sigma, lem, args, safe
+
+let get_goal_context pf i =
+ let p = get pf in
+ Proof.get_goal_context_gen p i
+
+let get_current_goal_context pf =
+ let p = get pf in
+ try Proof.get_goal_context_gen p 1
+ with
+ | Proof.NoSuchGoal _ ->
+ (* spiwack: returning empty evar_map, since if there is no goal,
+ under focus, there is no accessible evar either. EJGA: this
+ seems strange, as we have pf *)
+ let env = Global.env () in
+ Evd.from_env env, env
+
+let get_current_context pf =
+ let p = get pf in
+ Proof.get_proof_context p
+
+(* Support for mutually proved theorems *)
+
(* XXX: this should be unified with the code for non-interactive
mutuals previously on this file. *)
module MutualEntry : sig
val declare_variable
- : info:Info.t
+ : pinfo:Proof_info.t
-> uctx:UState.t
-> Entries.parameter_entry
-> Names.GlobRef.t list
val declare_mutdef
(* Common to all recthms *)
- : info:Info.t
+ : pinfo:Proof_info.t
-> uctx:UState.t
- -> Evd.side_effects proof_entry
+ -> entry:Evd.side_effects proof_entry
-> Names.GlobRef.t list
end = struct
@@ -1788,8 +1884,9 @@ end = struct
Pp.(str "Not a proof by induction: " ++
Termops.Internal.debug_print_constr (EConstr.of_constr t) ++ str ".")
- let declare_mutdef ~uctx ~info pe i Recthm.{ name; impargs; typ; _} =
- let { Info.hook; scope; kind; compute_guard; _ } = info in
+ let declare_mutdef ~uctx ~pinfo pe i CInfo.{ name; impargs; typ; _} =
+ let { Proof_info.info; compute_guard; _ } = pinfo in
+ let { Info.hook; scope; kind; _ } = info in
(* if i = 0 , we don't touch the type; this is for compat
but not clear it is the right thing to do.
*)
@@ -1808,25 +1905,25 @@ end = struct
in
declare_entry ~name ~scope ~kind ?hook ~impargs ~uctx pe
- let declare_mutdef ~info ~uctx const =
- let pe = match info.Info.compute_guard with
+ let declare_mutdef ~pinfo ~uctx ~entry =
+ let pe = match pinfo.Proof_info.compute_guard with
| [] ->
(* Not a recursive statement *)
- const
+ entry
| possible_indexes ->
(* Try all combinations... not optimal *)
let env = Global.env() in
- Internal.map_entry_body const
+ Internal.map_entry_body entry
~f:(guess_decreasing env possible_indexes)
in
- List.map_i (declare_mutdef ~info ~uctx pe) 0 info.Info.thms
+ List.map_i (declare_mutdef ~pinfo ~uctx pe) 0 pinfo.Proof_info.cinfo
- let declare_variable ~info ~uctx pe =
- let { Info.scope; hook } = info in
+ let declare_variable ~pinfo ~uctx pe =
+ let { Info.scope; hook } = pinfo.Proof_info.info in
List.map_i (
- fun i { Recthm.name; typ; impargs } ->
+ fun i { CInfo.name; typ; impargs } ->
declare_assumption ~name ~scope ~hook ~impargs ~uctx pe
- ) 0 info.Info.thms
+ ) 0 pinfo.Proof_info.cinfo
end
@@ -1854,41 +1951,33 @@ let compute_proof_using_for_admitted proof typ pproofs =
Some (Environ.really_needed env (Id.Set.union ids_typ ids_def))
| _ -> None
-let finish_admitted ~info ~uctx pe =
- let cst = MutualEntry.declare_variable ~info ~uctx pe in
+let finish_admitted ~pinfo ~uctx pe =
+ let cst = MutualEntry.declare_variable ~pinfo ~uctx pe in
(* If the constant was an obligation we need to update the program map *)
- match CEphemeron.get info.Info.proof_ending with
+ match CEphemeron.get pinfo.Proof_info.proof_ending with
| Proof_ending.End_obligation oinfo ->
- Obls.obligation_admitted_terminator oinfo uctx (List.hd cst)
+ Obls_.obligation_admitted_terminator oinfo uctx (List.hd cst)
| _ -> ()
-let save_lemma_admitted ~proof ~info =
+let save_admitted ~proof =
let udecl = get_universe_decl proof in
- let Proof.{ poly; entry } = Proof.data (get_proof proof) in
+ let Proof.{ poly; entry } = Proof.data (get proof) in
let typ = match Proofview.initial_goals entry with
| [typ] -> snd typ
| _ -> CErrors.anomaly ~label:"Lemmas.save_lemma_admitted" (Pp.str "more than one statement.")
in
let typ = EConstr.Unsafe.to_constr typ in
- let iproof = get_proof proof in
+ let iproof = get proof in
let pproofs = Proof.partial_proof iproof in
let sec_vars = compute_proof_using_for_admitted proof typ pproofs in
let uctx = get_initial_euctx proof in
let univs = UState.check_univ_decl ~poly uctx udecl in
- finish_admitted ~info ~uctx (sec_vars, (typ, univs), None)
+ finish_admitted ~pinfo:proof.pinfo ~uctx (sec_vars, (typ, univs), None)
(************************************************************************)
(* Saving a lemma-like constant *)
(************************************************************************)
-let finish_proved po info =
- match po with
- | { entries=[const]; uctx } ->
- let _r : Names.GlobRef.t list = MutualEntry.declare_mutdef ~info ~uctx const in
- ()
- | _ ->
- CErrors.anomaly ~label:"finish_proved" Pp.(str "close_proof returned more than one proof term")
-
let finish_derived ~f ~name ~entries =
(* [f] and [name] correspond to the proof of [f] and of [suchthat], respectively. *)
@@ -1921,8 +2010,8 @@ let finish_derived ~f ~name ~entries =
(* The same is done in the body of the proof. *)
let lemma_def = Internal.map_entry_body lemma_def ~f:(fun ((b,ctx),fx) -> (substf b, ctx), fx) in
let lemma_def = DefinitionEntry lemma_def in
- let _ : Names.Constant.t = declare_constant ~name ~kind:Decls.(IsProof Proposition) lemma_def in
- ()
+ let ct = declare_constant ~name ~kind:Decls.(IsProof Proposition) lemma_def in
+ [GlobRef.ConstRef ct]
let finish_proved_equations ~kind ~hook i proof_obj types sigma0 =
@@ -1941,19 +2030,29 @@ let finish_proved_equations ~kind ~hook i proof_obj types sigma0 =
sigma, cst) sigma0
types proof_obj.entries
in
- hook recobls sigma
+ hook recobls sigma;
+ List.map (fun cst -> GlobRef.ConstRef cst) recobls
+
+let check_single_entry { entries; uctx } label =
+ match entries with
+ | [entry] -> entry, uctx
+ | _ ->
+ CErrors.anomaly ~label Pp.(str "close_proof returned more than one proof term")
let finalize_proof proof_obj proof_info =
let open Proof_ending in
- match CEphemeron.default proof_info.Info.proof_ending Regular with
+ match CEphemeron.default proof_info.Proof_info.proof_ending Regular with
| Regular ->
- finish_proved proof_obj proof_info
+ let entry, uctx = check_single_entry proof_obj "Proof.save" in
+ MutualEntry.declare_mutdef ~entry ~uctx ~pinfo:proof_info
| End_obligation oinfo ->
- Obls.obligation_terminator proof_obj.entries proof_obj.uctx oinfo
+ let entry, uctx = check_single_entry proof_obj "Obligation.save" in
+ Obls_.obligation_terminator ~entry ~uctx ~oinfo
| End_derive { f ; name } ->
finish_derived ~f ~name ~entries:proof_obj.entries
| End_equations { hook; i; types; sigma } ->
- finish_proved_equations ~kind:proof_info.Info.kind ~hook i proof_obj types sigma
+ let kind = proof_info.Proof_info.info.Info.kind in
+ finish_proved_equations ~kind ~hook i proof_obj types sigma
let err_save_forbidden_in_place_of_qed () =
CErrors.user_err (Pp.str "Cannot use Save with more than one constant or in this proof mode")
@@ -1963,24 +2062,24 @@ let process_idopt_for_save ~idopt info =
| None -> info
| Some { CAst.v = save_name } ->
(* Save foo was used; we override the info in the first theorem *)
- let thms =
- match info.Info.thms, CEphemeron.default info.Info.proof_ending Proof_ending.Regular with
- | [ { Recthm.name; _} as decl ], Proof_ending.Regular ->
- [ { decl with Recthm.name = save_name } ]
+ let cinfo =
+ match info.Proof_info.cinfo, CEphemeron.default info.Proof_info.proof_ending Proof_ending.Regular with
+ | [ { CInfo.name; _} as decl ], Proof_ending.Regular ->
+ [ { decl with CInfo.name = save_name } ]
| _ ->
err_save_forbidden_in_place_of_qed ()
- in { info with Info.thms }
+ in { info with Proof_info.cinfo }
-let save_lemma_proved ~proof ~info ~opaque ~idopt =
+let save ~proof ~opaque ~idopt =
(* Env and sigma are just used for error printing in save_remaining_recthms *)
let proof_obj = close_proof ~opaque ~keep_body_ucst_separate:false proof in
- let proof_info = process_idopt_for_save ~idopt info in
+ let proof_info = process_idopt_for_save ~idopt proof.pinfo in
finalize_proof proof_obj proof_info
(***********************************************************************)
(* Special case to close a lemma without forcing a proof *)
(***********************************************************************)
-let save_lemma_admitted_delayed ~proof ~info =
+let save_lemma_admitted_delayed ~proof ~pinfo =
let { entries; uctx } = proof in
if List.length entries <> 1 then
CErrors.user_err Pp.(str "Admitted does not support multiple statements");
@@ -1993,29 +2092,429 @@ let save_lemma_admitted_delayed ~proof ~info =
| Some typ -> typ in
let ctx = UState.univ_entry ~poly uctx in
let sec_vars = if get_keep_admitted_vars () then proof_entry_secctx else None in
- finish_admitted ~uctx ~info (sec_vars, (typ, ctx), None)
+ finish_admitted ~uctx ~pinfo (sec_vars, (typ, ctx), None)
-let save_lemma_proved_delayed ~proof ~info ~idopt =
+let save_lemma_proved_delayed ~proof ~pinfo ~idopt =
(* vio2vo calls this but with invalid info, we have to workaround
that to add the name to the info structure *)
- if CList.is_empty info.Info.thms then
+ if CList.is_empty pinfo.Proof_info.cinfo then
let name = get_po_name proof in
- let info = Info.add_first_thm ~info ~name ~typ:EConstr.mkSet ~impargs:[] in
+ let info = Proof_info.add_first_thm ~pinfo ~name ~typ:EConstr.mkSet ~impargs:[] in
finalize_proof proof info
else
- let info = process_idopt_for_save ~idopt info in
+ let info = process_idopt_for_save ~idopt pinfo in
finalize_proof proof info
-module Proof = struct
- type nonrec t = t
- let get_proof = get_proof
- let get_proof_name = get_proof_name
- let map_proof = map_proof
- let map_fold_proof = map_fold_proof
- let map_fold_proof_endline = map_fold_proof_endline
- let set_endline_tactic = set_endline_tactic
- let set_used_variables = set_used_variables
- let compact = compact_the_proof
- let update_global_env = update_global_env
- let get_open_goals = get_open_goals
+end (* Proof module *)
+
+let _ = Ind_tables.declare_definition_scheme := declare_definition_scheme
+let _ = Abstract.declare_abstract := Proof.declare_abstract
+
+let build_by_tactic = Proof.build_by_tactic
+
+(* This module could be merged with Obl, and placed before [Proof],
+ however there is a single dependency on [Proof.start] for the interactive case *)
+module Obls = struct
+(* For the records fields, opens should go away one these types are private *)
+open Obls_
+open Obls_.Obligation
+open Obls_.ProgramDecl
+
+let reduce c =
+ let env = Global.env () in
+ let sigma = Evd.from_env env in
+ EConstr.Unsafe.to_constr (Reductionops.clos_norm_flags CClosure.betaiota env sigma (EConstr.of_constr c))
+
+let explain_no_obligations = function
+ Some ident -> str "No obligations for program " ++ Id.print ident
+ | None -> str "No obligations remaining"
+
+module Error = struct
+
+ let no_obligations n =
+ CErrors.user_err (explain_no_obligations n)
+
+ let ambiguous_program id ids =
+ CErrors.user_err
+ Pp.(str "More than one program with unsolved obligations: " ++ prlist Id.print ids
+ ++ str "; use the \"of\" clause to specify, as in \"Obligation 1 of " ++ Id.print id ++ str "\"")
+
+ let unknown_obligation num =
+ CErrors.user_err (Pp.str (Printf.sprintf "Unknown obligation number %i" (succ num)))
+
+ let already_solved num =
+ CErrors.user_err
+ ( str "Obligation" ++ spc () ++ int num ++ str "already" ++ spc ()
+ ++ str "solved." )
+
+ let depends num rem =
+ CErrors.user_err
+ ( str "Obligation " ++ int num
+ ++ str " depends on obligation(s) "
+ ++ pr_sequence (fun x -> int (succ x)) rem)
+
+end
+
+let default_tactic = ref (Proofview.tclUNIT ())
+
+let evar_of_obligation o = Evd.make_evar (Global.named_context_val ()) (EConstr.of_constr o.obl_type)
+
+let subst_deps expand obls deps t =
+ let osubst = Obls_.obl_substitution expand obls deps in
+ (Vars.replace_vars (List.map (fun (n, (_, b)) -> n, b) osubst) t)
+
+let subst_deps_obl obls obl =
+ let t' = subst_deps true obls obl.obl_deps obl.obl_type in
+ Obligation.set_type ~typ:t' obl
+
+open Evd
+
+let is_defined obls x = not (Option.is_empty obls.(x).obl_body)
+
+let deps_remaining obls deps =
+ Int.Set.fold
+ (fun x acc ->
+ if is_defined obls x then acc
+ else x :: acc)
+ deps []
+
+let goal_kind = Decls.(IsDefinition Definition)
+let goal_proof_kind = Decls.(IsProof Lemma)
+
+let kind_of_obligation o =
+ match o with
+ | Evar_kinds.Define false
+ | Evar_kinds.Expand -> goal_kind
+ | _ -> goal_proof_kind
+
+(* Solve an obligation using tactics, return the corresponding proof term *)
+let warn_solve_errored =
+ CWarnings.create ~name:"solve_obligation_error" ~category:"tactics"
+ (fun err ->
+ Pp.seq
+ [ str "Solve Obligations tactic returned error: "
+ ; err
+ ; fnl ()
+ ; str "This will become an error in the future" ])
+
+let solve_by_tac ?loc name evi t ~poly ~uctx =
+ (* the status is dropped. *)
+ try
+ let env = Global.env () in
+ let body, types, _univs, _, uctx =
+ build_by_tactic env ~uctx ~poly ~typ:evi.evar_concl t in
+ Inductiveops.control_only_guard env (Evd.from_ctx uctx) (EConstr.of_constr body);
+ Some (body, types, uctx)
+ with
+ | Refiner.FailError (_, s) as exn ->
+ let _ = Exninfo.capture exn in
+ CErrors.user_err ?loc ~hdr:"solve_obligation" (Lazy.force s)
+ (* If the proof is open we absorb the error and leave the obligation open *)
+ | Proof_.OpenProof _ ->
+ None
+ | e when CErrors.noncritical e ->
+ let err = CErrors.print e in
+ warn_solve_errored ?loc err;
+ None
+
+let get_unique_prog prg =
+ match State.get_unique_open_prog prg with
+ | Ok prg -> prg
+ | Error [] ->
+ Error.no_obligations None
+ | Error ((id :: _) as ids) ->
+ Error.ambiguous_program id ids
+
+let rec solve_obligation prg num tac =
+ let user_num = succ num in
+ let { obls; remaining=rem } = Internal.get_obligations prg in
+ let obl = obls.(num) in
+ let remaining = deps_remaining obls obl.obl_deps in
+ let () =
+ if not (Option.is_empty obl.obl_body)
+ then Error.already_solved user_num;
+ if not (List.is_empty remaining)
+ then Error.depends user_num remaining
+ in
+ let obl = subst_deps_obl obls obl in
+ let scope = Locality.Global Locality.ImportNeedQualified in
+ let kind = kind_of_obligation (snd obl.obl_status) in
+ let evd = Evd.from_ctx (Internal.get_uctx prg) in
+ let evd = Evd.update_sigma_env evd (Global.env ()) in
+ let auto n oblset tac = auto_solve_obligations n ~oblset tac in
+ let proof_ending =
+ let name = Internal.get_name prg in
+ Proof_ending.End_obligation {name; num; auto}
+ in
+ let cinfo = CInfo.make ~name:obl.obl_name ~typ:(EConstr.of_constr obl.obl_type) () in
+ let poly = Internal.get_poly prg in
+ let info = Info.make ~scope ~kind ~poly () in
+ let lemma = Proof.start_core ~cinfo ~info ~proof_ending evd in
+ let lemma = fst @@ Proof.by !default_tactic lemma in
+ let lemma = Option.cata (fun tac -> Proof.set_endline_tactic tac lemma) lemma tac in
+ lemma
+
+and obligation (user_num, name, typ) tac =
+ let num = pred user_num in
+ let prg = get_unique_prog name in
+ let { obls; remaining } = Internal.get_obligations prg in
+ if num >= 0 && num < Array.length obls then
+ let obl = obls.(num) in
+ match obl.obl_body with
+ | None -> solve_obligation prg num tac
+ | Some r -> Error.already_solved num
+ else Error.unknown_obligation num
+
+and solve_obligation_by_tac prg obls i tac =
+ let obl = obls.(i) in
+ match obl.obl_body with
+ | Some _ -> None
+ | None ->
+ if List.is_empty (deps_remaining obls obl.obl_deps) then
+ let obl = subst_deps_obl obls obl in
+ let tac =
+ match tac with
+ | Some t -> t
+ | None ->
+ match obl.obl_tac with
+ | Some t -> t
+ | None -> !default_tactic
+ in
+ let uctx = Internal.get_uctx prg in
+ let uctx = UState.update_sigma_env uctx (Global.env ()) in
+ let poly = Internal.get_poly prg in
+ match solve_by_tac ?loc:(fst obl.obl_location) obl.obl_name (evar_of_obligation obl) tac ~poly ~uctx with
+ | None -> None
+ | Some (t, ty, uctx) ->
+ let prg = ProgramDecl.Internal.set_uctx ~uctx prg in
+ let def, obl', _cst = declare_obligation prg obl ~body:t ~types:ty ~uctx in
+ obls.(i) <- obl';
+ if def && not poly then (
+ (* Declare the term constraints with the first obligation only *)
+ let uctx_global = UState.from_env (Global.env ()) in
+ let uctx = UState.merge_subst uctx_global (UState.subst uctx) in
+ Some (ProgramDecl.Internal.set_uctx ~uctx prg))
+ else Some prg
+ else None
+
+and solve_prg_obligations prg ?oblset tac =
+ let { obls; remaining } = Internal.get_obligations prg in
+ let rem = ref remaining in
+ let obls' = Array.copy obls in
+ let set = ref Int.Set.empty in
+ let p = match oblset with
+ | None -> (fun _ -> true)
+ | Some s -> set := s;
+ (fun i -> Int.Set.mem i !set)
+ in
+ let (), prg =
+ Array.fold_left_i
+ (fun i ((), prg) x ->
+ if p i then (
+ match solve_obligation_by_tac prg obls' i tac with
+ | None -> (), prg
+ | Some prg ->
+ let deps = dependencies obls i in
+ set := Int.Set.union !set deps;
+ decr rem;
+ (), prg)
+ else (), prg)
+ ((), prg) obls'
+ in
+ update_obls prg obls' !rem
+
+and solve_obligations n tac =
+ let prg = get_unique_prog n in
+ solve_prg_obligations prg tac
+
+and solve_all_obligations tac =
+ State.fold ~init:() ~f:(fun k v () ->
+ let _ = solve_prg_obligations v tac in ())
+
+and try_solve_obligation n prg tac =
+ let prg = get_unique_prog prg in
+ let {obls; remaining} = Internal.get_obligations prg in
+ let obls' = Array.copy obls in
+ match solve_obligation_by_tac prg obls' n tac with
+ | Some prg' ->
+ let _r = update_obls prg' obls' (pred remaining) in
+ ()
+ | None -> ()
+
+and try_solve_obligations n tac =
+ let _ = solve_obligations n tac in
+ ()
+
+and auto_solve_obligations n ?oblset tac : progress =
+ Flags.if_verbose Feedback.msg_info
+ (str "Solving obligations automatically...");
+ let prg = get_unique_prog n in
+ solve_prg_obligations prg ?oblset tac
+
+let show_single_obligation i n obls x =
+ let x = subst_deps_obl obls x in
+ let env = Global.env () in
+ let sigma = Evd.from_env env in
+ let msg =
+ str "Obligation" ++ spc ()
+ ++ int (succ i)
+ ++ spc () ++ str "of" ++ spc () ++ Id.print n ++ str ":" ++ spc ()
+ ++ hov 1 (Printer.pr_constr_env env sigma x.obl_type
+ ++ str "." ++ fnl ()) in
+ Feedback.msg_info msg
+
+let show_obligations_of_prg ?(msg = true) prg =
+ let n = Internal.get_name prg in
+ let {obls; remaining} = Internal.get_obligations prg in
+ let showed = ref 5 in
+ if msg then Feedback.msg_info (int remaining ++ str " obligation(s) remaining: ");
+ Array.iteri
+ (fun i x ->
+ match x.obl_body with
+ | None ->
+ if !showed > 0 then begin
+ decr showed;
+ show_single_obligation i n obls x
+ end
+ | Some _ -> ())
+ obls
+
+let show_obligations ?(msg = true) n =
+ let progs =
+ match n with
+ | None ->
+ State.all ()
+ | Some n ->
+ (match State.find n with
+ | Some prg -> [prg]
+ | None -> Error.no_obligations (Some n))
+ in
+ List.iter (fun x -> show_obligations_of_prg ~msg x) progs
+
+let show_term n =
+ let prg = get_unique_prog n in
+ ProgramDecl.show prg
+
+let msg_generating_obl name obls =
+ let len = Array.length obls in
+ let info = Id.print name ++ str " has type-checked" in
+ Feedback.msg_info
+ (if len = 0 then info ++ str "."
+ else
+ info ++ str ", generating " ++ int len ++
+ str (String.plural len " obligation"))
+
+let add_definition ~cinfo ~info ?term ~uctx
+ ?tactic ?(reduce = reduce) ?(opaque = false) obls =
+ let prg =
+ ProgramDecl.make ~info ~cinfo ~body:term ~opaque ~uctx ~reduce ~ntns:[] ~deps:[] ~fixpoint_kind:None obls
+ in
+ let name = CInfo.get_name cinfo in
+ let {obls;_} = Internal.get_obligations prg in
+ if Int.equal (Array.length obls) 0 then (
+ Flags.if_verbose (msg_generating_obl name) obls;
+ let cst = Obls_.declare_definition prg in
+ Defined cst)
+ else
+ let () = Flags.if_verbose (msg_generating_obl name) obls in
+ let () = State.add name prg in
+ let res = auto_solve_obligations (Some name) tactic in
+ match res with
+ | Remain rem ->
+ Flags.if_verbose (show_obligations ~msg:false) (Some name);
+ res
+ | _ -> res
+
+let add_mutual_definitions l ~info ~uctx
+ ?tactic ?(reduce = reduce) ?(opaque = false) ~ntns fixkind =
+ let deps = List.map (fun (ci,_,_) -> CInfo.get_name ci) l in
+ let pm =
+ List.fold_left
+ (fun () (cinfo, b, obls) ->
+ let prg =
+ ProgramDecl.make ~info ~cinfo ~opaque ~body:(Some b) ~uctx ~deps
+ ~fixpoint_kind:(Some fixkind) ~ntns obls ~reduce
+ in
+ State.add (CInfo.get_name cinfo) prg)
+ () l
+ in
+ let pm, _defined =
+ List.fold_left
+ (fun (pm, finished) x ->
+ if finished then (pm, finished)
+ else
+ let res = auto_solve_obligations (Some x) tactic in
+ match res with
+ | Defined _ ->
+ (* If one definition is turned into a constant,
+ the whole block is defined. *)
+ (pm, true)
+ | _ -> (pm, false))
+ (pm, false) deps
+ in
+ pm
+
+let admit_prog prg =
+ let {obls; remaining} = Internal.get_obligations prg in
+ let obls = Array.copy obls in
+ Array.iteri
+ (fun i x ->
+ match x.obl_body with
+ | None ->
+ let x = subst_deps_obl obls x in
+ let uctx = Internal.get_uctx prg in
+ let univs = UState.univ_entry ~poly:false uctx in
+ let kn = declare_constant ~name:x.obl_name ~local:Locality.ImportNeedQualified
+ (ParameterEntry (None, (x.obl_type, univs), None)) ~kind:Decls.(IsAssumption Conjectural)
+ in
+ assumption_message x.obl_name;
+ obls.(i) <- Obligation.set_body ~body:(DefinedObl (kn, Univ.Instance.empty)) x
+ | Some _ -> ())
+ obls;
+ Obls_.update_obls prg obls 0
+
+(* get_any_prog *)
+let rec admit_all_obligations () =
+ let prg = State.first_pending () in
+ match prg with
+ | None -> ()
+ | Some prg ->
+ let _prog = admit_prog prg in
+ admit_all_obligations ()
+
+let admit_obligations n =
+ match n with
+ | None -> admit_all_obligations ()
+ | Some _ ->
+ let prg = get_unique_prog n in
+ let _ = admit_prog prg in
+ ()
+
+let next_obligation n tac =
+ let prg = match n with
+ | None -> State.first_pending () |> Option.get
+ | Some _ -> get_unique_prog n
+ in
+ let {obls; remaining} = Internal.get_obligations prg in
+ let is_open _ x = Option.is_empty x.obl_body && List.is_empty (deps_remaining obls x.obl_deps) in
+ let i = match Array.findi is_open obls with
+ | Some i -> i
+ | None -> CErrors.anomaly (Pp.str "Could not find a solvable obligation.")
+ in
+ solve_obligation prg i tac
+
+let check_program_libraries () =
+ Coqlib.check_required_library Coqlib.datatypes_module_name;
+ Coqlib.check_required_library ["Coq";"Init";"Specif"];
+ Coqlib.check_required_library ["Coq";"Program";"Tactics"]
+
+(* aliases *)
+module State = Obls_.State
+let prepare_obligation = prepare_obligation
+let check_solved_obligations = Obls_.check_solved_obligations
+type fixpoint_kind = Obls_.fixpoint_kind =
+ | IsFixpoint of lident option list | IsCoFixpoint
+type nonrec progress = progress =
+ | Remain of int | Dependent | Defined of GlobRef.t
+
end
diff --git a/vernac/declare.mli b/vernac/declare.mli
index 979bdd4334..4891e66803 100644
--- a/vernac/declare.mli
+++ b/vernac/declare.mli
@@ -9,25 +9,23 @@
(************************************************************************)
open Names
-open Constr
-open Entries
-(** This module provides the official functions to declare new
+(** This module provides the functions to declare new
variables, parameters, constants and inductive types in the global
environment. It also updates some accesory tables such as [Nametab]
(name resolution), [Impargs], and [Notations]. *)
-(** We provide two kind of functions:
+(** We provide three main entry points:
- one-go functions, that will register a constant in one go, suited
for non-interactive definitions where the term is given.
- - two-phase [start/declare] functions which will create an
- interactive proof, allow its modification, and saving when
- complete.
+ - two-phase [start/save] functions which will create an
+ interactive proof, allow its modification using tactics, and saving
+ when complete.
- Internally, these functions mainly differ in that usually, the first
- case doesn't require setting up the tactic engine.
+ - program mode API, that allow to declare a constant with holes, to
+ be fullfilled later.
Note that the API in this file is still in a state of flux, don't
hesitate to contact the maintainers if you have any question.
@@ -38,27 +36,196 @@ open Entries
*)
+(** Declaration hooks, to be run when a constant is saved. Use with
+ care, as imperative effects may become not supported in the
+ future. *)
+module Hook : sig
+ type t
+
+ (** Hooks allow users of the API to perform arbitrary actions at
+ proof/definition saving time. For example, to register a constant
+ as a Coercion, perform some cleanup, update the search database,
+ etc... *)
+ module S : sig
+ type t =
+ { uctx : UState.t
+ (** [ustate]: universe constraints obtained when the term was closed *)
+ ; obls : (Id.t * Constr.t) list
+ (** [(n1,t1),...(nm,tm)]: association list between obligation
+ name and the corresponding defined term (might be a constant,
+ but also an arbitrary term in the Expand case of obligations) *)
+ ; scope : Locality.locality
+ (** [scope]: Locality of the original declaration *)
+ ; dref : GlobRef.t
+ (** [dref]: identifier of the original declaration *)
+ }
+ end
+
+ val make : (S.t -> unit) -> t
+ val call : ?hook:t -> S.t -> unit
+end
+
+(** {2 One-go, non-interactive declaration API } *)
+
+(** Information for a single top-level named constant *)
+module CInfo : sig
+ type 'constr t
+
+ val make :
+ name : Id.t
+ -> typ:'constr
+ -> ?args:Name.t list
+ -> ?impargs:Impargs.manual_implicits
+ -> unit
+ -> 'constr t
+
+ (* Used only in Vernacentries, may disappear from public API *)
+ val to_constr : Evd.evar_map -> EConstr.t t -> Constr.t t
+
+ (* Used only in RecLemmas, may disappear from public API *)
+ val get_typ : 'constr t -> 'constr
+
+end
+
+(** Information for a declaration, interactive or not, includes
+ parameters shared by mutual constants *)
+module Info : sig
+
+ type t
+
+ (** Note that [opaque] doesn't appear here as it is not known at the
+ start of the proof in the interactive case. *)
+ val make
+ : ?poly:bool
+ -> ?inline : bool
+ -> ?kind : Decls.logical_kind
+ (** Theorem, etc... *)
+ -> ?udecl : UState.universe_decl
+ -> ?scope : Locality.locality
+ (** locality *)
+ -> ?hook : Hook.t
+ (** Callback to be executed after saving the constant *)
+ -> unit
+ -> t
+
+end
+
+(** Declares a non-interactive constant; [body] and [types] will be
+ normalized w.r.t. the passed [evar_map] [sigma]. Universes should
+ be handled properly, including minimization and restriction. Note
+ that [sigma] is checked for unresolved evars, thus you should be
+ careful not to submit open terms or evar maps with stale,
+ unresolved existentials *)
+val declare_definition
+ : info:Info.t
+ -> cinfo:EConstr.t option CInfo.t
+ -> opaque:bool
+ -> body:EConstr.t
+ -> Evd.evar_map
+ -> GlobRef.t
+
+val declare_assumption
+ : name:Id.t
+ -> scope:Locality.locality
+ -> hook:Hook.t option
+ -> impargs:Impargs.manual_implicits
+ -> uctx:UState.t
+ -> Entries.parameter_entry
+ -> GlobRef.t
+
+type lemma_possible_guards = int list list
+
+val declare_mutually_recursive
+ : info:Info.t
+ -> cinfo: Constr.t CInfo.t list
+ -> opaque:bool
+ -> ntns:Vernacexpr.decl_notation list
+ -> uctx:UState.t
+ -> rec_declaration:Constr.rec_declaration
+ -> possible_indexes:lemma_possible_guards option
+ -> Names.GlobRef.t list
+
+(** {2 Declaration of interactive constants } *)
+
(** [Declare.Proof.t] Construction of constants using interactive proofs. *)
module Proof : sig
type t
- (** XXX: These are internal and will go away from publis API once
- lemmas is merged here *)
- val get_proof : t -> Proof.t
- val get_proof_name : t -> Names.Id.t
+ (** [start_proof ~info ~cinfo sigma] starts a proof of [cinfo].
+ The proof is started in the evar map [sigma] (which
+ can typically contain universe constraints) *)
+ val start
+ : info:Info.t
+ -> cinfo:EConstr.t CInfo.t
+ -> Evd.evar_map
+ -> t
+
+ (** [start_{derive,equations}] are functions meant to handle
+ interactive proofs with multiple goals, they should be considered
+ experimental until we provide a more general API encompassing
+ both of them. Please, get in touch with the developers if you
+ would like to experiment with multi-goal dependent proofs so we
+ can use your input on the design of the new API. *)
+ val start_derive : f:Id.t -> name:Id.t -> info:Info.t -> Proofview.telescope -> t
+
+ val start_equations :
+ name:Id.t
+ -> info:Info.t
+ -> hook:(Constant.t list -> Evd.evar_map -> unit)
+ -> types:(Environ.env * Evar.t * Evd.evar_info * EConstr.named_context * Evd.econstr) list
+ -> Evd.evar_map
+ -> Proofview.telescope
+ -> t
+
+ (** Pretty much internal, used by the Lemma vernaculars *)
+ val start_with_initialization
+ : info:Info.t
+ -> cinfo:Constr.t CInfo.t
+ -> Evd.evar_map
+ -> t
+
+ type mutual_info = (bool * lemma_possible_guards * Constr.t option list option)
+
+ (** Pretty much internal, used by mutual Lemma / Fixpoint vernaculars *)
+ val start_mutual_with_initialization
+ : info:Info.t
+ -> cinfo:Constr.t CInfo.t list
+ -> mutual_info:mutual_info
+ -> Evd.evar_map
+ -> int list option
+ -> t
+
+ (** Qed a proof *)
+ val save
+ : proof:t
+ -> opaque:Vernacexpr.opacity_flag
+ -> idopt:Names.lident option
+ -> GlobRef.t list
+
+ (** Admit a proof *)
+ val save_admitted : proof:t -> unit
- val map_proof : (Proof.t -> Proof.t) -> t -> t
- val map_fold_proof : (Proof.t -> Proof.t * 'a) -> t -> t * 'a
- val map_fold_proof_endline : (unit Proofview.tactic -> Proof.t -> Proof.t * 'a) -> t -> t * 'a
+ (** [by tac] applies tactic [tac] to the 1st subgoal of the current
+ focused proof.
+ Returns [false] if an unsafe tactic has been used. *)
+ val by : unit Proofview.tactic -> t -> t * bool
+
+ (** Operations on ongoing proofs *)
+ val get : t -> Proof.t
+ val get_name : t -> Names.Id.t
+
+ val fold : f:(Proof.t -> 'a) -> t -> 'a
+ val map : f:(Proof.t -> Proof.t) -> t -> t
+ val map_fold : f:(Proof.t -> Proof.t * 'a) -> t -> t * 'a
+ val map_fold_endline : f:(unit Proofview.tactic -> Proof.t -> Proof.t * 'a) -> t -> t * 'a
(** Sets the tactic to be used when a tactic line is closed with [...] *)
val set_endline_tactic : Genarg.glob_generic_argument -> t -> t
(** Sets the section variables assumed by the proof, returns its closure
* (w.r.t. type dependencies and let-ins covered by it) *)
- val set_used_variables : t ->
- Names.Id.t list -> Constr.named_context * t
+ val set_used_variables : t -> Names.Id.t list -> Constr.named_context * t
val compact : t -> t
@@ -69,32 +236,73 @@ module Proof : sig
val get_open_goals : t -> int
-end
+ (** Helpers to obtain proof state when in an interactive proof *)
-type opacity_flag = Vernacexpr.opacity_flag = Opaque | Transparent
+ (** [get_goal_context n] returns the context of the [n]th subgoal of
+ the current focused proof or raises a [UserError] if there is no
+ focused proof or if there is no more subgoals *)
-(** [start_proof ~name ~udecl ~poly sigma goals] starts a proof of
- name [name] with goals [goals] (a list of pairs of environment and
- conclusion); [poly] determines if the proof is universe
- polymorphic. The proof is started in the evar map [sigma] (which
- can typically contain universe constraints), and with universe
- bindings [udecl]. *)
-val start_proof
- : name:Names.Id.t
- -> udecl:UState.universe_decl
- -> poly:bool
- -> Evd.evar_map
- -> (Environ.env * EConstr.types) list
- -> Proof.t
+ val get_goal_context : t -> int -> Evd.evar_map * Environ.env
-(** Like [start_proof] except that there may be dependencies between
- initial goals. *)
-val start_dependent_proof
- : name:Names.Id.t
- -> udecl:UState.universe_decl
- -> poly:bool
- -> Proofview.telescope
- -> Proof.t
+ (** [get_current_goal_context ()] works as [get_goal_context 1] *)
+ val get_current_goal_context : t -> Evd.evar_map * Environ.env
+
+ (** [get_current_context ()] returns the context of the
+ current focused goal. If there is no focused goal but there
+ is a proof in progress, it returns the corresponding evar_map.
+ If there is no pending proof then it returns the current global
+ environment and empty evar_map. *)
+ val get_current_context : t -> Evd.evar_map * Environ.env
+
+ (* Internal, don't use *)
+ module Proof_info : sig
+ type t
+ (* Make a dummy value, used in the stm *)
+ val default : unit -> t
+ end
+ val info : t -> Proof_info.t
+
+ (** {2 Proof delay API, warning, internal, not stable *)
+
+ (* Intermediate step necessary to delegate the future.
+ * Both access the current proof state. The former is supposed to be
+ * chained with a computation that completed the proof *)
+ type closed_proof_output
+
+ (** Requires a complete proof. *)
+ val return_proof : t -> closed_proof_output
+
+ (** An incomplete proof is allowed (no error), and a warn is given if
+ the proof is complete. *)
+ val return_partial_proof : t -> closed_proof_output
+
+ (** XXX: This is an internal, low-level API and could become scheduled
+ for removal from the public API, use higher-level declare APIs
+ instead *)
+ type proof_object
+
+ val close_proof : opaque:Vernacexpr.opacity_flag -> keep_body_ucst_separate:bool -> t -> proof_object
+ val close_future_proof : feedback_id:Stateid.t -> t -> closed_proof_output Future.computation -> proof_object
+
+ (** Special cases for delayed proofs, in this case we must provide the
+ proof information so the proof won't be forced. *)
+ val save_lemma_admitted_delayed :
+ proof:proof_object
+ -> pinfo:Proof_info.t
+ -> unit
+
+ val save_lemma_proved_delayed
+ : proof:proof_object
+ -> pinfo:Proof_info.t
+ -> idopt:Names.lident option
+ -> GlobRef.t list
+
+ (** Used by the STM only to store info, should go away *)
+ val get_po_name : proof_object -> Id.t
+
+end
+
+(** {2 low-level, internla API, avoid using unless you have special needs } *)
(** Proof entries represent a proof that has been finished, but still
not registered with the kernel.
@@ -104,30 +312,32 @@ val start_dependent_proof
instead *)
type 'a proof_entry
-(** XXX: This is an internal, low-level API and could become scheduled
- for removal from the public API, use higher-level declare APIs
- instead *)
-type proof_object
-
-(** Used by the STM only to store info, should go away *)
-val get_po_name : proof_object -> Id.t
-
-val close_proof : opaque:opacity_flag -> keep_body_ucst_separate:bool -> Proof.t -> proof_object
-
-(** Declaration of local constructions (Variable/Hypothesis/Local) *)
+val definition_entry
+ : ?opaque:bool
+ -> ?inline:bool
+ -> ?types:Constr.types
+ -> ?univs:Entries.universes_entry
+ -> Constr.constr
+ -> Evd.side_effects proof_entry
(** XXX: This is an internal, low-level API and could become scheduled
- for removal from the public API, use higher-level declare APIs
- instead *)
-type 'a constant_entry =
- | DefinitionEntry of 'a proof_entry
- | ParameterEntry of parameter_entry
- | PrimitiveEntry of primitive_entry
+ for removal from the public API, use higher-level declare APIs
+ instead *)
+val declare_entry
+ : name:Id.t
+ -> scope:Locality.locality
+ -> kind:Decls.logical_kind
+ -> ?hook:Hook.t
+ -> impargs:Impargs.manual_implicits
+ -> uctx:UState.t
+ -> Evd.side_effects proof_entry
+ -> GlobRef.t
+(** Declaration of local constructions (Variable/Hypothesis/Local) *)
val declare_variable
: name:variable
-> kind:Decls.logical_kind
- -> typ:types
+ -> typ:Constr.types
-> impl:Glob_term.binding_kind
-> unit
@@ -137,34 +347,33 @@ val declare_variable
XXX: This is an internal, low-level API and could become scheduled
for removal from the public API, use higher-level declare APIs
instead *)
-val definition_entry
- : ?opaque:bool
- -> ?inline:bool
- -> ?types:types
- -> ?univs:Entries.universes_entry
- -> constr
- -> Evd.side_effects proof_entry
+type 'a constant_entry =
+ | DefinitionEntry of 'a proof_entry
+ | ParameterEntry of Entries.parameter_entry
+ | PrimitiveEntry of Entries.primitive_entry
-type import_status = Locality.import_status = ImportDefaultBehavior | ImportNeedQualified
+val prepare_parameter
+ : poly:bool
+ -> udecl:UState.universe_decl
+ -> types:EConstr.types
+ -> Evd.evar_map
+ -> Evd.evar_map * Entries.parameter_entry
(** [declare_constant id cd] declares a global declaration
(constant/parameter) with name [id] in the current section; it returns
the full path of the declaration
- internal specify if the constant has been created by the kernel or by the
- user, and in the former case, if its errors should be silent
-
XXX: This is an internal, low-level API and could become scheduled
for removal from the public API, use higher-level declare APIs
instead *)
val declare_constant
- : ?local:import_status
+ : ?local:Locality.import_status
-> name:Id.t
-> kind:Decls.logical_kind
-> Evd.side_effects constant_entry
-> Constant.t
-(** Declaration messages *)
+(** Declaration messages, for internal use *)
(** XXX: Scheduled for removal from public API, do not use *)
val definition_message : Id.t -> unit
@@ -173,35 +382,6 @@ val fixpoint_message : int array option -> Id.t list -> unit
val check_exists : Id.t -> unit
-(** {6 For legacy support, do not use} *)
-
-module Internal : sig
-
- type constant_obj
-
- val objConstant : constant_obj Libobject.Dyn.tag
- val objVariable : unit Libobject.Dyn.tag
-
-end
-
-(* Intermediate step necessary to delegate the future.
- * Both access the current proof state. The former is supposed to be
- * chained with a computation that completed the proof *)
-type closed_proof_output
-
-(** Requires a complete proof. *)
-val return_proof : Proof.t -> closed_proof_output
-
-(** An incomplete proof is allowed (no error), and a warn is given if
- the proof is complete. *)
-val return_partial_proof : Proof.t -> closed_proof_output
-val close_future_proof : feedback_id:Stateid.t -> Proof.t -> closed_proof_output Future.computation -> proof_object
-
-(** [by tac] applies tactic [tac] to the 1st subgoal of the current
- focused proof.
- Returns [false] if an unsafe tactic has been used. *)
-val by : unit Proofview.tactic -> Proof.t -> Proof.t * bool
-
(** Semantics of this function is a bit dubious, use with care *)
val build_by_tactic
: ?side_eff:bool
@@ -212,138 +392,77 @@ val build_by_tactic
-> unit Proofview.tactic
-> Constr.constr * Constr.types option * Entries.universes_entry * bool * UState.t
-(** {6 Helpers to obtain proof state when in an interactive proof } *)
-
-(** [get_goal_context n] returns the context of the [n]th subgoal of
- the current focused proof or raises a [UserError] if there is no
- focused proof or if there is no more subgoals *)
-
-val get_goal_context : Proof.t -> int -> Evd.evar_map * Environ.env
+(** {2 Program mode API} *)
+
+(** Coq's Program mode support. This mode extends declarations of
+ constants and fixpoints with [Program Definition] and [Program
+ Fixpoint] to support incremental construction of terms using
+ delayed proofs, called "obligations"
+
+ The mode also provides facilities for managing and auto-solving
+ sets of obligations.
+
+ The basic code flow of programs/obligations is as follows:
+
+ - [add_definition] / [add_mutual_definitions] are called from the
+ respective [Program] vernacular command interpretation; at this
+ point the only extra work we do is to prepare the new definition
+ [d] using [RetrieveObl], which consists in turning unsolved evars
+ into obligations. [d] is not sent to the kernel yet, as it is not
+ complete and cannot be typchecked, but saved in a special
+ data-structure. Auto-solving of obligations is tried at this stage
+ (see below)
+
+ - [next_obligation] will retrieve the next obligation
+ ([RetrieveObl] sorts them by topological order) and will try to
+ solve it. When all obligations are solved, the original constant
+ [d] is grounded and sent to the kernel for addition to the global
+ environment. Auto-solving of obligations is also triggered on
+ obligation completion.
+
+{2} Solving of obligations: Solved obligations are stored as regular
+ global declarations in the global environment, usually with name
+ [constant_obligation_number] where [constant] is the original
+ [constant] and [number] is the corresponding (internal) number.
+
+ Solving an obligation can trigger a bit of a complex cascaded
+ callback path; closing an obligation can indeed allow all other
+ obligations to be closed, which in turn may trigged the declaration
+ of the original constant. Care must be taken, as this can modify
+ [Global.env] in arbitrarily ways. Current code takes some care to
+ refresh the [env] in the proper boundaries, but the invariants
+ remain delicate.
+
+{2} Saving of obligations: as open obligations use the regular proof
+ mode, a `Qed` will call `Lemmas.save_lemma` first. For this reason
+ obligations code is split in two: this file, [Obligations], taking
+ care of the top-level vernac commands, and [Declare], which is
+ called by `Lemmas` to close an obligation proof and eventually to
+ declare the top-level [Program]ed constant.
-(** [get_current_goal_context ()] works as [get_goal_context 1] *)
-val get_current_goal_context : Proof.t -> Evd.evar_map * Environ.env
-
-(** [get_current_context ()] returns the context of the
- current focused goal. If there is no focused goal but there
- is a proof in progress, it returns the corresponding evar_map.
- If there is no pending proof then it returns the current global
- environment and empty evar_map. *)
-val get_current_context : Proof.t -> Evd.evar_map * Environ.env
-
-(** XXX: Temporarily re-exported for 3rd party code; don't use *)
-val build_constant_by_tactic :
- name:Names.Id.t ->
- ?opaque:opacity_flag ->
- uctx:UState.t ->
- sign:Environ.named_context_val ->
- poly:bool ->
- EConstr.types ->
- unit Proofview.tactic ->
- Evd.side_effects proof_entry * bool * UState.t
-[@@ocaml.deprecated "This function is deprecated, used newer API in declare"]
+ *)
-val declare_universe_context : poly:bool -> Univ.ContextSet.t -> unit
-[@@ocaml.deprecated "Use DeclareUctx.declare_universe_context"]
+module Obls : sig
-type locality = Locality.locality = Discharge | Global of import_status
+type fixpoint_kind = IsFixpoint of lident option list | IsCoFixpoint
-(** Declaration hooks *)
-module Hook : sig
+module State : sig
+ (* Internal *)
type t
-
- (** Hooks allow users of the API to perform arbitrary actions at
- proof/definition saving time. For example, to register a constant
- as a Coercion, perform some cleanup, update the search database,
- etc... *)
- module S : sig
- type t =
- { uctx : UState.t
- (** [ustate]: universe constraints obtained when the term was closed *)
- ; obls : (Id.t * Constr.t) list
- (** [(n1,t1),...(nm,tm)]: association list between obligation
- name and the corresponding defined term (might be a constant,
- but also an arbitrary term in the Expand case of obligations) *)
- ; scope : locality
- (** [scope]: Locality of the original declaration *)
- ; dref : GlobRef.t
- (** [dref]: identifier of the original declaration *)
- }
- end
-
- val make : (S.t -> unit) -> t
- val call : ?hook:t -> S.t -> unit
+ val prg_tag : t Summary.Dyn.tag
end
-(** XXX: This is an internal, low-level API and could become scheduled
- for removal from the public API, use higher-level declare APIs
- instead *)
-val declare_entry
- : name:Id.t
- -> scope:locality
- -> kind:Decls.logical_kind
- -> ?hook:Hook.t
- -> impargs:Impargs.manual_implicits
- -> uctx:UState.t
- -> Evd.side_effects proof_entry
- -> GlobRef.t
-
-(** Declares a non-interactive constant; [body] and [types] will be
- normalized w.r.t. the passed [evar_map] [sigma]. Universes should
- be handled properly, including minimization and restriction. Note
- that [sigma] is checked for unresolved evars, thus you should be
- careful not to submit open terms or evar maps with stale,
- unresolved existentials *)
-val declare_definition
- : name:Id.t
- -> scope:locality
- -> kind:Decls.logical_kind
- -> opaque:bool
- -> impargs:Impargs.manual_implicits
- -> udecl:UState.universe_decl
- -> ?hook:Hook.t
- -> poly:bool
- -> ?inline:bool
- -> types:EConstr.t option
- -> body:EConstr.t
- -> Evd.evar_map
- -> GlobRef.t
-
-val declare_assumption
- : name:Id.t
- -> scope:locality
- -> hook:Hook.t option
- -> impargs:Impargs.manual_implicits
- -> uctx:UState.t
- -> Entries.parameter_entry
- -> GlobRef.t
-
-module Recthm : sig
- type t =
- { name : Id.t
- (** Name of theorem *)
- ; typ : Constr.t
- (** Type of theorem *)
- ; args : Name.t list
- (** Names to pre-introduce *)
- ; impargs : Impargs.manual_implicits
- (** Explicitily declared implicit arguments *)
- }
-end
+(** Check obligations are properly solved before closing the
+ [what_for] section / module *)
+val check_solved_obligations : what_for:Pp.t -> unit
-type lemma_possible_guards = int list list
+val default_tactic : unit Proofview.tactic ref
-val declare_mutually_recursive
- : opaque:bool
- -> scope:locality
- -> kind:Decls.logical_kind
- -> poly:bool
- -> uctx:UState.t
- -> udecl:UState.universe_decl
- -> ntns:Vernacexpr.decl_notation list
- -> rec_declaration:Constr.rec_declaration
- -> possible_indexes:lemma_possible_guards option
- -> Recthm.t list
- -> Names.GlobRef.t list
+(** Resolution status of a program *)
+type progress =
+ | Remain of int (** n obligations remaining *)
+ | Dependent (** Dependent on other definitions *)
+ | Defined of GlobRef.t (** Defined as id *)
(** Prepare API, to be removed once we provide the corresponding 1-step API *)
val prepare_obligation
@@ -353,212 +472,75 @@ val prepare_obligation
-> Evd.evar_map
-> Constr.constr * Constr.types * UState.t * RetrieveObl.obligation_info
-val prepare_parameter
- : poly:bool
- -> udecl:UState.universe_decl
- -> types:EConstr.types
- -> Evd.evar_map
- -> Evd.evar_map * Entries.parameter_entry
-
-(* Compat: will remove *)
-exception AlreadyDeclared of (string option * Names.Id.t)
-
-module Obls : sig
-
-type 'a obligation_body = DefinedObl of 'a | TermObl of constr
-
-module Obligation : sig
- type t = private
- { obl_name : Id.t
- ; obl_type : types
- ; obl_location : Evar_kinds.t Loc.located
- ; obl_body : pconstant obligation_body option
- ; obl_status : bool * Evar_kinds.obligation_definition_status
- ; obl_deps : Int.Set.t
- ; obl_tac : unit Proofview.tactic option }
-
- val set_type : typ:Constr.types -> t -> t
- val set_body : body:pconstant obligation_body -> t -> t
-end
-
-type obligations = {obls : Obligation.t array; remaining : int}
-type fixpoint_kind = IsFixpoint of lident option list | IsCoFixpoint
-
-(* Information about a single [Program {Definition,Lemma,..}] declaration *)
-module ProgramDecl : sig
- type t = private
- { prg_name : Id.t
- ; prg_body : constr
- ; prg_type : constr
- ; prg_ctx : UState.t
- ; prg_univdecl : UState.universe_decl
- ; prg_obligations : obligations
- ; prg_deps : Id.t list
- ; prg_fixkind : fixpoint_kind option
- ; prg_implicits : Impargs.manual_implicits
- ; prg_notations : Vernacexpr.decl_notation list
- ; prg_poly : bool
- ; prg_scope : locality
- ; prg_kind : Decls.definition_object_kind
- ; prg_reduce : constr -> constr
- ; prg_hook : Hook.t option
- ; prg_opaque : bool }
-
- val make :
- ?opaque:bool
- -> ?hook:Hook.t
- -> Names.Id.t
- -> udecl:UState.universe_decl
- -> uctx:UState.t
- -> impargs:Impargs.manual_implicits
- -> poly:bool
- -> scope:locality
- -> kind:Decls.definition_object_kind
- -> Constr.constr option
- -> Constr.types
- -> Names.Id.t list
- -> fixpoint_kind option
- -> Vernacexpr.decl_notation list
- -> RetrieveObl.obligation_info
- -> (Constr.constr -> Constr.constr)
- -> t
-
- val set_uctx : uctx:UState.t -> t -> t
-end
-
-(** [declare_obligation prg obl ~uctx ~types ~body] Save an obligation
- [obl] for program definition [prg] *)
-val declare_obligation :
- ProgramDecl.t
- -> Obligation.t
+(** Start a [Program Definition c] proof. [uctx] [udecl] [impargs]
+ [kind] [scope] [poly] etc... come from the interpretation of the
+ vernacular; `obligation_info` was generated by [RetrieveObl] It
+ will return whether all the obligations were solved; if so, it will
+ also register [c] with the kernel. *)
+val add_definition :
+ cinfo:Constr.types CInfo.t
+ -> info:Info.t
+ -> ?term:Constr.t
-> uctx:UState.t
- -> types:Constr.types option
- -> body:Constr.types
- -> bool * Obligation.t
-
-module State : sig
-
- val num_pending : unit -> int
- val first_pending : unit -> ProgramDecl.t option
-
- (** Returns [Error duplicate_list] if not a single program is open *)
- val get_unique_open_prog :
- Id.t option -> (ProgramDecl.t, Id.t list) result
-
- (** Add a new obligation *)
- val add : Id.t -> ProgramDecl.t -> unit
-
- val fold : f:(Id.t -> ProgramDecl.t -> 'a -> 'a) -> init:'a -> 'a
-
- val all : unit -> ProgramDecl.t list
+ -> ?tactic:unit Proofview.tactic
+ -> ?reduce:(Constr.t -> Constr.t)
+ -> ?opaque:bool
+ -> RetrieveObl.obligation_info
+ -> progress
- val find : Id.t -> ProgramDecl.t option
+(* XXX: unify with MutualEntry *)
- (* Internal *)
- type t
- val prg_tag : t Summary.Dyn.tag
-end
-
-val declare_definition : ProgramDecl.t -> Names.GlobRef.t
+(** Start a [Program Fixpoint] declaration, similar to the above,
+ except it takes a list now. *)
+val add_mutual_definitions :
+ (Constr.t CInfo.t * Constr.t * RetrieveObl.obligation_info) list
+ -> info:Info.t
+ -> uctx:UState.t
+ -> ?tactic:unit Proofview.tactic
+ -> ?reduce:(Constr.t -> Constr.t)
+ -> ?opaque:bool
+ -> ntns:Vernacexpr.decl_notation list
+ -> fixpoint_kind
+ -> unit
-(** Resolution status of a program *)
-type progress =
- | Remain of int (** n obligations remaining *)
- | Dependent (** Dependent on other definitions *)
- | Defined of GlobRef.t (** Defined as id *)
+(** Implementation of the [Obligation] command *)
+val obligation :
+ int * Names.Id.t option * Constrexpr.constr_expr option
+ -> Genarg.glob_generic_argument option
+ -> Proof.t
-type obligation_resolver =
- Id.t option
- -> Int.Set.t
- -> unit Proofview.tactic option
- -> progress
+(** Implementation of the [Next Obligation] command *)
+val next_obligation :
+ Names.Id.t option -> Genarg.glob_generic_argument option -> Proof.t
-type obligation_qed_info = {name : Id.t; num : int; auto : obligation_resolver}
+(** Implementation of the [Solve Obligation] command *)
+val solve_obligations :
+ Names.Id.t option -> unit Proofview.tactic option -> progress
-(** [update_obls prg obls n progress] What does this do? *)
-val update_obls :
- ProgramDecl.t -> Obligation.t array -> int -> progress
+val solve_all_obligations : unit Proofview.tactic option -> unit
-(** Check obligations are properly solved before closing the
- [what_for] section / module *)
-val check_solved_obligations : what_for:Pp.t -> unit
+(** Number of remaining obligations to be solved for this program *)
+val try_solve_obligation :
+ int -> Names.Id.t option -> unit Proofview.tactic option -> unit
-(** { 2 Util } *)
+val try_solve_obligations :
+ Names.Id.t option -> unit Proofview.tactic option -> unit
-val obl_substitution :
- bool
- -> Obligation.t array
- -> Int.Set.t
- -> (Id.t * (Constr.types * Constr.types)) list
+val show_obligations : ?msg:bool -> Names.Id.t option -> unit
+val show_term : Names.Id.t option -> Pp.t
+val admit_obligations : Names.Id.t option -> unit
-val dependencies : Obligation.t array -> int -> Int.Set.t
+val check_program_libraries : unit -> unit
end
-(** Creating high-level proofs with an associated constant *)
-module Proof_ending : sig
+(** {6 For internal support, do not use} *)
- type t =
- | Regular
- | End_obligation of Obls.obligation_qed_info
- | End_derive of { f : Id.t; name : Id.t }
- | End_equations of
- { hook : Constant.t list -> Evd.evar_map -> unit
- ; i : Id.t
- ; types : (Environ.env * Evar.t * Evd.evar_info * EConstr.named_context * Evd.econstr) list
- ; sigma : Evd.evar_map
- }
+module Internal : sig
-end
+ type constant_obj
-module Info : sig
- type t
- val make
- : ?hook: Hook.t
- (** Callback to be executed at the end of the proof *)
- -> ?proof_ending : Proof_ending.t
- (** Info for special constants *)
- -> ?scope : locality
- (** locality *)
- -> ?kind:Decls.logical_kind
- (** Theorem, etc... *)
- -> ?compute_guard:lemma_possible_guards
- -> ?thms:Recthm.t list
- (** Both of those are internal, used by the upper layers but will
- become handled natively here in the future *)
- -> unit
- -> t
+ val objConstant : constant_obj Libobject.Dyn.tag
+ val objVariable : unit Libobject.Dyn.tag
- (* Internal; used to initialize non-mutual proofs *)
- val add_first_thm :
- info:t
- -> name:Id.t
- -> typ:EConstr.t
- -> impargs:Impargs.manual_implicits
- -> t
end
-
-val save_lemma_proved
- : proof:Proof.t
- -> info:Info.t
- -> opaque:opacity_flag
- -> idopt:Names.lident option
- -> unit
-
-val save_lemma_admitted :
- proof:Proof.t
- -> info:Info.t
- -> unit
-
-(** Special cases for delayed proofs, in this case we must provide the
- proof information so the proof won't be forced. *)
-val save_lemma_admitted_delayed :
- proof:proof_object
- -> info:Info.t
- -> unit
-
-val save_lemma_proved_delayed
- : proof:proof_object
- -> info:Info.t
- -> idopt:Names.lident option
- -> unit
diff --git a/vernac/declareDef.ml b/vernac/declareDef.ml
deleted file mode 100644
index 83bb1dae71..0000000000
--- a/vernac/declareDef.ml
+++ /dev/null
@@ -1,9 +0,0 @@
-type locality = Declare.locality =
- | Discharge [@ocaml.deprecated "Use [Declare.Discharge]"]
- | Global of Declare.import_status [@ocaml.deprecated "Use [Declare.Global]"]
-[@@ocaml.deprecated "Use [Declare.locality]"]
-
-let declare_definition = Declare.declare_definition
-[@@ocaml.deprecated "Use [Declare.declare_definition]"]
-module Hook = Declare.Hook
-[@@ocaml.deprecated "Use [Declare.Hook]"]
diff --git a/vernac/g_proofs.mlg b/vernac/g_proofs.mlg
index 80a4de472c..ebec720ce2 100644
--- a/vernac/g_proofs.mlg
+++ b/vernac/g_proofs.mlg
@@ -64,12 +64,12 @@ GRAMMAR EXTEND Gram
| IDENT "Existential"; n = natural; c = constr_body ->
{ VernacSolveExistential (n,c) }
| IDENT "Admitted" -> { VernacEndProof Admitted }
- | IDENT "Qed" -> { VernacEndProof (Proved (Declare.Opaque,None)) }
+ | IDENT "Qed" -> { VernacEndProof (Proved (Opaque,None)) }
| IDENT "Save"; id = identref ->
- { VernacEndProof (Proved (Declare.Opaque, Some id)) }
- | IDENT "Defined" -> { VernacEndProof (Proved (Declare.Transparent,None)) }
+ { VernacEndProof (Proved (Opaque, Some id)) }
+ | IDENT "Defined" -> { VernacEndProof (Proved (Transparent,None)) }
| IDENT "Defined"; id=identref ->
- { VernacEndProof (Proved (Declare.Transparent,Some id)) }
+ { VernacEndProof (Proved (Transparent,Some id)) }
| IDENT "Restart" -> { VernacRestart }
| IDENT "Undo" -> { VernacUndo 1 }
| IDENT "Undo"; n = natural -> { VernacUndo n }
diff --git a/vernac/lemmas.ml b/vernac/lemmas.ml
deleted file mode 100644
index 10d63ff2ff..0000000000
--- a/vernac/lemmas.ml
+++ /dev/null
@@ -1,130 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * Copyright INRIA, CNRS and contributors *)
-(* <O___,, * (see version control and CREDITS file for authors & dates) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-(* Created by Hugo Herbelin from contents related to lemma proofs in
- file command.ml, Aug 2009 *)
-
-open Util
-
-module NamedDecl = Context.Named.Declaration
-
-(* Support for terminators and proofs with an associated constant
- [that can be saved] *)
-
-type lemma_possible_guards = int list list
-
-module Proof_ending = Declare.Proof_ending
-module Info = Declare.Info
-
-(* Proofs with a save constant function *)
-type t =
- { proof : Declare.Proof.t
- ; info : Info.t
- }
-
-let pf_map f pf = { pf with proof = f pf.proof }
-let pf_fold f pf = f pf.proof
-
-let set_endline_tactic t = pf_map (Declare.Proof.set_endline_tactic t)
-
-(* To be removed *)
-module Internal = struct
-
- (** Gets the current terminator without checking that the proof has
- been completed. Useful for the likes of [Admitted]. *)
- let get_info ps = ps.info
-
-end
-
-let by tac pf =
- let proof, res = Declare.by tac pf.proof in
- { pf with proof }, res
-
-(************************************************************************)
-(* Creating a lemma-like constant *)
-(************************************************************************)
-
-let initialize_named_context_for_proof () =
- let sign = Global.named_context () in
- List.fold_right
- (fun d signv ->
- let id = NamedDecl.get_id d in
- let d = if Decls.variable_opacity id then NamedDecl.drop_body d else d in
- Environ.push_named_context_val d signv) sign Environ.empty_named_context_val
-
-(* Starting a goal *)
-let start_lemma ~name ~poly
- ?(udecl=UState.default_univ_decl)
- ?(info=Info.make ()) ?(impargs=[]) sigma c =
- (* We remove the bodies of variables in the named context marked
- "opaque", this is a hack tho, see #10446 *)
- let sign = initialize_named_context_for_proof () in
- let goals = [ Global.env_of_context sign , c ] in
- let proof = Declare.start_proof sigma ~name ~udecl ~poly goals in
- let info = Declare.Info.add_first_thm ~info ~name ~typ:c ~impargs in
- { proof; info }
-
-(* Note that proofs opened by start_dependent lemma cannot be closed
- by the regular terminators, thus we don't need to update the [thms]
- field. We will capture this invariant by typing in the future *)
-let start_dependent_lemma ~name ~poly
- ?(udecl=UState.default_univ_decl)
- ?(info=Info.make ()) telescope =
- let proof = Declare.start_dependent_proof ~name ~udecl ~poly telescope in
- { proof; info }
-
-let rec_tac_initializer finite guard thms snl =
- if finite then
- match List.map (fun { Declare.Recthm.name; typ } -> name, (EConstr.of_constr typ)) thms with
- | (id,_)::l -> Tactics.mutual_cofix id l 0
- | _ -> assert false
- else
- (* nl is dummy: it will be recomputed at Qed-time *)
- let nl = match snl with
- | None -> List.map succ (List.map List.last guard)
- | Some nl -> nl
- in match List.map2 (fun { Declare.Recthm.name; typ } n -> (name, n, (EConstr.of_constr typ))) thms nl with
- | (id,n,_)::l -> Tactics.mutual_fix id n l 0
- | _ -> assert false
-
-let start_lemma_with_initialization ?hook ~poly ~scope ~kind ~udecl sigma recguard thms snl =
- let intro_tac { Declare.Recthm.args; _ } = Tactics.auto_intros_tac args in
- let init_tac, compute_guard = match recguard with
- | Some (finite,guard,init_terms) ->
- let rec_tac = rec_tac_initializer finite guard thms snl in
- let term_tac =
- match init_terms with
- | None ->
- List.map intro_tac thms
- | Some init_terms ->
- (* This is the case for hybrid proof mode / definition
- fixpoint, where terms for some constants are given with := *)
- let tacl = List.map (Option.cata (EConstr.of_constr %> Tactics.exact_no_check) Tacticals.New.tclIDTAC) init_terms in
- List.map2 (fun tac thm -> Tacticals.New.tclTHEN tac (intro_tac thm)) tacl thms
- in
- Tacticals.New.tclTHENS rec_tac term_tac, guard
- | None ->
- let () = match thms with [_] -> () | _ -> assert false in
- intro_tac (List.hd thms), [] in
- match thms with
- | [] -> CErrors.anomaly (Pp.str "No proof to start.")
- | { Declare.Recthm.name; typ; impargs; _} :: thms ->
- let info = Info.make ?hook ~scope ~kind ~compute_guard ~thms () in
- (* start_lemma has the responsibility to add (name, impargs, typ)
- to thms, once Info.t is more refined this won't be necessary *)
- let lemma = start_lemma ~name ~impargs ~poly ~udecl ~info sigma (EConstr.of_constr typ) in
- pf_map (Declare.Proof.map_proof (fun p ->
- pi1 @@ Proof.run_tactic Global.(env ()) init_tac p)) lemma
-
-let save_lemma_admitted ~lemma =
- Declare.save_lemma_admitted ~proof:lemma.proof ~info:lemma.info
-
-let save_lemma_proved ~lemma ~opaque ~idopt =
- Declare.save_lemma_proved ~proof:lemma.proof ~info:lemma.info ~opaque ~idopt
diff --git a/vernac/lemmas.mli b/vernac/lemmas.mli
deleted file mode 100644
index 4787a940da..0000000000
--- a/vernac/lemmas.mli
+++ /dev/null
@@ -1,82 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * Copyright INRIA, CNRS and contributors *)
-(* <O___,, * (see version control and CREDITS file for authors & dates) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-open Names
-
-(** {4 Proofs attached to a constant} *)
-
-type t
-(** [Lemmas.t] represents a constant that is being proved, usually
- interactively *)
-
-val set_endline_tactic : Genarg.glob_generic_argument -> t -> t
-(** [set_endline_tactic tac lemma] set ending tactic for [lemma] *)
-
-val pf_map : (Declare.Proof.t -> Declare.Proof.t) -> t -> t
-(** [pf_map f l] map the underlying proof object *)
-
-val pf_fold : (Declare.Proof.t -> 'a) -> t -> 'a
-(** [pf_fold f l] fold over the underlying proof object *)
-
-val by : unit Proofview.tactic -> t -> t * bool
-(** [by tac l] apply a tactic to [l] *)
-
-module Proof_ending = Declare.Proof_ending
-module Info = Declare.Info
-
-(** Starts the proof of a constant *)
-val start_lemma
- : name:Id.t
- -> poly:bool
- -> ?udecl:UState.universe_decl
- -> ?info:Info.t
- -> ?impargs:Impargs.manual_implicits
- -> Evd.evar_map
- -> EConstr.types
- -> t
-
-val start_dependent_lemma
- : name:Id.t
- -> poly:bool
- -> ?udecl:UState.universe_decl
- -> ?info:Info.t
- -> Proofview.telescope
- -> t
-
-type lemma_possible_guards = int list list
-
-(** Pretty much internal, used by the Lemma / Fixpoint vernaculars *)
-val start_lemma_with_initialization
- : ?hook:Declare.Hook.t
- -> poly:bool
- -> scope:Declare.locality
- -> kind:Decls.logical_kind
- -> udecl:UState.universe_decl
- -> Evd.evar_map
- -> (bool * lemma_possible_guards * Constr.t option list option) option
- -> Declare.Recthm.t list
- -> int list option
- -> t
-
-(** {4 Saving proofs} *)
-
-val save_lemma_admitted : lemma:t -> unit
-
-val save_lemma_proved
- : lemma:t
- -> opaque:Declare.opacity_flag
- -> idopt:Names.lident option
- -> unit
-
-(** To be removed, don't use! *)
-module Internal : sig
- val get_info : t -> Info.t
- (** Only needed due to the Declare compatibility layer. *)
-end
diff --git a/vernac/obligations.ml b/vernac/obligations.ml
deleted file mode 100644
index a8eac8fd2d..0000000000
--- a/vernac/obligations.ml
+++ /dev/null
@@ -1,417 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * Copyright INRIA, CNRS and contributors *)
-(* <O___,, * (see version control and CREDITS file for authors & dates) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-open Printf
-open Names
-open Pp
-open Util
-
-(* For the records fields, opens should go away one these types are private *)
-open Declare.Obls
-open Declare.Obls.Obligation
-open Declare.Obls.ProgramDecl
-
-let reduce c =
- let env = Global.env () in
- let sigma = Evd.from_env env in
- EConstr.Unsafe.to_constr (Reductionops.clos_norm_flags CClosure.betaiota env sigma (EConstr.of_constr c))
-
-let explain_no_obligations = function
- Some ident -> str "No obligations for program " ++ Id.print ident
- | None -> str "No obligations remaining"
-
-module Error = struct
-
- let no_obligations n =
- CErrors.user_err (explain_no_obligations n)
-
- let ambiguous_program id ids =
- CErrors.user_err
- Pp.(str "More than one program with unsolved obligations: " ++ prlist Id.print ids
- ++ str "; use the \"of\" clause to specify, as in \"Obligation 1 of " ++ Id.print id ++ str "\"")
-
- let unknown_obligation num =
- CErrors.user_err (Pp.str (sprintf "Unknown obligation number %i" (succ num)))
-
- let already_solved num =
- CErrors.user_err
- ( str "Obligation" ++ spc () ++ int num ++ str "already" ++ spc ()
- ++ str "solved." )
-
- let depends num rem =
- CErrors.user_err
- ( str "Obligation " ++ int num
- ++ str " depends on obligation(s) "
- ++ pr_sequence (fun x -> int (succ x)) rem)
-
-end
-
-let default_tactic = ref (Proofview.tclUNIT ())
-
-let evar_of_obligation o = Evd.make_evar (Global.named_context_val ()) (EConstr.of_constr o.obl_type)
-
-let subst_deps expand obls deps t =
- let osubst = Declare.Obls.obl_substitution expand obls deps in
- (Vars.replace_vars (List.map (fun (n, (_, b)) -> n, b) osubst) t)
-
-let subst_deps_obl obls obl =
- let t' = subst_deps true obls obl.obl_deps obl.obl_type in
- Obligation.set_type ~typ:t' obl
-
-open Evd
-
-let is_defined obls x = not (Option.is_empty obls.(x).obl_body)
-
-let deps_remaining obls deps =
- Int.Set.fold
- (fun x acc ->
- if is_defined obls x then acc
- else x :: acc)
- deps []
-
-let goal_kind = Decls.(IsDefinition Definition)
-let goal_proof_kind = Decls.(IsProof Lemma)
-
-let kind_of_obligation o =
- match o with
- | Evar_kinds.Define false
- | Evar_kinds.Expand -> goal_kind
- | _ -> goal_proof_kind
-
-(* Solve an obligation using tactics, return the corresponding proof term *)
-let warn_solve_errored =
- CWarnings.create ~name:"solve_obligation_error" ~category:"tactics"
- (fun err ->
- Pp.seq
- [ str "Solve Obligations tactic returned error: "
- ; err
- ; fnl ()
- ; str "This will become an error in the future" ])
-
-let solve_by_tac ?loc name evi t poly uctx =
- (* the status is dropped. *)
- try
- let env = Global.env () in
- let body, types, _univs, _, uctx =
- Declare.build_by_tactic env ~uctx ~poly ~typ:evi.evar_concl t in
- Inductiveops.control_only_guard env (Evd.from_ctx uctx) (EConstr.of_constr body);
- Some (body, types, uctx)
- with
- | Refiner.FailError (_, s) as exn ->
- let _ = Exninfo.capture exn in
- CErrors.user_err ?loc ~hdr:"solve_obligation" (Lazy.force s)
- (* If the proof is open we absorb the error and leave the obligation open *)
- | Proof.OpenProof _ ->
- None
- | e when CErrors.noncritical e ->
- let err = CErrors.print e in
- warn_solve_errored ?loc err;
- None
-
-let get_unique_prog prg =
- match State.get_unique_open_prog prg with
- | Ok prg -> prg
- | Error [] ->
- Error.no_obligations None
- | Error ((id :: _) as ids) ->
- Error.ambiguous_program id ids
-
-let rec solve_obligation prg num tac =
- let user_num = succ num in
- let { obls; remaining=rem } = prg.prg_obligations in
- let obl = obls.(num) in
- let remaining = deps_remaining obls obl.obl_deps in
- let () =
- if not (Option.is_empty obl.obl_body)
- then Error.already_solved user_num;
- if not (List.is_empty remaining)
- then Error.depends user_num remaining
- in
- let obl = subst_deps_obl obls obl in
- let scope = Declare.(Global Declare.ImportNeedQualified) in
- let kind = kind_of_obligation (snd obl.obl_status) in
- let evd = Evd.from_ctx prg.prg_ctx in
- let evd = Evd.update_sigma_env evd (Global.env ()) in
- let auto n oblset tac = auto_solve_obligations n ~oblset tac in
- let proof_ending =
- Declare.Proof_ending.End_obligation
- {Declare.Obls.name = prg.prg_name; num; auto}
- in
- let info = Lemmas.Info.make ~proof_ending ~scope ~kind () in
- let poly = prg.prg_poly in
- let lemma = Lemmas.start_lemma ~name:obl.obl_name ~poly ~info evd (EConstr.of_constr obl.obl_type) in
- let lemma = fst @@ Lemmas.by !default_tactic lemma in
- let lemma = Option.cata (fun tac -> Lemmas.set_endline_tactic tac lemma) lemma tac in
- lemma
-
-and obligation (user_num, name, typ) tac =
- let num = pred user_num in
- let prg = get_unique_prog name in
- let { obls; remaining } = prg.prg_obligations in
- if num >= 0 && num < Array.length obls then
- let obl = obls.(num) in
- match obl.obl_body with
- | None -> solve_obligation prg num tac
- | Some r -> Error.already_solved num
- else Error.unknown_obligation num
-
-and solve_obligation_by_tac prg obls i tac =
- let obl = obls.(i) in
- match obl.obl_body with
- | Some _ -> None
- | None ->
- if List.is_empty (deps_remaining obls obl.obl_deps) then
- let obl = subst_deps_obl obls obl in
- let tac =
- match tac with
- | Some t -> t
- | None ->
- match obl.obl_tac with
- | Some t -> t
- | None -> !default_tactic
- in
- let evd = Evd.from_ctx prg.prg_ctx in
- let evd = Evd.update_sigma_env evd (Global.env ()) in
- match solve_by_tac ?loc:(fst obl.obl_location) obl.obl_name (evar_of_obligation obl) tac
- prg.prg_poly (Evd.evar_universe_context evd) with
- | None -> None
- | Some (t, ty, uctx) ->
- let prg = ProgramDecl.set_uctx ~uctx prg in
- (* Why is uctx not used above? *)
- let def, obl' = declare_obligation prg obl ~body:t ~types:ty ~uctx in
- obls.(i) <- obl';
- if def && not prg.prg_poly then (
- (* Declare the term constraints with the first obligation only *)
- let uctx_global = UState.from_env (Global.env ()) in
- let uctx = UState.merge_subst uctx_global (UState.subst uctx) in
- Some (ProgramDecl.set_uctx ~uctx prg))
- else Some prg
- else None
-
-and solve_prg_obligations prg ?oblset tac =
- let { obls; remaining } = prg.prg_obligations in
- let rem = ref remaining in
- let obls' = Array.copy obls in
- let set = ref Int.Set.empty in
- let p = match oblset with
- | None -> (fun _ -> true)
- | Some s -> set := s;
- (fun i -> Int.Set.mem i !set)
- in
- let (), prg =
- Array.fold_left_i
- (fun i ((), prg) x ->
- if p i then (
- match solve_obligation_by_tac prg obls' i tac with
- | None -> (), prg
- | Some prg ->
- let deps = dependencies obls i in
- set := Int.Set.union !set deps;
- decr rem;
- (), prg)
- else (), prg)
- ((), prg) obls'
- in
- update_obls prg obls' !rem
-
-and solve_obligations n tac =
- let prg = get_unique_prog n in
- solve_prg_obligations prg tac
-
-and solve_all_obligations tac =
- State.fold ~init:() ~f:(fun k v () ->
- let _ = solve_prg_obligations v tac in ())
-
-and try_solve_obligation n prg tac =
- let prg = get_unique_prog prg in
- let {obls; remaining } = prg.prg_obligations in
- let obls' = Array.copy obls in
- match solve_obligation_by_tac prg obls' n tac with
- | Some prg' ->
- let _r = update_obls prg' obls' (pred remaining) in
- ()
- | None -> ()
-
-and try_solve_obligations n tac =
- let _ = solve_obligations n tac in
- ()
-
-and auto_solve_obligations n ?oblset tac : progress =
- Flags.if_verbose Feedback.msg_info
- (str "Solving obligations automatically...");
- let prg = get_unique_prog n in
- solve_prg_obligations prg ?oblset tac
-
-open Pp
-
-let show_single_obligation i n obls x =
- let x = subst_deps_obl obls x in
- let env = Global.env () in
- let sigma = Evd.from_env env in
- let msg =
- str "Obligation" ++ spc ()
- ++ int (succ i)
- ++ spc () ++ str "of" ++ spc () ++ Id.print n ++ str ":" ++ spc ()
- ++ hov 1 (Printer.pr_constr_env env sigma x.obl_type
- ++ str "." ++ fnl ()) in
- Feedback.msg_info msg
-
-let show_obligations_of_prg ?(msg = true) prg =
- let n = prg.prg_name in
- let {obls; remaining} = prg.prg_obligations in
- let showed = ref 5 in
- if msg then Feedback.msg_info (int remaining ++ str " obligation(s) remaining: ");
- Array.iteri
- (fun i x ->
- match x.obl_body with
- | None ->
- if !showed > 0 then begin
- decr showed;
- show_single_obligation i n obls x
- end
- | Some _ -> ())
- obls
-
-let show_obligations ?(msg = true) n =
- let progs =
- match n with
- | None ->
- State.all ()
- | Some n ->
- (match State.find n with
- | Some prg -> [prg]
- | None -> Error.no_obligations (Some n))
- in
- List.iter (fun x -> show_obligations_of_prg ~msg x) progs
-
-let show_term n =
- let prg = get_unique_prog n in
- let n = prg.prg_name in
- let env = Global.env () in
- let sigma = Evd.from_env env in
- Id.print n ++ spc () ++ str ":" ++ spc ()
- ++ Printer.pr_constr_env env sigma prg.prg_type
- ++ spc () ++ str ":=" ++ fnl ()
- ++ Printer.pr_constr_env env sigma prg.prg_body
-
-let msg_generating_obl name obls =
- let len = Array.length obls in
- let info = Id.print name ++ str " has type-checked" in
- Feedback.msg_info
- (if len = 0 then info ++ str "."
- else
- info ++ str ", generating " ++ int len ++
- str (String.plural len " obligation"))
-
-let add_definition ~name ?term t ~uctx ?(udecl = UState.default_univ_decl)
- ?(impargs = []) ~poly
- ?(scope = Declare.Global Declare.ImportDefaultBehavior)
- ?(kind = Decls.Definition) ?tactic ?(reduce = reduce) ?hook
- ?(opaque = false) obls =
- let prg = ProgramDecl.make ~opaque name ~udecl term t ~uctx [] None [] obls ~impargs ~poly ~scope ~kind reduce ?hook in
- let {obls;_} = prg.prg_obligations in
- if Int.equal (Array.length obls) 0 then (
- Flags.if_verbose (msg_generating_obl name) obls;
- let cst = Declare.Obls.declare_definition prg in
- Defined cst)
- else
- let () = Flags.if_verbose (msg_generating_obl name) obls in
- let () = State.add name prg in
- let res = auto_solve_obligations (Some name) tactic in
- match res with
- | Remain rem ->
- Flags.if_verbose (show_obligations ~msg:false) (Some name);
- res
- | _ -> res
-
-let add_mutual_definitions l ~uctx ?(udecl = UState.default_univ_decl)
- ?tactic ~poly ?(scope = Declare.Global Declare.ImportDefaultBehavior)
- ?(kind = Decls.Definition) ?(reduce = reduce) ?hook ?(opaque = false)
- notations fixkind =
- let deps = List.map (fun ({Declare.Recthm.name; _}, _, _) -> name) l in
- let pm =
- List.fold_left
- (fun () ({Declare.Recthm.name; typ; impargs; _}, b, obls) ->
- let prg =
- ProgramDecl.make ~opaque name ~udecl (Some b) typ ~uctx deps
- (Some fixkind) notations obls ~impargs ~poly ~scope ~kind reduce
- ?hook
- in
- State.add name prg)
- () l
- in
- let pm, _defined =
- List.fold_left
- (fun (pm, finished) x ->
- if finished then (pm, finished)
- else
- let res = auto_solve_obligations (Some x) tactic in
- match res with
- | Defined _ ->
- (* If one definition is turned into a constant,
- the whole block is defined. *)
- (pm, true)
- | _ -> (pm, false))
- (pm, false) deps
- in
- pm
-
-let admit_prog prg =
- let {obls; remaining} = prg.prg_obligations in
- let obls = Array.copy obls in
- Array.iteri
- (fun i x ->
- match x.obl_body with
- | None ->
- let x = subst_deps_obl obls x in
- let ctx = UState.univ_entry ~poly:false prg.prg_ctx in
- let kn = Declare.declare_constant ~name:x.obl_name ~local:Declare.ImportNeedQualified
- (Declare.ParameterEntry (None, (x.obl_type, ctx), None)) ~kind:Decls.(IsAssumption Conjectural)
- in
- Declare.assumption_message x.obl_name;
- obls.(i) <- Obligation.set_body ~body:(DefinedObl (kn, Univ.Instance.empty)) x
- | Some _ -> ())
- obls;
- Declare.Obls.update_obls prg obls 0
-
-(* get_any_prog *)
-let rec admit_all_obligations () =
- let prg = State.first_pending () in
- match prg with
- | None -> ()
- | Some prg ->
- let _prog = admit_prog prg in
- admit_all_obligations ()
-
-let admit_obligations n =
- match n with
- | None -> admit_all_obligations ()
- | Some _ ->
- let prg = get_unique_prog n in
- let _ = admit_prog prg in
- ()
-
-let next_obligation n tac =
- let prg = match n with
- | None -> State.first_pending () |> Option.get
- | Some _ -> get_unique_prog n
- in
- let {obls; remaining} = prg.prg_obligations in
- let is_open _ x = Option.is_empty x.obl_body && List.is_empty (deps_remaining obls x.obl_deps) in
- let i = match Array.findi is_open obls with
- | Some i -> i
- | None -> CErrors.anomaly (Pp.str "Could not find a solvable obligation.")
- in
- solve_obligation prg i tac
-
-let check_program_libraries () =
- Coqlib.check_required_library Coqlib.datatypes_module_name;
- Coqlib.check_required_library ["Coq";"Init";"Specif"];
- Coqlib.check_required_library ["Coq";"Program";"Tactics"]
diff --git a/vernac/obligations.mli b/vernac/obligations.mli
deleted file mode 100644
index c21951373b..0000000000
--- a/vernac/obligations.mli
+++ /dev/null
@@ -1,135 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * Copyright INRIA, CNRS and contributors *)
-(* <O___,, * (see version control and CREDITS file for authors & dates) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-open Constr
-
-(** Coq's Program mode support. This mode extends declarations of
- constants and fixpoints with [Program Definition] and [Program
- Fixpoint] to support incremental construction of terms using
- delayed proofs, called "obligations"
-
- The mode also provides facilities for managing and auto-solving
- sets of obligations.
-
- The basic code flow of programs/obligations is as follows:
-
- - [add_definition] / [add_mutual_definitions] are called from the
- respective [Program] vernacular command interpretation; at this
- point the only extra work we do is to prepare the new definition
- [d] using [RetrieveObl], which consists in turning unsolved evars
- into obligations. [d] is not sent to the kernel yet, as it is not
- complete and cannot be typchecked, but saved in a special
- data-structure. Auto-solving of obligations is tried at this stage
- (see below)
-
- - [next_obligation] will retrieve the next obligation
- ([RetrieveObl] sorts them by topological order) and will try to
- solve it. When all obligations are solved, the original constant
- [d] is grounded and sent to the kernel for addition to the global
- environment. Auto-solving of obligations is also triggered on
- obligation completion.
-
-{2} Solving of obligations: Solved obligations are stored as regular
- global declarations in the global environment, usually with name
- [constant_obligation_number] where [constant] is the original
- [constant] and [number] is the corresponding (internal) number.
-
- Solving an obligation can trigger a bit of a complex cascaded
- callback path; closing an obligation can indeed allow all other
- obligations to be closed, which in turn may trigged the declaration
- of the original constant. Care must be taken, as this can modify
- [Global.env] in arbitrarily ways. Current code takes some care to
- refresh the [env] in the proper boundaries, but the invariants
- remain delicate.
-
-{2} Saving of obligations: as open obligations use the regular proof
- mode, a `Qed` will call `Lemmas.save_lemma` first. For this reason
- obligations code is split in two: this file, [Obligations], taking
- care of the top-level vernac commands, and [DeclareObl], which is
- called by `Lemmas` to close an obligation proof and eventually to
- declare the top-level [Program]ed constant.
-
- There is little obligations-specific code in [DeclareObl], so
- eventually that file should be integrated in the regular [Declare]
- path, as it gains better support for "dependent_proofs".
-
- *)
-
-val default_tactic : unit Proofview.tactic ref
-
-(** Start a [Program Definition c] proof. [uctx] [udecl] [impargs]
- [kind] [scope] [poly] etc... come from the interpretation of the
- vernacular; `obligation_info` was generated by [RetrieveObl] It
- will return whether all the obligations were solved; if so, it will
- also register [c] with the kernel. *)
-val add_definition :
- name:Names.Id.t
- -> ?term:constr
- -> types
- -> uctx:UState.t
- -> ?udecl:UState.universe_decl (** Universe binders and constraints *)
- -> ?impargs:Impargs.manual_implicits
- -> poly:bool
- -> ?scope:Declare.locality
- -> ?kind:Decls.definition_object_kind
- -> ?tactic:unit Proofview.tactic
- -> ?reduce:(constr -> constr)
- -> ?hook:Declare.Hook.t
- -> ?opaque:bool
- -> RetrieveObl.obligation_info
- -> Declare.Obls.progress
-
-(* XXX: unify with MutualEntry *)
-
-(** Start a [Program Fixpoint] declaration, similar to the above,
- except it takes a list now. *)
-val add_mutual_definitions :
- (Declare.Recthm.t * Constr.t * RetrieveObl.obligation_info) list
- -> uctx:UState.t
- -> ?udecl:UState.universe_decl (** Universe binders and constraints *)
- -> ?tactic:unit Proofview.tactic
- -> poly:bool
- -> ?scope:Declare.locality
- -> ?kind:Decls.definition_object_kind
- -> ?reduce:(constr -> constr)
- -> ?hook:Declare.Hook.t
- -> ?opaque:bool
- -> Vernacexpr.decl_notation list
- -> Declare.Obls.fixpoint_kind
- -> unit
-
-(** Implementation of the [Obligation] command *)
-val obligation :
- int * Names.Id.t option * Constrexpr.constr_expr option
- -> Genarg.glob_generic_argument option
- -> Lemmas.t
-
-(** Implementation of the [Next Obligation] command *)
-val next_obligation :
- Names.Id.t option -> Genarg.glob_generic_argument option -> Lemmas.t
-
-(** Implementation of the [Solve Obligation] command *)
-val solve_obligations :
- Names.Id.t option -> unit Proofview.tactic option -> Declare.Obls.progress
-
-val solve_all_obligations : unit Proofview.tactic option -> unit
-
-(** Number of remaining obligations to be solved for this program *)
-val try_solve_obligation :
- int -> Names.Id.t option -> unit Proofview.tactic option -> unit
-
-val try_solve_obligations :
- Names.Id.t option -> unit Proofview.tactic option -> unit
-
-val show_obligations : ?msg:bool -> Names.Id.t option -> unit
-val show_term : Names.Id.t option -> Pp.t
-val admit_obligations : Names.Id.t option -> unit
-
-val check_program_libraries : unit -> unit
diff --git a/vernac/pfedit.ml b/vernac/pfedit.ml
deleted file mode 100644
index 150311ffaa..0000000000
--- a/vernac/pfedit.ml
+++ /dev/null
@@ -1,19 +0,0 @@
-(* Compat API / *)
-let get_current_context = Declare.get_current_context
-[@@ocaml.deprecated "Use [Declare.get_current_context]"]
-let solve = Proof.solve
-[@@ocaml.deprecated "Use [Proof.solve]"]
-let by = Declare.by
-[@@ocaml.deprecated "Use [Declare.by]"]
-let refine_by_tactic = Proof.refine_by_tactic
-[@@ocaml.deprecated "Use [Proof.refine_by_tactic]"]
-
-(* We don't want to export this anymore, but we do for now *)
-let build_by_tactic ?side_eff env ~uctx ~poly ~typ tac =
- let b, t, _unis, safe, uctx =
- Declare.build_by_tactic ?side_eff env ~uctx ~poly ~typ tac in
- b, t, safe, uctx
-[@@ocaml.deprecated "Use [Proof.build_by_tactic]"]
-
-let build_constant_by_tactic = Declare.build_constant_by_tactic [@ocaml.warning "-3"]
-[@@ocaml.deprecated "Use [Proof.build_constant_by_tactic]"]
diff --git a/vernac/proof_global.ml b/vernac/proof_global.ml
deleted file mode 100644
index 0c5bc39020..0000000000
--- a/vernac/proof_global.ml
+++ /dev/null
@@ -1,13 +0,0 @@
-(* compatibility module; can be removed once we agree on the API *)
-
-type t = Declare.Proof.t
-[@@ocaml.deprecated "Use [Declare.Proof.t]"]
-let map_proof = Declare.Proof.map_proof
-[@@ocaml.deprecated "Use [Declare.Proof.map_proof]"]
-let get_proof = Declare.Proof.get_proof
-[@@ocaml.deprecated "Use [Declare.Proof.get_proof]"]
-
-type opacity_flag = Declare.opacity_flag =
- | Opaque [@ocaml.deprecated "Use [Declare.Opaque]"]
- | Transparent [@ocaml.deprecated "Use [Declare.Transparent]"]
-[@@ocaml.deprecated "Use [Declare.opacity_flag]"]
diff --git a/vernac/recLemmas.ml b/vernac/recLemmas.ml
index eb0e1fb795..534c358a3f 100644
--- a/vernac/recLemmas.ml
+++ b/vernac/recLemmas.ml
@@ -16,9 +16,9 @@ module RelDecl = Context.Rel.Declaration
let find_mutually_recursive_statements sigma thms =
let n = List.length thms in
- let inds = List.map (fun (id,(t,impls)) ->
- let (hyps,ccl) = EConstr.decompose_prod_assum sigma t in
- let x = (id,(t,impls)) in
+ let inds = List.map (fun x ->
+ let typ = Declare.CInfo.get_typ x in
+ let (hyps,ccl) = EConstr.decompose_prod_assum sigma typ in
let whnf_hyp_hds = EConstr.map_rel_context_in_env
(fun env c -> fst (Reductionops.whd_all_stack env sigma c))
(Global.env()) hyps in
@@ -89,14 +89,23 @@ let find_mutually_recursive_statements sigma thms =
in
(finite,guard,None), ordered_inds
-let look_for_possibly_mutual_statements sigma = function
- | [id,(t,impls)] ->
+type mutual_info =
+ | NonMutual of EConstr.t Declare.CInfo.t
+ | Mutual of
+ { mutual_info : Declare.Proof.mutual_info
+ ; cinfo : EConstr.t Declare.CInfo.t list
+ ; possible_guards : int list
+ }
+
+let look_for_possibly_mutual_statements sigma thms : mutual_info =
+ match thms with
+ | [thm] ->
(* One non recursively proved theorem *)
- None,[id,(t,impls)],None
+ NonMutual thm
| _::_ as thms ->
(* More than one statement and/or an explicit decreasing mark: *)
(* we look for a common inductive hyp or a common coinductive conclusion *)
let recguard,ordered_inds = find_mutually_recursive_statements sigma thms in
- let thms = List.map pi2 ordered_inds in
- Some recguard,thms, Some (List.map (fun (_,_,i) -> succ i) ordered_inds)
+ let cinfo = List.map pi2 ordered_inds in
+ Mutual { mutual_info = recguard; cinfo; possible_guards = List.map (fun (_,_,i) -> succ i) ordered_inds }
| [] -> CErrors.anomaly (Pp.str "Empty list of theorems.")
diff --git a/vernac/recLemmas.mli b/vernac/recLemmas.mli
index 1a697c1e88..93aae29b18 100644
--- a/vernac/recLemmas.mli
+++ b/vernac/recLemmas.mli
@@ -8,8 +8,15 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+type mutual_info =
+ | NonMutual of EConstr.t Declare.CInfo.t
+ | Mutual of
+ { mutual_info : Declare.Proof.mutual_info
+ ; cinfo : EConstr.t Declare.CInfo.t list
+ ; possible_guards : int list
+ }
+
val look_for_possibly_mutual_statements
: Evd.evar_map
- -> ('a * (EConstr.t * 'b)) list
- -> (bool * int list list * 'c option) option *
- ('a * (EConstr.t * 'b)) list * int list option
+ -> EConstr.t Declare.CInfo.t list
+ -> mutual_info
diff --git a/vernac/vernac.mllib b/vernac/vernac.mllib
index 1cad052bce..23dde0dd29 100644
--- a/vernac/vernac.mllib
+++ b/vernac/vernac.mllib
@@ -20,11 +20,9 @@ ComHints
Canonical
RecLemmas
Library
-Lemmas
ComCoercion
Auto_ind_decl
Indschemes
-Obligations
ComDefinition
Classes
ComPrimitive
@@ -45,6 +43,3 @@ ComArguments
Vernacentries
Vernacstate
Vernacinterp
-Proof_global
-Pfedit
-DeclareDef
diff --git a/vernac/vernacentries.ml b/vernac/vernacentries.ml
index 9a1d935928..d44e4babf4 100644
--- a/vernac/vernacentries.ml
+++ b/vernac/vernacentries.ml
@@ -34,12 +34,12 @@ let (f_interp_redexp, interp_redexp_hook) = Hook.make ()
let get_current_or_global_context ~pstate =
match pstate with
| None -> let env = Global.env () in Evd.(from_env env, env)
- | Some p -> Declare.get_current_context p
+ | Some p -> Declare.Proof.get_current_context p
let get_goal_or_global_context ~pstate glnum =
match pstate with
| None -> let env = Global.env () in Evd.(from_env env, env)
- | Some p -> Declare.get_goal_context p glnum
+ | Some p -> Declare.Proof.get_goal_context p glnum
let cl_of_qualid = function
| FunClass -> Coercionops.CL_FUN
@@ -84,7 +84,7 @@ let with_module_locality ~atts f =
let with_def_attributes ~atts f =
let atts = DefAttributes.parse atts in
- if atts.DefAttributes.program then Obligations.check_program_libraries ();
+ if atts.DefAttributes.program then Declare.Obls.check_program_libraries ();
f ~atts
(*******************)
@@ -94,8 +94,8 @@ let show_proof ~pstate =
(* spiwack: this would probably be cooler with a bit of polishing. *)
try
let pstate = Option.get pstate in
- let p = Declare.Proof.get_proof pstate in
- let sigma, _ = Declare.get_current_context pstate in
+ let p = Declare.Proof.get pstate in
+ let sigma, _ = Declare.Proof.get_current_context pstate in
let pprf = Proof.partial_proof p in
(* In the absence of an environment explicitly attached to the
proof and on top of which side effects of the proof would be pushed, ,
@@ -466,12 +466,12 @@ let vernac_custom_entry ~module_local s =
let check_name_freshness locality {CAst.loc;v=id} : unit =
(* We check existence here: it's a bit late at Qed time *)
if Nametab.exists_cci (Lib.make_path id) || Termops.is_section_variable id ||
- locality <> Declare.Discharge && Nametab.exists_cci (Lib.make_path_except_section id)
+ locality <> Locality.Discharge && Nametab.exists_cci (Lib.make_path_except_section id)
then
user_err ?loc (Id.print id ++ str " already exists.")
let program_inference_hook env sigma ev =
- let tac = !Obligations.default_tactic in
+ let tac = !Declare.Obls.default_tactic in
let evi = Evd.find sigma ev in
let evi = Evarutil.nf_evar_info sigma evi in
let env = Evd.evar_filtered_env env evi in
@@ -490,38 +490,54 @@ let program_inference_hook env sigma ev =
user_err Pp.(str "The statement obligations could not be resolved \
automatically, write a statement definition first.")
+(* XXX: Interpretation of lemma command, duplication with ComFixpoint
+ / ComDefinition ? *)
+let interp_lemma ~program_mode ~flags ~scope env0 evd thms =
+ let inference_hook = if program_mode then Some program_inference_hook else None in
+ List.fold_left_map (fun evd ((id, _), (bl, t)) ->
+ let evd, (impls, ((env, ctx), imps)) =
+ Constrintern.interp_context_evars ~program_mode env0 evd bl
+ in
+ let evd, (t', imps') = Constrintern.interp_type_evars_impls ~flags ~impls env evd t in
+ let flags = Pretyping.{ all_and_fail_flags with program_mode } in
+ let evd = Pretyping.solve_remaining_evars ?hook:inference_hook flags env evd in
+ let ids = List.map Context.Rel.Declaration.get_name ctx in
+ check_name_freshness scope id;
+ let thm = Declare.CInfo.make ~name:id.CAst.v ~typ:(EConstr.it_mkProd_or_LetIn t' ctx)
+ ~args:ids ~impargs:(imps @ imps') () in
+ evd, thm)
+ evd thms
+
+(* Checks done in start_lemma_com *)
+let post_check_evd ~udecl ~poly evd =
+ let () =
+ if not UState.(udecl.univdecl_extensible_instance &&
+ udecl.univdecl_extensible_constraints) then
+ ignore (Evd.check_univ_decl ~poly evd udecl)
+ in
+ if poly then evd
+ else (* We fix the variables to ensure they won't be lowered to Set *)
+ Evd.fix_undefined_variables evd
+
let start_lemma_com ~program_mode ~poly ~scope ~kind ?hook thms =
let env0 = Global.env () in
let flags = Pretyping.{ all_no_fail_flags with program_mode } in
let decl = fst (List.hd thms) in
let evd, udecl = Constrexpr_ops.interp_univ_decl_opt env0 (snd decl) in
- let evd, thms = List.fold_left_map (fun evd ((id, _), (bl, t)) ->
- let evd, (impls, ((env, ctx), imps)) =
- Constrintern.interp_context_evars ~program_mode env0 evd bl
- in
- let evd, (t', imps') = Constrintern.interp_type_evars_impls ~flags ~impls env evd t in
- let flags = Pretyping.{ all_and_fail_flags with program_mode } in
- let inference_hook = if program_mode then Some program_inference_hook else None in
- let evd = Pretyping.solve_remaining_evars ?hook:inference_hook flags env evd in
- let ids = List.map Context.Rel.Declaration.get_name ctx in
- check_name_freshness scope id;
- evd, (id.CAst.v, (EConstr.it_mkProd_or_LetIn t' ctx, (ids, imps @ imps'))))
- evd thms in
- let recguard,thms,snl = RecLemmas.look_for_possibly_mutual_statements evd thms in
+ let evd, thms = interp_lemma ~program_mode ~flags ~scope env0 evd thms in
+ let mut_analysis = RecLemmas.look_for_possibly_mutual_statements evd thms in
let evd = Evd.minimize_universes evd in
- let thms = List.map (fun (name, (typ, (args, impargs))) ->
- { Declare.Recthm.name; typ = EConstr.to_constr evd typ; args; impargs} ) thms in
- let () =
- let open UState in
- if not (udecl.univdecl_extensible_instance && udecl.univdecl_extensible_constraints) then
- ignore (Evd.check_univ_decl ~poly evd udecl)
- in
- let evd =
- if poly then evd
- else (* We fix the variables to ensure they won't be lowered to Set *)
- Evd.fix_undefined_variables evd
- in
- Lemmas.start_lemma_with_initialization ?hook ~poly ~scope ~kind evd ~udecl recguard thms snl
+ match mut_analysis with
+ | RecLemmas.NonMutual thm ->
+ let thm = Declare.CInfo.to_constr evd thm in
+ let evd = post_check_evd ~udecl ~poly evd in
+ let info = Declare.Info.make ?hook ~poly ~scope ~kind ~udecl () in
+ Declare.Proof.start_with_initialization ~info ~cinfo:thm evd
+ | RecLemmas.Mutual { mutual_info; cinfo ; possible_guards } ->
+ let cinfo = List.map (Declare.CInfo.to_constr evd) cinfo in
+ let evd = post_check_evd ~udecl ~poly evd in
+ let info = Declare.Info.make ?hook ~poly ~scope ~kind ~udecl () in
+ Declare.Proof.start_mutual_with_initialization ~info ~cinfo evd ~mutual_info (Some possible_guards)
let vernac_definition_hook ~canonical_instance ~local ~poly = let open Decls in function
| Coercion ->
@@ -548,7 +564,6 @@ let vernac_definition_name lid local =
CAst.make ?loc (fresh_name_for_anonymous_theorem ())
| { v = Name.Name n; loc } -> CAst.make ?loc n in
let () =
- let open Declare in
match local with
| Discharge -> Dumpglob.dump_definition lid true "var"
| Global _ -> Dumpglob.dump_definition lid false "def"
@@ -577,6 +592,7 @@ let vernac_definition ~atts (discharge, kind) (lid, pl) bl red_option c typ_opt
let sigma = Evd.from_env env in
Some (snd (Hook.get f_interp_redexp env sigma r)) in
if program_mode then
+ let kind = Decls.IsDefinition kind in
ComDefinition.do_definition_program ~name:name.v
~poly:atts.polymorphic ~scope ~kind pl bl red_option c typ_opt ?hook
else
@@ -595,15 +611,16 @@ let vernac_start_proof ~atts kind l =
let vernac_end_proof ~lemma = let open Vernacexpr in function
| Admitted ->
- Lemmas.save_lemma_admitted ~lemma
+ Declare.Proof.save_admitted ~proof:lemma
| Proved (opaque,idopt) ->
- Lemmas.save_lemma_proved ~lemma ~opaque ~idopt
+ let _ : Names.GlobRef.t list = Declare.Proof.save ~proof:lemma ~opaque ~idopt
+ in ()
let vernac_exact_proof ~lemma c =
(* spiwack: for simplicity I do not enforce that "Proof proof_term" is
called only at the beginning of a proof. *)
- let lemma, status = Lemmas.by (Tactics.exact_proof c) lemma in
- let () = Lemmas.save_lemma_proved ~lemma ~opaque:Declare.Opaque ~idopt:None in
+ let lemma, status = Declare.Proof.by (Tactics.exact_proof c) lemma in
+ let _ : _ list = Declare.Proof.save ~proof:lemma ~opaque:Opaque ~idopt:None in
if not status then Feedback.feedback Feedback.AddedAxiom
let vernac_assumption ~atts discharge kind l nl =
@@ -613,8 +630,8 @@ let vernac_assumption ~atts discharge kind l nl =
if Dumpglob.dump () then
List.iter (fun (lid, _) ->
match scope with
- | Declare.Global _ -> Dumpglob.dump_definition lid false "ax"
- | Declare.Discharge -> Dumpglob.dump_definition lid true "var") idl) l;
+ | Global _ -> Dumpglob.dump_definition lid false "ax"
+ | Discharge -> Dumpglob.dump_definition lid true "var") idl) l;
ComAssumption.do_assumptions ~poly:atts.polymorphic ~program_mode:atts.program ~scope ~kind nl l
let is_polymorphic_inductive_cumulativity =
@@ -1187,7 +1204,7 @@ let focus_command_cond = Proof.no_cond command_focus
all tactics fail if there are no further goals to prove. *)
let vernac_solve_existential ~pstate n com =
- Declare.Proof.map_proof (fun p ->
+ Declare.Proof.map ~f:(fun p ->
let intern env sigma = Constrintern.intern_constr env sigma com in
Proof.V82.instantiate_evar (Global.env ()) n intern p) pstate
@@ -1200,7 +1217,7 @@ let vernac_set_end_tac ~pstate tac =
let vernac_set_used_variables ~pstate e : Declare.Proof.t =
let env = Global.env () in
let initial_goals pf = Proofview.initial_goals Proof.(data pf).Proof.entry in
- let tys = List.map snd (initial_goals (Declare.Proof.get_proof pstate)) in
+ let tys = List.map snd (initial_goals (Declare.Proof.get pstate)) in
let tys = List.map EConstr.Unsafe.to_constr tys in
let l = Proof_using.process_expr env e tys in
let vars = Environ.named_context env in
@@ -1602,8 +1619,8 @@ let get_current_context_of_args ~pstate =
let env = Global.env () in Evd.(from_env env, env)
| Some lemma ->
function
- | Some n -> Declare.get_goal_context lemma n
- | None -> Declare.get_current_context lemma
+ | Some n -> Declare.Proof.get_goal_context lemma n
+ | None -> Declare.Proof.get_current_context lemma
let query_command_selector ?loc = function
| None -> None
@@ -1668,7 +1685,7 @@ let vernac_global_check c =
let get_nth_goal ~pstate n =
- let pf = Declare.Proof.get_proof pstate in
+ let pf = Declare.Proof.get pstate in
let Proof.{goals;sigma} = Proof.data pf in
let gl = {Evd.it=List.nth goals (n-1) ; sigma = sigma; } in
gl
@@ -1703,7 +1720,7 @@ let print_about_hyp_globs ~pstate ?loc ref_or_by_not udecl glopt =
let natureofid = match decl with
| LocalAssum _ -> "Hypothesis"
| LocalDef (_,bdy,_) ->"Constant (let in)" in
- let sigma, env = Declare.get_current_context pstate in
+ let sigma, env = Declare.Proof.get_current_context pstate in
v 0 (Id.print id ++ str":" ++ pr_econstr_env env sigma (NamedDecl.get_type decl) ++ fnl() ++ fnl()
++ str natureofid ++ str " of the goal context.")
with (* fallback to globals *)
@@ -1747,7 +1764,7 @@ let vernac_print ~pstate ~atts =
| PrintHintGoal ->
begin match pstate with
| Some pstate ->
- let pf = Declare.Proof.get_proof pstate in
+ let pf = Declare.Proof.get pstate in
Hints.pr_applicable_hint pf
| None ->
str "No proof in progress"
@@ -1833,7 +1850,7 @@ let vernac_register qid r =
(* Proof management *)
let vernac_focus ~pstate gln =
- Declare.Proof.map_proof (fun p ->
+ Declare.Proof.map ~f:(fun p ->
match gln with
| None -> Proof.focus focus_command_cond () 1 p
| Some 0 ->
@@ -1844,13 +1861,13 @@ let vernac_focus ~pstate gln =
(* Unfocuses one step in the focus stack. *)
let vernac_unfocus ~pstate =
- Declare.Proof.map_proof
- (fun p -> Proof.unfocus command_focus p ())
+ Declare.Proof.map
+ ~f:(fun p -> Proof.unfocus command_focus p ())
pstate
(* Checks that a proof is fully unfocused. Raises an error if not. *)
let vernac_unfocused ~pstate =
- let p = Declare.Proof.get_proof pstate in
+ let p = Declare.Proof.get pstate in
if Proof.unfocused p then
str"The proof is indeed fully unfocused."
else
@@ -1863,7 +1880,7 @@ let subproof_kind = Proof.new_focus_kind ()
let subproof_cond = Proof.done_cond subproof_kind
let vernac_subproof gln ~pstate =
- Declare.Proof.map_proof (fun p ->
+ Declare.Proof.map ~f:(fun p ->
match gln with
| None -> Proof.focus subproof_cond () 1 p
| Some (Goal_select.SelectNth n) -> Proof.focus subproof_cond () n p
@@ -1873,12 +1890,12 @@ let vernac_subproof gln ~pstate =
pstate
let vernac_end_subproof ~pstate =
- Declare.Proof.map_proof (fun p ->
+ Declare.Proof.map ~f:(fun p ->
Proof.unfocus subproof_kind p ())
pstate
let vernac_bullet (bullet : Proof_bullet.t) ~pstate =
- Declare.Proof.map_proof (fun p ->
+ Declare.Proof.map ~f:(fun p ->
Proof_bullet.put p bullet) pstate
(* Stack is needed due to show proof names, should deprecate / remove
@@ -1895,7 +1912,7 @@ let vernac_show ~pstate =
end
(* Show functions that require a proof state *)
| Some pstate ->
- let proof = Declare.Proof.get_proof pstate in
+ let proof = Declare.Proof.get pstate in
begin function
| ShowGoal goalref ->
begin match goalref with
@@ -1907,14 +1924,14 @@ let vernac_show ~pstate =
| ShowUniverses -> show_universes ~proof
(* Deprecate *)
| ShowProofNames ->
- Id.print (Declare.Proof.get_proof_name pstate)
+ Id.print (Declare.Proof.get_name pstate)
| ShowIntros all -> show_intro ~proof all
| ShowProof -> show_proof ~pstate:(Some pstate)
| ShowMatch id -> show_match id
end
let vernac_check_guard ~pstate =
- let pts = Declare.Proof.get_proof pstate in
+ let pts = Declare.Proof.get pstate in
let pfterm = List.hd (Proof.partial_proof pts) in
let message =
try
diff --git a/vernac/vernacextend.ml b/vernac/vernacextend.ml
index d772f274a2..f8a80e8feb 100644
--- a/vernac/vernacextend.ml
+++ b/vernac/vernacextend.ml
@@ -55,8 +55,8 @@ and proof_block_name = string (** open type of delimiters *)
type typed_vernac =
| VtDefault of (unit -> unit)
| VtNoProof of (unit -> unit)
- | VtCloseProof of (lemma:Lemmas.t -> unit)
- | VtOpenProof of (unit -> Lemmas.t)
+ | VtCloseProof of (lemma:Declare.Proof.t -> unit)
+ | VtOpenProof of (unit -> Declare.Proof.t)
| VtModifyProof of (pstate:Declare.Proof.t -> Declare.Proof.t)
| VtReadProofOpt of (pstate:Declare.Proof.t option -> unit)
| VtReadProof of (pstate:Declare.Proof.t -> unit)
diff --git a/vernac/vernacextend.mli b/vernac/vernacextend.mli
index 58c267080a..103e24233b 100644
--- a/vernac/vernacextend.mli
+++ b/vernac/vernacextend.mli
@@ -73,8 +73,8 @@ and proof_block_name = string (** open type of delimiters *)
type typed_vernac =
| VtDefault of (unit -> unit)
| VtNoProof of (unit -> unit)
- | VtCloseProof of (lemma:Lemmas.t -> unit)
- | VtOpenProof of (unit -> Lemmas.t)
+ | VtCloseProof of (lemma:Declare.Proof.t -> unit)
+ | VtOpenProof of (unit -> Declare.Proof.t)
| VtModifyProof of (pstate:Declare.Proof.t -> Declare.Proof.t)
| VtReadProofOpt of (pstate:Declare.Proof.t option -> unit)
| VtReadProof of (pstate:Declare.Proof.t -> unit)
diff --git a/vernac/vernacinterp.ml b/vernac/vernacinterp.ml
index 7ab21141df..1b977b8e10 100644
--- a/vernac/vernacinterp.ml
+++ b/vernac/vernacinterp.ml
@@ -39,14 +39,14 @@ let interp_typed_vernac c ~stack =
| VtOpenProof f ->
Some (Vernacstate.LemmaStack.push stack (f ()))
| VtModifyProof f ->
- Option.map (Vernacstate.LemmaStack.map_top_pstate ~f:(fun pstate -> f ~pstate)) stack
+ Option.map (Vernacstate.LemmaStack.map_top ~f:(fun pstate -> f ~pstate)) stack
| VtReadProofOpt f ->
- let pstate = Option.map (Vernacstate.LemmaStack.with_top_pstate ~f:(fun x -> x)) stack in
+ let pstate = Option.map (Vernacstate.LemmaStack.with_top ~f:(fun x -> x)) stack in
f ~pstate;
stack
| VtReadProof f ->
vernac_require_open_lemma ~stack
- (Vernacstate.LemmaStack.with_top_pstate ~f:(fun pstate -> f ~pstate));
+ (Vernacstate.LemmaStack.with_top ~f:(fun pstate -> f ~pstate));
stack
(* Default proof mode, to be set at the beginning of proofs for
@@ -202,7 +202,7 @@ and interp_control ~st ({ CAst.v = cmd } as vernac) =
let before_univs = Global.universes () in
let pstack = interp_expr ~atts:cmd.attrs ~st cmd.expr in
if before_univs == Global.universes () then pstack
- else Option.map (Vernacstate.LemmaStack.map_top_pstate ~f:Declare.Proof.update_global_env) pstack)
+ else Option.map (Vernacstate.LemmaStack.map_top ~f:Declare.Proof.update_global_env) pstack)
~st
(* XXX: This won't properly set the proof mode, as of today, it is
@@ -213,21 +213,23 @@ and interp_control ~st ({ CAst.v = cmd } as vernac) =
*)
(* Interpreting a possibly delayed proof *)
-let interp_qed_delayed ~proof ~info ~st pe : Vernacstate.LemmaStack.t option =
+let interp_qed_delayed ~proof ~pinfo ~st pe : Vernacstate.LemmaStack.t option =
let stack = st.Vernacstate.lemmas in
let stack = Option.cata (fun stack -> snd @@ Vernacstate.LemmaStack.pop stack) None stack in
let () = match pe with
| Admitted ->
- Declare.save_lemma_admitted_delayed ~proof ~info
+ Declare.Proof.save_lemma_admitted_delayed ~proof ~pinfo
| Proved (_,idopt) ->
- Declare.save_lemma_proved_delayed ~proof ~info ~idopt in
+ let _ : _ list = Declare.Proof.save_lemma_proved_delayed ~proof ~pinfo ~idopt in
+ ()
+ in
stack
-let interp_qed_delayed_control ~proof ~info ~st ~control { CAst.loc; v=pe } =
+let interp_qed_delayed_control ~proof ~pinfo ~st ~control { CAst.loc; v=pe } =
let time_header = mk_time_header (CAst.make ?loc { control; attrs = []; expr = VernacEndProof pe }) in
List.fold_right (fun flag fn -> interp_control_flag ~time_header flag fn)
control
- (fun ~st -> interp_qed_delayed ~proof ~info ~st pe)
+ (fun ~st -> interp_qed_delayed ~proof ~pinfo ~st pe)
~st
(* General interp with management of state *)
@@ -257,6 +259,6 @@ let interp_gen ~verbosely ~st ~interp_fn cmd =
let interp ?(verbosely=true) ~st cmd =
interp_gen ~verbosely ~st ~interp_fn:interp_control cmd
-let interp_qed_delayed_proof ~proof ~info ~st ~control pe : Vernacstate.t =
+let interp_qed_delayed_proof ~proof ~pinfo ~st ~control pe : Vernacstate.t =
interp_gen ~verbosely:false ~st
- ~interp_fn:(interp_qed_delayed_control ~proof ~info ~control) pe
+ ~interp_fn:(interp_qed_delayed_control ~proof ~pinfo ~control) pe
diff --git a/vernac/vernacinterp.mli b/vernac/vernacinterp.mli
index e3e708e87d..84d3256c9f 100644
--- a/vernac/vernacinterp.mli
+++ b/vernac/vernacinterp.mli
@@ -14,8 +14,8 @@ val interp : ?verbosely:bool -> st:Vernacstate.t -> Vernacexpr.vernac_control ->
(** Execute a Qed but with a proof_object which may contain a delayed
proof and won't be forced *)
val interp_qed_delayed_proof
- : proof:Declare.proof_object
- -> info:Lemmas.Info.t
+ : proof:Declare.Proof.proof_object
+ -> pinfo:Declare.Proof.Proof_info.t
-> st:Vernacstate.t
-> control:Vernacexpr.control_flag list
-> Vernacexpr.proof_end CAst.t
diff --git a/vernac/vernacstate.ml b/vernac/vernacstate.ml
index 0fca1e9078..17c89897fe 100644
--- a/vernac/vernacstate.ml
+++ b/vernac/vernacstate.ml
@@ -26,18 +26,16 @@ end
module LemmaStack = struct
- type t = Lemmas.t * Lemmas.t list
+ type t = Declare.Proof.t * Declare.Proof.t list
let map f (pf, pfl) = (f pf, List.map f pfl)
-
- let map_top_pstate ~f (pf, pfl) = (Lemmas.pf_map f pf, pfl)
+ let map_top ~f (pf, pfl) = (f pf, pfl)
let pop (ps, p) = match p with
| [] -> ps, None
| pp :: p -> ps, Some (pp, p)
let with_top (p, _) ~f = f p
- let with_top_pstate (p, _) ~f = Lemmas.pf_fold f p
let push ontop a =
match ontop with
@@ -45,14 +43,14 @@ module LemmaStack = struct
| Some (l,ls) -> a, (l :: ls)
let get_all_proof_names (pf : t) =
- let prj x = Lemmas.pf_fold Declare.Proof.get_proof x in
+ let prj x = Declare.Proof.get x in
let (pn, pns) = map Proof.(function pf -> (data (prj pf)).name) pf in
pn :: pns
let copy_info src tgt =
- Lemmas.pf_map (fun _ -> Lemmas.pf_fold (fun x -> x) tgt) src
+ Declare.Proof.map ~f:(fun _ -> Declare.Proof.get tgt) src
- let copy_info ~src ~tgt =
+ let copy_info ~(src : t) ~(tgt : t) =
let (ps, psl), (ts,tsl) = src, tgt in
copy_info ps ts,
List.map2 (fun op p -> copy_info op p) psl tsl
@@ -111,7 +109,7 @@ module Declare = struct
let set x = s_lemmas := x
let get_pstate () =
- Option.map (LemmaStack.with_top ~f:(Lemmas.pf_fold (fun x -> x))) !s_lemmas
+ Option.map (LemmaStack.with_top ~f:(fun x -> x)) !s_lemmas
let freeze ~marshallable:_ = get ()
let unfreeze x = s_lemmas := Some x
@@ -125,15 +123,8 @@ module Declare = struct
| _ -> None
end
- open Lemmas
- open Declare
-
let cc f = match !s_lemmas with
| None -> raise NoCurrentProof
- | Some x -> LemmaStack.with_top_pstate ~f x
-
- let cc_lemma f = match !s_lemmas with
- | None -> raise NoCurrentProof
| Some x -> LemmaStack.with_top ~f x
let cc_stack f = match !s_lemmas with
@@ -142,43 +133,42 @@ module Declare = struct
let dd f = match !s_lemmas with
| None -> raise NoCurrentProof
- | Some x -> s_lemmas := Some (LemmaStack.map_top_pstate ~f x)
+ | Some x -> s_lemmas := Some (LemmaStack.map_top ~f x)
let there_are_pending_proofs () = !s_lemmas <> None
- let get_open_goals () = cc Proof.get_open_goals
+ let get_open_goals () = cc Declare.Proof.get_open_goals
- let give_me_the_proof_opt () = Option.map (LemmaStack.with_top_pstate ~f:Proof.get_proof) !s_lemmas
- let give_me_the_proof () = cc Proof.get_proof
- let get_current_proof_name () = cc Proof.get_proof_name
+ let give_me_the_proof_opt () = Option.map (LemmaStack.with_top ~f:Declare.Proof.get) !s_lemmas
+ let give_me_the_proof () = cc Declare.Proof.get
+ let get_current_proof_name () = cc Declare.Proof.get_name
- let map_proof f = dd (Proof.map_proof f)
+ let map_proof f = dd (Declare.Proof.map ~f)
let with_current_proof f =
match !s_lemmas with
| None -> raise NoCurrentProof
| Some stack ->
- let pf, res = LemmaStack.with_top_pstate stack ~f:(Proof.map_fold_proof_endline f) in
- let stack = LemmaStack.map_top_pstate stack ~f:(fun _ -> pf) in
+ let pf, res = LemmaStack.with_top stack ~f:(Declare.Proof.map_fold_endline ~f) in
+ let stack = LemmaStack.map_top stack ~f:(fun _ -> pf) in
s_lemmas := Some stack;
res
- type closed_proof = Declare.proof_object * Lemmas.Info.t
-
+ type closed_proof = Declare.Proof.proof_object * Declare.Proof.Proof_info.t
- let return_proof () = cc return_proof
- let return_partial_proof () = cc return_partial_proof
+ let return_proof () = cc Declare.Proof.return_proof
+ let return_partial_proof () = cc Declare.Proof.return_partial_proof
let close_future_proof ~feedback_id pf =
- cc_lemma (fun pt -> pf_fold (fun st -> close_future_proof ~feedback_id st pf) pt,
- Lemmas.Internal.get_info pt)
+ cc (fun pt -> Declare.Proof.close_future_proof ~feedback_id pt pf,
+ Declare.Proof.info pt)
let close_proof ~opaque ~keep_body_ucst_separate =
- cc_lemma (fun pt -> pf_fold ((close_proof ~opaque ~keep_body_ucst_separate)) pt,
- Lemmas.Internal.get_info pt)
+ cc (fun pt -> Declare.Proof.close_proof ~opaque ~keep_body_ucst_separate pt,
+ Declare.Proof.info pt)
let discard_all () = s_lemmas := None
- let update_global_env () = dd (Proof.update_global_env)
+ let update_global_env () = dd (Declare.Proof.update_global_env)
- let get_current_context () = cc Declare.get_current_context
+ let get_current_context () = cc Declare.Proof.get_current_context
let get_all_proof_names () =
try cc_stack LemmaStack.get_all_proof_names
diff --git a/vernac/vernacstate.mli b/vernac/vernacstate.mli
index fb6d8b6db6..c99db34873 100644
--- a/vernac/vernacstate.mli
+++ b/vernac/vernacstate.mli
@@ -22,11 +22,11 @@ module LemmaStack : sig
type t
- val pop : t -> Lemmas.t * t option
- val push : t option -> Lemmas.t -> t
+ val pop : t -> Declare.Proof.t * t option
+ val push : t option -> Declare.Proof.t -> t
- val map_top_pstate : f:(Declare.Proof.t -> Declare.Proof.t) -> t -> t
- val with_top_pstate : t -> f:(Declare.Proof.t -> 'a ) -> 'a
+ val map_top : f:(Declare.Proof.t -> Declare.Proof.t) -> t -> t
+ val with_top : t -> f:(Declare.Proof.t -> 'a ) -> 'a
end
@@ -65,16 +65,16 @@ module Declare : sig
val with_current_proof :
(unit Proofview.tactic -> Proof.t -> Proof.t * 'a) -> 'a
- val return_proof : unit -> Declare.closed_proof_output
- val return_partial_proof : unit -> Declare.closed_proof_output
+ val return_proof : unit -> Declare.Proof.closed_proof_output
+ val return_partial_proof : unit -> Declare.Proof.closed_proof_output
- type closed_proof = Declare.proof_object * Lemmas.Info.t
+ type closed_proof = Declare.Proof.proof_object * Declare.Proof.Proof_info.t
val close_future_proof :
feedback_id:Stateid.t ->
- Declare.closed_proof_output Future.computation -> closed_proof
+ Declare.Proof.closed_proof_output Future.computation -> closed_proof
- val close_proof : opaque:Declare.opacity_flag -> keep_body_ucst_separate:bool -> closed_proof
+ val close_proof : opaque:Vernacexpr.opacity_flag -> keep_body_ucst_separate:bool -> closed_proof
val discard_all : unit -> unit
val update_global_env : unit -> unit