aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthieu Sozeau2016-05-20 03:39:51 +0200
committerMatthieu Sozeau2016-06-16 18:21:08 +0200
commit2c07b6d95c7b8fd754cdf9dd767dda989723125a (patch)
tree089d115ad32ec20ca5dc0ac2f4d662fa279daed5
parent677d5deb72734a0e5502bcf47a905fcdf9374e51 (diff)
Typeclasses: verbosity and Limit Intros options
To deactivate the limitation of introductions (which was added to avoid eta expansions in proof terms). This can cause huge blowups due to dumb backtracking. The arrow introduction rule is reversible, so better do it eagerly!
-rw-r--r--tactics/class_tactics.ml213
1 files changed, 129 insertions, 84 deletions
diff --git a/tactics/class_tactics.ml b/tactics/class_tactics.ml
index e645182b8a..76316f6191 100644
--- a/tactics/class_tactics.ml
+++ b/tactics/class_tactics.ml
@@ -37,13 +37,17 @@ open Hints
(** Hint database named "typeclass_instances", now created directly in Auto *)
-let typeclasses_debug = ref false
+let typeclasses_debug = ref 0
let typeclasses_depth = ref None
let typeclasses_modulo_eta = ref false
let set_typeclasses_modulo_eta d = (:=) typeclasses_modulo_eta d
let get_typeclasses_modulo_eta () = !typeclasses_modulo_eta
+let typeclasses_limit_intros = ref false
+let set_typeclasses_limit_intros d = (:=) typeclasses_limit_intros d
+let get_typeclasses_limit_intros () = !typeclasses_limit_intros
+
let typeclasses_dependency_order = ref false
let set_typeclasses_dependency_order d = (:=) typeclasses_dependency_order d
let get_typeclasses_dependency_order () = !typeclasses_dependency_order
@@ -58,7 +62,11 @@ let get_compat_version d =
| _ -> Flags.Current
let typeclasses_unif_compat = ref Flags.V8_5
-let set_typeclasses_unif_compat d = (:=) typeclasses_unif_compat d
+let set_typeclasses_unif_compat d =
+ if d == Flags.Current then set_typeclasses_limit_intros false
+ else set_typeclasses_limit_intros true;
+ (:=) typeclasses_unif_compat d
+
let get_typeclasses_unif_compat () = !typeclasses_unif_compat
let set_typeclasses_unif_compat_string d =
set_typeclasses_unif_compat (get_compat_version d)
@@ -73,9 +81,21 @@ let set_typeclasses_compat_string d =
let get_typeclasses_compat_string () =
Flags.pr_version (get_typeclasses_compat ())
-
-open Goptions
+let set_typeclasses_debug d = (:=) typeclasses_debug (if d then 1 else 0)
+let get_typeclasses_debug () = if !typeclasses_debug > 0 then true else false
+
+let set_typeclasses_verbose =
+ function None -> typeclasses_debug := 0
+ | Some n -> (:=) typeclasses_debug n
+let get_typeclasses_verbose () =
+ if !typeclasses_debug = 0 then None else Some !typeclasses_debug
+
+let set_typeclasses_depth d = (:=) typeclasses_depth d
+let get_typeclasses_depth () = !typeclasses_depth
+
+open Goptions
+
let _ =
declare_bool_option
{ optsync = true;
@@ -89,6 +109,16 @@ let _ =
declare_bool_option
{ optsync = true;
optdepr = false;
+ optname = "do typeclass search avoiding eta-expansions " ^
+ " in proof terms (expensive)";
+ optkey = ["Typeclasses";"Limit";"Intros"];
+ optread = get_typeclasses_limit_intros;
+ optwrite = set_typeclasses_limit_intros; }
+
+let _ =
+ declare_bool_option
+ { optsync = true;
+ optdepr = false;
optname = "during typeclass resolution, solve instances according to their dependency order";
optkey = ["Typeclasses";"Dependency";"Order"];
optread = get_typeclasses_dependency_order;
@@ -120,6 +150,44 @@ let _ =
optkey = ["Typeclasses";"Unification";"Compatibility"];
optread = get_typeclasses_unif_compat_string;
optwrite = set_typeclasses_unif_compat_string; }
+
+let set_typeclasses_debug =
+ declare_bool_option
+ { optsync = true;
+ optdepr = false;
+ optname = "debug output for typeclasses proof search";
+ optkey = ["Typeclasses";"Debug"];
+ optread = get_typeclasses_debug;
+ optwrite = set_typeclasses_debug; }
+
+let _ =
+ declare_bool_option
+ { optsync = true;
+ optdepr = false;
+ optname = "debug output for typeclasses proof search";
+ optkey = ["Debug";"Typeclasses"];
+ optread = get_typeclasses_debug;
+ optwrite = set_typeclasses_debug; }
+
+let _ =
+ declare_int_option
+ { optsync = true;
+ optdepr = false;
+ optname = "verbosity of debug output for typeclasses proof search";
+ optkey = ["Typeclasses";"Debug";"Verbosity"];
+ optread = get_typeclasses_verbose;
+ optwrite = set_typeclasses_verbose; }
+
+let set_typeclasses_depth =
+ declare_int_option
+ { optsync = true;
+ optdepr = false;
+ optname = "depth for typeclasses proof search";
+ optkey = ["Typeclasses";"Depth"];
+ optread = get_typeclasses_depth;
+ optwrite = set_typeclasses_depth; }
+
+let pr_ev evs ev = Printer.pr_constr_env (Goal.V82.env evs ev) evs (Evarutil.nf_evar evs (Goal.V82.concl evs ev))
(** We transform the evars that are concerned by this resolution
(according to predicate p) into goals.
@@ -235,7 +303,7 @@ let unify_resolve_newcl poly flags =
{ enter = begin fun gls ((c, t, ctx),n,clenv) ->
let env = Proofview.Goal.env gls in
let concl = Proofview.Goal.concl gls in
- Proofview.Refine.refine ~unsafe:true { Sigma.run = fun sigma ->
+ Refine.refine ~unsafe:true { Sigma.run = fun sigma ->
let sigma = Sigma.to_evar_map sigma in
let sigma, term, ty =
if poly then
@@ -274,12 +342,16 @@ let clenv_of_prods poly nprods (c, clenv) gl =
else None
let with_prods nprods poly (c, clenv) f =
- Proofview.Goal.nf_enter { enter = begin fun gl ->
- match clenv_of_prods poly nprods (c, clenv) gl with
- | None -> Tacticals.New.tclZEROMSG (str"Not enough premisses")
- | Some (diff, clenv') -> f.enter gl (c, diff, clenv')
- end }
-
+ if get_typeclasses_limit_intros () then
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
+ match clenv_of_prods poly nprods (c, clenv) gl with
+ | None -> Tacticals.New.tclZEROMSG (str"Not enough premisses")
+ | Some (diff, clenv') -> f.enter gl (c, diff, clenv') end }
+ else Proofview.Goal.nf_enter
+ { enter = begin fun gl ->
+ if Int.equal nprods 0 then f.enter gl (c, None, clenv)
+ else Tacticals.New.tclZEROMSG (str"Not enough premisses") end }
+
let matches_pattern concl pat =
let matches env sigma =
match pat with
@@ -636,8 +708,8 @@ let new_hints_tac_gl only_classes hints info kont gl
let concl = Goal.concl gl in
let sigma = Goal.sigma gl in
let s = Sigma.to_evar_map sigma in
- if !typeclasses_debug then
- msg_debug (pr_depth info.search_depth ++ str": looking for " ++
+ if !typeclasses_debug > 0 then
+ Feedback.msg_debug (pr_depth info.search_depth ++ str": looking for " ++
Printer.pr_constr_env (Goal.env gl) s concl);
let poss = e_possible_resolve hints info.search_hints s concl in
let unique = is_unique env concl in
@@ -647,10 +719,11 @@ let new_hints_tac_gl only_classes hints info kont gl
let rec aux foundone e = function
| (tac, pat, b, name, pp) :: tl ->
let derivs = path_derivate info.search_cut name in
- (if !typeclasses_debug then
- msg_debug (pr_depth (!idx :: info.search_depth) ++ str": trying " ++
- Lazy.force pp ++
- str" on" ++ spc () ++ pr_ev s (Proofview.Goal.goal gl)));
+ (if !typeclasses_debug > 0 then
+ Feedback.msg_debug
+ (pr_depth (!idx :: info.search_depth) ++ str": trying " ++
+ Lazy.force pp ++
+ str" on" ++ spc () ++ pr_ev s (Proofview.Goal.goal gl)));
let tac_of i j =
Goal.nf_enter { enter = fun gl' ->
let sigma' = Goal.sigma gl' in
@@ -670,19 +743,21 @@ let new_hints_tac_gl only_classes hints info kont gl
search_hints = hints';
search_cut = derivs }
in
- if !typeclasses_debug then
- msg_debug (pr_depth (succ j :: i :: info.search_depth) ++ str" : " ++
- pr_ev s' (Proofview.Goal.goal gl'));
+ if !typeclasses_debug > 0 then
+ Feedback.msg_debug
+ (pr_depth (succ j :: i :: info.search_depth) ++ str" : " ++
+ pr_ev s' (Proofview.Goal.goal gl'));
kont info' }
in
let result () =
let i = !idx in
incr idx;
Proofview.numgoals >>= fun j ->
- (if !typeclasses_debug then
- msg_debug (pr_depth (i :: info.search_depth) ++ str": " ++ Lazy.force pp
- ++ str" on" ++ spc () ++ pr_ev s (Proofview.Goal.goal gl)
- ++ str", " ++ int j ++ str" subgoals");
+ (if !typeclasses_debug > 0 then
+ Feedback.msg_debug
+ (pr_depth (i :: info.search_depth) ++ str": " ++ Lazy.force pp
+ ++ str" on" ++ spc () ++ pr_ev s (Proofview.Goal.goal gl)
+ ++ str", " ++ int j ++ str" subgoals");
if j = 0 then
Proofview.tclUNIT ()
else Proofview.tclDISPATCH (List.init j (tac_of i)))
@@ -691,11 +766,12 @@ let new_hints_tac_gl only_classes hints info kont gl
else ortac (Proofview.tclBIND tac result)
(fun e' -> aux foundone (merge_exceptions e e') tl)
| [] ->
- if foundone == None && !typeclasses_debug then
- msg_debug (pr_depth info.search_depth ++ str": no match for " ++
- Printer.pr_constr_env (Goal.env gl) s concl ++
- spc () ++ str ", " ++ int (List.length poss) ++
- str" possibilities");
+ if foundone == None && !typeclasses_debug > 0 then
+ Feedback.msg_debug
+ (pr_depth info.search_depth ++ str": no match for " ++
+ Printer.pr_constr_env (Goal.env gl) s concl ++
+ spc () ++ str ", " ++ int (List.length poss) ++
+ str" possibilities");
match e with
| (ReachedLimitEx,ie) -> Proofview.tclZERO ~info:ie ReachedLimitEx
| (_,ie) -> Proofview.tclZERO ~info:ie NotApplicableEx
@@ -736,9 +812,10 @@ let intro_tac' only_classes info kont =
let rec eauto_tac' only_classes hints limit depth =
let kont info =
Proofview.numgoals >>= fun i ->
- if !typeclasses_debug then
- msg_debug (str"calling eauto recursively at depth " ++ int (succ depth)
- ++ str" on " ++ int i ++ str" subgoals");
+ if !typeclasses_debug > 1 then
+ Feedback.msg_debug
+ (str"calling eauto recursively at depth " ++ int (succ depth)
+ ++ str" on " ++ int i ++ str" subgoals");
eauto_tac' only_classes hints limit (succ depth) info
in
fun info ->
@@ -863,7 +940,7 @@ let hints_tac hints =
(match res with
| None -> aux i foundone tl
| Some {it = gls; sigma = s';} ->
- if !typeclasses_debug then
+ if !typeclasses_debug > 0 then
Feedback.msg_debug (pr_depth (i :: info.auto_depth) ++ str": " ++ Lazy.force pp
++ str" on" ++ spc () ++ pr_ev s gl);
let sgls =
@@ -891,13 +968,15 @@ let hints_tac hints =
let gls' = List.map_i
(fun j (evar, g) ->
let info =
- { info with auto_depth = j :: i :: info.auto_depth; auto_last_tac = pp;
+ { info with
+ auto_depth = j :: i :: info.auto_depth;
+ auto_last_tac = pp;
is_evar = evar;
hints =
if b && not (Environ.eq_named_context_val (Goal.V82.hyps s' g)
- (Goal.V82.hyps s' gl))
+ (Goal.V82.hyps s' gl))
then make_autogoal_hints info.only_classes
- ~st:(Hint_db.transparent_state info.hints) {it = g; sigma = s';}
+ ~st:(Hint_db.transparent_state info.hints) {it = g; sigma = s';}
else info.hints;
auto_cut = derivs }
in g, info) 1 newgls in
@@ -912,7 +991,7 @@ let hints_tac hints =
else true
in
let e' = match foundone with None -> e | Some e' -> merge_failures e e' in
- if !typeclasses_debug then
+ if !typeclasses_debug > 0 then
Feedback.msg_debug
((if do_backtrack then str"Backtracking after "
else str "Not backtracking after ")
@@ -922,7 +1001,7 @@ let hints_tac hints =
in
sk glsv fk')
| [] ->
- if foundone == None && !typeclasses_debug then
+ if foundone == None && !typeclasses_debug > 0 then
Feedback.msg_debug (pr_depth info.auto_depth ++ str": no match for " ++
Printer.pr_constr_env (Goal.V82.env s gl) s concl ++
spc () ++ str ", " ++ int (List.length poss) ++ str" possibilities");
@@ -995,10 +1074,12 @@ let fix_iterative_limit limit (t : 'a tac) : 'a tac =
else or_tac (fix_limit depth t) { skft = fun sk fk -> (aux (succ depth)).skft sk fk }
in aux 1
-let make_autogoal ?(only_classes=true) ?(unique=false) ?(st=full_transparent_state) cut ev g =
+let make_autogoal ?(only_classes=true) ?(unique=false) ?(st=full_transparent_state)
+ cut ev g =
let hints = make_autogoal_hints only_classes ~st g in
(g.it, { hints = hints ; is_evar = ev; unique = unique;
- only_classes = only_classes; auto_depth = []; auto_last_tac = lazy (str"none");
+ only_classes = only_classes; auto_depth = [];
+ auto_last_tac = lazy (str"none");
auto_path = []; auto_cut = cut })
@@ -1062,7 +1143,8 @@ let resolve_all_evars_once debug limit unique p evd =
real_eauto ?limit unique (Hint_db.transparent_state db) [db] p evd
let eauto ?(only_classes=true) ?st ?limit hints g =
- let gl = { it = make_autogoal ~only_classes ?st (cut_of_hints hints) None g; sigma = project g; } in
+ let gl = { it = make_autogoal ~only_classes ?st
+ (cut_of_hints hints) None g; sigma = project g; } in
match run_tac (eauto_tac ?limit hints) gl with
| None -> raise Not_found
| Some {it = goals; sigma = s; } ->
@@ -1233,51 +1315,14 @@ let resolve_typeclass_evars debug m unique env evd filter split fail =
in
resolve_all_evars debug m unique env (initial_select_evars filter) evd split fail
-let solve_inst debug depth env evd filter unique split fail =
- resolve_typeclass_evars debug depth unique env evd filter split fail
+let solve_inst env evd filter unique split fail =
+ resolve_typeclass_evars
+ (get_typeclasses_debug ())
+ (get_typeclasses_depth ())
+ unique env evd filter split fail
let _ =
- Typeclasses.solve_instantiations_problem :=
- solve_inst false !typeclasses_depth
-
-let set_typeclasses_debug d = (:=) typeclasses_debug d;
- Typeclasses.solve_instantiations_problem := solve_inst d !typeclasses_depth
-
-let get_typeclasses_debug () = !typeclasses_debug
-
-let set_typeclasses_depth d = (:=) typeclasses_depth d;
- Typeclasses.solve_instantiations_problem := solve_inst !typeclasses_debug !typeclasses_depth
-
-let get_typeclasses_depth () = !typeclasses_depth
-
-open Goptions
-
-let set_typeclasses_debug =
- declare_bool_option
- { optsync = true;
- optdepr = false;
- optname = "debug output for typeclasses proof search";
- optkey = ["Typeclasses";"Debug"];
- optread = get_typeclasses_debug;
- optwrite = set_typeclasses_debug; }
-
-let set_typeclasses_debug =
- declare_bool_option
- { optsync = true;
- optdepr = false;
- optname = "debug output for typeclasses proof search";
- optkey = ["Debug";"Typeclasses"];
- optread = get_typeclasses_debug;
- optwrite = set_typeclasses_debug; }
-
-let set_typeclasses_depth =
- declare_int_option
- { optsync = true;
- optdepr = false;
- optname = "depth for typeclasses proof search";
- optkey = ["Typeclasses";"Depth"];
- optread = get_typeclasses_depth;
- optwrite = set_typeclasses_depth; }
+ Typeclasses.solve_instantiations_problem := solve_inst
let typeclasses_eauto ?(only_classes=false) ?(st=full_transparent_state) dbs gl =
try