Skip to content

Commit 1e2d5c5

Browse files
authored
flambda-backend: zero alloc: warning 198 about assume (#1409)
* Add warning 198 * Report warning 198 when "assume" is used unsafely on a function "assume" is safe only on functions that are annotated with [@inline never] and [@specialise never] * Fix existing tests * Add tests for warning 198 and warning 199 while we are at it
1 parent 9270fee commit 1e2d5c5

File tree

3 files changed

+40
-6
lines changed

3 files changed

+40
-6
lines changed

lambda/translattribute.ml

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -297,24 +297,45 @@ let get_local_attribute l =
297297
let attr = find_attribute is_local_attribute l in
298298
parse_local_attribute attr
299299

300-
let get_property_attribute l p =
300+
let get_property_attribute l p ~fun_attr =
301301
let attr = find_attribute (is_property_attribute p) l in
302302
let res = parse_property_attribute attr p in
303303
(match attr, res with
304304
| None, Default_check -> ()
305305
| _, Default_check -> ()
306306
| None, (Check _ | Ignore_assert_all _ ) -> assert false
307307
| Some _, Ignore_assert_all _ -> ()
308-
| Some attr, Check _ ->
308+
| Some attr, Check { assume; _ } ->
309309
if !Clflags.zero_alloc_check && !Clflags.native_code then
310310
(* The warning for unchecked functions will not trigger if the check is requested
311311
through the [@@@zero_alloc all] top-level annotation rather than through the
312312
function annotation [@zero_alloc]. *)
313-
Builtin_attributes.register_property attr.attr_name);
313+
if assume then begin
314+
(* [attr.inline] and [attr.specialise] must be set before the
315+
check for [Warnings.Misplaced_assume_attribute].
316+
For attributes from the same list, it's fine because
317+
[add_check_attribute] is called after
318+
[add_inline_attribute] and [add_specialise_attribute].
319+
The warning will spuriously fire in the following case:
320+
let[@inline never][@specialise never] f =
321+
fun[@zero_alloc assume] x -> ..
322+
*)
323+
let never_specialise =
324+
if Config.flambda then
325+
fun_attr.specialise = Never_specialise
326+
else
327+
(* closure drops [@specialise never] and never specialises *)
328+
(* flambda2 does not have specialisation support yet *)
329+
true
330+
in
331+
if not ((fun_attr.inline = Never_inline) && never_specialise) then
332+
Location.prerr_warning attr.attr_name.loc
333+
(Warnings.Misplaced_assume_attribute attr.attr_name.txt)
334+
end
335+
else
336+
Builtin_attributes.register_property attr.attr_name);
314337
res
315338

316-
let get_check_attribute l = get_property_attribute l Zero_alloc
317-
318339
let get_poll_attribute l =
319340
let attr = find_attribute is_poll_attribute l in
320341
parse_poll_attribute attr
@@ -425,7 +446,7 @@ let add_check_attribute expr loc attributes =
425446
in
426447
match expr with
427448
| Lfunction({ attr = { stub = false } as attr; } as funct) ->
428-
begin match get_check_attribute attributes with
449+
begin match get_property_attribute attributes Zero_alloc ~fun_attr:attr with
429450
| Default_check -> expr
430451
| (Ignore_assert_all p | Check { property = p; _ }) as check ->
431452
begin match attr.check with

utils/warnings.ml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ type t =
108108
| Unused_tmc_attribute (* 71 *)
109109
| Tmc_breaks_tailcall (* 72 *)
110110
| Probe_name_too_long of string (* 190 *)
111+
| Misplaced_assume_attribute of string (* 198 *)
111112
| Unchecked_property_attribute of string (* 199 *)
112113
;;
113114

@@ -192,6 +193,7 @@ let number = function
192193
| Unused_tmc_attribute -> 71
193194
| Tmc_breaks_tailcall -> 72
194195
| Probe_name_too_long _ -> 190
196+
| Misplaced_assume_attribute _ -> 198
195197
| Unchecked_property_attribute _ -> 199
196198
;;
197199

@@ -453,6 +455,10 @@ let descriptions = [
453455
{ number = 190;
454456
names = ["probe-name-too-long"];
455457
description = "Probe name must be at most 100 characters long." };
458+
{ number = 198;
459+
names = ["misplaced-assume-attribute"];
460+
description = "Assume of a property is ignored \
461+
if the function is inlined or specialised." };
456462
{ number = 199;
457463
names = ["unchecked-property-attribute"];
458464
description = "A property of a function that was \
@@ -1060,6 +1066,12 @@ let message = function
10601066
Printf.sprintf
10611067
"This probe name is too long: `%s'. \
10621068
Probe names must be at most 100 characters long." name
1069+
| Misplaced_assume_attribute property ->
1070+
Printf.sprintf
1071+
"the \"%s assume\" attribute will be ignored by the check \
1072+
when the function is inlined or specialised.\n\
1073+
Mark this function as [@inline never][@specialise never]."
1074+
property
10631075
| Unchecked_property_attribute property ->
10641076
Printf.sprintf "the %S attribute cannot be checked.\n\
10651077
The function it is attached to was optimized away. \n\

utils/warnings.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ type t =
111111
| Tmc_breaks_tailcall (* 72 *)
112112
(* Flambda_backend specific warnings: numbers should go down from 199 *)
113113
| Probe_name_too_long of string (* 190 *)
114+
| Misplaced_assume_attribute of string (* 198 *)
114115
| Unchecked_property_attribute of string (* 199 *)
115116
;;
116117

0 commit comments

Comments
 (0)