Skip to content

Commit 6ed7f37

Browse files
authored
flambda-backend: Zero alloc: assume error means never raises (#2512)
* Add Builtin_attributes.check_attribute.never_raises field * Add a test for "assume error" * "error" implies "div=safe" * fmt * Add a comment that explains the intended meaning of [never_raises] never lets exceptions escape * Update comment in test
1 parent 4220d48 commit 6ed7f37

File tree

9 files changed

+30
-10
lines changed

9 files changed

+30
-10
lines changed

lambda/lambda.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,7 @@ type check_attribute = Builtin_attributes.check_attribute =
640640
| Assume of { property: property;
641641
strict: bool;
642642
never_returns_normally: bool;
643+
never_raises: bool;
643644
arity: int;
644645
loc: Location.t;
645646
}

lambda/lambda.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,7 @@ type check_attribute = Builtin_attributes.check_attribute =
521521
| Assume of { property: property;
522522
strict: bool;
523523
never_returns_normally: bool;
524+
never_raises: bool;
524525
arity: int;
525526
loc: Location.t;
526527
}

parsing/builtin_attributes.ml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,7 @@ type check_attribute =
691691
| Assume of { property: property;
692692
strict: bool;
693693
never_returns_normally: bool;
694+
never_raises: bool;
694695
arity: int;
695696
loc: Location.t;
696697
}
@@ -825,6 +826,7 @@ let zero_alloc_lookup_table =
825826
(["assume"],
826827
fun arity loc ->
827828
Assume { property; strict = false; never_returns_normally = false;
829+
never_raises = false;
828830
arity; loc; });
829831
(["strict"],
830832
fun arity loc ->
@@ -838,18 +840,22 @@ let zero_alloc_lookup_table =
838840
(["assume"; "strict"],
839841
fun arity loc ->
840842
Assume { property; strict = true; never_returns_normally = false;
843+
never_raises = false;
841844
arity; loc; });
842845
(["assume"; "never_returns_normally"],
843846
fun arity loc ->
844847
Assume { property; strict = false; never_returns_normally = true;
848+
never_raises = false;
845849
arity; loc; });
846850
(["assume"; "never_returns_normally"; "strict"],
847851
fun arity loc ->
848852
Assume { property; strict = true; never_returns_normally = true;
853+
never_raises = false;
849854
arity; loc; });
850855
(["assume"; "error"],
851856
fun arity loc ->
852-
Assume { property; strict = false; never_returns_normally = true;
857+
Assume { property; strict = true; never_returns_normally = true;
858+
never_raises = true;
853859
arity; loc; });
854860
(["ignore"], fun _ _ -> Ignore_assert_all property)
855861
]
@@ -926,8 +932,8 @@ let assume_zero_alloc ~is_check_allowed check : Zero_alloc_utils.Assume_info.t =
926932
match check with
927933
| Default_check -> Zero_alloc_utils.Assume_info.none
928934
| Ignore_assert_all Zero_alloc -> Zero_alloc_utils.Assume_info.none
929-
| Assume { property=Zero_alloc; strict; never_returns_normally; } ->
930-
Zero_alloc_utils.Assume_info.create ~strict ~never_returns_normally
935+
| Assume { property=Zero_alloc; strict; never_returns_normally; never_raises; } ->
936+
Zero_alloc_utils.Assume_info.create ~strict ~never_returns_normally ~never_raises
931937
| Check { property=Zero_alloc; loc; _ } ->
932938
if not is_check_allowed then begin
933939
let name = "zero_alloc" in

parsing/builtin_attributes.mli

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,11 @@ type check_attribute =
257257
| Assume of { property: property;
258258
strict: bool;
259259
never_returns_normally: bool;
260+
never_raises: bool;
261+
(* [never_raises=true] the function never returns
262+
via an exception. The function (directly or transitively)
263+
may raise exceptions that do not escape, i.e.,
264+
handled before the function returns. *)
260265
arity: int;
261266
loc: Location.t;
262267
}

typing/includecore.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,10 @@ let zero_alloc za1 za2 =
117117
| Default_check | Ignore_assert_all _ -> ZA.Assume_info.Value.top ()
118118
| Check { strict; _ } ->
119119
ZA.Assume_info.Value.of_annotation ~strict ~never_returns_normally:false
120-
| Assume { strict; never_returns_normally } ->
120+
~never_raises:false
121+
| Assume { strict; never_returns_normally; never_raises; } ->
121122
ZA.Assume_info.Value.of_annotation ~strict ~never_returns_normally
123+
~never_raises
122124
in
123125
let v1 = abstract_value za1 in
124126
let v2 = abstract_value za2 in

typing/typecore.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5087,6 +5087,7 @@ let zero_alloc_of_application ~num_args attrs funct =
50875087
property = Zero_alloc;
50885088
strict = c.strict;
50895089
never_returns_normally = false;
5090+
never_raises = false;
50905091
arity = c.arity;
50915092
loc = c.loc
50925093
}

typing/typemod.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2816,7 +2816,8 @@ and type_structure ?(toplevel = None) funct_body anchor env sstr =
28162816
| Default_check | Ignore_assert_all _ -> Default_check
28172817
| Check _ -> zero_alloc
28182818
| Assume { property; strict; arity; loc;
2819-
never_returns_normally = _ } ->
2819+
never_returns_normally = _;
2820+
never_raises = _} ->
28202821
Check { strict; property; arity; loc; opt = false }
28212822
in
28222823
let (first_loc, _, _) = List.hd id_info in

utils/zero_alloc_utils.ml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,9 @@ module Make (Witnesses : WS) = struct
137137

138138
let relaxed w = { nor = V.Safe; exn = V.Top w; div = V.Top w }
139139

140-
let of_annotation ~strict ~never_returns_normally =
140+
let of_annotation ~strict ~never_returns_normally ~never_raises =
141141
let res = if strict then safe else relaxed Witnesses.empty in
142+
let res = if never_raises then { res with exn = V.Bot } else res in
142143
if never_returns_normally then { res with nor = V.Bot } else res
143144

144145
let print ~witnesses ppf { nor; exn; div } =
@@ -211,8 +212,8 @@ module Assume_info = struct
211212

212213
let none = No_assume
213214

214-
let create ~strict ~never_returns_normally =
215-
Assume (Value.of_annotation ~strict ~never_returns_normally)
215+
let create ~strict ~never_returns_normally ~never_raises =
216+
Assume (Value.of_annotation ~strict ~never_returns_normally ~never_raises)
216217

217218
let get_value t = match t with No_assume -> None | Assume v -> Some v
218219

utils/zero_alloc_utils.mli

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ module Make (Witnesses : WS) : sig
8383
val relaxed : Witnesses.t -> t
8484

8585
(** Constructs a value from a user annotation. The witness will be empty. *)
86-
val of_annotation : strict:bool -> never_returns_normally:bool -> t
86+
val of_annotation :
87+
strict:bool -> never_returns_normally:bool -> never_raises:bool -> t
8788

8889
val print : witnesses:bool -> Format.formatter -> t -> unit
8990

@@ -113,7 +114,8 @@ module Assume_info : sig
113114

114115
val none : t
115116

116-
val create : strict:bool -> never_returns_normally:bool -> t
117+
val create :
118+
strict:bool -> never_returns_normally:bool -> never_raises:bool -> t
117119

118120
val compare : t -> t -> int
119121

0 commit comments

Comments
 (0)