aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--Makefile.ci2
-rw-r--r--Makefile.make3
-rw-r--r--coq.opam2
-rwxr-xr-xdev/ci/ci-fiat-crypto-legacy.sh4
-rwxr-xr-xdev/ci/ci-fiat-crypto.sh8
-rw-r--r--doc/changelog/04-tactics/11474-lia-bug-fix-11436.rst9
-rw-r--r--doc/changelog/09-coqide/11414-remove-ide-tactic-menu.rst4
-rw-r--r--doc/sphinx/addendum/micromega.rst6
-rw-r--r--doc/tools/coqrst/checkdeps.py20
-rw-r--r--engine/proofview.ml18
-rw-r--r--ide/coq_commands.ml195
-rw-r--r--ide/coq_commands.mli1
-rw-r--r--ide/coqide.ml9
-rw-r--r--ide/coqide_ui.ml4
-rw-r--r--ide/preferences.ml10
-rw-r--r--ide/preferences.mli1
-rw-r--r--interp/constrextern.ml327
-rw-r--r--interp/constrintern.ml2
-rw-r--r--kernel/float64.ml16
-rw-r--r--kernel/indTyping.ml14
-rw-r--r--kernel/safe_typing.ml12
-rw-r--r--kernel/safe_typing.mli6
-rw-r--r--kernel/type_errors.ml7
-rw-r--r--kernel/type_errors.mli12
-rw-r--r--library/global.mli4
-rw-r--r--plugins/extraction/extract_env.ml37
-rw-r--r--plugins/micromega/coq_micromega.ml30
-rw-r--r--plugins/micromega/coq_micromega.mli2
-rw-r--r--plugins/micromega/g_micromega.mlg7
-rw-r--r--plugins/micromega/simplex.ml142
-rw-r--r--plugins/micromega/simplex.mli14
-rw-r--r--pretyping/evarsolve.ml66
-rw-r--r--proofs/proof.ml15
-rw-r--r--proofs/proof_bullet.ml7
-rw-r--r--tactics/declare.ml74
-rw-r--r--tactics/pfedit.ml2
-rw-r--r--test-suite/bugs/closed/bug_5617.v8
-rw-r--r--test-suite/micromega/bug_11436.v19
-rw-r--r--test-suite/micromega/evars_loops_in_8_10_fixed_8_11.v4
-rw-r--r--test-suite/micromega/square.v10
-rw-r--r--test-suite/output/Notations4.out8
-rw-r--r--test-suite/output/Notations4.v26
-rw-r--r--test-suite/output/Notations5.out248
-rw-r--r--test-suite/output/Notations5.v340
-rw-r--r--toplevel/coqloop.ml10
-rw-r--r--vernac/himsg.ml10
-rw-r--r--vernac/metasyntax.ml61
-rw-r--r--vernac/vernacstate.ml2
49 files changed, 1254 insertions, 586 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 73b979c6a3..b39e74ffee 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -632,13 +632,11 @@ library:ci-fiat-crypto:
stage: stage-4
needs:
- build:edge+flambda
- - library:ci-bedrock2
- library:ci-coqprime
- plugin:ci-bignums
- plugin:ci-rewriter
dependencies:
- build:edge+flambda
- - library:ci-bedrock2
- library:ci-coqprime
- plugin:ci-rewriter
diff --git a/Makefile.ci b/Makefile.ci
index 4fc0e69748..10c3b027c3 100644
--- a/Makefile.ci
+++ b/Makefile.ci
@@ -65,7 +65,7 @@ ci-math-classes: ci-bignums
ci-corn: ci-math-classes
-ci-fiat-crypto: ci-bedrock2 ci-coqprime ci-rewriter
+ci-fiat-crypto: ci-coqprime ci-rewriter
ci-simple-io: ci-ext-lib
ci-quickchick: ci-ext-lib ci-simple-io
diff --git a/Makefile.make b/Makefile.make
index e19053462d..e63a578e37 100644
--- a/Makefile.make
+++ b/Makefile.make
@@ -56,6 +56,7 @@ FIND_SKIP_DIRS:=-not -name . '(' \
-name "$${GIT_DIR}" -o \
-name '_build' -o \
-name '_build_ci' -o \
+ -name '_build_boot' -o \
-name '_install_ci' -o \
-name 'gramlib' -o \
-name 'user-contrib' -o \
@@ -251,7 +252,7 @@ docclean:
rm -rf doc/sphinx/_build
archclean: clean-ide optclean voclean plugin-tutorialclean
- rm -rf _build
+ rm -rf _build _build_boot
rm -f $(ALLSTDLIB).*
optclean:
diff --git a/coq.opam b/coq.opam
index 50f746abec..39191c21d9 100644
--- a/coq.opam
+++ b/coq.opam
@@ -28,7 +28,7 @@ depends: [
]
build: [
- [ "./configure" "-prefix" prefix "-native-compiler" "no" ]
+ [ "./configure" "-prefix" prefix ]
[ "make" "-f" "Makefile.dune" "voboot" ]
[ "dune" "build" "-p" name "-j" jobs ]
]
diff --git a/dev/ci/ci-fiat-crypto-legacy.sh b/dev/ci/ci-fiat-crypto-legacy.sh
index 2af4b58201..9ce5da9f50 100755
--- a/dev/ci/ci-fiat-crypto-legacy.sh
+++ b/dev/ci/ci-fiat-crypto-legacy.sh
@@ -6,8 +6,8 @@ ci_dir="$(dirname "$0")"
FORCE_GIT=1
git_download fiat_crypto_legacy
-fiat_crypto_legacy_CI_TARGETS1="print-old-pipeline-lite old-pipeline-lite lite-display"
-fiat_crypto_legacy_CI_TARGETS2="print-old-pipeline-nobigmem old-pipeline-nobigmem nonautogenerated-specific nonautogenerated-specific-display"
+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"
( cd "${CI_BUILD_DIR}/fiat_crypto_legacy" && git submodule update --init --recursive && \
./etc/ci/remove_autogenerated.sh && \
diff --git a/dev/ci/ci-fiat-crypto.sh b/dev/ci/ci-fiat-crypto.sh
index 000c418137..811fefda35 100755
--- a/dev/ci/ci-fiat-crypto.sh
+++ b/dev/ci/ci-fiat-crypto.sh
@@ -9,11 +9,15 @@ git_download fiat_crypto
# We need a larger stack size to not overflow ocamlopt+flambda when
# building the executables.
# c.f. https://github.com/coq/coq/pull/8313#issuecomment-416650241
+fiat_crypto_CI_STACKSIZE=32768
-fiat_crypto_CI_MAKE_ARGS="EXTERNAL_DEPENDENCIES=1"
+# fiat-crypto is not guaranteed to build with the latest version of
+# bedrock2, so we use the pinned version of bedrock2, but the external
+# version of other developments
+fiat_crypto_CI_MAKE_ARGS="EXTERNAL_REWRITER=1 EXTERNAL_COQPRIME=1"
fiat_crypto_CI_TARGETS1="${fiat_crypto_CI_MAKE_ARGS} standalone-ocaml c-files rust-files printlite lite"
fiat_crypto_CI_TARGETS2="${fiat_crypto_CI_MAKE_ARGS} all"
( cd "${CI_BUILD_DIR}/fiat_crypto" && git submodule update --init --recursive && \
- ulimit -s 32768 && \
+ ulimit -s ${fiat_crypto_CI_STACKSIZE} && \
make ${fiat_crypto_CI_TARGETS1} && make -j 1 ${fiat_crypto_CI_TARGETS2} )
diff --git a/doc/changelog/04-tactics/11474-lia-bug-fix-11436.rst b/doc/changelog/04-tactics/11474-lia-bug-fix-11436.rst
new file mode 100644
index 0000000000..2a341261e5
--- /dev/null
+++ b/doc/changelog/04-tactics/11474-lia-bug-fix-11436.rst
@@ -0,0 +1,9 @@
+- **Added:**
+ :cmd:`Show Lia Profile` prints some statistics about :tacn:`lia` calls.
+ (`#11474 <https://github.com/coq/coq/pull/11474>`_, by Frédéric Besson).
+
+- **Fixed:**
+ Efficiency regression of ``lia``
+ (`#11474 <https://github.com/coq/coq/pull/11474>`_,
+ fixes `#11436 <https://github.com/coq/coq/issues/11436>`_,
+ by Frédéric Besson).
diff --git a/doc/changelog/09-coqide/11414-remove-ide-tactic-menu.rst b/doc/changelog/09-coqide/11414-remove-ide-tactic-menu.rst
new file mode 100644
index 0000000000..6294cdb24a
--- /dev/null
+++ b/doc/changelog/09-coqide/11414-remove-ide-tactic-menu.rst
@@ -0,0 +1,4 @@
+- **Removed:**
+ Removed the "Tactic" menu from CoqIDE which had been unmaintained for a number of years
+ (`#11414 <https://github.com/coq/coq/pull/11414>`_,
+ by Pierre-Marie Pédrot).
diff --git a/doc/sphinx/addendum/micromega.rst b/doc/sphinx/addendum/micromega.rst
index cc19c8b6a9..b0197c500c 100644
--- a/doc/sphinx/addendum/micromega.rst
+++ b/doc/sphinx/addendum/micromega.rst
@@ -35,6 +35,12 @@ tactics for solving arithmetic goals over :math:`\mathbb{Q}`,
use the Simplex method for solving linear goals. If it is not set,
the decision procedures are using Fourier elimination.
+.. cmd:: Show Lia Profile
+
+ This command prints some statistics about the amount of pivoting
+ operations needed by :tacn:`lia` and may be useful to detect
+ inefficiencies (only meaningful if flag :flag:`Simplex` is set).
+
.. flag:: Lia Cache
This flag (set by default) instructs :tacn:`lia` to cache its results in the file `.lia.cache`
diff --git a/doc/tools/coqrst/checkdeps.py b/doc/tools/coqrst/checkdeps.py
index 91f0a7cb1b..feafcba026 100644
--- a/doc/tools/coqrst/checkdeps.py
+++ b/doc/tools/coqrst/checkdeps.py
@@ -10,13 +10,20 @@
from __future__ import print_function
import sys
+missing_deps = []
+
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
def missing_dep(dep):
- eprint('Cannot find %s (needed to build documentation)' % dep)
- eprint('You can run `pip3 install %s` to install it.' % dep)
- sys.exit(1)
+ missing_deps.append(dep)
+
+def report_missing_deps():
+ if len(missing_deps) > 0:
+ deps = " ".join(missing_deps)
+ eprint('Cannot find package(s) `%s` (needed to build documentation)' % deps)
+ eprint('You can run `pip3 install %s` to install it/them.' % deps)
+ sys.exit(1)
try:
import sphinx_rtd_theme
@@ -37,3 +44,10 @@ try:
import bs4
except:
missing_dep('beautifulsoup4')
+
+try:
+ import sphinxcontrib.bibtex
+except:
+ missing_dep('sphinxcontrib-bibtex')
+
+report_missing_deps()
diff --git a/engine/proofview.ml b/engine/proofview.ml
index 16be96454e..b0ea75ac60 100644
--- a/engine/proofview.ml
+++ b/engine/proofview.ml
@@ -302,7 +302,8 @@ let tclONCE = Proof.once
exception MoreThanOneSuccess
let _ = CErrors.register_handler begin function
- | MoreThanOneSuccess -> CErrors.user_err Pp.(str "This tactic has more than one success.")
+ | MoreThanOneSuccess ->
+ Pp.str "This tactic has more than one success."
| _ -> raise CErrors.Unhandled
end
@@ -347,8 +348,7 @@ exception NoSuchGoals of int
let _ = CErrors.register_handler begin function
| NoSuchGoals n ->
- CErrors.user_err
- (str "No such " ++ str (String.plural n "goal") ++ str ".")
+ str "No such " ++ str (String.plural n "goal") ++ str "."
| _ -> raise CErrors.Unhandled
end
@@ -420,12 +420,9 @@ let tclFOCUSID ?(nosuchgoal=tclZERO (NoSuchGoals 1)) id t =
exception SizeMismatch of int*int
let _ = CErrors.register_handler begin function
| SizeMismatch (i,j) ->
- let open Pp in
- let errmsg =
- str"Incorrect number of goals" ++ spc() ++
- str"(expected "++int i++str(String.plural i " tactic") ++ str", was given "++ int j++str")."
- in
- CErrors.user_err errmsg
+ let open Pp in
+ str"Incorrect number of goals" ++ spc() ++
+ str"(expected "++int i++str(String.plural i " tactic") ++ str", was given "++ int j++str")."
| _ -> raise CErrors.Unhandled
end
@@ -910,7 +907,8 @@ let tclPROGRESS t =
tclZERO (CErrors.UserError (Some "Proofview.tclPROGRESS", Pp.str "Failed to progress."))
let _ = CErrors.register_handler begin function
- | Logic_monad.Tac_Timeout -> CErrors.user_err ~hdr:"Proofview.tclTIMEOUT" (Pp.str"Tactic timeout!")
+ | Logic_monad.Tac_Timeout ->
+ Pp.str "[Proofview.tclTIMEOUT] Tactic timeout!"
| _ -> raise CErrors.Unhandled
end
diff --git a/ide/coq_commands.ml b/ide/coq_commands.ml
index bfd99e7ce3..5b9ea17ba7 100644
--- a/ide/coq_commands.ml
+++ b/ide/coq_commands.ml
@@ -228,198 +228,3 @@ let state_preserving = [
"Test Printing Wildcard";
]
-
-
-let tactics =
- [
- [
- "abstract";
- "absurd";
- "apply";
- "apply __ with";
- "assert";
- "assert (__:__)";
- "assert (__:=__)";
- "assumption";
- "auto";
- "auto with";
- "autorewrite";
- ];
-
- [
- "case";
- "case __ with";
- "casetype";
- "cbv";
- "cbv in";
- "change";
- "change __ in";
- "clear";
- "clearbody";
- "cofix";
- "compare";
- "compute";
- "compute in";
- "congruence";
- "constructor";
- "constructor __ with";
- "contradiction";
- "cut";
- "cutrewrite";
- ];
-
- [
- "decide equality";
- "decompose";
- "decompose record";
- "decompose sum";
- "dependent inversion";
- "dependent inversion __ with";
- "dependent inversion__clear";
- "dependent inversion__clear __ with";
- "dependent rewrite ->";
- "dependent rewrite <-";
- "destruct";
- "discriminate";
- "do";
- "double induction";
- ];
-
- [
- "eapply";
- "eauto";
- "eauto with";
- "eexact";
- "elim";
- "elim __ using";
- "elim __ with";
- "elimtype";
- "exact";
- "exists";
- ];
-
- [
- "fail";
- "field";
- "first";
- "firstorder";
- "firstorder using";
- "firstorder with";
- "fix";
- "fix __ with";
- "fold";
- "fold __ in";
- "functional induction";
- ];
-
- [
- "generalize";
- "generalize dependent";
- ];
-
- [
- "hnf";
- ];
-
- [
- "idtac";
- "induction";
- "info";
- "injection";
- "instantiate (__:=__)";
- "intro";
- "intro after";
- "intro __ after";
- "intros";
- "intros until";
- "intuition";
- "inversion";
- "inversion __ in";
- "inversion __ using";
- "inversion __ using __ in";
- "inversion__clear";
- "inversion__clear __ in";
- ];
-
- [
- "jp <n>";
- "jp";
- ];
-
- [
- "lapply";
- "lazy";
- "lazy in";
- "left";
- ];
-
- [
- "move __ after";
- ];
-
- [
- "omega";
- ];
-
- [
- "pattern";
- "pose";
- "pose __:=__)";
- "progress";
- ];
-
- [
- "quote";
- ];
-
- [
- "red";
- "red in";
- "refine";
- "reflexivity";
- "rename __ into";
- "repeat";
- "replace __ with";
- "rewrite";
- "rewrite __ in";
- "rewrite <-";
- "rewrite <- __ in";
- "right";
- "ring";
- ];
-
- [
- "set";
- "set (__:=__)";
- "setoid__replace";
- "setoid__rewrite";
- "simpl";
- "simpl __ in";
- "simple destruct";
- "simple induction";
- "simple inversion";
- "simplify__eq";
- "solve";
- "split";
-(* "split__Rabs";
- "split__Rmult";
-*)
- "subst";
- "symmetry";
- "symmetry in";
- ];
-
- [
- "tauto";
- "transitivity";
- "trivial";
- "try";
- ];
-
- [
- "unfold";
- "unfold __ in";
- ];
-]
-
-
diff --git a/ide/coq_commands.mli b/ide/coq_commands.mli
index 5f8ce30901..c8c11f77af 100644
--- a/ide/coq_commands.mli
+++ b/ide/coq_commands.mli
@@ -8,6 +8,5 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
-val tactics : string list list
val commands : string list list
val state_preserving : string list
diff --git a/ide/coqide.ml b/ide/coqide.ml
index e0347d3c5f..ccf6d40b2b 100644
--- a/ide/coqide.ml
+++ b/ide/coqide.ml
@@ -977,7 +977,6 @@ let build_ui () =
let view_menu = GAction.action_group ~name:"View" () in
let export_menu = GAction.action_group ~name:"Export" () in
let navigation_menu = GAction.action_group ~name:"Navigation" () in
- let tactics_menu = GAction.action_group ~name:"Tactics" () in
let templates_menu = GAction.action_group ~name:"Templates" () in
let tools_menu = GAction.action_group ~name:"Tools" () in
let queries_menu = GAction.action_group ~name:"Queries" () in
@@ -985,7 +984,7 @@ let build_ui () =
let windows_menu = GAction.action_group ~name:"Windows" () in
let help_menu = GAction.action_group ~name:"Help" () in
let all_menus = [
- file_menu; edit_menu; view_menu; export_menu; navigation_menu; tactics_menu;
+ file_menu; edit_menu; view_menu; export_menu; navigation_menu;
templates_menu; tools_menu; queries_menu; compile_menu; windows_menu;
help_menu; ] in
@@ -1119,11 +1118,6 @@ let build_ui () =
("Force", "_Force", `EXECUTE, Nav.join_document, "Fully check the document", "f");
] end;
- menu tactics_menu [
- item "Tactics" ~label:"_Tactics";
- ];
- alpha_items tactics_menu "Tactic" Coq_commands.tactics;
-
menu templates_menu [
item "Templates" ~label:"Te_mplates";
template_item ("Lemma new_lemma : .\nProof.\n\nQed.\n", 6,9, "J");
@@ -1207,7 +1201,6 @@ let build_ui () =
Coqide_ui.ui_m#insert_action_group edit_menu 0;
Coqide_ui.ui_m#insert_action_group view_menu 0;
Coqide_ui.ui_m#insert_action_group navigation_menu 0;
- Coqide_ui.ui_m#insert_action_group tactics_menu 0;
Coqide_ui.ui_m#insert_action_group templates_menu 0;
Coqide_ui.ui_m#insert_action_group tools_menu 0;
Coqide_ui.ui_m#insert_action_group queries_menu 0;
diff --git a/ide/coqide_ui.ml b/ide/coqide_ui.ml
index 59dd9c0e4c..f22821c6ea 100644
--- a/ide/coqide_ui.ml
+++ b/ide/coqide_ui.ml
@@ -99,9 +99,6 @@ let init () =
\n <menuitem action='Previous' />\
\n <menuitem action='Next' />\
\n </menu>\
-\n <menu action='Tactics'>\
-\n %s\
-\n </menu>\
\n <menu action='Templates'>\
\n <menuitem action='Lemma' />\
\n <menuitem action='Theorem' />\
@@ -164,7 +161,6 @@ let init () =
\n</toolbar>\
\n</ui>"
(if Coq_config.gtk_platform <> `QUARTZ then "<menuitem action='Quit' />" else "")
- (Buffer.contents (list_items "Tactic" Coq_commands.tactics))
(Buffer.contents (list_items "Template" Coq_commands.commands))
(Buffer.contents (list_queries "User-Query" Preferences.user_queries#get))
in
diff --git a/ide/preferences.ml b/ide/preferences.ml
index d3cf08e90e..af1759b0bb 100644
--- a/ide/preferences.ml
+++ b/ide/preferences.ml
@@ -331,10 +331,6 @@ let modifier_for_navigation =
let modifier_for_templates =
new preference ~name:["modifier_for_templates"] ~init:"<Control><Shift>" ~repr:Repr.(string)
-let modifier_for_tactics =
- new preference ~name:["modifier_for_tactics"]
- ~init:(select_arch "<Control><Alt>" "<Control><Primary>") ~repr:Repr.(string)
-
let modifier_for_display =
new preference ~name:["modifier_for_display"]
~init:(select_arch "<Alt><Shift>" "<Primary><Shift>")~repr:Repr.(string)
@@ -347,7 +343,6 @@ let attach_modifiers_callback () =
(* To be done after the preferences are loaded *)
let _ = attach_modifiers modifier_for_navigation "<Actions>/Navigation/" in
let _ = attach_modifiers modifier_for_templates "<Actions>/Templates/" in
- let _ = attach_modifiers modifier_for_tactics "<Actions>/Tactics/" in
let _ = attach_modifiers modifier_for_display "<Actions>/View/" in
let _ = attach_modifiers modifier_for_queries "<Actions>/Queries/" in
()
@@ -951,9 +946,6 @@ let configure ?(apply=(fun () -> ())) parent =
(string_of_project_behavior read_project#get)
in
let project_file_name = pstring "Default name for project file" project_file_name in
- let modifier_for_tactics =
- pmodifiers "Global change of modifiers for Tactics Menu" modifier_for_tactics
- in
let modifier_for_templates =
pmodifiers "Global change of modifiers for Templates Menu" modifier_for_templates
in
@@ -1056,7 +1048,7 @@ let configure ?(apply=(fun () -> ())) parent =
[cmd_coqtop;cmd_coqc;cmd_make;cmd_coqmakefile; cmd_coqdoc;
cmd_print;cmd_editor;cmd_browse]);
Section("Shortcuts", Some `PREFERENCES,
- [modifiers_valid; modifier_for_tactics;
+ [modifiers_valid;
modifier_for_templates; modifier_for_display; modifier_for_navigation;
modifier_for_queries (*; user_queries *)]);
Section("Misc", Some `ADD,
diff --git a/ide/preferences.mli b/ide/preferences.mli
index 7b43079b4f..754f15c575 100644
--- a/ide/preferences.mli
+++ b/ide/preferences.mli
@@ -71,7 +71,6 @@ val automatic_tactics : string list preference
val cmd_print : string preference
val modifier_for_navigation : string preference
val modifier_for_templates : string preference
-val modifier_for_tactics : string preference
val modifier_for_display : string preference
val modifier_for_queries : string preference
val modifiers_valid : string preference
diff --git a/interp/constrextern.ml b/interp/constrextern.ml
index cc0c1e4602..c55e17e7a3 100644
--- a/interp/constrextern.ml
+++ b/interp/constrextern.ml
@@ -281,6 +281,17 @@ let get_extern_reference () = !my_extern_reference
let extern_reference ?loc vars l = !my_extern_reference vars l
(**********************************************************************)
+(* utilities *)
+
+let rec fill_arg_scopes args subscopes (entry,(_,scopes) as all) =
+ match args, subscopes with
+ | [], _ -> []
+ | a :: args, scopt :: subscopes ->
+ (a, (entry, (scopt, scopes))) :: fill_arg_scopes args subscopes all
+ | a :: args, [] ->
+ (a, (entry, (None, scopes))) :: fill_arg_scopes args [] all
+
+(**********************************************************************)
(* mapping patterns to cases_pattern_expr *)
let add_patt_for_params ind l =
@@ -550,14 +561,14 @@ let is_gvar id c = match DAst.get c with
| GVar id' -> Id.equal id id'
| _ -> false
-let is_projection nargs = function
- | Some r when not !Flags.in_debugger && not !Flags.raw_print && !print_projections ->
- (try
- let n = Recordops.find_projection_nparams r + 1 in
- if n <= nargs then Some n
- else None
- with Not_found -> None)
- | _ -> None
+let is_projection nargs r =
+ if not !Flags.in_debugger && not !Flags.raw_print && !print_projections then
+ try
+ let n = Recordops.find_projection_nparams r + 1 in
+ if n <= nargs then Some n
+ else None
+ with Not_found -> None
+ else None
let is_hole = function CHole _ | CEvar _ -> true | _ -> false
@@ -569,11 +580,12 @@ let is_needed_for_correct_partial_application tail imp =
exception Expl
-(* Implicit args indexes are in ascending order *)
-(* inctx is useful only if there is a last argument to be deduced from ctxt *)
-let explicitize inctx impl (cf,f) args =
- let impl = if !Constrintern.parsing_explicit then [] else impl in
- let n = List.length args in
+(* Take a list of arguments starting at position [q] and their implicit status *)
+(* Decide for each implicit argument if it skipped or made explicit *)
+(* If the removal of implicit arguments is not possible, raise [Expl] *)
+(* [inctx] tells if the term is in a context which will enforce the external type *)
+(* [n] is the total number of arguments block to which the [args] belong *)
+let adjust_implicit_arguments inctx n q args impl =
let rec exprec q = function
| a::args, imp::impl when is_status_implicit imp ->
let tail = exprec (q+1) (args,impl) in
@@ -595,10 +607,11 @@ let explicitize inctx impl (cf,f) args =
(* The non-explicit application cannot be parsed back with the same type *)
raise Expl
| [], _ -> []
- in
+ in exprec q (args,impl)
+
+let extern_projection (cf,f) args impl =
let ip = is_projection (List.length args) cf in
- let expl () =
- match ip with
+ match ip with
| Some i ->
(* Careful: It is possible to have declared implicits ending
before the principal argument *)
@@ -607,33 +620,61 @@ let explicitize inctx impl (cf,f) args =
with Failure _ -> false
in
if is_impl
- then raise Expl
+ then None
else
let (args1,args2) = List.chop i args in
let (impl1,impl2) = try List.chop i impl with Failure _ -> impl, [] in
- let args1 = exprec 1 (args1,impl1) in
- let args2 = exprec (i+1) (args2,impl2) in
- let ip = Some (List.length args1) in
- CApp ((ip,f),args1@args2)
- | None ->
- let args = exprec 1 (args,impl) in
- if List.is_empty args then f.CAst.v else
- match f.CAst.v with
- | CApp (g,args') ->
- (* may happen with notations for a prefix of an n-ary
- application *)
- CApp (g,args'@args)
- | _ -> CApp ((None, f), args) in
- try expl ()
- with Expl ->
- let f',us = match f with { CAst.v = CRef (f,us) } -> f,us | _ -> assert false in
- let ip = if !print_projections then ip else None in
- CAppExpl ((ip, f', us), List.map Lazy.force args)
+ Some (i,(args1,impl1),(args2,impl2))
+ | None -> None
let is_start_implicit = function
| imp :: _ -> is_status_implicit imp && maximal_insertion_of imp
| [] -> false
+let extern_record ref args =
+ try
+ if !Flags.raw_print then raise Exit;
+ let cstrsp = match ref with GlobRef.ConstructRef c -> c | _ -> raise Not_found in
+ let struc = Recordops.lookup_structure (fst cstrsp) in
+ if PrintingRecord.active (fst cstrsp) then
+ ()
+ else if PrintingConstructor.active (fst cstrsp) then
+ raise Exit
+ else if not (get_record_print ()) then
+ raise Exit;
+ let projs = struc.Recordops.s_PROJ in
+ let locals = struc.Recordops.s_PROJKIND in
+ let rec cut args n =
+ if Int.equal n 0 then args
+ else
+ match args with
+ | [] -> raise No_match
+ | _ :: t -> cut t (n - 1) in
+ let args = cut args struc.Recordops.s_EXPECTEDPARAM in
+ let rec ip projs locs args acc =
+ match projs with
+ | [] -> acc
+ | None :: q -> raise No_match
+ | Some c :: q ->
+ match locs with
+ | [] -> anomaly (Pp.str "projections corruption [Constrextern.extern].")
+ | { Recordops.pk_true_proj = false } :: locs' ->
+ (* we don't want to print locals *)
+ ip q locs' args acc
+ | { Recordops.pk_true_proj = true } :: locs' ->
+ match args with
+ | [] -> raise No_match
+ (* we give up since the constructor is not complete *)
+ | arg :: tail ->
+ let arg = Lazy.force arg in
+ let loc = arg.CAst.loc in
+ let ref = extern_reference ?loc Id.Set.empty (GlobRef.ConstRef c) in
+ ip q locs' tail ((ref, arg) :: acc)
+ in
+ Some (List.rev (ip projs locals args []))
+ with
+ | Not_found | No_match | Exit -> None
+
let extern_global impl f us =
if not !Constrintern.parsing_explicit && is_start_implicit impl
then
@@ -641,26 +682,63 @@ let extern_global impl f us =
else
CRef (f,us)
-let extern_app inctx impl (cf,f) us args =
- if List.is_empty args then
- (* If coming from a notation "Notation a := @b" *)
- CAppExpl ((None, f, us), [])
- else if not !Constrintern.parsing_explicit &&
- ((!Flags.raw_print ||
- (!print_implicits && not !print_implicits_explicit_args)) &&
- List.exists is_status_implicit impl)
- then
+(* Implicit args indexes are in ascending order *)
+(* inctx is useful only if there is a last argument to be deduced from ctxt *)
+let extern_applied_ref inctx impl (cf,f) us args =
+ let isproj = is_projection (List.length args) cf in
+ try
+ if not !Constrintern.parsing_explicit &&
+ ((!Flags.raw_print ||
+ (!print_implicits && not !print_implicits_explicit_args)) &&
+ List.exists is_status_implicit impl)
+ then raise Expl;
+ let impl = if !Constrintern.parsing_explicit then [] else impl in
+ let n = List.length args in
+ let ref = CRef (f,us) in
+ let f = CAst.make ref in
+ match extern_projection (cf,f) args impl with
+ (* Try a [t.(f args1) args2] projection-style notation *)
+ | Some (i,(args1,impl1),(args2,impl2)) ->
+ let args1 = adjust_implicit_arguments inctx n 1 args1 impl1 in
+ let args2 = adjust_implicit_arguments inctx n (i+1) args2 impl2 in
+ let ip = Some (List.length args1) in
+ CApp ((ip,f),args1@args2)
+ (* A normal application node with each individual implicit
+ arguments either dropped or made explicit *)
+ | None ->
+ let args = adjust_implicit_arguments inctx n 1 args impl in
+ if args = [] then ref else CApp ((None, f), args)
+ with Expl ->
+ (* A [@f args] node *)
let args = List.map Lazy.force args in
- CAppExpl ((is_projection (List.length args) cf,f,us), args)
- else
- explicitize inctx impl (cf, CAst.make @@ CRef (f,us)) args
+ let isproj = if !print_projections then isproj else None in
+ CAppExpl ((isproj,f,us), args)
-let rec fill_arg_scopes args subscopes (entry,(_,scopes) as all) = match args, subscopes with
-| [], _ -> []
-| a :: args, scopt :: subscopes ->
- (a, (entry, (scopt, scopes))) :: fill_arg_scopes args subscopes all
-| a :: args, [] ->
- (a, (entry, (None, scopes))) :: fill_arg_scopes args [] all
+let extern_applied_syntactic_definition n extraimpl (cf,f) syndefargs extraargs =
+ try
+ let syndefargs = List.map (fun a -> (a,None)) syndefargs in
+ let extraargs = adjust_implicit_arguments false (List.length extraargs) 1 extraargs extraimpl in
+ let args = syndefargs @ extraargs in
+ if args = [] then cf else CApp ((None, CAst.make cf), args)
+ with Expl ->
+ let args = syndefargs @ List.map Lazy.force extraargs in
+ CAppExpl ((None,f,None), args)
+
+let mkFlattenedCApp (head,args) =
+ match head.CAst.v with
+ | CApp (g,args') ->
+ (* may happen with notations for a prefix of an n-ary application *)
+ (* or after removal of a coercion to funclass *)
+ CApp (g,args'@args)
+ | _ ->
+ CApp ((None, head), args)
+
+let extern_applied_notation n impl f args =
+ if List.is_empty args then
+ f.CAst.v
+ else
+ let args = adjust_implicit_arguments false (List.length args) 1 args impl in
+ mkFlattenedCApp (f,args)
let extern_args extern env args =
let map (arg, argscopes) = lazy (extern argscopes env arg) in
@@ -838,56 +916,19 @@ let rec extern inctx scopes vars r =
| GRef (ref,us) ->
let subscopes = find_arguments_scope ref in
let args = fill_arg_scopes args subscopes scopes in
- begin
- try
- if !Flags.raw_print then raise Exit;
- let cstrsp = match ref with GlobRef.ConstructRef c -> c | _ -> raise Not_found in
- let struc = Recordops.lookup_structure (fst cstrsp) in
- if PrintingRecord.active (fst cstrsp) then
- ()
- else if PrintingConstructor.active (fst cstrsp) then
- raise Exit
- else if not (get_record_print ()) then
- raise Exit;
- let projs = struc.Recordops.s_PROJ in
- let locals = struc.Recordops.s_PROJKIND in
- let rec cut args n =
- if Int.equal n 0 then args
- else
- match args with
- | [] -> raise No_match
- | _ :: t -> cut t (n - 1) in
- let args = cut args struc.Recordops.s_EXPECTEDPARAM in
- let rec ip projs locs args acc =
- match projs with
- | [] -> acc
- | None :: q -> raise No_match
- | Some c :: q ->
- match locs with
- | [] -> anomaly (Pp.str "projections corruption [Constrextern.extern].")
- | { Recordops.pk_true_proj = false } :: locs' ->
- (* we don't want to print locals *)
- ip q locs' args acc
- | { Recordops.pk_true_proj = true } :: locs' ->
- match args with
- | [] -> raise No_match
- (* we give up since the constructor is not complete *)
- | (arg, scopes) :: tail ->
- let head = extern true scopes vars arg in
- ip q locs' tail ((extern_reference ?loc Id.Set.empty (GlobRef.ConstRef c), head) :: acc)
- in
- CRecord (List.rev (ip projs locals args []))
- with
- | Not_found | No_match | Exit ->
- let args = extern_args (extern true) vars args in
- extern_app inctx
- (select_stronger_impargs (implicits_of_global ref))
- (Some ref,extern_reference ?loc vars ref) (extern_universes us) args
- end
-
- | _ ->
- explicitize inctx [] (None,sub_extern false scopes vars f)
- (List.map (fun c -> lazy (sub_extern true scopes vars c)) args))
+ let args = extern_args (extern true) vars args in
+ (* Try a "{|...|}" record notation *)
+ (match extern_record ref args with
+ | Some l -> CRecord l
+ | None ->
+ (* Otherwise... *)
+ extern_applied_ref inctx
+ (select_stronger_impargs (implicits_of_global ref))
+ (ref,extern_reference ?loc vars ref) (extern_universes us) args)
+ | _ ->
+ let args = List.map (fun c -> (sub_extern true scopes vars c,None)) args in
+ let head = sub_extern false scopes vars f in
+ mkFlattenedCApp (head,args))
| GLetIn (na,b,t,c) ->
CLetIn (make ?loc na,sub_extern false scopes vars b,
@@ -1104,46 +1145,45 @@ and extern_notation (custom,scopes as allscopes) vars t rules =
let loc = Glob_ops.loc_of_glob_constr t in
try
if is_inactive_rule keyrule then raise No_match;
- (* Adjusts to the number of arguments expected by the notation *)
- let (t,args,argsscopes,argsimpls) = match DAst.get t ,n with
- | GApp (f,args), Some n
- when List.length args >= n ->
+ let f,args =
+ match DAst.get t with
+ | GApp (f,args) -> f,args
+ | _ -> t,[] in
+ let nallargs = List.length args in
+ let argsscopes,argsimpls =
+ match DAst.get f with
+ | GRef (ref,_) ->
+ let subscopes = find_arguments_scope ref in
+ let impls = select_impargs_size nallargs (implicits_of_global ref) in
+ subscopes, impls
+ | _ ->
+ [], [] in
+ (* Adjust to the number of arguments expected by the notation *)
+ let (t,args,argsscopes,argsimpls) = match n with
+ | Some n when nallargs >= n && nallargs > 0 ->
let args1, args2 = List.chop n args in
- let subscopes, impls =
- match DAst.get f with
- | GRef (ref,us) ->
- let subscopes =
- try List.skipn n (find_arguments_scope ref)
- with Failure _ -> [] in
- let impls =
- let impls =
- select_impargs_size
- (List.length args) (implicits_of_global ref) in
- try List.skipn n impls with Failure _ -> [] in
- subscopes,impls
- | _ ->
- [], [] in
+ let args2scopes = try List.skipn n argsscopes with Failure _ -> [] in
+ let args2impls = try List.skipn n argsimpls with Failure _ -> [] in
+ (* Note: NApp(NRef f,[]), hence n=0, encodes @f *)
(if Int.equal n 0 then f else DAst.make @@ GApp (f,args1)),
- args2, subscopes, impls
- | GApp (f, args), None ->
+ args2, args2scopes, args2impls
+ | None when nallargs > 0 ->
begin match DAst.get f with
- | GRef (ref,us) ->
- let subscopes = find_arguments_scope ref in
- let impls =
- select_impargs_size
- (List.length args) (implicits_of_global ref) in
- f, args, subscopes, impls
+ | GRef (ref,us) -> f, args, argsscopes, argsimpls
| _ -> t, [], [], []
end
- | GRef (ref,us), Some 0 -> DAst.make @@ GApp (t,[]), [], [], []
- | _, None -> t, [], [], []
+ | Some 0 when nallargs = 0 ->
+ begin match DAst.get f with
+ | GRef (ref,us) -> DAst.make @@ GApp (t,[]), [], [], []
+ | _ -> t, [], [], []
+ end
+ | None -> t, [], [], []
| _ -> raise No_match in
(* Try matching ... *)
let terms,termlists,binders,binderlists =
match_notation_constr !print_universes t pat in
(* Try availability of interpretation ... *)
- let e =
- match keyrule with
+ match keyrule with
| NotationRule (sc,ntn) ->
(match availability_of_entry_coercion custom (fst ntn) with
| None -> raise No_match
@@ -1171,22 +1211,25 @@ and extern_notation (custom,scopes as allscopes) vars t rules =
List.map (fun (bl,(subentry,(scopt,scl))) ->
pi3 (extern_local_binder (subentry,(scopt,scl@scopes')) vars bl))
binderlists in
- insert_coercion coercion (insert_delimiters (make_notation loc ntn (l,ll,bl,bll)) key))
+ let c = make_notation loc ntn (l,ll,bl,bll) in
+ let c = insert_coercion coercion (insert_delimiters c key) in
+ let args = fill_arg_scopes args argsscopes allscopes in
+ let args = extern_args (extern true) vars args in
+ CAst.make ?loc @@ extern_applied_notation nallargs argsimpls c args)
| SynDefRule kn ->
match availability_of_entry_coercion custom InConstrEntrySomeLevel with
| None -> raise No_match
| Some coercion ->
let l =
List.map (fun (c,(subentry,(scopt,scl))) ->
- extern true (subentry,(scopt,scl@snd scopes)) vars c, None)
+ extern true (subentry,(scopt,scl@snd scopes)) vars c)
terms in
- let a = CRef (Nametab.shortest_qualid_of_syndef ?loc vars kn,None) in
- insert_coercion coercion (CAst.make ?loc @@ if List.is_empty l then a else CApp ((None, CAst.make a),l)) in
- if List.is_empty args then e
- else
- let args = fill_arg_scopes args argsscopes allscopes in
- let args = extern_args (extern true) vars args in
- CAst.make ?loc @@ explicitize false argsimpls (None,e) args
+ let cf = Nametab.shortest_qualid_of_syndef ?loc vars kn in
+ let a = CRef (cf,None) in
+ let args = fill_arg_scopes args argsscopes allscopes in
+ let args = extern_args (extern true) vars args in
+ let c = CAst.make ?loc @@ extern_applied_syntactic_definition nallargs argsimpls (a,cf) l args in
+ insert_coercion coercion c
with
No_match -> extern_notation allscopes vars t rules
diff --git a/interp/constrintern.ml b/interp/constrintern.ml
index c699f79351..f4ae5bf676 100644
--- a/interp/constrintern.ml
+++ b/interp/constrintern.ml
@@ -1643,7 +1643,7 @@ let drop_notations_pattern looked_for genv =
| Some (a,b,c) -> DAst.make ?loc @@ RCPatCstr(a, b, c)
| None -> raise (InternalizationError (loc,NotAConstructor head))
end
- | CPatCstr (qid, Some expl_pl, pl) ->
+ | CPatCstr (qid, Some expl_pl, pl) ->
let g = try Nametab.locate qid
with Not_found ->
raise (InternalizationError (loc,NotAConstructor qid)) in
diff --git a/kernel/float64.ml b/kernel/float64.ml
index 3e36373b77..cc661aeba3 100644
--- a/kernel/float64.ml
+++ b/kernel/float64.ml
@@ -12,7 +12,10 @@
format *)
type t = float
-let is_nan f = f <> f
+(* The [f : float] type annotation enable the compiler to compile f <> f
+ as comparison on floats rather than the polymorphic OCaml comparison
+ which is much slower. *)
+let is_nan (f : float) = f <> f
let is_infinity f = f = infinity
let is_neg_infinity f = f = neg_infinity
@@ -42,19 +45,20 @@ let abs = abs_float
type float_comparison = FEq | FLt | FGt | FNotComparable
-let eq x y = x = y
+(* See above comment on [is_nan] for the [float] type annotations. *)
+let eq (x : float) (y : float) = x = y
[@@ocaml.inline always]
-let lt x y = x < y
+let lt (x : float) (y : float) = x < y
[@@ocaml.inline always]
-let le x y = x <= y
+let le (x : float) (y : float) = x <= y
[@@ocaml.inline always]
(* inspired by lib/util.ml; see also #10471 *)
-let pervasives_compare = compare
+let pervasives_compare (x : float) (y : float) = compare x y
-let compare x y =
+let compare (x : float) (y : float) =
if x < y then FLt
else
(
diff --git a/kernel/indTyping.ml b/kernel/indTyping.ml
index 591cd050a5..719eb276df 100644
--- a/kernel/indTyping.ml
+++ b/kernel/indTyping.ml
@@ -66,7 +66,9 @@ let mind_check_names mie =
type univ_info = { ind_squashed : bool; ind_has_relevant_arg : bool;
ind_min_univ : Universe.t option; (* Some for template *)
- ind_univ : Universe.t }
+ ind_univ : Universe.t;
+ missing : Universe.Set.t; (* missing u <= ind_univ constraints *)
+ }
let check_univ_leq ?(is_real_arg=false) env u info =
let ind_univ = info.ind_univ in
@@ -78,9 +80,8 @@ let check_univ_leq ?(is_real_arg=false) env u info =
if type_in_type env || Univ.Universe.is_sprop u || UGraph.check_leq (universes env) u ind_univ
then { info with ind_min_univ = Option.map (Universe.sup u) info.ind_min_univ }
else if is_impredicative_univ env ind_univ
- then if Option.is_empty info.ind_min_univ then { info with ind_squashed = true }
- else raise (InductiveError BadUnivs)
- else raise (InductiveError BadUnivs)
+ && Option.is_empty info.ind_min_univ then { info with ind_squashed = true }
+ else {info with missing = Universe.Set.add u info.missing}
let check_context_univs ~ctor env info ctx =
let check_one d (info,env) =
@@ -109,6 +110,7 @@ let check_arity env_params env_ar ind =
ind_has_relevant_arg=false;
ind_min_univ;
ind_univ=Sorts.univ_of_sort ind_sort;
+ missing=Universe.Set.empty;
}
in
let univ_info = check_indices_matter env_params univ_info indices in
@@ -174,7 +176,7 @@ let check_record data =
(* - all_sorts in case of small, unitary Prop (not smashed) *)
(* - logical_sorts in case of large, unitary Prop (smashed) *)
-let allowed_sorts {ind_squashed;ind_univ;ind_min_univ=_;ind_has_relevant_arg=_} =
+let allowed_sorts {ind_squashed;ind_univ;ind_min_univ=_;ind_has_relevant_arg=_;missing=_} =
if not ind_squashed then InType
else Sorts.family (Sorts.sort_of_univ ind_univ)
@@ -224,6 +226,8 @@ let template_polymorphic_univs ~template_check ~ctor_levels uctx paramsctxt conc
params, univs
let abstract_packets ~template_check univs usubst params ((arity,lc),(indices,splayed_lc),univ_info) =
+ if not (Universe.Set.is_empty univ_info.missing)
+ then raise (InductiveError (MissingConstraints (univ_info.missing,univ_info.ind_univ)));
let arity = Vars.subst_univs_level_constr usubst arity in
let lc = Array.map (Vars.subst_univs_level_constr usubst) lc in
let indices = Vars.subst_univs_level_context usubst indices in
diff --git a/kernel/safe_typing.ml b/kernel/safe_typing.ml
index f6f2058c13..8db8a044a8 100644
--- a/kernel/safe_typing.ml
+++ b/kernel/safe_typing.ml
@@ -321,6 +321,8 @@ let universes_of_private eff =
let env_of_safe_env senv = senv.env
let env_of_senv = env_of_safe_env
+let structure_body_of_safe_env env = env.revstruct
+
let sections_of_safe_env senv = senv.sections
let get_section = function
@@ -757,7 +759,7 @@ let translate_direct_opaque env kn ce =
let () = assert (is_empty_private u) in
{ cb with const_body = OpaqueDef c }
-let export_side_effects mb env (b_ctx, eff) =
+let export_side_effects mb env eff =
let not_exists e = not (Environ.mem_constant e.seff_constant env) in
let aux (acc,sl) e =
if not (not_exists e) then acc, sl
@@ -774,7 +776,7 @@ let export_side_effects mb env (b_ctx, eff) =
in
let rec translate_seff sl seff acc env =
match seff with
- | [] -> List.rev acc, b_ctx
+ | [] -> List.rev acc
| eff :: rest ->
if Int.equal sl 0 then
let env, cb =
@@ -803,8 +805,8 @@ let push_opaque_proof pf senv =
let senv = { senv with env = Environ.set_opaque_tables senv.env otab } in
senv, o
-let export_private_constants ce senv =
- let exported, ce = export_side_effects senv.revstruct senv.env ce in
+let export_private_constants eff senv =
+ let exported = export_side_effects senv.revstruct senv.env eff in
let map senv (kn, c) = match c.const_body with
| OpaqueDef p ->
let local = empty_private c.const_universes in
@@ -817,7 +819,7 @@ let export_private_constants ce senv =
let exported = List.map (fun (kn, _) -> kn) exported in
(* No delayed constants to declare *)
let senv = List.fold_left add_constant_aux senv bodies in
- (ce, exported), senv
+ exported, senv
let add_constant l decl senv =
let kn = Constant.make2 senv.modpath l in
diff --git a/kernel/safe_typing.mli b/kernel/safe_typing.mli
index 92bbd264fa..e472dfd5e5 100644
--- a/kernel/safe_typing.mli
+++ b/kernel/safe_typing.mli
@@ -37,6 +37,8 @@ val env_of_safe_env : safe_environment -> Environ.env
val sections_of_safe_env : safe_environment -> section_data Section.t option
+val structure_body_of_safe_env : safe_environment -> Declarations.structure_body
+
(** The safe_environment state monad *)
type safe_transformer0 = safe_environment -> safe_environment
@@ -84,8 +86,8 @@ type side_effect_declaration =
type exported_private_constant = Constant.t
val export_private_constants :
- private_constants Entries.proof_output ->
- (Constr.constr Univ.in_universe_context_set * exported_private_constant list) safe_transformer
+ private_constants ->
+ exported_private_constant list safe_transformer
(** returns the main constant *)
val add_constant :
diff --git a/kernel/type_errors.ml b/kernel/type_errors.ml
index f221ac7a4f..c2cdf98ee8 100644
--- a/kernel/type_errors.ml
+++ b/kernel/type_errors.ml
@@ -12,6 +12,7 @@ open Names
open Constr
open Environ
open Reduction
+open Univ
(* Type errors. *)
@@ -63,8 +64,8 @@ type ('constr, 'types) ptype_error =
| IllFormedRecBody of 'constr pguard_error * Name.t Context.binder_annot array * int * env * ('constr, 'types) punsafe_judgment array
| IllTypedRecBody of
int * Name.t Context.binder_annot array * ('constr, 'types) punsafe_judgment array * 'types array
- | UnsatisfiedConstraints of Univ.Constraint.t
- | UndeclaredUniverse of Univ.Level.t
+ | UnsatisfiedConstraints of Constraint.t
+ | UndeclaredUniverse of Level.t
| DisallowedSProp
| BadRelevance
@@ -83,7 +84,7 @@ type inductive_error =
| NotAnArity of env * constr
| BadEntry
| LargeNonPropInductiveNotInType
- | BadUnivs
+ | MissingConstraints of (Universe.Set.t * Universe.t)
exception InductiveError of inductive_error
diff --git a/kernel/type_errors.mli b/kernel/type_errors.mli
index ae6fd31762..0f29717f12 100644
--- a/kernel/type_errors.mli
+++ b/kernel/type_errors.mli
@@ -11,6 +11,7 @@
open Names
open Constr
open Environ
+open Univ
(** Type errors. {% \label{typeerrors} %} *)
@@ -64,8 +65,8 @@ type ('constr, 'types) ptype_error =
| IllFormedRecBody of 'constr pguard_error * Name.t Context.binder_annot array * int * env * ('constr, 'types) punsafe_judgment array
| IllTypedRecBody of
int * Name.t Context.binder_annot array * ('constr, 'types) punsafe_judgment array * 'types array
- | UnsatisfiedConstraints of Univ.Constraint.t
- | UndeclaredUniverse of Univ.Level.t
+ | UnsatisfiedConstraints of Constraint.t
+ | UndeclaredUniverse of Level.t
| DisallowedSProp
| BadRelevance
@@ -86,7 +87,8 @@ type inductive_error =
| NotAnArity of env * constr
| BadEntry
| LargeNonPropInductiveNotInType
- | BadUnivs
+ | MissingConstraints of (Universe.Set.t * Universe.t)
+ (* each universe in the set should have been <= the other one *)
exception InductiveError of inductive_error
@@ -133,9 +135,9 @@ val error_ill_typed_rec_body :
val error_elim_explain : Sorts.family -> Sorts.family -> arity_error
-val error_unsatisfied_constraints : env -> Univ.Constraint.t -> 'a
+val error_unsatisfied_constraints : env -> Constraint.t -> 'a
-val error_undeclared_universe : env -> Univ.Level.t -> 'a
+val error_undeclared_universe : env -> Level.t -> 'a
val error_disallowed_sprop : env -> 'a
diff --git a/library/global.mli b/library/global.mli
index a38fde41a5..b6bd69c17c 100644
--- a/library/global.mli
+++ b/library/global.mli
@@ -47,8 +47,8 @@ val push_named_def : (Id.t * Entries.section_def_entry) -> unit
val push_section_context : (Name.t array * Univ.UContext.t) -> unit
val export_private_constants :
- Safe_typing.private_constants Entries.proof_output ->
- Constr.constr Univ.in_universe_context_set * Safe_typing.exported_private_constant list
+ Safe_typing.private_constants ->
+ Safe_typing.exported_private_constant list
val add_constant :
Id.t -> Safe_typing.global_declaration -> Constant.t
diff --git a/plugins/extraction/extract_env.ml b/plugins/extraction/extract_env.ml
index 2dc3e8a934..853be82eb8 100644
--- a/plugins/extraction/extract_env.ml
+++ b/plugins/extraction/extract_env.ml
@@ -26,43 +26,8 @@ open Common
(*S Part I: computing Coq environment. *)
(***************************************)
-(* FIXME: this is a Libobject hack that should be removed. *)
-module DynHandle = Libobject.Dyn.Map(struct type 'a t = 'a -> (Label.t * structure_field_body) option end)
-
-let handle h (Libobject.Dyn.Dyn (tag, o)) = match DynHandle.find tag h with
-| f -> f o
-| exception Not_found -> None
-
let toplevel_env () =
- let get_reference = function
- | (_,kn), Lib.Leaf Libobject.AtomicObject o ->
- let mp,l = KerName.repr kn in
- let handler =
- DynHandle.add Declare.Internal.objConstant begin fun _ ->
- let constant = Global.lookup_constant (Constant.make1 kn) in
- Some (l, SFBconst constant)
- end @@
- DynHandle.add DeclareInd.Internal.objInductive begin fun _ ->
- let inductive = Global.lookup_mind (MutInd.make1 kn) in
- Some (l, SFBmind inductive)
- end @@
- DynHandle.empty
- in
- handle handler o
- | (_,kn), Lib.Leaf Libobject.ModuleObject _ ->
- let mp,l = KerName.repr kn in
- let modl = Global.lookup_module (MPdot (mp, l)) in
- Some (l, SFBmodule modl)
- | (_,kn), Lib.Leaf Libobject.ModuleTypeObject _ ->
- let mp,l = KerName.repr kn in
- let modtype = Global.lookup_modtype (MPdot (mp, l)) in
- Some (l, SFBmodtype modtype)
- | (_,kn), Lib.Leaf Libobject.IncludeObject _ ->
- user_err Pp.(str "No extraction of toplevel Include yet.")
- | _ -> None
- in
- List.rev (List.map_filter get_reference (Lib.contents ()))
-
+ List.rev (Safe_typing.structure_body_of_safe_env (Global.safe_env ()))
let environment_until dir_opt =
let rec parse = function
diff --git a/plugins/micromega/coq_micromega.ml b/plugins/micromega/coq_micromega.ml
index 92a2222cfa..cdadde8621 100644
--- a/plugins/micromega/coq_micromega.ml
+++ b/plugins/micromega/coq_micromega.ml
@@ -2416,6 +2416,36 @@ let nqa =
(fun _ x -> x)
Mc.cnfQ qq_domain_spec dump_qexpr nlinear_prover_R
+let print_lia_profile () =
+ Simplex.(
+ let { number_of_successes
+ ; number_of_failures
+ ; success_pivots
+ ; failure_pivots
+ ; average_pivots
+ ; maximum_pivots } =
+ Simplex.get_profile_info ()
+ in
+ Feedback.msg_notice
+ Pp.(
+ (* successes *)
+ str "number of successes: "
+ ++ int number_of_successes ++ fnl ()
+ (* success pivots *)
+ ++ str "number of success pivots: "
+ ++ int success_pivots ++ fnl ()
+ (* failure *)
+ ++ str "number of failures: "
+ ++ int number_of_failures ++ fnl ()
+ (* failure pivots *)
+ ++ str "number of failure pivots: "
+ ++ int failure_pivots ++ fnl ()
+ (* Other *)
+ ++ str "average number of pivots: "
+ ++ int average_pivots ++ fnl ()
+ ++ str "maximum number of pivots: "
+ ++ int maximum_pivots ++ fnl ()))
+
(* Local Variables: *)
(* coding: utf-8 *)
(* End: *)
diff --git a/plugins/micromega/coq_micromega.mli b/plugins/micromega/coq_micromega.mli
index 37ea560241..bcfc47357f 100644
--- a/plugins/micromega/coq_micromega.mli
+++ b/plugins/micromega/coq_micromega.mli
@@ -8,7 +8,6 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
-(*val is_ground_tac : EConstr.constr -> unit Proofview.tactic*)
val psatz_Z : int -> unit Proofview.tactic -> unit Proofview.tactic
val psatz_Q : int -> unit Proofview.tactic -> unit Proofview.tactic
val psatz_R : int -> unit Proofview.tactic -> unit Proofview.tactic
@@ -21,6 +20,7 @@ val sos_Q : unit Proofview.tactic -> unit Proofview.tactic
val sos_R : unit Proofview.tactic -> unit Proofview.tactic
val lra_Q : unit Proofview.tactic -> unit Proofview.tactic
val lra_R : unit Proofview.tactic -> unit Proofview.tactic
+val print_lia_profile : unit -> unit
(** {5 Use Micromega independently from tactics. } *)
diff --git a/plugins/micromega/g_micromega.mlg b/plugins/micromega/g_micromega.mlg
index edf8106f30..d0f70bceac 100644
--- a/plugins/micromega/g_micromega.mlg
+++ b/plugins/micromega/g_micromega.mlg
@@ -28,10 +28,6 @@ open Tacarg
DECLARE PLUGIN "micromega_plugin"
-TACTIC EXTEND RED
-| [ "myred" ] -> { Tactics.red_in_concl }
-END
-
TACTIC EXTEND PsatzZ
| [ "psatz_Z" int_or_var(i) tactic(t) ] -> { (Coq_micromega.psatz_Z i
(Tacinterp.tactic_of_value ist t))
@@ -87,3 +83,6 @@ TACTIC EXTEND PsatzQ
| [ "psatz_Q" tactic(t) ] -> { (Coq_micromega.psatz_Q (-1) (Tacinterp.tactic_of_value ist t)) }
END
+VERNAC COMMAND EXTEND ShowLiaProfile CLASSIFIED AS QUERY
+| [ "Show" "Lia" "Profile" ] -> { Coq_micromega.print_lia_profile () }
+END
diff --git a/plugins/micromega/simplex.ml b/plugins/micromega/simplex.ml
index ade8143f3c..54976221bc 100644
--- a/plugins/micromega/simplex.ml
+++ b/plugins/micromega/simplex.ml
@@ -18,6 +18,49 @@ type ('a, 'b) sum = Inl of 'a | Inr of 'b
let debug = false
+(** Exploiting profiling information *)
+
+let profile_info = ref []
+let nb_pivot = ref 0
+
+type profile_info =
+ { number_of_successes : int
+ ; number_of_failures : int
+ ; success_pivots : int
+ ; failure_pivots : int
+ ; average_pivots : int
+ ; maximum_pivots : int }
+
+let init_profile =
+ { number_of_successes = 0
+ ; number_of_failures = 0
+ ; success_pivots = 0
+ ; failure_pivots = 0
+ ; average_pivots = 0
+ ; maximum_pivots = 0 }
+
+let get_profile_info () =
+ let update_profile
+ { number_of_successes
+ ; number_of_failures
+ ; success_pivots
+ ; failure_pivots
+ ; average_pivots
+ ; maximum_pivots } (b, i) =
+ { number_of_successes = (number_of_successes + if b then 1 else 0)
+ ; number_of_failures = (number_of_failures + if b then 0 else 1)
+ ; success_pivots = (success_pivots + if b then i else 0)
+ ; failure_pivots = (failure_pivots + if b then 0 else i)
+ ; average_pivots = average_pivots + 1 (* number of proofs *)
+ ; maximum_pivots = max maximum_pivots i }
+ in
+ let p = List.fold_left update_profile init_profile !profile_info in
+ profile_info := [];
+ { p with
+ average_pivots =
+ ( try (p.success_pivots + p.failure_pivots) / p.average_pivots
+ with Division_by_zero -> 0 ) }
+
type iset = unit IMap.t
type tableau = Vect.t IMap.t
@@ -60,10 +103,7 @@ let output_tableau o t =
t
let output_env o t =
- IMap.iter
- (fun k v ->
- Printf.fprintf o "%a : %a\n" LinPoly.pp_var k WithProof.output v)
- t
+ IMap.iter (fun k v -> Printf.fprintf o "%i : %a\n" k WithProof.output v) t
let output_vars o m =
IMap.iter (fun k _ -> Printf.fprintf o "%a " LinPoly.pp_var k) m
@@ -224,6 +264,7 @@ let pivot_with (m : tableau) (v : var) (p : Vect.t) =
IMap.map (fun (r : Vect.t) -> pivot_row r v p) m
let pivot (m : tableau) (r : var) (c : var) =
+ incr nb_pivot;
let row = safe_find "pivot" r m in
let piv = solve_column c r row in
IMap.add c piv (pivot_with (IMap.remove r m) c piv)
@@ -477,8 +518,11 @@ let make_farkas_proof (env : WithProof.t IMap.t) vm v =
try
let x', b = IMap.find x vm in
let n = if b then n else Num.minus_num n in
- WithProof.mult (Vect.cst n) (IMap.find x' env)
- with Not_found -> WithProof.mult (Vect.cst n) (IMap.find x env)
+ let prf = IMap.find x' env in
+ WithProof.mult (Vect.cst n) prf
+ with Not_found ->
+ let prf = IMap.find x env in
+ WithProof.mult (Vect.cst n) prf
end)
WithProof.zero v
@@ -493,21 +537,43 @@ type ('a, 'b) hitkind =
let cut env rmin sol vm (rst : Restricted.t) tbl (x, v) =
let n, r = Vect.decomp_cst v in
- let f = frac_num n in
- if f =/ Int 0 then Forget (* The solution is integral *)
+ let fn = frac_num n in
+ if fn =/ Int 0 then Forget (* The solution is integral *)
else
- (* This is potentially a cut *)
- let t =
- if f </ Int 1 // Int 2 then
- let t' = Int 1 // f in
- if Num.is_integer_num t' then t' -/ Int 1 else Num.floor_num t'
- else Int 1
- in
- let cut_coeff1 v =
+ (* The cut construction is from:
+ Letchford and Lodi. Strengthening Chvatal-Gomory cuts and Gomory fractional cuts.
+
+ We implement the classic Proposition 2 from the "known results"
+ *)
+
+ (* Proposition 3 requires all the variables to be restricted and is
+ therefore not always applicable. *)
+ (* let ccoeff_prop1 v = frac_num v in
+ let ccoeff_prop3 v =
+ (* mixed integer cut *)
let fv = frac_num v in
- if fv <=/ Int 1 -/ f then fv // (Int 1 -/ f) else (Int 1 -/ fv) // f
+ Num.min_num fv (fn */ (Int 1 -/ fv) // (Int 1 -/ fn))
in
- let cut_coeff2 v = frac_num (t */ v) in
+ let ccoeff_prop3 =
+ if Restricted.is_restricted x rst then ("Prop3", ccoeff_prop3)
+ else ("Prop1", ccoeff_prop1)
+ in *)
+ let n0_5 = Int 1 // Int 2 in
+ (* If the fractional part [fn] is small, we construct the t-cut.
+ If the fractional part [fn] is big, we construct the t-cut of the negated row.
+ (This is only a cut if all the fractional variables are restricted.)
+ *)
+ let ccoeff_prop2 =
+ let tmin =
+ if fn </ n0_5 then (* t-cut *)
+ Num.ceiling_num (n0_5 // fn)
+ else
+ (* multiply by -1 & t-cut *)
+ minus_num (Num.ceiling_num (n0_5 // (Int 1 -/ fn)))
+ in
+ ("Prop2", fun v -> frac_num (v */ tmin))
+ in
+ let ccoeff = ccoeff_prop2 in
let cut_vector ccoeff =
Vect.fold
(fun acc x n ->
@@ -516,35 +582,31 @@ let cut env rmin sol vm (rst : Restricted.t) tbl (x, v) =
Vect.null r
in
let lcut =
- List.map
- (fun cv -> Vect.normalise (cut_vector cv))
- [cut_coeff1; cut_coeff2]
+ ( fst ccoeff
+ , make_farkas_proof env vm (Vect.normalise (cut_vector (snd ccoeff))) )
in
- let lcut = List.map (make_farkas_proof env vm) lcut in
- let check_cutting_plane c =
+ let check_cutting_plane (p, c) =
match WithProof.cutting_plane c with
| None ->
if debug then
- Printf.printf "This is not a cutting plane for %a\n%a:" LinPoly.pp_var
- x WithProof.output c;
+ Printf.printf "%s: This is not a cutting plane for %a\n%a:" p
+ LinPoly.pp_var x WithProof.output c;
None
| Some (v, prf) ->
if debug then (
- Printf.printf "This is a cutting plane for %a:" LinPoly.pp_var x;
+ Printf.printf "%s: This is a cutting plane for %a:" p LinPoly.pp_var x;
Printf.printf " %a\n" WithProof.output (v, prf) );
- if snd v = Eq then (* Unsat *) Some (x, (v, prf))
- else
- let vl = Vect.dotproduct (fst v) (Vect.set 0 (Int 1) sol) in
- if eval_op Ge vl (Int 0) then (
- if debug then
- Printf.printf "The cut is feasible %s >= 0 \n"
- (Num.string_of_num vl);
- None )
- else Some (x, (v, prf))
+ Some (x, (v, prf))
in
- match find_some check_cutting_plane lcut with
+ match check_cutting_plane lcut with
| Some r -> Hit r
- | None -> Keep (x, v)
+ | None ->
+ let has_unrestricted =
+ Vect.fold
+ (fun acc v vl -> acc || not (Restricted.is_restricted v rst))
+ false r
+ in
+ if has_unrestricted then Keep (x, v) else Forget
let merge_result_old oldr f x =
match oldr with
@@ -681,12 +743,16 @@ let integer_solver lp =
isolve env None vr res
let integer_solver lp =
+ nb_pivot := 0;
if debug then
Printf.printf "Input integer solver\n%a\n" WithProof.output_sys
(List.map WithProof.of_cstr lp);
match integer_solver lp with
- | None -> None
+ | None ->
+ profile_info := (false, !nb_pivot) :: !profile_info;
+ None
| Some prf ->
+ profile_info := (true, !nb_pivot) :: !profile_info;
if debug then
Printf.fprintf stdout "Proof %a\n" ProofFormat.output_proof prf;
Some prf
diff --git a/plugins/micromega/simplex.mli b/plugins/micromega/simplex.mli
index 19bcce3590..ff672edafd 100644
--- a/plugins/micromega/simplex.mli
+++ b/plugins/micromega/simplex.mli
@@ -9,6 +9,20 @@
(************************************************************************)
open Polynomial
+(** Profiling *)
+
+type profile_info =
+ { number_of_successes : int
+ ; number_of_failures : int
+ ; success_pivots : int
+ ; failure_pivots : int
+ ; average_pivots : int
+ ; maximum_pivots : int }
+
+val get_profile_info : unit -> profile_info
+
+(** Simplex interface *)
+
val optimise : Vect.t -> cstr list -> (Num.num option * Num.num option) option
val find_point : cstr list -> Vect.t option
val find_unsat_certificate : cstr list -> Vect.t option
diff --git a/pretyping/evarsolve.ml b/pretyping/evarsolve.ml
index b54a713a16..aafd662f7d 100644
--- a/pretyping/evarsolve.ml
+++ b/pretyping/evarsolve.ml
@@ -311,21 +311,47 @@ let eq_alias a b = match a, b with
| VarAlias id1, VarAlias id2 -> Id.equal id1 id2
| _ -> false
-type aliasing = EConstr.t option * alias list
+type 'a aliasing = 'a option * alias list
let empty_aliasing = None, []
let make_aliasing c = Some c, []
let push_alias (alias, l) a = (alias, a :: l)
+
+module Alias =
+struct
+type t = { mutable lift : int; mutable data : EConstr.t }
+
+let make c = { lift = 0; data = c }
+
+let lift n { lift; data } = { lift = lift + n; data }
+
+let eval alias =
+ let c = EConstr.Vars.lift alias.lift alias.data in
+ let () = alias.lift <- 0 in
+ let () = alias.data <- c in
+ c
+
+let repr sigma alias = match EConstr.kind sigma alias.data with
+| Rel n -> Some (RelAlias (n + alias.lift))
+| Var id -> Some (VarAlias id)
+| _ -> None
+
+end
+
let lift_aliasing n (alias, l) =
let map a = match a with
| VarAlias _ -> a
| RelAlias m -> RelAlias (m + n)
in
- (Option.map (fun c -> lift n c) alias, List.map map l)
+ (Option.map (fun c -> Alias.lift n c) alias, List.map map l)
+
+let cast_aliasing (alias, l) = match alias with
+| None -> (None, l)
+| Some c -> (Some (Alias.make c), l)
type aliases = {
- rel_aliases : aliasing Int.Map.t;
- var_aliases : aliasing Id.Map.t;
+ rel_aliases : Alias.t aliasing Int.Map.t;
+ var_aliases : EConstr.t aliasing Id.Map.t;
(** Only contains [VarAlias] *)
}
@@ -359,13 +385,14 @@ let compute_rel_aliases var_aliases rels sigma =
| Var id' ->
let aliases_of_n =
try Id.Map.find id' var_aliases with Not_found -> empty_aliasing in
- Int.Map.add n (push_alias aliases_of_n (VarAlias id')) aliases
+ Int.Map.add n (push_alias (cast_aliasing aliases_of_n) (VarAlias id')) aliases
| Rel p ->
let aliases_of_n =
try Int.Map.find (p+n) aliases with Not_found -> empty_aliasing in
Int.Map.add n (push_alias aliases_of_n (RelAlias (p+n))) aliases
| _ ->
- Int.Map.add n (make_aliasing (lift n (mkCast(t,DEFAULTcast,u)))) aliases)
+ let alias = Alias.lift n (Alias.make @@ mkCast(t,DEFAULTcast, u)) in
+ Int.Map.add n (make_aliasing alias) aliases)
| LocalAssum _ -> aliases)
)
rels
@@ -387,7 +414,7 @@ let lift_aliases n aliases =
let get_alias_chain_of sigma aliases x = match x with
| RelAlias n -> (try Int.Map.find n aliases.rel_aliases with Not_found -> empty_aliasing)
- | VarAlias id -> (try Id.Map.find id aliases.var_aliases with Not_found -> empty_aliasing)
+ | VarAlias id -> (try cast_aliasing (Id.Map.find id aliases.var_aliases) with Not_found -> empty_aliasing)
let normalize_alias_opt_alias sigma aliases x =
match get_alias_chain_of sigma aliases x with
@@ -420,13 +447,14 @@ let extend_alias sigma decl { var_aliases; rel_aliases } =
| Var id' ->
let aliases_of_binder =
try Id.Map.find id' var_aliases with Not_found -> empty_aliasing in
- Int.Map.add 1 (push_alias aliases_of_binder (VarAlias id')) rel_aliases
+ Int.Map.add 1 (push_alias (cast_aliasing aliases_of_binder) (VarAlias id')) rel_aliases
| Rel p ->
let aliases_of_binder =
try Int.Map.find (p+1) rel_aliases with Not_found -> empty_aliasing in
Int.Map.add 1 (push_alias aliases_of_binder (RelAlias (p+1))) rel_aliases
| _ ->
- Int.Map.add 1 (make_aliasing (lift 1 t)) rel_aliases)
+ let alias = Alias.lift 1 (Alias.make t) in
+ Int.Map.add 1 (make_aliasing alias) rel_aliases)
| LocalAssum _ -> rel_aliases in
{ var_aliases; rel_aliases }
@@ -434,7 +462,7 @@ let expand_alias_once sigma aliases x =
match get_alias_chain_of sigma aliases x with
| None, [] -> None
| Some a, [] -> Some a
- | _, l -> Some (of_alias (List.last l))
+ | _, l -> Some (Alias.make (of_alias (List.last l)))
let expansions_of_var sigma aliases x =
let (_, l) = get_alias_chain_of sigma aliases x in
@@ -442,9 +470,9 @@ let expansions_of_var sigma aliases x =
let expansion_of_var sigma aliases x =
match get_alias_chain_of sigma aliases x with
- | None, [] -> (false, of_alias x)
- | Some a, _ -> (true, a)
- | None, a :: _ -> (true, of_alias a)
+ | None, [] -> (false, Some x)
+ | Some a, _ -> (true, Alias.repr sigma a)
+ | None, a :: _ -> (true, Some a)
let rec expand_vars_in_term_using sigma aliases t = match EConstr.kind sigma t with
| Rel n -> of_alias (normalize_alias sigma aliases (RelAlias n))
@@ -482,10 +510,10 @@ let free_vars_and_rels_up_alias_expansion env sigma aliases c =
match ck with
| VarAlias id -> acc4 := Id.Set.add id !acc4
| RelAlias n -> if n >= depth+1 then acc3 := Int.Set.add (n-depth) !acc3);
- match EConstr.kind sigma c' with
- | Var id -> acc2 := Id.Set.add id !acc2
- | Rel n -> if n >= depth+1 then acc1 := Int.Set.add (n-depth) !acc1
- | _ -> frec (aliases,depth) c end
+ match c' with
+ | Some (VarAlias id) -> acc2 := Id.Set.add id !acc2
+ | Some (RelAlias n) -> if n >= depth+1 then acc1 := Int.Set.add (n-depth) !acc1
+ | None -> frec (aliases,depth) c end
| Const _ | Ind _ | Construct _ ->
acc2 := Id.Set.union (vars_of_global env (fst @@ EConstr.destRef sigma c)) !acc2
| _ ->
@@ -971,7 +999,7 @@ let invert_arg_from_subst evd aliases k0 subst_in_env_extended_with_k_binders c_
with Not_found ->
match expand_alias_once evd aliases t with
| None -> raise Not_found
- | Some c -> aux k (lift k c) in
+ | Some c -> aux k (Alias.eval (Alias.lift k c)) in
try
let c = aux 0 c_in_env_extended_with_k_binders in
Invertible (UniqueProjection (c,!effects))
@@ -1223,7 +1251,7 @@ let rec is_constrainable_in top env evd k (ev,(fv_rels,fv_ids) as g) t =
let has_constrainable_free_vars env evd aliases force k ev (fv_rels,fv_ids,let_rels,let_ids) t =
match to_alias evd t with
| Some t ->
- let expanded, t' = expansion_of_var evd aliases t in
+ let expanded, _ = expansion_of_var evd aliases t in
if expanded then
(* t is a local definition, we keep it only if appears in the list *)
(* of let-in variables effectively occurring on the right-hand side, *)
diff --git a/proofs/proof.ml b/proofs/proof.ml
index 5ab4409f8b..e2ee5426b5 100644
--- a/proofs/proof.ml
+++ b/proofs/proof.ml
@@ -69,18 +69,15 @@ exception FullyUnfocused
let _ = CErrors.register_handler begin function
| CannotUnfocusThisWay ->
- CErrors.user_err Pp.(str "This proof is focused, but cannot be unfocused this way")
+ Pp.str "This proof is focused, but cannot be unfocused this way"
| NoSuchGoals (i,j) when Int.equal i j ->
- CErrors.user_err ~hdr:"Focus" Pp.(str"No such goal (" ++ int i ++ str").")
+ Pp.(str "[Focus] No such goal (" ++ int i ++ str").")
| NoSuchGoals (i,j) ->
- CErrors.user_err ~hdr:"Focus" Pp.(
- str"Not every goal in range ["++ int i ++ str","++int j++str"] exist."
- )
+ Pp.(str "[Focus] Not every goal in range ["++ int i ++ str","++int j++str"] exist.")
| NoSuchGoal id ->
- CErrors.user_err
- ~hdr:"Focus"
- Pp.(str "No such goal: " ++ str (Names.Id.to_string id) ++ str ".")
- | FullyUnfocused -> CErrors.user_err Pp.(str "The proof is not focused")
+ Pp.(str "[Focus] No such goal: " ++ str (Names.Id.to_string id) ++ str ".")
+ | FullyUnfocused ->
+ Pp.str "The proof is not focused"
| _ -> raise CErrors.Unhandled
end
diff --git a/proofs/proof_bullet.ml b/proofs/proof_bullet.ml
index 66e2ae5c29..61e8741973 100644
--- a/proofs/proof_bullet.ml
+++ b/proofs/proof_bullet.ml
@@ -79,7 +79,7 @@ module Strict = struct
(function
| FailedBullet (b,sugg) ->
let prefix = Pp.(str"Wrong bullet " ++ pr_bullet b ++ str": ") in
- CErrors.user_err ~hdr:"Focus" Pp.(prefix ++ suggest_on_error sugg)
+ Pp.(str "[Focus]" ++ spc () ++ prefix ++ suggest_on_error sugg)
| _ -> raise CErrors.Unhandled)
@@ -204,8 +204,7 @@ exception SuggestNoSuchGoals of int * Proof.t
let _ = CErrors.register_handler begin function
| SuggestNoSuchGoals(n,proof) ->
let suffix = suggest proof in
- CErrors.user_err
- Pp.(str "No such " ++ str (CString.plural n "goal") ++ str "." ++
- pr_non_empty_arg (fun x -> x) suffix)
+ Pp.(str "No such " ++ str (CString.plural n "goal") ++ str "." ++
+ pr_non_empty_arg (fun x -> x) suffix)
| _ -> raise CErrors.Unhandled
end
diff --git a/tactics/declare.ml b/tactics/declare.ml
index c7581fb0e0..ce2f3ec2c5 100644
--- a/tactics/declare.ml
+++ b/tactics/declare.ml
@@ -160,6 +160,18 @@ let register_side_effect (c, role) =
| None -> ()
| Some (Evd.Schema (ind, kind)) -> DeclareScheme.declare_scheme kind [|ind,c|]
+let get_roles export eff =
+ let map c =
+ let role = try Some (Cmap.find c eff.Evd.seff_roles) with Not_found -> None in
+ (c, role)
+ in
+ List.map map export
+
+let export_side_effects eff =
+ let export = Global.export_private_constants eff.Evd.seff_private in
+ let export = get_roles export eff in
+ List.iter register_side_effect export
+
let record_aux env s_ty s_bo =
let open Environ in
let in_ty = keep_hyps env s_ty in
@@ -278,13 +290,6 @@ let cast_opaque_proof_entry (type a b) (entry : (a, b) effect_entry) (e : a proo
opaque_entry_universes = univs;
}
-let get_roles export eff =
- let map c =
- let role = try Some (Cmap.find c eff.Evd.seff_roles) with Not_found -> None in
- (c, role)
- in
- List.map map export
-
let feedback_axiom () = Feedback.(feedback AddedAxiom)
let is_unsafe_typing_flags () =
@@ -293,37 +298,36 @@ let is_unsafe_typing_flags () =
let define_constant ~name cd =
(* Logically define the constant and its subproofs, no libobject tampering *)
- let export, decl, unsafe = match cd with
- | DefinitionEntry de ->
- (* We deal with side effects *)
- if not de.proof_entry_opaque then
- (* This globally defines the side-effects in the environment. *)
- let body, eff = Future.force de.proof_entry_body in
- let body, export = Global.export_private_constants (body, eff.Evd.seff_private) in
- let export = get_roles export eff in
- let de = { de with proof_entry_body = Future.from_val (body, ()) } in
- let cd = Entries.DefinitionEntry (cast_proof_entry de) in
- export, ConstantEntry cd, false
- else
- let map (body, eff) = body, eff.Evd.seff_private in
- let body = Future.chain de.proof_entry_body map in
- let de = { de with proof_entry_body = body } in
- let de = cast_opaque_proof_entry EffectEntry de in
- [], OpaqueEntry de, false
- | ParameterEntry e ->
- [], ConstantEntry (Entries.ParameterEntry e), not (Lib.is_modtype_strict())
- | PrimitiveEntry e ->
- [], ConstantEntry (Entries.PrimitiveEntry e), false
+ let decl, unsafe = match cd with
+ | DefinitionEntry de ->
+ (* We deal with side effects *)
+ if not de.proof_entry_opaque then
+ let body, eff = Future.force de.proof_entry_body in
+ (* This globally defines the side-effects in the environment
+ and registers their libobjects. *)
+ let () = export_side_effects eff in
+ let de = { de with proof_entry_body = Future.from_val (body, ()) } in
+ let cd = Entries.DefinitionEntry (cast_proof_entry de) in
+ ConstantEntry cd, false
+ else
+ let map (body, eff) = body, eff.Evd.seff_private in
+ let body = Future.chain de.proof_entry_body map in
+ let de = { de with proof_entry_body = body } in
+ let de = cast_opaque_proof_entry EffectEntry de in
+ OpaqueEntry de, false
+ | ParameterEntry e ->
+ ConstantEntry (Entries.ParameterEntry e), not (Lib.is_modtype_strict())
+ | PrimitiveEntry e ->
+ ConstantEntry (Entries.PrimitiveEntry e), false
in
let kn = Global.add_constant name decl in
if unsafe || is_unsafe_typing_flags() then feedback_axiom();
- kn, export
+ kn
let declare_constant ?(local = ImportDefaultBehavior) ~name ~kind cd =
let () = check_exists name in
- let kn, export = define_constant ~name cd in
- (* Register the libobjects attached to the constants and its subproofs *)
- let () = List.iter register_side_effect export in
+ let kn = define_constant ~name cd in
+ (* Register the libobjects attached to the constants *)
let () = register_constant kn kind local in
kn
@@ -377,10 +381,8 @@ let declare_variable ~name ~kind d =
| SectionLocalDef (de) ->
(* The body should already have been forced upstream because it is a
section-local definition, but it's not enforced by typing *)
- let (body, eff) = Future.force de.proof_entry_body in
- let ((body, uctx), export) = Global.export_private_constants (body, eff.Evd.seff_private) in
- let eff = get_roles export eff in
- let () = List.iter register_side_effect eff in
+ let ((body, uctx), eff) = Future.force de.proof_entry_body in
+ let () = export_side_effects eff in
let poly, univs = match de.proof_entry_universes with
| Monomorphic_entry uctx -> false, uctx
| Polymorphic_entry (_, uctx) -> true, Univ.ContextSet.of_context uctx
diff --git a/tactics/pfedit.ml b/tactics/pfedit.ml
index 3c9803432a..a4a06873b8 100644
--- a/tactics/pfedit.ml
+++ b/tactics/pfedit.ml
@@ -27,7 +27,7 @@ let use_unification_heuristics () = !use_unification_heuristics_ref
exception NoSuchGoal
let () = CErrors.register_handler begin function
- | NoSuchGoal -> CErrors.user_err Pp.(str "No such goal.")
+ | NoSuchGoal -> Pp.(str "No such goal.")
| _ -> raise CErrors.Unhandled
end
diff --git a/test-suite/bugs/closed/bug_5617.v b/test-suite/bugs/closed/bug_5617.v
new file mode 100644
index 0000000000..c18e79295c
--- /dev/null
+++ b/test-suite/bugs/closed/bug_5617.v
@@ -0,0 +1,8 @@
+Set Primitive Projections.
+Record T X := { F : X }.
+
+Fixpoint f (n : nat) : nat :=
+match n with
+| 0 => 0
+| S m => F _ {| F := f |} m
+end.
diff --git a/test-suite/micromega/bug_11436.v b/test-suite/micromega/bug_11436.v
new file mode 100644
index 0000000000..fc6ccbb233
--- /dev/null
+++ b/test-suite/micromega/bug_11436.v
@@ -0,0 +1,19 @@
+Require Import ZArith Lia.
+Local Open Scope Z_scope.
+
+Unset Lia Cache.
+
+Goal forall a q q0 q1 r r0 r1: Z,
+ 0 <= a < 2 ^ 64 ->
+ r1 = 4 * q + r ->
+ 0 <= r < 4 ->
+ a = 4 * q0 + r0 ->
+ 0 <= r0 < 4 ->
+ a + 4 = 2 ^ 64 * q1 + r1 ->
+ 0 <= r1 < 2 ^ 64 ->
+ r = r0.
+Proof.
+ intros.
+ (* subst. *)
+ Time lia.
+Qed.
diff --git a/test-suite/micromega/evars_loops_in_8_10_fixed_8_11.v b/test-suite/micromega/evars_loops_in_8_10_fixed_8_11.v
new file mode 100644
index 0000000000..a53c160e45
--- /dev/null
+++ b/test-suite/micromega/evars_loops_in_8_10_fixed_8_11.v
@@ -0,0 +1,4 @@
+Require Import Lia.
+Goal forall n (B: n >= 0), exists Goal1 Goal2 Goal3,
+ (0 * (Goal1 * Goal2 + Goal1) <> Goal3 * 0 * (Goal1 * S Goal2)).
+Proof. eexists _, _, _. Fail lia. Abort.
diff --git a/test-suite/micromega/square.v b/test-suite/micromega/square.v
index 9efb81a901..36b4243ef8 100644
--- a/test-suite/micromega/square.v
+++ b/test-suite/micromega/square.v
@@ -11,15 +11,14 @@ Open Scope Z_scope.
Lemma Zabs_square : forall x, (Z.abs x)^2 = x^2.
Proof.
- intros ; case (Zabs_dec x) ; intros ; nia.
+ intros ; nia.
Qed.
-Hint Resolve Z.abs_nonneg Zabs_square.
Lemma integer_statement : ~exists n, exists p, n^2 = 2*p^2 /\ n <> 0.
Proof.
intros [n [p [Heq Hnz]]]; pose (n' := Z.abs n); pose (p':=Z.abs p).
assert (facts : 0 <= Z.abs n /\ 0 <= Z.abs p /\ Z.abs n^2=n^2
- /\ Z.abs p^2 = p^2) by auto.
+ /\ Z.abs p^2 = p^2) by auto using Z.abs_nonneg, Zabs_square.
assert (H : (0 < n' /\ 0 <= p' /\ n' ^2 = 2* p' ^2)) by
(destruct facts as [Hf1 [Hf2 [Hf3 Hf4]]]; unfold n', p' ; nia).
generalize p' H; elim n' using (well_founded_ind (Zwf_well_founded 0)); clear.
@@ -45,10 +44,7 @@ Proof.
intros.
destruct x.
simpl.
- unfold Z.pow_pos.
- simpl.
- rewrite Pos.mul_1_r.
- reflexivity.
+ lia.
Qed.
Theorem sqrt2_not_rational : ~exists x:Q, x^2==2#1.
diff --git a/test-suite/output/Notations4.out b/test-suite/output/Notations4.out
index 799d310fa7..43f88f42a5 100644
--- a/test-suite/output/Notations4.out
+++ b/test-suite/output/Notations4.out
@@ -63,3 +63,11 @@ fun '{| |} => true
: R -> bool
b = a
: Prop
+The command has indeed failed with message:
+The format is not the same on the right- and left-hand sides of the special token "..".
+The command has indeed failed with message:
+The format is not the same on the right- and left-hand sides of the special token "..".
+The command has indeed failed with message:
+The format is not the same on the right- and left-hand sides of the special token "..".
+The command has indeed failed with message:
+The format is not the same on the right- and left-hand sides of the special token "..".
diff --git a/test-suite/output/Notations4.v b/test-suite/output/Notations4.v
index 26c7840a16..4de6ce19b4 100644
--- a/test-suite/output/Notations4.v
+++ b/test-suite/output/Notations4.v
@@ -158,3 +158,29 @@ Check b = a.
End Test.
End L.
+
+Module M.
+
+(* Accept boxes around the end variables of a recursive notation (if equal boxes) *)
+
+Notation " {@ T1 ; T2 ; .. ; Tn } " :=
+ (and T1 (and T2 .. (and Tn True)..))
+ (format "'[v' {@ '[' T1 ']' ; '//' '[' T2 ']' ; '//' .. ; '//' '[' Tn ']' } ']'").
+
+Fail Notation " {@ T1 ; T2 ; .. ; Tn } " :=
+ (and T1 (and T2 .. (and Tn True)..))
+ (format "'[v' {@ '[' T1 ']' ; '//' '[' T2 ']' ; '//' .. ; '//' '[' Tn ']' } ']'").
+
+Fail Notation " {@ T1 ; T2 ; .. ; Tn } " :=
+ (and T1 (and T2 .. (and Tn True)..))
+ (format "'[v' {@ '[' T1 ']' ; '//' '[' T2 ']' ; '//' .. ; '//' '[v' Tn ']' } ']'").
+
+Fail Notation " {@ T1 ; T2 ; .. ; Tn } " :=
+ (and T1 (and T2 .. (and Tn True)..))
+ (format "'[v' {@ '[' T1 ']' ; '//' '[' T2 ']' ; '//' .. ; '//' '[' Tn ']' } ']'").
+
+Fail Notation " {@ T1 ; T2 ; .. ; Tn } " :=
+ (and T1 (and T2 .. (and Tn True)..))
+ (format "'[v' {@ '[' T1 ']' ; '//' '[' T2 ']' ; '//' .. ; '//' '[' Tn ']' } ']'").
+
+End M.
diff --git a/test-suite/output/Notations5.out b/test-suite/output/Notations5.out
new file mode 100644
index 0000000000..83dd2f40fb
--- /dev/null
+++ b/test-suite/output/Notations5.out
@@ -0,0 +1,248 @@
+p 0 0 true
+ : 0 = 0 /\ true = true
+p 0 0
+ : forall b : ?B, 0 = 0 /\ b = b
+where
+?B : [ |- Type]
+p 0
+ : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b
+p 0 0 (B:=bool)
+ : forall b : bool, 0 = 0 /\ b = b
+p 0 0 (B:=bool)
+ : forall b : bool, 0 = 0 /\ b = b
+p (A:=nat)
+ : forall (a1 a2 : nat) (B : Type) (b : B), a1 = a2 /\ b = b
+p (A:=nat)
+ : forall (a1 a2 : nat) (B : Type) (b : B), a1 = a2 /\ b = b
+@p nat 0 0
+ : forall (B : Type) (b : B), 0 = 0 /\ b = b
+@p
+ : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b
+p 0 0
+ : forall b : bool, 0 = 0 /\ b = b
+p
+ : forall (a1 a2 : nat) (B : Type) (b : B), a1 = a2 /\ b = b
+p 0 0 true
+ : 0 = 0 /\ true = true
+p 0 0
+ : forall b : ?B, 0 = 0 /\ b = b
+where
+?B : [ |- Type]
+p 0
+ : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b
+p 0 0
+ : forall b : bool, 0 = 0 /\ b = b
+p 0 0
+ : forall b : bool, 0 = 0 /\ b = b
+p
+ : forall (a1 a2 : nat) (B : Type) (b : B), a1 = a2 /\ b = b
+p
+ : forall (a1 a2 : nat) (B : Type) (b : B), a1 = a2 /\ b = b
+@p nat 0 0
+ : forall (B : Type) (b : B), 0 = 0 /\ b = b
+@p
+ : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b
+f x true
+ : 0 = 0 /\ true = true
+f x (B:=bool)
+ : forall b : bool, 0 = 0 /\ b = b
+f x (B:=bool)
+ : forall b : bool, 0 = 0 /\ b = b
+@f nat
+ : forall a1 a2 : nat,
+ T a1 a2 -> forall (B : Type) (b : B), a1 = a2 /\ b = b
+f (a1:=0) (a2:=0)
+ : T 0 0 -> forall (B : Type) (b : B), 0 = 0 /\ b = b
+f (a1:=0) (a2:=0)
+ : T 0 0 -> forall (B : Type) (b : B), 0 = 0 /\ b = b
+@f
+ : forall (A : Type) (a1 a2 : A),
+ T a1 a2 -> forall (B : Type) (b : B), a1 = a2 /\ b = b
+f
+ : T 0 0 -> forall (B : Type) (b : B), 0 = 0 /\ b = b
+x.(f) true
+ : 0 = 0 /\ true = true
+x.(f) (B:=bool)
+ : forall b : bool, 0 = 0 /\ b = b
+x.(f) (B:=bool)
+ : forall b : bool, 0 = 0 /\ b = b
+@f nat
+ : forall a1 a2 : nat,
+ T a1 a2 -> forall (B : Type) (b : B), a1 = a2 /\ b = b
+f (a1:=0) (a2:=0)
+ : T 0 0 -> forall (B : Type) (b : B), 0 = 0 /\ b = b
+f (a1:=0) (a2:=0)
+ : T 0 0 -> forall (B : Type) (b : B), 0 = 0 /\ b = b
+@f
+ : forall (A : Type) (a1 a2 : A),
+ T a1 a2 -> forall (B : Type) (b : B), a1 = a2 /\ b = b
+f
+ : T 0 0 -> forall (B : Type) (b : B), 0 = 0 /\ b = b
+p
+ : forall (a1 a2 : ?A) (B : Type) (b : B), a1 = a2 /\ b = b
+where
+?A : [ |- Type]
+p
+ : forall (a1 a2 : ?A) (B : Type) (b : B), a1 = a2 /\ b = b
+where
+?A : [ |- Type]
+u
+ : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b
+u
+ : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b
+p 0 0
+ : forall b : ?B, 0 = 0 /\ b = b
+where
+?B : [ |- Type]
+p 0 0
+ : forall b : bool, 0 = 0 /\ b = b
+@p nat 0 0
+ : forall (B : Type) (b : B), 0 = 0 /\ b = b
+@p nat 0 0
+ : forall (B : Type) (b : B), 0 = 0 /\ b = b
+u
+ : forall (a1 a2 : ?A) (B : Type) (b : B), a1 = a2 /\ b = b
+where
+?A : [ |- Type]
+u
+ : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b
+u
+ : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b
+u
+ : forall (a1 a2 : ?A) (B : Type) (b : B), a1 = a2 /\ b = b
+where
+?A : [ |- Type]
+u 0 0
+ : forall b : ?B, 0 = 0 /\ b = b
+where
+?B : [ |- Type]
+u 0 0
+ : forall b : ?B, 0 = 0 /\ b = b
+where
+?B : [ |- Type]
+@u nat 0 0
+ : forall (B : Type) (b : B), 0 = 0 /\ b = b
+@u nat 0 0
+ : forall (B : Type) (b : B), 0 = 0 /\ b = b
+u 0 0 true
+ : 0 = 0 /\ true = true
+u 0 0 true
+ : 0 = 0 /\ true = true
+v
+ : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b
+v 0
+ : forall b : ?B, 0 = 0 /\ b = b
+where
+?B : [ |- Type]
+v 0
+ : forall b : ?B, 0 = 0 /\ b = b
+where
+?B : [ |- Type]
+v 0 (B:=bool) true
+ : 0 = 0 /\ true = true
+v
+ : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b
+@v 0
+ : forall (B : Type) (b : B), 0 = 0 /\ b = b
+@v 0
+ : forall (B : Type) (b : B), 0 = 0 /\ b = b
+v 0 (B:=bool)
+ : forall b : bool, 0 = 0 /\ b = b
+v
+ : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b
+v 0
+ : forall b : ?B, 0 = 0 /\ b = b
+where
+?B : [ |- Type]
+v 0
+ : forall b : ?B, 0 = 0 /\ b = b
+where
+?B : [ |- Type]
+v 0 (B:=bool) true
+ : 0 = 0 /\ true = true
+v
+ : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b
+@v 0
+ : forall (B : Type) (b : B), 0 = 0 /\ b = b
+@v 0
+ : forall (B : Type) (b : B), 0 = 0 /\ b = b
+v 0 (B:=bool)
+ : forall b : bool, 0 = 0 /\ b = b
+##
+ : forall (a1 a2 : ?A) (B : Type) (b : B), a1 = a2 /\ b = b
+where
+?A : [ |- Type]
+##
+ : forall (a1 a2 : ?A) (B : Type) (b : B), a1 = a2 /\ b = b
+where
+?A : [ |- Type]
+## 0
+ : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b
+## 0
+ : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b
+## 0 0
+ : forall b : ?B, 0 = 0 /\ b = b
+where
+?B : [ |- Type]
+## 0 0
+ : forall b : ?B, 0 = 0 /\ b = b
+where
+?B : [ |- Type]
+## 0 0 (B:=bool) true
+ : 0 = 0 /\ true = true
+## 0 0 (B:=bool) true
+ : 0 = 0 /\ true = true
+## 0 0 (B:=bool)
+ : forall b : bool, 0 = 0 /\ b = b
+## 0 0 (B:=bool)
+ : forall b : bool, 0 = 0 /\ b = b
+p
+ : forall (a1 a2 : ?A) (B : Type) (b : B), a1 = a2 /\ b = b
+where
+?A : [ |- Type]
+##
+ : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b
+##
+ : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b
+p 0
+ : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b
+p 0
+ : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b
+@p nat 0 0
+ : forall (B : Type) (b : B), 0 = 0 /\ b = b
+p 0 0
+ : forall b : ?B, 0 = 0 /\ b = b
+where
+?B : [ |- Type]
+p 0 0
+ : forall b : ?B, 0 = 0 /\ b = b
+where
+?B : [ |- Type]
+p 0 0 (B:=bool)
+ : forall b : bool, 0 = 0 /\ b = b
+p 0 0 true
+ : 0 = 0 /\ true = true
+## 0
+ : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b
+## 0
+ : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b
+## 0 0 (B:=bool)
+ : forall b : bool, 0 = 0 /\ b = b
+## 0 0 (B:=bool)
+ : forall b : bool, 0 = 0 /\ b = b
+## 0 0 (B:=bool) true
+ : 0 = 0 /\ true = true
+## 0 0 (B:=bool) true
+ : 0 = 0 /\ true = true
+## 0
+ : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b
+## 0
+ : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b
+## 0 0 (B:=bool)
+ : forall b : bool, 0 = 0 /\ b = b
+## 0 0 (B:=bool)
+ : forall b : bool, 0 = 0 /\ b = b
+## 0 0 (B:=bool) true
+ : 0 = 0 /\ true = true
+## 0 0 (B:=bool) true
+ : 0 = 0 /\ true = true
diff --git a/test-suite/output/Notations5.v b/test-suite/output/Notations5.v
new file mode 100644
index 0000000000..b3bea929ba
--- /dev/null
+++ b/test-suite/output/Notations5.v
@@ -0,0 +1,340 @@
+Module AppliedTermsPrinting.
+
+(* Test different printing paths for applied terms *)
+
+ Module InferredGivenImplicit.
+ Set Implicit Arguments.
+ Set Maximal Implicit Insertion.
+
+ Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b.
+
+ Check p 0 0 true.
+ (* p 0 0 true *)
+ Check p 0 0.
+ (* p 0 0 *)
+ Check p 0.
+ (* p 0 *)
+ Check @p _ 0 0 bool.
+ (* p 0 0 (B:=bool) *)
+ Check p 0 0 (B:=bool).
+ (* p 0 0 (B:=bool) *)
+ Check @p nat.
+ (* p (A:=nat) *)
+ Check p (A:=nat).
+ (* p (A:=nat) *)
+ Check @p _ 0 0.
+ (* @p nat 0 0 *)
+ Check @p.
+ (* @p *)
+
+ Unset Printing Implicit Defensive.
+ Check @p _ 0 0 bool.
+ (* p 0 0 *)
+ Check @p nat.
+ (* p *)
+ Set Printing Implicit Defensive.
+ End InferredGivenImplicit.
+
+ Module ManuallyGivenImplicit.
+ Axiom p : forall {A} (a1 a2:A) {B} (b:B), a1 = a2 /\ b = b.
+
+ Check p 0 0 true.
+ (* p 0 0 true *)
+ Check p 0 0.
+ (* p 0 0 *)
+ Check p 0.
+ (* p 0 *)
+ Check @p _ 0 0 bool.
+ (* p 0 0 *)
+ Check p 0 0 (B:=bool).
+ (* p 0 0 *)
+ Check @p nat.
+ (* p *)
+ Check p (A:=nat).
+ (* p *)
+ Check @p _ 0 0.
+ (* @p nat 0 0 *)
+ Check @p.
+ (* @p *)
+
+ End ManuallyGivenImplicit.
+
+ Module ProjectionWithImplicits.
+ Set Implicit Arguments.
+ Set Maximal Implicit Insertion.
+
+ Record T {A} (a1 a2:A) := { f : forall B (b:B), a1 = a2 /\ b = b }.
+ Parameter x : T 0 0.
+ Check f x true.
+ (* f x true *)
+ Check @f _ _ _ x bool.
+ (* f x (B:=bool) *)
+ Check f x (B:=bool).
+ (* f x (B:=bool) *)
+ Check @f nat.
+ (* @f nat *)
+ Check @f _ 0 0.
+ (* f (a1:=0) (a2:=0) *)
+ Check f (a1:=0) (a2:=0).
+ (* f (a1:=0) (a2:=0) *)
+ Check @f.
+ (* @f *)
+
+ Unset Printing Implicit Defensive.
+ Check f (a1:=0) (a2:=0).
+ (* f *)
+ Set Printing Implicit Defensive.
+
+ Set Printing Projections.
+
+ Check x.(f) true.
+ (* x.(f) true *)
+ Check x.(@f _ _ _) bool.
+ (* x.(f) (B:=bool) *)
+ Check x.(f) (B:=bool).
+ (* x.(f) (B:=bool) *)
+ Check @f nat.
+ (* @f nat *)
+ Check @f _ 0 0.
+ (* f (a1:=0) (a2:=0) *)
+ Check f (a1:=0) (a2:=0).
+ (* f (a1:=0) (a2:=0) *)
+ Check @f.
+ (* @f *)
+
+ Unset Printing Implicit Defensive.
+ Check f (a1:=0) (a2:=0).
+ (* f *)
+
+ End ProjectionWithImplicits.
+
+ Module AtAbbreviationForApplicationHead.
+
+ Axiom p : forall {A} (a1 a2:A) {B} (b:B), a1 = a2 /\ b = b.
+
+ Notation u := @p.
+
+ Check u _.
+ (* p *)
+ Check p.
+ (* p *)
+ Check @p.
+ (* u *)
+ Check u.
+ (* u *)
+ Check p 0 0.
+ (* p 0 0 *)
+ Check u nat 0 0 bool.
+ (* p 0 0 -- WEAKNESS should ideally be (B:=bool) *)
+ Check u nat 0 0.
+ (* @p nat 0 0 *)
+ Check @p nat 0 0.
+ (* @p nat 0 0 *)
+
+ End AtAbbreviationForApplicationHead.
+
+ Module AbbreviationForApplicationHead.
+
+ Set Implicit Arguments.
+ Set Maximal Implicit Insertion.
+
+ Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b.
+
+ Notation u := p.
+
+ Check p.
+ (* u *)
+ Check @p.
+ (* u -- BUG *)
+ Check @u.
+ (* u -- BUG *)
+ Check u.
+ (* u *)
+ Check p 0 0.
+ (* u 0 0 *)
+ Check u 0 0.
+ (* u 0 0 *)
+ Check @p nat 0 0.
+ (* @u nat 0 0 *)
+ Check @u nat 0 0.
+ (* @u nat 0 0 *)
+ Check p 0 0 true.
+ (* u 0 0 true *)
+ Check u 0 0 true.
+ (* u 0 0 true *)
+
+ End AbbreviationForApplicationHead.
+
+ Module AtAbbreviationForPartialApplication.
+
+ Set Implicit Arguments.
+ Set Maximal Implicit Insertion.
+
+ Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b.
+
+ Notation v := (@p _ 0).
+
+ Check v.
+ (* v *)
+ Check p 0 0.
+ (* v 0 *)
+ Check v 0.
+ (* v 0 *)
+ Check v 0 true.
+ (* v 0 (B:=bool) true -- BUG *)
+ Check @p nat 0.
+ (* v *)
+ Check @p nat 0 0.
+ (* @v 0 *)
+ Check @v 0.
+ (* @v 0 *)
+ Check @p nat 0 0 bool.
+ (* v 0 (B:=bool) *)
+
+ End AtAbbreviationForPartialApplication.
+
+ Module AbbreviationForPartialApplication.
+
+ Set Implicit Arguments.
+ Set Maximal Implicit Insertion.
+
+ Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b.
+
+ Notation v := (p 0).
+
+ Check v.
+ (* v *)
+ Check p 0 0.
+ (* v 0 *)
+ Check v 0.
+ (* v 0 *)
+ Check v 0 true.
+ (* v 0 (B:=bool) true -- BUG *)
+ Check @p nat 0.
+ (* v *)
+ Check @p nat 0 0.
+ (* @v 0 *)
+ Check @v 0.
+ (* @v 0 *)
+ Check @p nat 0 0 bool.
+ (* v 0 (B:=bool) *)
+
+ End AbbreviationForPartialApplication.
+
+ Module NotationForHeadApplication.
+
+ Set Implicit Arguments.
+ Set Maximal Implicit Insertion.
+
+ Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b.
+
+ Notation "##" := p (at level 0).
+
+ Check p.
+ (* ## *)
+ Check ##.
+ (* ## *)
+ Check p 0.
+ (* ## 0 *)
+ Check ## 0.
+ (* ## 0 *)
+ Check p 0 0.
+ (* ## 0 0 *)
+ Check ## 0 0.
+ (* ## 0 0 *)
+ Check p 0 0 true.
+ (* ## 0 0 (B:=bool) true -- BUG B should not be displayed *)
+ Check ## 0 0 true.
+ (* ## 0 0 (B:=bool) true -- BUG B should not be displayed *)
+ Check p 0 0 (B:=bool).
+ (* ## 0 0 (B:=bool) *)
+ Check ## 0 0 (B:=bool).
+ (* ## 0 0 (B:=bool) *)
+
+ End NotationForHeadApplication.
+
+ Module AtNotationForHeadApplication.
+
+ Set Implicit Arguments.
+ Set Maximal Implicit Insertion.
+
+ Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b.
+
+ Notation "##" := @p (at level 0).
+
+ Check p.
+ (* p *)
+ Check @p.
+ (* ## *)
+ Check ##.
+ (* ## *)
+ Check p 0.
+ (* p 0 -- why not "## nat 0" *)
+ Check ## nat 0.
+ (* p 0 *)
+ Check ## nat 0 0.
+ (* @p nat 0 0 *)
+ Check p 0 0.
+ (* p 0 0 *)
+ Check ## nat 0 0 _.
+ (* p 0 0 *)
+ Check ## nat 0 0 bool.
+ (* p 0 0 (B:=bool) *)
+ Check ## nat 0 0 bool true.
+ (* p 0 0 true *)
+
+ End AtNotationForHeadApplication.
+
+ Module NotationForPartialApplication.
+
+ Set Implicit Arguments.
+ Set Maximal Implicit Insertion.
+
+ Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b.
+
+ Notation "## q" := (p q) (at level 0, q at level 0).
+
+ Check p 0.
+ (* ## 0 *)
+ Check ## 0.
+ (* ## 0 *)
+ (* Check ## 0 0. *)
+ (* Anomaly *)
+ Check p 0 0 (B:=bool).
+ (* ## 0 0 (B:=bool) *)
+ Check ## 0 0 bool.
+ (* ## 0 0 (B:=bool) -- INCONSISTENT parsing/printing *)
+ Check p 0 0 true.
+ (* ## 0 0 (B:=bool) true -- BUG B should not be displayed *)
+ Check ## 0 0 bool true.
+ (* ## 0 0 (B:=bool) true -- INCONSISTENT parsing/printing + BUG B should not be displayed *)
+
+ End NotationForPartialApplication.
+
+ Module AtNotationForPartialApplication.
+
+ Set Implicit Arguments.
+ Set Maximal Implicit Insertion.
+
+ Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b.
+
+ Notation "## q" := (@p _ q) (at level 0, q at level 0).
+
+ Check p 0.
+ (* ## 0 *)
+ Check ## 0.
+ (* ## 0 *)
+ (* Check ## 0 0. *)
+ (* Anomaly *)
+ Check p 0 0 (B:=bool).
+ (* ## 0 0 (B:=bool) *)
+ Check ## 0 0 bool.
+ (* ## 0 0 (B:=bool) -- INCONSISTENT parsing/printing *)
+ Check p 0 0 true.
+ (* ## 0 0 (B:=bool) true -- BUG B should not be displayed *)
+ Check ## 0 0 bool true.
+ (* ## 0 0 (B:=bool) true -- INCONSISTENCY parsing/printing + BUG B should not be displayed *)
+
+ End AtNotationForPartialApplication.
+
+End AppliedTermsPrinting.
diff --git a/toplevel/coqloop.ml b/toplevel/coqloop.ml
index e1748d5c1c..977cae6254 100644
--- a/toplevel/coqloop.ml
+++ b/toplevel/coqloop.ml
@@ -469,6 +469,16 @@ let rec vernac_loop ~state =
(* Exception printing should be done by the feedback listener,
however this is not yet ready so we rely on the exception for
now. *)
+ | Sys_blocked_io ->
+ (* the parser doesn't like nonblocking mode, cf #10918 *)
+ let msg =
+ Pp.(strbrk "Coqtop needs the standard input to be in blocking mode." ++ spc()
+ ++ str "One way of clearing the non-blocking flag is through python:" ++ fnl()
+ ++ str " import os" ++ fnl()
+ ++ str " os.set_blocking(0, True)")
+ in
+ TopErr.print_error_for_buffer Feedback.Error msg top_buffer;
+ exit 1
| any ->
let (e, info) = CErrors.push any in
let loc = Loc.get_loc info in
diff --git a/vernac/himsg.ml b/vernac/himsg.ml
index eb39564fed..17c3e0395a 100644
--- a/vernac/himsg.ml
+++ b/vernac/himsg.ml
@@ -1216,8 +1216,12 @@ let error_bad_entry () =
let error_large_non_prop_inductive_not_in_type () =
str "Large non-propositional inductive types must be in Type."
-let error_inductive_bad_univs () =
- str "Incorrect universe constraints declared for inductive type."
+let error_inductive_missing_constraints (us,ind_univ) =
+ let pr_u = Univ.Universe.pr_with UnivNames.pr_with_global_universes in
+ str "Missing universe constraint declared for inductive type:" ++ spc()
+ ++ v 0 (prlist_with_sep spc (fun u ->
+ hov 0 (pr_u u ++ str " <= " ++ pr_u ind_univ))
+ (Univ.Universe.Set.elements us))
(* Recursion schemes errors *)
@@ -1256,7 +1260,7 @@ let explain_inductive_error = function
| BadEntry -> error_bad_entry ()
| LargeNonPropInductiveNotInType ->
error_large_non_prop_inductive_not_in_type ()
- | BadUnivs -> error_inductive_bad_univs ()
+ | MissingConstraints csts -> error_inductive_missing_constraints csts
(* Recursion schemes errors *)
diff --git a/vernac/metasyntax.ml b/vernac/metasyntax.ml
index 05e23164b1..0c39aba70a 100644
--- a/vernac/metasyntax.ml
+++ b/vernac/metasyntax.ml
@@ -126,7 +126,7 @@ let parse_format ({CAst.loc;v=str} : lstring) =
let rec parse_non_format i =
let n = nonspaces false 0 i in
push_token (make_loc i (i+n-1)) (UnpTerminal (String.sub str i n)) (parse_token 1 (i+n))
- and parse_quoted n i =
+ and parse_quoted n k i =
if i < len then match str.[i] with
(* Parse " // " *)
| '/' when i+1 < len && str.[i+1] == '/' ->
@@ -140,7 +140,7 @@ let parse_format ({CAst.loc;v=str} : lstring) =
(parse_token 1 (close_quotation i (i+p+1)))
| c ->
(* The spaces are real spaces *)
- push_white i n (match c with
+ push_white (i-n-1-k) n (match c with
| '[' ->
if i+1 < len then match str.[i+1] with
(* Parse " [h .. ", *)
@@ -177,7 +177,7 @@ let parse_format ({CAst.loc;v=str} : lstring) =
push_white (i-n) (n-k) (push_token (make_loc i (i+1)) (UnpTerminal "'") (parse_token 1 (i+1)))
(* Parse the beginning of a quoted expression *)
| '\'' ->
- parse_quoted (n-k) (i+1)
+ parse_quoted (n-k) k (i+1)
(* Otherwise *)
| _ ->
push_white (i-n) (n-k) (parse_non_format i)
@@ -477,6 +477,9 @@ let warn_format_break =
(fun () ->
strbrk "Discarding format implicitly indicated by multiple spaces in notation because an explicit format modifier is given.")
+let has_ldots l =
+ List.exists (function (_,UnpTerminal s) -> String.equal s (Id.to_string Notation_ops.ldots_var) | _ -> false) l
+
let rec split_format_at_ldots hd = function
| (loc,UnpTerminal s) :: fmt when String.equal s (Id.to_string Notation_ops.ldots_var) -> loc, List.rev hd, fmt
| u :: fmt ->
@@ -504,11 +507,32 @@ let find_prod_list_loc sfmt fmt =
(* A separator; we highlight the separating sequence *)
Loc.merge_opt (fst (List.hd sfmt)) (fst (List.last sfmt))
+let is_blank s =
+ let n = String.length s in
+ let rec aux i s = i >= n || s.[i] = ' ' && aux (i+1) s in
+ aux 0 s
+
+let is_formatting = function
+ | (_,UnpCut _) -> true
+ | (_,UnpTerminal s) -> is_blank s
+ | _ -> false
+
+let rec is_var_in_recursive_format = function
+ | (_,UnpTerminal s) when not (is_blank s) -> true
+ | (loc,UnpBox (b,l)) ->
+ (match List.filter (fun a -> not (is_formatting a)) l with
+ | [a] -> is_var_in_recursive_format a
+ | _ -> error_not_same ?loc ())
+ | _ -> false
+
+let rec check_eq_var_upto_name = function
+ | (_,UnpTerminal s1), (_,UnpTerminal s2) when not (is_blank s1 && is_blank s2) || s1 = s2 -> ()
+ | (_,UnpBox (b1,l1)), (_,UnpBox (b2,l2)) when b1 = b2 -> List.iter check_eq_var_upto_name (List.combine l1 l2)
+ | (_,UnpCut b1), (_,UnpCut b2) when b1 = b2 -> ()
+ | _, (loc,_) -> error_not_same ?loc ()
+
let skip_var_in_recursive_format = function
- | (_,UnpTerminal s) :: sl (* skip first var *) when not (List.for_all (fun c -> c = " ") (String.explode s)) ->
- (* To do, though not so important: check that the names match
- the names in the notation *)
- sl
+ | a :: sl when is_var_in_recursive_format a -> a, sl
| (loc,_) :: _ -> error_not_same ?loc ()
| [] -> assert false
@@ -516,15 +540,20 @@ let read_recursive_format sl fmt =
(* Turn [[UnpTerminal s :: some-list @ UnpTerminal ".." :: same-some-list @ UnpTerminal s' :: rest] *)
(* into [(some-list,rest)] *)
let get_head fmt =
- let sl = skip_var_in_recursive_format fmt in
- try split_format_at_ldots [] sl with Exit -> error_not_same ?loc:(fst (List.last (if sl = [] then fmt else sl))) () in
+ let var,sl = skip_var_in_recursive_format fmt in
+ try var, split_format_at_ldots [] sl
+ with Exit -> error_not_same ?loc:(fst (List.last (if sl = [] then fmt else sl))) () in
let rec get_tail = function
| (loc,a) :: sepfmt, (_,b) :: fmt when (=) a b -> get_tail (sepfmt, fmt) (* FIXME *)
| [], tail -> skip_var_in_recursive_format tail
| (loc,_) :: _, ([] | (_,UnpTerminal _) :: _)-> error_not_same ?loc ()
| _, (loc,_)::_ -> error_not_same ?loc () in
- let loc, slfmt, fmt = get_head fmt in
- slfmt, get_tail (slfmt, fmt)
+ let var1, (loc, slfmt, fmt) = get_head fmt in
+ let var2, res = get_tail (slfmt, fmt) in
+ check_eq_var_upto_name (var1,var2);
+ (* To do, though not so important: check that the names match
+ the names in the notation *)
+ slfmt, res
let hunks_of_format (from,(vars,typs)) symfmt =
let rec aux = function
@@ -537,13 +566,9 @@ let hunks_of_format (from,(vars,typs)) symfmt =
| NonTerminal s :: symbs, (_,UnpTerminal s') :: fmt when Id.equal s (Id.of_string s') ->
let i = index_id s vars in
let symbs, l = aux (symbs,fmt) in symbs, unparsing_metavar i from typs :: l
- | symbs, (_,UnpBox (a,b)) :: fmt ->
- let symbs', b' = aux (symbs,b) in
- let symbs', l = aux (symbs',fmt) in
- symbs', UnpBox (a,List.map (fun x -> (None,x)) b') :: l
| symbs, (_,(UnpCut _ as u)) :: fmt ->
let symbs, l = aux (symbs,fmt) in symbs, u :: l
- | SProdList (m,sl) :: symbs, fmt ->
+ | SProdList (m,sl) :: symbs, fmt when has_ldots fmt ->
let i = index_id m vars in
let typ = List.nth typs (i-1) in
let _,prec = precedence_of_entry_type from typ in
@@ -558,6 +583,10 @@ let hunks_of_format (from,(vars,typs)) symfmt =
UnpBinderListMetaVar (i,isopen,slfmt)
| _ -> assert false in
symbs, hunk :: l
+ | symbs, (_,UnpBox (a,b)) :: fmt ->
+ let symbs', b' = aux (symbs,b) in
+ let symbs', l = aux (symbs',fmt) in
+ symbs', UnpBox (a,List.map (fun x -> (None,x)) b') :: l
| symbs, [] -> symbs, []
| Break _ :: symbs, fmt -> warn_format_break (); aux (symbs,fmt)
| _, fmt -> error_format ?loc:(fst (List.hd fmt)) ()
diff --git a/vernac/vernacstate.ml b/vernac/vernacstate.ml
index c81a4abc1b..80b72225f0 100644
--- a/vernac/vernacstate.ml
+++ b/vernac/vernacstate.ml
@@ -124,7 +124,7 @@ module Proof_global = struct
let () =
CErrors.register_handler begin function
| NoCurrentProof ->
- CErrors.user_err Pp.(str "No focused proof (No proof-editing in progress).")
+ Pp.(str "No focused proof (No proof-editing in progress).")
| _ -> raise CErrors.Unhandled
end