summaryrefslogtreecommitdiff
path: root/tactics/equality.ml
diff options
context:
space:
mode:
authorGravatar Enrico Tassi <gareuselesinge@debian.org>2015-11-13 11:31:34 +0100
committerGravatar Enrico Tassi <gareuselesinge@debian.org>2015-11-13 11:31:34 +0100
commit2280477a96e19ba5060de2d48dcc8fd7c8079d22 (patch)
tree074182834cb406d1304aec4233718564a9c06ba1 /tactics/equality.ml
parent0aa2544d04dbd4b6ee665b551ed165e4fb02d2fa (diff)
Imported Upstream version 8.5~beta3+dfsg
Diffstat (limited to 'tactics/equality.ml')
-rw-r--r--tactics/equality.ml143
1 files changed, 107 insertions, 36 deletions
diff --git a/tactics/equality.ml b/tactics/equality.ml
index 7ab8d0c3..674c85af 100644
--- a/tactics/equality.ml
+++ b/tactics/equality.ml
@@ -88,7 +88,7 @@ type freeze_evars_flag = bool (* true = don't instantiate existing evars *)
type orientation = bool
type conditions =
- | Naive (* Only try the first occurence of the lemma (default) *)
+ | Naive (* Only try the first occurrence of the lemma (default) *)
| FirstSolved (* Use the first match whose side-conditions are solved *)
| AllMatches (* Rewrite all matches whose side-conditions are solved *)
@@ -165,10 +165,10 @@ let instantiate_lemma_all frzevars gl c ty l l2r concl =
in List.map try_occ occs
let instantiate_lemma gl c ty l l2r concl =
- let ct = pf_type_of gl c in
- let t = try snd (pf_reduce_to_quantified_ind gl ct) with UserError _ -> ct in
- let eqclause = pf_apply Clenv.make_clenv_binding gl (c,t) l in
- [eqclause]
+ let sigma, ct = pf_type_of gl c in
+ let t = try snd (reduce_to_quantified_ind (pf_env gl) sigma ct) with UserError _ -> ct in
+ let eqclause = Clenv.make_clenv_binding (pf_env gl) sigma (c,t) l in
+ [eqclause]
let rewrite_conv_closed_core_unif_flags = {
modulo_conv_on_closed_terms = Some full_transparent_state;
@@ -306,8 +306,8 @@ let find_elim hdcncl lft2rgt dep cls ot gl =
let _ = Global.lookup_constant c1' in
c1'
with Not_found ->
- let rwr_thm = Label.to_string l' in
- error ("Cannot find rewrite principle "^rwr_thm^".")
+ errorlabstrm "Equality.find_elim"
+ (str "Cannot find rewrite principle " ++ pr_label l' ++ str ".")
end
| _ -> destConstRef pr1
end
@@ -317,7 +317,7 @@ let find_elim hdcncl lft2rgt dep cls ot gl =
assert false
in
let sigma, elim = Evd.fresh_global (Global.env ()) (Proofview.Goal.sigma gl) (ConstRef c) in
- sigma, elim, Declareops.no_seff
+ sigma, elim, Safe_typing.empty_private_constants
else
let scheme_name = match dep, lft2rgt, inccl with
(* Non dependent case *)
@@ -335,7 +335,9 @@ let find_elim hdcncl lft2rgt dep cls ot gl =
| Ind (ind,u) ->
let c, eff = find_scheme scheme_name ind in
(* MS: cannot use pf_constr_of_global as the eliminator might be generated by side-effect *)
- let sigma, elim = Evd.fresh_global (Global.env ()) (Proofview.Goal.sigma gl) (ConstRef c) in
+ let sigma, elim =
+ Evd.fresh_global (Global.env ()) (Proofview.Goal.sigma gl) (ConstRef c)
+ in
sigma, elim, eff
| _ -> assert false
@@ -454,7 +456,7 @@ let general_rewrite_clause l2r with_evars ?tac c cl =
(* Otherwise, if we are told to rewrite in all hypothesis via the
syntax "* |-", we fail iff all the different rewrites fail *)
let rec do_hyps_atleastonce = function
- | [] -> Proofview.tclZERO (Errors.UserError ("",Pp.str"Nothing to rewrite."))
+ | [] -> tclZEROMSG (Pp.str"Nothing to rewrite.")
| id :: l ->
tclIFTHENTRYELSEMUST
(general_rewrite_ebindings_in l2r AllOccurrences false true ?tac id c with_evars)
@@ -540,7 +542,7 @@ let replace_core clause l2r eq =
if check_setoid clause
then init_setoid ();
tclTHENFIRST
- (assert_as false None eq)
+ (assert_as false None None eq)
(onLastHypId (fun id ->
tclTHEN
(tclTRY (general_rewrite_clause l2r false (mkVar id,NoBindings) clause))
@@ -874,7 +876,7 @@ let gen_absurdity id =
then
simplest_elim (mkVar id)
else
- Proofview.tclZERO (Errors.UserError ("Equality.gen_absurdity" , str "Not the negation of an equality."))
+ tclZEROMSG (str "Not the negation of an equality.")
end
(* Precondition: eq is leibniz equality
@@ -899,7 +901,7 @@ let discrimination_pf env sigma e (t,t1,t2) discriminator lbeq =
let i = build_coq_I () in
let absurd_term = build_coq_False () in
let eq_elim, eff = ind_scheme_of_eq lbeq in
- let sigma, eq_elim = Evd.fresh_global env sigma eq_elim in
+ let sigma, eq_elim = Evd.fresh_global (Global.env ()) sigma eq_elim in
sigma, (applist (eq_elim, [t;t1;mkNamedLambda e t discriminator;i;t2]), absurd_term),
eff
@@ -936,7 +938,7 @@ let discrEq (lbeq,_,(t,t1,t2) as u) eq_clause =
let concl = Proofview.Goal.concl gl in
match find_positions env sigma t1 t2 with
| Inr _ ->
- Proofview.tclZERO (Errors.UserError ("discr" , str"Not a discriminable equality."))
+ tclZEROMSG (str"Not a discriminable equality.")
| Inl (cpath, (_,dirn), _) ->
let sort = pf_apply get_type_of gl concl in
discr_positions env sigma u eq_clause cpath dirn sort
@@ -944,7 +946,7 @@ let discrEq (lbeq,_,(t,t1,t2) as u) eq_clause =
let onEquality with_evars tac (c,lbindc) =
Proofview.Goal.nf_enter begin fun gl ->
- let type_of = pf_type_of gl in
+ let type_of = pf_unsafe_type_of gl in
let reduce_to_quantified_ind = pf_apply Tacred.reduce_to_quantified_ind gl in
let t = type_of c in
let t' = try snd (reduce_to_quantified_ind t) with UserError _ -> t in
@@ -968,7 +970,7 @@ let onNegatedEquality with_evars tac =
(onLastHypId (fun id ->
onEquality with_evars tac (mkVar id,NoBindings)))
| _ ->
- Proofview.tclZERO (Errors.UserError ("" , str "Not a negated primitive equality."))
+ tclZEROMSG (str "Not a negated primitive equality.")
end
let discrSimpleClause with_evars = function
@@ -1019,7 +1021,7 @@ let find_sigma_data env s = build_sigma_type ()
let make_tuple env sigma (rterm,rty) lind =
assert (dependent (mkRel lind) rty);
let sigdata = find_sigma_data env (get_sort_of env sigma rty) in
- let sigma, a = e_type_of ~refresh:true env sigma (mkRel lind) in
+ let sigma, a = type_of ~refresh:true env sigma (mkRel lind) in
let (na,_,_) = lookup_rel lind env in
(* We move [lind] to [1] and lift other rels > [lind] by 1 *)
let rty = lift (1-lind) (liftn lind (lind+1) rty) in
@@ -1053,7 +1055,7 @@ let minimal_free_rels_rec env sigma =
let rec minimalrec_free_rels_rec prev_rels (c,cty) =
let (cty,direct_rels) = minimal_free_rels env sigma (c,cty) in
let combined_rels = Int.Set.union prev_rels direct_rels in
- let folder rels i = snd (minimalrec_free_rels_rec rels (c, type_of env sigma (mkRel i)))
+ let folder rels i = snd (minimalrec_free_rels_rec rels (c, unsafe_type_of env sigma (mkRel i)))
in (cty, List.fold_left folder combined_rels (Int.Set.elements (Int.Set.diff direct_rels prev_rels)))
in minimalrec_free_rels_rec Int.Set.empty
@@ -1099,7 +1101,7 @@ let sig_clausal_form env sigma sort_of_ty siglen ty dflt =
let rec sigrec_clausal_form siglen p_i =
if Int.equal siglen 0 then
(* is the default value typable with the expected type *)
- let dflt_typ = type_of env sigma dflt in
+ let dflt_typ = unsafe_type_of env sigma dflt in
try
let () = evdref := Evarconv.the_conv_x_leq env dflt_typ p_i !evdref in
let () = evdref := Evarconv.consider_remaining_unif_problems env !evdref in
@@ -1118,13 +1120,20 @@ let sig_clausal_form env sigma sort_of_ty siglen ty dflt =
(destEvar ev)
with
| Some w ->
- let w_type = type_of env sigma w in
+ let w_type = unsafe_type_of env sigma w in
if Evarconv.e_cumul env evdref w_type a then
let exist_term = Evarutil.evd_comb1 (Evd.fresh_global env) evdref sigdata.intro in
applist(exist_term,[a;p_i_minus_1;w;tuple_tail])
else
error "Cannot solve a unification problem."
- | None -> anomaly (Pp.str "Not enough components to build the dependent tuple")
+ | None ->
+ (* This at least happens if what has been detected as a
+ dependency is not one; use an evasive error message;
+ even if the problem is upwards: unification should be
+ tried in the first place in make_iterated_tuple instead
+ of approximatively computing the free rels; then
+ unsolved evars would mean not binding rel *)
+ error "Cannot solve a unification problem."
in
let scf = sigrec_clausal_form siglen ty in
!evdref, Evarutil.nf_evar !evdref scf
@@ -1200,7 +1209,7 @@ let make_iterated_tuple env sigma dflt (z,zty) =
sigma, (tuple,tuplety,dfltval)
let rec build_injrec env sigma dflt c = function
- | [] -> make_iterated_tuple env sigma dflt (c,type_of env sigma c)
+ | [] -> make_iterated_tuple env sigma dflt (c,unsafe_type_of env sigma c)
| ((sp,cnum),argnum)::l ->
try
let (cnum_nlams,cnum_env,kont) = descend_then env sigma c cnum in
@@ -1253,7 +1262,7 @@ let inject_if_homogenous_dependent_pair ty =
if not (Ind_tables.check_scheme (!eq_dec_scheme_kind_name()) (fst ind) &&
pf_apply is_conv gl ar1.(2) ar2.(2)) then raise Exit;
Coqlib.check_required_library ["Coq";"Logic";"Eqdep_dec"];
- let new_eq_args = [|pf_type_of gl ar1.(3);ar1.(3);ar2.(3)|] in
+ let new_eq_args = [|pf_unsafe_type_of gl ar1.(3);ar1.(3);ar2.(3)|] in
let inj2 = Coqlib.coq_constant "inj_pair2_eq_dec is missing"
["Logic";"Eqdep_dec"] "inj_pair2_eq_dec" in
let c, eff = find_scheme (!eq_dec_scheme_kind_name()) (Univ.out_punivs ind) in
@@ -1293,7 +1302,7 @@ let inject_at_positions env sigma l2r (eq,_,(t,t1,t2)) eq_clause posns tac =
let injfun = mkNamedLambda e t injbody in
let sigma,congr = Evd.fresh_global env sigma eq.congr in
let pf = applist(congr,[t;resty;injfun;t1;t2]) in
- let sigma, pf_typ = Typing.e_type_of env sigma pf in
+ let sigma, pf_typ = Typing.type_of env sigma pf in
let inj_clause = apply_on_clause (pf,pf_typ) eq_clause in
let pf = Clenvtac.clenv_value_cast_meta inj_clause in
let ty = simplify_args env sigma (clenv_type inj_clause) in
@@ -1303,7 +1312,7 @@ let inject_at_positions env sigma l2r (eq,_,(t,t1,t2)) eq_clause posns tac =
in
let injectors = List.map_filter filter posns in
if List.is_empty injectors then
- Proofview.tclZERO (Errors.UserError ("Equality.inj" , str "Failed to decompose the equality."))
+ tclZEROMSG (str "Failed to decompose the equality.")
else
Proofview.tclTHEN (Proofview.Unsafe.tclEVARS !evdref)
(Proofview.tclBIND
@@ -1319,12 +1328,12 @@ let injEqThen tac l2r (eq,_,(t,t1,t2) as u) eq_clause =
let env = eq_clause.env in
match find_positions env sigma t1 t2 with
| Inl _ ->
- Proofview.tclZERO (Errors.UserError ("Inj",strbrk"This equality is discriminable. You should use the discriminate tactic to solve the goal."))
+ tclZEROMSG (strbrk"This equality is discriminable. You should use the discriminate tactic to solve the goal.")
| Inr [] ->
let suggestion = if !injection_on_proofs then "" else " You can try to use option Set Injection On Proofs." in
- Proofview.tclZERO (Errors.UserError ("Equality.inj",strbrk("No information can be deduced from this equality and the injectivity of constructors. This may be because the terms are convertible, or due to pattern matching restrictions in the sort Prop." ^ suggestion)))
+ tclZEROMSG (strbrk("No information can be deduced from this equality and the injectivity of constructors. This may be because the terms are convertible, or due to pattern matching restrictions in the sort Prop." ^ suggestion))
| Inr [([],_,_)] when Flags.version_strictly_greater Flags.V8_3 ->
- Proofview.tclZERO (Errors.UserError ("Equality.inj" , str"Nothing to inject."))
+ tclZEROMSG (str"Nothing to inject.")
| Inr posns ->
inject_at_positions env sigma l2r u eq_clause posns
(tac (clenv_value eq_clause))
@@ -1460,8 +1469,8 @@ let subst_tuple_term env sigma dep_pair1 dep_pair2 b =
(* Simulate now the normalisation treatment made by Logic.mk_refgoals *)
let expected_goal = nf_betaiota sigma expected_goal in
(* Retype to get universes right *)
- let sigma, expected_goal_ty = Typing.e_type_of env sigma expected_goal in
- let sigma, _ = Typing.e_type_of env sigma body in
+ let sigma, expected_goal_ty = Typing.type_of env sigma expected_goal in
+ let sigma, _ = Typing.type_of env sigma body in
sigma,body,expected_goal
(* Like "replace" but decompose dependent equalities *)
@@ -1575,7 +1584,7 @@ let restrict_to_eq_and_identity eq = (* compatibility *)
exception FoundHyp of (Id.t * constr * bool)
-(* tests whether hyp [c] is [x = t] or [t = x], [x] not occuring in [t] *)
+(* tests whether hyp [c] is [x = t] or [t = x], [x] not occurring in [t] *)
let is_eq_x gl x (id,_,c) =
try
let c = pf_nf_evar gl c in
@@ -1589,10 +1598,10 @@ let is_eq_x gl x (id,_,c) =
erase hyp and x; proceed by generalizing all dep hyps *)
let subst_one dep_proof_ok x (hyp,rhs,dir) =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let env = Proofview.Goal.env gl in
- let hyps = Proofview.Goal.hyps gl in
- let concl = Proofview.Goal.concl gl in
+ let hyps = Proofview.Goal.hyps (Proofview.Goal.assume gl) in
+ let concl = Proofview.Goal.concl (Proofview.Goal.assume gl) in
(* The set of hypotheses using x *)
let dephyps =
List.rev (snd (List.fold_right (fun (id,b,_ as dcl) (deps,allhyps) ->
@@ -1662,7 +1671,70 @@ let default_subst_tactic_flags () =
else
{ only_leibniz = true; rewrite_dependent_proof = false }
+let regular_subst_tactic = ref false
+
+let _ =
+ declare_bool_option
+ { optsync = true;
+ optdepr = false;
+ optname = "more regular behavior of tactic subst";
+ optkey = ["Regular";"Subst";"Tactic"];
+ optread = (fun () -> !regular_subst_tactic);
+ optwrite = (:=) regular_subst_tactic }
+
let subst_all ?(flags=default_subst_tactic_flags ()) () =
+
+ if !regular_subst_tactic then
+
+ (* First step: find hypotheses to treat in linear time *)
+ let find_equations gl =
+ let gl = Proofview.Goal.assume gl in
+ let env = Proofview.Goal.env gl in
+ let find_eq_data_decompose = find_eq_data_decompose gl in
+ let test (hyp,_,c) =
+ try
+ let lbeq,u,(_,x,y) = find_eq_data_decompose c in
+ let eq = Universes.constr_of_global_univ (lbeq.eq,u) in
+ if flags.only_leibniz then restrict_to_eq_and_identity eq;
+ match kind_of_term x, kind_of_term y with
+ | Var z, _ | _, Var z when not (is_evaluable env (EvalVarRef z)) ->
+ Some hyp
+ | _ ->
+ None
+ with Constr_matching.PatternMatchingFailure -> None
+ in
+ let hyps = Proofview.Goal.hyps gl in
+ List.rev (List.map_filter test hyps)
+ in
+
+ (* Second step: treat equations *)
+ let process hyp =
+ Proofview.Goal.enter begin fun gl ->
+ let gl = Proofview.Goal.assume gl in
+ let find_eq_data_decompose = find_eq_data_decompose gl in
+ let (_,_,c) = pf_get_hyp hyp gl in
+ let _,_,(_,x,y) = find_eq_data_decompose c in
+ (* J.F.: added to prevent failure on goal containing x=x as an hyp *)
+ if Term.eq_constr x y then Proofview.tclUNIT () else
+ match kind_of_term x, kind_of_term y with
+ | Var x', _ when not (occur_term x y) ->
+ subst_one flags.rewrite_dependent_proof x' (hyp,y,true)
+ | _, Var y' when not (occur_term y x) ->
+ subst_one flags.rewrite_dependent_proof y' (hyp,x,false)
+ | _ ->
+ Proofview.tclUNIT ()
+ end
+ in
+ Proofview.Goal.nf_enter begin fun gl ->
+ let ids = find_equations gl in
+ tclMAP process ids
+ end
+
+ else
+
+(* Old implementation, not able to manage configurations like a=b, a=t,
+ or situations like "a = S b, b = S a", or also accidentally unfolding
+ let-ins *)
Proofview.Goal.nf_enter begin fun gl ->
let find_eq_data_decompose = find_eq_data_decompose gl in
let test (_,c) =
@@ -1674,8 +1746,7 @@ let subst_all ?(flags=default_subst_tactic_flags ()) () =
if Term.eq_constr x y then failwith "caught";
match kind_of_term x with Var x -> x | _ ->
match kind_of_term y with Var y -> y | _ -> failwith "caught"
- with Constr_matching.PatternMatchingFailure -> failwith "caught"
- in
+ with Constr_matching.PatternMatchingFailure -> failwith "caught" in
let test p = try Some (test p) with Failure _ -> None in
let hyps = pf_hyps_types gl in
let ids = List.map_filter test hyps in