New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tactics in terms sometimes run twice on failure, giving exponential slowdown in failing cases #6252
Comments
Random thought: could that come from the pattern-matching compilation algorithm? Otherwise I don't see what in tactics-in-term could produce that... |
Is there a way to trace pattern matching compilation? |
Oh, this is fascinating. This prints "fail" twice: Ltac foo _ :=
idtac "begin";
try (let v := constr:(match (1+1)%nat with
| _ => ltac:(idtac "fail";
let f := constr:(I : I) in
exact True)
| _ => True
end) in
pose v);
idtac "end".
Goal True.
foo (). while this: Ltac foo _ :=
idtac "begin";
try (let v := constr:(match (1+1)%nat with
| _ => True
| _ => ltac:(idtac "fail";
let f := constr:(I : I) in
exact True)
end) in
pose v);
idtac "end".
Goal True.
foo (). raises the uncatchable error "This clause is redundant." |
This looks like a likely candidate: Lines 1530 to 1549 in 8d176db
|
And, indeed, we have coq/pretyping/pretype_errors.ml Lines 64 to 67 in 8d176db
which seems to match pretty well with which errors are which |
The magic of control by side-effect. |
Sorry for late answer, I did not realize it was about Indeed, the algorithm for pattern-matching compilation is potentially "exponential" in that it may try two different forms of return clauses. If you give the return clause explicitly, it will write "fail" only once: Definition a x := match x return Prop with
| O => ltac:(idtac "fail";
let f := constr:(I : I) in
exact True)
| S _ => True
end. There were some attemps to unify the two attempts into one but the unification was not strong enough to handle the both forms into one. There is another source of backtrack which is the one you highlighted (in Definition a x := match x with
| S (S y as z) => ltac:(idtac "fail";
let f := constr:(I : I) in
exact True)
| _ => True
end.
(* "fail" printed four times *) For this second source of backtrack, it would be good to do something too. |
@herbelin Thanks! Indeed, adding This is fairly surprising though, I think. I think the default behavior should be that tactics in terms in matches get run only once. It might be the case that being able to interleave tactic backtracking and pattern match compilation backtracking is useful (but I'm dubious). At the very least, the user should have to explicitly specify that they want this behavior, at the site of pattern match compilation / tactic usage, to get it. |
This time without exponential slowdown in failure cases and without needing to manually think up all of the possible errors and write them out. Possible thanks to Hugo's comment at coq/coq#6252 (comment)
This time without exponential slowdown in failure cases and without needing to manually think up all of the possible errors and write them out. Possible thanks to Hugo's comment at coq/coq#6252 (comment)
This time without exponential slowdown in failure cases and without needing to manually think up all of the possible errors and write them out. Possible thanks to Hugo's comment at coq/coq#6252 (comment)
* [demo] Add reification in src/Experiments/SimplyTypedArithmetic.v It's rather verbose, unfortunately. The reification also doesn't have any of the nice debugging features of the version of reification in Compilers, because that's even more boilerplate. Not sure if I should add that back in, at the moment. Also, for some strange reason, places where `constr`s fail to typecheck seem to induce backtracking where I don't think they should, and I'm not sure what's going on... * [demo] Add more namespacing * Update llet notation, update is_known_const name As per code review suggestions * Namespace var_context, add some coqbug references * Rename is_type_arg to is_template_parameter As per #275 (comment) * Simplify the logic around delayed arguments a bit We no longer pass around dummy markers in the tuple of arguments. * [demo] More informative reification error messages This time without exponential slowdown in failure cases and without needing to manually think up all of the possible errors and write them out. Possible thanks to Hugo's comment at coq/coq#6252 (comment) * [demo] respond to code review, add comments * Update documentation with suggestions from Andres
@JasonGross Is it still high priority? |
Version
8.7.0
Operating system
Linux
Description of the problem
Consider this:
If I nest this, I can see exponential growth in the number of times a tactic is run. All of these elements seem to be important:
match
,fail
does not trigger double execution, butidtac k
(fork
unbound) does, as does trying to run a constr as a tactic;rewrite Datatypes.S
triggers double execution, butrewrite H
(for unboundH
) does not),This shows up in my reification routine, and it is hard to work around in a way that preserves error messages.
The text was updated successfully, but these errors were encountered: