diff options
-rw-r--r-- | plugins/funind/functional_principles_proofs.ml | 2 | ||||
-rw-r--r-- | plugins/funind/recdef.ml | 2 | ||||
-rw-r--r-- | pretyping/namegen.mli | 3 | ||||
-rw-r--r-- | pretyping/termops.ml | 16 | ||||
-rw-r--r-- | pretyping/termops.mli | 2 | ||||
-rw-r--r-- | tactics/auto.ml | 54 | ||||
-rw-r--r-- | tactics/auto.mli | 30 | ||||
-rw-r--r-- | tactics/eauto.ml4 | 16 | ||||
-rw-r--r-- | tactics/eauto.mli | 7 | ||||
-rw-r--r-- | tactics/tacinterp.ml | 13 | ||||
-rw-r--r-- | test-suite/success/auto.v | 8 |
11 files changed, 108 insertions, 45 deletions
diff --git a/plugins/funind/functional_principles_proofs.ml b/plugins/funind/functional_principles_proofs.ml index 43658e802..e047f13d5 100644 --- a/plugins/funind/functional_principles_proofs.ml +++ b/plugins/funind/functional_principles_proofs.ml @@ -1450,7 +1450,7 @@ let new_prove_with_tcc is_mes acc_inv hrec tcc_hyps eqs : tactic = Eauto.eauto_with_bases false (true,5) - [Lazy.force refl_equal] + [Evd.empty,Lazy.force refl_equal] [Auto.Hint_db.empty empty_transparent_state false] ) ) diff --git a/plugins/funind/recdef.ml b/plugins/funind/recdef.ml index 057ffb9b3..f066e39d0 100644 --- a/plugins/funind/recdef.ml +++ b/plugins/funind/recdef.ml @@ -1005,7 +1005,7 @@ let open_new_goal (build_proof:tactic -> tactic -> unit) using_lemmas ref_ goal_ Eauto.eauto_with_bases false (true,5) - [delayed_force refl_equal] + [Evd.empty,delayed_force refl_equal] [Auto.Hint_db.empty empty_transparent_state false] ] ) diff --git a/pretyping/namegen.mli b/pretyping/namegen.mli index 8849c9ed3..0c9fc4f6b 100644 --- a/pretyping/namegen.mli +++ b/pretyping/namegen.mli @@ -39,6 +39,9 @@ val it_mkLambda_or_LetIn_name : env -> constr -> rel_context -> constr (********************************************************************* Fresh names *) +(** Avoid clashing with a name satisfying some predicate *) +val next_ident_away_from : identifier -> (identifier -> bool) -> identifier + (** Avoid clashing with a name of the given list *) val next_ident_away : identifier -> identifier list -> identifier diff --git a/pretyping/termops.ml b/pretyping/termops.ml index d31242aa2..9888821d1 100644 --- a/pretyping/termops.ml +++ b/pretyping/termops.ml @@ -262,6 +262,14 @@ let rec strip_head_cast c = match kind_of_term c with | Cast (c,_,_) -> strip_head_cast c | _ -> c +let rec drop_extra_implicit_args c = match kind_of_term c with + (* Removed trailing extra implicit arguments, what improves compatibility + for constants with recently added maximal implicit arguments *) + | App (f,args) when isEvar (array_last args) -> + drop_extra_implicit_args + (mkApp (f,fst (array_chop (Array.length args - 1) args))) + | _ -> c + (* Get the last arg of an application *) let last_arg c = match kind_of_term c with | App (f,cl) -> array_last cl @@ -526,6 +534,14 @@ let collect_metas c = in List.rev (collrec [] c) +(* collects all vars; warning: this is only visible vars, not dependencies in + all section variables; for the latter, use global_vars_set *) +let collect_vars c = + let rec aux vars c = match kind_of_term c with + | Var id -> Idset.add id vars + | _ -> fold_constr aux vars c in + aux Idset.empty c + (* Tests whether [m] is a subterm of [t]: [m] is appropriately lifted through abstractions of [t] *) diff --git a/pretyping/termops.mli b/pretyping/termops.mli index 385bd3022..1350743d5 100644 --- a/pretyping/termops.mli +++ b/pretyping/termops.mli @@ -91,6 +91,7 @@ val iter_constr_with_full_binders : (**********************************************************************) val strip_head_cast : constr -> constr +val drop_extra_implicit_args : constr -> constr (** occur checks *) exception Occur @@ -107,6 +108,7 @@ val free_rels : constr -> Intset.t val dependent : constr -> constr -> bool val dependent_no_evar : constr -> constr -> bool val collect_metas : constr -> int list +val collect_vars : constr -> Idset.t (** for visible vars only *) val occur_term : constr -> constr -> bool (** Synonymous of dependent Substitution of metavariables *) diff --git a/tactics/auto.ml b/tactics/auto.ml index 8e77bb53f..440f92b7f 100644 --- a/tactics/auto.ml +++ b/tactics/auto.ml @@ -569,17 +569,43 @@ type hints_entry = | HintsDestructEntry of identifier * int * (bool,unit) location * (patvar list * constr_pattern) * glob_tactic_expr -let rec drop_extra_args c = match kind_of_term c with - (* Removed trailing extra implicit arguments, what improves compatibility - for constants with recently added maximal implicit arguments *) - | App (f,args) when isEvar (array_last args) -> - drop_extra_args (mkApp (f,fst (array_chop (Array.length args - 1) args))) - | _ -> c +let h = id_of_string "H" + +exception Found of constr * types + +let prepare_hint env (sigma,c) = + let sigma = Typeclasses.resolve_typeclasses ~fail:false env sigma in + (* We re-abstract over uninstantiated evars. + It is actually a bit stupid to generalize over evars since the first + thing make_resolves will do is to re-instantiate the products *) + let c = drop_extra_implicit_args (Evarutil.nf_evar sigma c) in + let vars = ref (collect_vars c) in + let subst = ref [] in + let rec find_next_evar c = match kind_of_term c with + | Evar (evk,args as ev) -> + (* We skip the test whether args is the identity or not *) + let t = Evarutil.nf_evar sigma (existential_type sigma ev) in + let t = List.fold_right (fun (e,id) c -> replace_term e id c) !subst t in + if free_rels t <> Intset.empty then + error "Hints with holes dependent on a bound variable not supported."; + if occur_existential t then + (* Not clever enough to construct dependency graph of evars *) + error "Not clever enough to deal with evars dependent in other evars."; + raise (Found (c,t)) + | _ -> iter_constr find_next_evar c in + let rec iter c = + try find_next_evar c; c + with Found (evar,t) -> + let id = next_ident_away_from h (fun id -> Idset.mem id !vars) in + vars := Idset.add id !vars; + subst := (evar,mkVar id)::!subst; + mkNamedLambda id t (iter (replace_term evar (mkVar id) c)) in + iter c let interp_hints h = let f c = let evd,c = Constrintern.interp_open_constr Evd.empty (Global.env()) c in - let c = drop_extra_args c in + let c = prepare_hint (Global.env()) (evd,c) in Evarutil.check_evars (Global.env()) Evd.empty evd c; c in let fr r = @@ -785,19 +811,19 @@ let unify_resolve_gen = function (* Util *) -let expand_constructor_hints lems = - list_map_append (fun lem -> +let expand_constructor_hints env lems = + list_map_append (fun (sigma,lem) -> match kind_of_term lem with | Ind ind -> list_tabulate (fun i -> mkConstruct (ind,i+1)) (nconstructors ind) | _ -> - [lem]) lems + [prepare_hint env (sigma,lem)]) lems (* builds a hint database from a constr signature *) (* typically used with (lid, ltyp) = pf_hyps_types <some goal> *) let add_hint_lemmas eapply lems hint_db gl = - let lems = expand_constructor_hints lems in + let lems = expand_constructor_hints (pf_env gl) lems in let hintlist' = list_map_append (pf_apply make_resolves gl (eapply,true,false) None) lems in Hint_db.add_list hintlist' hint_db @@ -958,7 +984,7 @@ let gen_trivial lems = function | Some l -> trivial lems l let h_trivial lems l = - Refiner.abstract_tactic (TacTrivial (lems,l)) + Refiner.abstract_tactic (TacTrivial (List.map snd lems,l)) (gen_trivial lems l) (**************************************************************************) @@ -1088,7 +1114,7 @@ let gen_auto n lems dbnames = let inj_or_var = Option.map (fun n -> ArgArg n) let h_auto n lems l = - Refiner.abstract_tactic (TacAuto (inj_or_var n,lems,l)) + Refiner.abstract_tactic (TacAuto (inj_or_var n,List.map snd lems,l)) (gen_auto n lems l) (**************************************************************************) @@ -1117,7 +1143,7 @@ let dauto (n,p) lems = let default_dauto = dauto (None,None) [] let h_dauto (n,p) lems = - Refiner.abstract_tactic (TacDAuto (inj_or_var n,p,lems)) + Refiner.abstract_tactic (TacDAuto (inj_or_var n,p,List.map snd lems)) (dauto (n,p) lems) (***************************************) diff --git a/tactics/auto.mli b/tactics/auto.mli index f4f7b9dfa..fa6f1d9ca 100644 --- a/tactics/auto.mli +++ b/tactics/auto.mli @@ -96,6 +96,8 @@ val interp_hints : hints_expr -> hints_entry val add_hints : locality_flag -> hint_db_name list -> hints_entry -> unit +val prepare_hint : env -> open_constr -> constr + val print_searchtable : unit -> unit val print_applicable_hint : unit -> unit @@ -112,7 +114,7 @@ val print_hint_db : Hint_db.t -> unit val make_exact_entry : evar_map -> int option -> constr * constr -> hint_entry -(** [make_apply_entry (eapply,verbose) pri (c,cty)]. +(** [make_apply_entry (eapply,hnf,verbose) pri (c,cty)]. [eapply] is true if this hint will be used only with EApply; [hnf] should be true if we should expand the head of cty before searching for products; @@ -163,7 +165,7 @@ val set_extern_subst_tactic : Useful to take the current goal hypotheses as hints; Boolean tells if lemmas with evars are allowed *) -val make_local_hint_db : bool -> constr list -> goal sigma -> hint_db +val make_local_hint_db : bool -> open_constr list -> goal sigma -> hint_db val priority : ('a * pri_auto_tactic) list -> ('a * pri_auto_tactic) list @@ -185,48 +187,48 @@ val conclPattern : constr -> constr_pattern option -> Tacexpr.glob_tactic_expr - (** The Auto tactic *) -val auto : int -> constr list -> hint_db_name list -> tactic +val auto : int -> open_constr list -> hint_db_name list -> tactic (** Auto with more delta. *) -val new_auto : int -> constr list -> hint_db_name list -> tactic +val new_auto : int -> open_constr list -> hint_db_name list -> tactic (** auto with default search depth and with the hint database "core" *) val default_auto : tactic (** auto with all hint databases except the "v62" compatibility database *) -val full_auto : int -> constr list -> tactic +val full_auto : int -> open_constr list -> tactic (** auto with all hint databases except the "v62" compatibility database and doing delta *) -val new_full_auto : int -> constr list -> tactic +val new_full_auto : int -> open_constr list -> tactic (** auto with default search depth and with all hint databases except the "v62" compatibility database *) val default_full_auto : tactic (** The generic form of auto (second arg [None] means all bases) *) -val gen_auto : int option -> constr list -> hint_db_name list option -> tactic +val gen_auto : int option -> open_constr list -> hint_db_name list option -> tactic (** The hidden version of auto *) -val h_auto : int option -> constr list -> hint_db_name list option -> tactic +val h_auto : int option -> open_constr list -> hint_db_name list option -> tactic (** Trivial *) -val trivial : constr list -> hint_db_name list -> tactic -val gen_trivial : constr list -> hint_db_name list option -> tactic -val full_trivial : constr list -> tactic -val h_trivial : constr list -> hint_db_name list option -> tactic +val trivial : open_constr list -> hint_db_name list -> tactic +val gen_trivial : open_constr list -> hint_db_name list option -> tactic +val full_trivial : open_constr list -> tactic +val h_trivial : open_constr list -> hint_db_name list option -> tactic val pr_autotactic : auto_tactic -> Pp.std_ppcmds (** {6 The following is not yet up to date -- Papageno. } *) (** DAuto *) -val dauto : int option * int option -> constr list -> tactic +val dauto : int option * int option -> open_constr list -> tactic val default_search_decomp : int ref val default_dauto : tactic -val h_dauto : int option * int option -> constr list -> tactic +val h_dauto : int option * int option -> open_constr list -> tactic (** SuperAuto *) diff --git a/tactics/eauto.ml4 b/tactics/eauto.ml4 index fab8d2d45..6f4d90ab4 100644 --- a/tactics/eauto.ml4 +++ b/tactics/eauto.ml4 @@ -68,6 +68,7 @@ let rec prolog l n gl = (tclFIRST (List.map (fun t -> (tclTHEN t prol)) (one_step l gl))) gl let prolog_tac l n gl = + let l = List.map (prepare_hint (pf_env gl)) l in let n = match n with | ArgArg n -> n @@ -78,7 +79,7 @@ let prolog_tac l n gl = errorlabstrm "Prolog.prolog" (str "Prolog failed.") TACTIC EXTEND prolog -| [ "prolog" "[" constr_list(l) "]" int_or_var(n) ] -> [ prolog_tac l n ] +| [ "prolog" "[" open_constr_list(l) "]" int_or_var(n) ] -> [ prolog_tac l n ] END open Auto @@ -345,19 +346,20 @@ ARGUMENT EXTEND hintbases | [ ] -> [ Some [] ] END -let pr_constr_coma_sequence prc _ _ = prlist_with_sep pr_comma prc +let pr_constr_coma_sequence prc _ _ = + prlist_with_sep pr_comma (fun (_,c) -> prc c) ARGUMENT EXTEND constr_coma_sequence - TYPED AS constr_list + TYPED AS open_constr_list PRINTED BY pr_constr_coma_sequence -| [ constr(c) "," constr_coma_sequence(l) ] -> [ c::l ] -| [ constr(c) ] -> [ [c] ] +| [ open_constr(c) "," constr_coma_sequence(l) ] -> [ c::l ] +| [ open_constr(c) ] -> [ [c] ] END -let pr_auto_using prc _prlc _prt = Pptactic.pr_auto_using prc +let pr_auto_using prc _prlc _prt = Pptactic.pr_auto_using (fun (_,c) -> prc c) ARGUMENT EXTEND auto_using - TYPED AS constr_list + TYPED AS open_constr_list PRINTED BY pr_auto_using | [ "using" constr_coma_sequence(l) ] -> [ l ] | [ ] -> [ [] ] diff --git a/tactics/eauto.mli b/tactics/eauto.mli index 093cd56e1..68ec42f4e 100644 --- a/tactics/eauto.mli +++ b/tactics/eauto.mli @@ -19,7 +19,7 @@ val hintbases : hint_db_name list option Pcoq.Gram.entry val wit_hintbases : hint_db_name list option typed_abstract_argument_type val rawwit_hintbases : hint_db_name list option raw_abstract_argument_type -val rawwit_auto_using : constr_expr list raw_abstract_argument_type +val rawwit_auto_using : Genarg.open_constr_expr list raw_abstract_argument_type val e_assumption : tactic @@ -27,13 +27,12 @@ val registered_e_assumption : tactic val e_give_exact : ?flags:Unification.unify_flags -> constr -> tactic -val gen_eauto : bool -> bool * int -> constr list -> +val gen_eauto : bool -> bool * int -> open_constr list -> hint_db_name list option -> tactic - val eauto_with_bases : bool -> bool * int -> - Term.constr list -> Auto.hint_db list -> Proof_type.tactic + open_constr list -> Auto.hint_db list -> Proof_type.tactic val autounfold : hint_db_name list -> Tacticals.clause -> tactic diff --git a/tactics/tacinterp.ml b/tactics/tacinterp.ml index a2caec7c5..d4ac859ad 100644 --- a/tactics/tacinterp.ml +++ b/tactics/tacinterp.ml @@ -1351,6 +1351,10 @@ let interp_open_constr_list = interp_constr_in_compound_list (fun x -> x) (fun x -> x) (interp_open_constr None) +let interp_auto_lemmas ist env sigma lems = + let local_sigma, lems = interp_open_constr_list ist env sigma lems in + List.map (fun lem -> (local_sigma,lem)) lems + (* Interprets a type expression *) let pf_interp_type ist gl = interp_type ist (pf_env gl) (project gl) @@ -2289,19 +2293,20 @@ and interp_atomic ist gl tac = (* Automation tactics *) | TacTrivial (lems,l) -> - Auto.h_trivial (interp_constr_list ist env sigma lems) + Auto.h_trivial + (interp_auto_lemmas ist env sigma lems) (Option.map (List.map (interp_hint_base ist)) l) | TacAuto (n,lems,l) -> Auto.h_auto (Option.map (interp_int_or_var ist) n) - (interp_constr_list ist env sigma lems) - (Option.map (List.map (interp_hint_base ist)) l) + (interp_auto_lemmas ist env sigma lems) + (Option.map (List.map (interp_hint_base ist)) l) | TacAutoTDB n -> Dhyp.h_auto_tdb n | TacDestructHyp (b,id) -> Dhyp.h_destructHyp b (interp_hyp ist gl id) | TacDestructConcl -> Dhyp.h_destructConcl | TacSuperAuto (n,l,b1,b2) -> Auto.h_superauto n l b1 b2 | TacDAuto (n,p,lems) -> Auto.h_dauto (Option.map (interp_int_or_var ist) n,p) - (interp_constr_list ist env sigma lems) + (interp_auto_lemmas ist env sigma lems) (* Derived basic tactics *) | TacSimpleInductionDestruct (isrec,h) -> diff --git a/test-suite/success/auto.v b/test-suite/success/auto.v index a2701f8bb..9b691e253 100644 --- a/test-suite/success/auto.v +++ b/test-suite/success/auto.v @@ -16,3 +16,11 @@ Goal G unit Q -> F (Q tt). intro. auto. Qed. + +(* Test implicit arguments in "using" clause *) + +Goal forall n:nat, nat * nat. +auto using (pair O). +Undo. +eauto using (pair O). +Qed. |