aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pretyping/termops.ml5
-rw-r--r--pretyping/termops.mli1
-rw-r--r--pretyping/unification.ml28
-rw-r--r--tactics/tactics.ml5
4 files changed, 31 insertions, 8 deletions
diff --git a/pretyping/termops.ml b/pretyping/termops.ml
index 67559e686..c68f2c4d9 100644
--- a/pretyping/termops.ml
+++ b/pretyping/termops.ml
@@ -575,6 +575,11 @@ let dependent_no_evar = dependent_main true false
let dependent_univs = dependent_main false true
let dependent_univs_no_evar = dependent_main true true
+let dependent_in_decl a (_,c,t) =
+ match c with
+ | None -> dependent a t
+ | Some body -> dependent a body || dependent a t
+
let count_occurrences m t =
let n = ref 0 in
let rec countrec m t =
diff --git a/pretyping/termops.mli b/pretyping/termops.mli
index 72a115231..ebcf4285c 100644
--- a/pretyping/termops.mli
+++ b/pretyping/termops.mli
@@ -110,6 +110,7 @@ val dependent : constr -> constr -> bool
val dependent_no_evar : constr -> constr -> bool
val dependent_univs : constr -> constr -> bool
val dependent_univs_no_evar : constr -> constr -> bool
+val dependent_in_decl : constr -> named_declaration -> bool
val count_occurrences : constr -> constr -> int
val collect_metas : constr -> int list
val collect_vars : constr -> Id.Set.t (** for visible vars only *)
diff --git a/pretyping/unification.ml b/pretyping/unification.ml
index dbdc0a4e4..9baabae77 100644
--- a/pretyping/unification.ml
+++ b/pretyping/unification.ml
@@ -7,6 +7,7 @@
(************************************************************************)
open Errors
+open Pp
open Util
open Names
open Term
@@ -1180,6 +1181,17 @@ let occurrences_of_goal cls =
let in_every_hyp cls = Option.is_empty cls.onhyps
+let indirectly_dependent c d decls =
+ not (isVar c) &&
+ (* This test is not needed if the original term is a variable, but
+ it is needed otherwise, as e.g. when abstracting over "2" in
+ "forall H:0=2, H=H:>(0=1+1) -> 0=2." where there is now obvious
+ way to see that the second hypothesis depends indirectly over 2 *)
+ List.exists (fun (id,_,_) -> dependent_in_decl (mkVar id) d) decls
+
+let indirect_dependency d decls =
+ pi1 (List.hd (List.filter (fun (id,_,_) -> dependent_in_decl (mkVar id) d) decls))
+
let finish_evar_resolution ?(flags=Pretyping.all_and_fail_flags) env initial_sigma (sigma,c) =
let sigma = Pretyping.solve_remaining_evars flags env initial_sigma sigma
in Evd.evar_universe_context sigma, nf_evar sigma c
@@ -1250,10 +1262,20 @@ let make_abstraction_core name (test,out) (sigmac,c) ty occs check_occs env conc
in
let compute_dependency _ (hyp,_,_ as d) depdecls =
match occurrences_of_hyp hyp occs with
- | None -> depdecls
+ | None ->
+ if indirectly_dependent c d depdecls then
+ (* Told explicitly not to abstract over [d], but it is dependent *)
+ let id' = indirect_dependency d depdecls in
+ errorlabstrm "" (str "Cannot abstract over " ++ Nameops.pr_id id'
+ ++ str " without also abstracting or erasing " ++ Nameops.pr_id hyp
+ ++ str ".")
+ else
+ depdecls
| Some ((AllOccurrences, InHyp) as occ) ->
let newdecl = subst_closed_term_occ_decl_modulo occ test d in
- if Context.eq_named_declaration d newdecl then
+ if Context.eq_named_declaration d newdecl
+ && not (indirectly_dependent c d depdecls)
+ then
if check_occs && not (in_every_hyp occs)
then raise (PretypeError (env,sigmac,NoOccurrenceFound (c,Some hyp)))
else depdecls
@@ -1280,7 +1302,7 @@ let make_abstraction_core name (test,out) (sigmac,c) ty occs check_occs env conc
or pattern at some occurrences; it returns:
- the id used for the abstraction
- the type of the abstraction
- - the hypotheses from the context which depend on the term or pattern
+ - the declarations from the context which depend on the term or pattern
- the most recent hyp before which there is no dependency in the term of pattern
- the abstracted conclusion
- an evar universe context effect to apply on the goal
diff --git a/tactics/tactics.ml b/tactics/tactics.ml
index 450b48d45..30568edab 100644
--- a/tactics/tactics.ml
+++ b/tactics/tactics.ml
@@ -660,11 +660,6 @@ let rec intros_move = function
Tacticals.New.tclTHEN (intro_gen dloc (IntroMustBe hyp) destopt false false)
(intros_move rest)
-let dependent_in_decl a (_,c,t) =
- match c with
- | None -> dependent a t
- | Some body -> dependent a body || dependent a t
-
(* Apply a tactic on a quantified hypothesis, an hypothesis in context
or a term with bindings *)