diff --git a/library/init/meta/tactic.lean b/library/init/meta/tactic.lean
index 0a6898d09e..9863d414ee 100644
--- a/library/init/meta/tactic.lean
+++ b/library/init/meta/tactic.lean
@@ -363,9 +363,10 @@ structure apply_cfg :=
(opt_param := tt)
/-- Apply the expression `e` to the main goal,
the unification is performed using the transparency mode in `cfg`.
- If cfg.approx is `tt`, then fallback to first-order unification, and approximate context during unification.
- If cfg.all is `tt`, then all unassigned meta-variables are added as new goals.
- If cfg.use_instances is `tt`, then use type class resolution to instantiate unassigned meta-variables.
+ If `cfg.approx` is `tt`, then fallback to first-order unification, and approximate context during unification.
+ `cfg.new_goals` specifies which unassigned metavariables become new goals, and their order.
+ If `cfg.instances` is `tt`, then use type class resolution to instantiate unassigned meta-variables.
+ The fields `cfg.auto_param` and `cfg.opt_param` are ignored by this tactic (See `tactic.apply`).
It returns a list of all introduced meta variables, even the assigned ones. -/
meta constant apply_core (e : expr) (cfg : apply_cfg := {}) : tactic (list expr)
/- Create a fresh meta universe variable. -/
@@ -810,14 +811,38 @@ meta def done : tactic unit :=
do n ← num_goals,
when (n ≠ 0) (fail "done tactic failed, there are unsolved goals")
-meta def apply (e : expr) : tactic unit :=
-apply_core e >> return ()
+meta def apply_opt_param : tactic unit :=
+do `(opt_param %%t %%v) ← target,
+ exact v
+
+meta def apply_auto_param : tactic unit :=
+do `(auto_param %%type %%tac_name_expr) ← target,
+ change type,
+ tac_name ← eval_expr name tac_name_expr,
+ tac ← eval_expr (tactic unit) (expr.const tac_name []),
+ tac
+
+meta def has_opt_auto_param (ms : list expr) : tactic bool :=
+ms.mfoldl
+ (λ r m, do type ← infer_type m,
+ return $ r || type.is_napp_of `opt_param 2 || type.is_napp_of `auto_param 2)
+ ff
+
+private meta def try_apply_opt_auto_param (cfg : apply_cfg) (ms : list expr) : tactic unit :=
+when (cfg.auto_param || cfg.opt_param) $
+mwhen (has_opt_auto_param ms) $ do
+ gs ← get_goals,
+ ms.mfor' (λ m, set_goals [m] >> try apply_opt_param >> try apply_auto_param),
+ set_goals gs
+
+meta def apply (e : expr) (cfg : apply_cfg := {}) : tactic unit :=
+apply_core e cfg >>= try_apply_opt_auto_param cfg
meta def fapply (e : expr) : tactic unit :=
-apply_core e {new_goals := new_goals.all} >> return ()
+apply e {new_goals := new_goals.all}
meta def eapply (e : expr) : tactic unit :=
-apply_core e {new_goals := new_goals.non_dep_only} >> return ()
+apply e {new_goals := new_goals.non_dep_only}
/-- Try to solve the main goal using type class resolution. -/
meta def apply_instance : tactic unit :=
@@ -1044,17 +1069,6 @@ updateex_env $ λe, e.add_inductive n ls p ty is is_meta
meta def add_meta_definition (n : name) (lvls : list name) (type value : expr) : tactic unit :=
add_decl (declaration.defn n lvls type value reducibility_hints.abbrev ff)
-meta def apply_opt_param : tactic unit :=
-do `(opt_param %%t %%v) ← target,
- exact v
-
-meta def apply_auto_param : tactic unit :=
-do `(auto_param %%type %%tac_name_expr) ← target,
- change type,
- tac_name ← eval_expr name tac_name_expr,
- tac ← eval_expr (tactic unit) (expr.const tac_name []),
- tac
-
meta def rename (curr : name) (new : name) : tactic unit :=
do h ← get_local curr,
n ← revert h,
diff --git a/src/library/tactic/apply_tactic.cpp b/src/library/tactic/apply_tactic.cpp
index e81e3eae0c..f17b33d31b 100644
--- a/src/library/tactic/apply_tactic.cpp
+++ b/src/library/tactic/apply_tactic.cpp
@@ -77,18 +77,6 @@ bool try_instance(type_context & ctx, expr const & meta, tactic_state const & s,
return true;
}
-bool try_auto_param(type_context & /* ctx */, expr const & /* meta */,
- tactic_state const & /* s */, vm_obj * /* out_error_obj */, char const * /* tac_name */) {
- // TODO(Leo)
- return true;
-}
-
-bool try_opt_param(type_context & /* ctx */, expr const & /* meta */,
- tactic_state const & /* s */, vm_obj * /* out_error_obj */, char const * /* tac_name */) {
- // TODO(Leo)
- return true;
-}
-
/** \brief Given a sequence metas/goals: (?m_1 ...) (?m_2 ... ) ... (?m_k ...),
we say ?m_i is "redundant" if it occurs in the type of some ?m_j.
This procedure removes from metas any redundant element. */
@@ -184,17 +172,6 @@ static optional apply(type_context & ctx, expr e, apply_cfg const
return none_tactic_state();
}
}
- /* Synthesize using auto_param and opt_param */
- if (cfg.m_opt_param || cfg.m_auto_param) {
- unsigned i = metas.size();
- while (i > 0) {
- --i;
- if (cfg.m_opt_param && !try_opt_param(ctx, metas[i], s, out_error_obj, "apply"))
- return none_tactic_state();
- if (cfg.m_auto_param && !try_auto_param(ctx, metas[i], s, out_error_obj, "apply"))
- return none_tactic_state();
- }
- }
/* Collect unassigned meta-variables */
buffer new_goals;
for (auto m : metas) {
diff --git a/tests/lean/apply_tac.lean b/tests/lean/apply_tac.lean
index e07d2c7653..f991cfc046 100644
--- a/tests/lean/apply_tac.lean
+++ b/tests/lean/apply_tac.lean
@@ -38,3 +38,31 @@ begin
apply le_refl,
apply le_refl
end
+
+def f (a := 10) : ℕ := a + 1
+
+def bla : nat :=
+begin
+ apply f -- uses opt_param for solving goal
+end
+
+example : bla = 11 :=
+rfl
+
+open tactic
+
+lemma foo {a b c : nat} (h₁ : a = b) (h₂ : b = c . assumption) : a = c :=
+eq.trans h₁ h₂
+
+example (a b c : nat) (h₁ : a = b) (h₂ : b = c) : a = c :=
+begin
+ apply foo h₁ -- uses auto_param for solving goal
+end
+
+lemma my_div_self (a : nat) (h : a ≠ 0 . assumption) : a / a = 1 :=
+sorry
+
+example (a : nat) (h : a ≠ 0) : a / a = 1 :=
+begin
+ apply my_div_self -- uses auto_param for solving goal
+end
diff --git a/tests/lean/apply_tac.lean.expected.out b/tests/lean/apply_tac.lean.expected.out
index 5cb81f17a9..df238c1475 100644
--- a/tests/lean/apply_tac.lean.expected.out
+++ b/tests/lean/apply_tac.lean.expected.out
@@ -16,3 +16,4 @@ a : ℕ
⊢ ?m_1 = a
a : ℕ
⊢ a = a
+apply_tac.lean:62:0: warning: declaration 'my_div_self' uses sorry
diff --git a/tests/lean/run/apply_auto_opt.lean b/tests/lean/run/apply_auto_opt.lean
index d8109bc1d0..0827d2300b 100644
--- a/tests/lean/run/apply_auto_opt.lean
+++ b/tests/lean/run/apply_auto_opt.lean
@@ -6,7 +6,7 @@ a + b
def val1 : nat :=
begin
- apply @p,
+ refine @p _ _,
exact 2,
apply_opt_param
end