aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGaëtan Gilbert2019-06-26 11:53:11 +0200
committerGaëtan Gilbert2019-06-26 11:53:11 +0200
commit2c39a12f5a8d7178b991595324692c1596ea9199 (patch)
treebbc5acce352b7700362c269381cf11f21919af83
parent8c5b2b21d1285306343099e4776258722973f4de (diff)
parent8a6a3b4f6cbdaf2047ab30b7eaf451c166a874bc (diff)
Merge PR #9855: [Fail] Simplify `Fail` implementation.
Reviewed-by: SkySkimmer
-rw-r--r--vernac/vernacentries.ml48
1 files changed, 21 insertions, 27 deletions
diff --git a/vernac/vernacentries.ml b/vernac/vernacentries.ml
index dba9d5dfc5..2bcd06b4d9 100644
--- a/vernac/vernacentries.ml
+++ b/vernac/vernacentries.ml
@@ -2292,36 +2292,30 @@ let vernac_timeout ?timeout (f : 'a -> 'b) (x : 'a) : 'b =
f x
(* Fail *)
-exception HasNotFailed
-exception HasFailed of Pp.t
-
let test_mode = ref false
-(* XXX STATE: this type hints that restoring the state should be the
- caller's responsibility *)
-let with_fail ~st f =
+(* Restoring the state is the caller's responsibility *)
+let with_fail f : (Pp.t, unit) result =
try
- (* If the command actually works, ignore its effects on the state.
- * Note that error has to be printed in the right state, hence
- * within the purified function *)
- try let _ = f () in raise HasNotFailed
- with
- | HasNotFailed as e -> raise e
- | e when CErrors.noncritical e || e = Timeout ->
- let e = CErrors.push e in
- raise (HasFailed (CErrors.iprint (ExplainErr.process_vernac_interp_error e)))
- with e when CErrors.noncritical e ->
- (* Restore the previous state XXX Careful here with the cache! *)
- Vernacstate.invalidate_cache ();
- Vernacstate.unfreeze_interp_state st;
- let (e, _) = CErrors.push e in
- match e with
- | HasNotFailed ->
- user_err ~hdr:"Fail" (str "The command has not failed!")
- | HasFailed msg ->
- if not !Flags.quiet || !test_mode then Feedback.msg_info
- (str "The command has indeed failed with message:" ++ fnl () ++ msg)
- | _ -> assert false
+ let _ = f () in
+ Error ()
+ with
+ (* Fail Timeout is a common pattern so we need to support it. *)
+ | e when CErrors.noncritical e || e = Timeout ->
+ (* The error has to be printed in the failing state *)
+ Ok CErrors.(iprint ExplainErr.(process_vernac_interp_error (push e)))
+
+(* We restore the state always *)
+let with_fail ~st f =
+ let res = with_fail f in
+ Vernacstate.invalidate_cache ();
+ Vernacstate.unfreeze_interp_state st;
+ match res with
+ | Error () ->
+ user_err ~hdr:"Fail" (str "The command has not failed!")
+ | Ok msg ->
+ if not !Flags.quiet || !test_mode
+ then Feedback.msg_info (str "The command has indeed failed with message:" ++ fnl () ++ msg)
let locate_if_not_already ?loc (e, info) =
match Loc.get_loc info with