diff options
| author | Gaëtan Gilbert | 2019-06-26 11:53:11 +0200 |
|---|---|---|
| committer | Gaëtan Gilbert | 2019-06-26 11:53:11 +0200 |
| commit | 2c39a12f5a8d7178b991595324692c1596ea9199 (patch) | |
| tree | bbc5acce352b7700362c269381cf11f21919af83 | |
| parent | 8c5b2b21d1285306343099e4776258722973f4de (diff) | |
| parent | 8a6a3b4f6cbdaf2047ab30b7eaf451c166a874bc (diff) | |
Merge PR #9855: [Fail] Simplify `Fail` implementation.
Reviewed-by: SkySkimmer
| -rw-r--r-- | vernac/vernacentries.ml | 48 |
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 |
