Skip to content

Commit a9268d2

Browse files
authored
Fix misplaced attribute warning when using external parser (and some cleanup) (oxcaml#101)
* Attributes are now tracked for warning 53 even when using a ppx My previous rework of warning 53 actually made it so that, if using a serialized parsetree, NO attributes are tracked for this warning. * fix @poll and @noalloc to use the new misplaced attributes system
1 parent 2b33f24 commit a9268d2

9 files changed

Lines changed: 138 additions & 31 deletions

File tree

lambda/translattribute.ml

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -260,12 +260,7 @@ let get_property_attribute l p =
260260
let attr = find_attribute (is_property_attribute p) l in
261261
parse_property_attribute attr p
262262

263-
let get_check_attribute l =
264-
List.filter_map (fun p ->
265-
match get_property_attribute l p with
266-
| Default_check -> None
267-
| a -> Some a)
268-
[Noalloc]
263+
let get_check_attribute l = get_property_attribute l Noalloc
269264

270265
let get_poll_attribute l =
271266
let attr = find_attribute is_poll_attribute l in
@@ -370,9 +365,11 @@ let add_check_attribute expr loc attributes =
370365
| Assume p -> Printf.sprintf "%s assume" (to_string p)
371366
| Default_check -> assert false
372367
in
373-
match expr, get_check_attribute attributes with
374-
| expr, [] -> expr
375-
| Lfunction({ attr = { stub = false } as attr } as funct), [check] ->
368+
match expr with
369+
| Lfunction({ attr = { stub = false } as attr } as funct) ->
370+
begin match get_check_attribute attributes with
371+
| Default_check -> expr
372+
| (Assert _ | Assume _) as check ->
376373
begin match attr.check with
377374
| Default_check -> ()
378375
| Assert Noalloc | Assume Noalloc ->
@@ -381,15 +378,8 @@ let add_check_attribute expr loc attributes =
381378
end;
382379
let attr = { attr with check } in
383380
lfunction_with_attr ~attr funct
384-
| expr, [check] ->
385-
Location.prerr_warning loc
386-
(Warnings.Misplaced_attribute (to_string check));
387-
expr
388-
| expr, a::b::_ ->
389-
Location.prerr_warning loc
390-
(Warnings.Duplicated_attribute
391-
(Printf.sprintf "%s/%s"(to_string a) (to_string b)));
392-
expr
381+
end
382+
| expr -> expr
393383

394384
let add_loop_attribute expr loc attributes =
395385
match expr with
@@ -424,9 +414,11 @@ let add_tmc_attribute expr loc attributes =
424414
| _ -> expr
425415

426416
let add_poll_attribute expr loc attributes =
427-
match expr, get_poll_attribute attributes with
428-
| expr, Default_poll -> expr
429-
| Lfunction({ attr = { stub = false } as attr } as funct), poll ->
417+
match expr with
418+
| Lfunction({ attr = { stub = false } as attr } as funct) ->
419+
begin match get_poll_attribute attributes with
420+
| Default_poll -> expr
421+
| Error_poll as poll ->
430422
begin match attr.poll with
431423
| Default_poll -> ()
432424
| Error_poll ->
@@ -438,10 +430,8 @@ let add_poll_attribute expr loc attributes =
438430
check_poll_local loc attr;
439431
let attr = { attr with inline = Never_inline; local = Never_local } in
440432
lfunction_with_attr ~attr funct
441-
| expr, Error_poll ->
442-
Location.prerr_warning loc
443-
(Warnings.Misplaced_attribute "error_poll");
444-
expr
433+
end
434+
| expr -> expr
445435

446436
(* Get the [@inlined] attribute payload (or default if not present). *)
447437
let get_inlined_attribute e =

parsing/ast_invariants.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ let iterator =
170170
"In object types, attaching attributes to inherited \
171171
subtypes is not allowed."
172172
in
173+
let attribute self attr =
174+
super.attribute self attr;
175+
Builtin_attributes.register_attr attr.attr_name
176+
in
173177
{ super with
174178
type_declaration
175179
; typ
@@ -185,6 +189,7 @@ let iterator =
185189
; signature_item
186190
; row_field
187191
; object_field
192+
; attribute
188193
}
189194

190195
let structure st = iterator.structure iterator st

parsing/builtin_attributes.ml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,12 @@ let builtin_attrs =
9292

9393
let is_builtin_attr s = Hashtbl.mem builtin_attrs s
9494

95-
let mk_internal ?(loc= !default_loc) name payload =
95+
let register_attr name =
9696
if is_builtin_attr name.txt
97-
then Attribute_table.add unused_attrs name ();
97+
then Attribute_table.replace unused_attrs name ()
98+
99+
let mk_internal ?(loc= !default_loc) name payload =
100+
register_attr name;
98101
Attr.mk ~loc name payload
99102

100103

parsing/builtin_attributes.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ val mk_internal:
4646
?loc:Location.t -> string Location.loc -> Parsetree.payload ->
4747
Parsetree.attribute
4848

49+
(** Used to record attributes that should be tracked for the purpose of
50+
misplaced attribute warnings. *)
51+
val register_attr: string Location.loc -> unit
52+
4953
(** Marks alert attributes used for the purposes of misplaced attribute
5054
warnings. Call this when moving things with alert attributes into the
5155
environment. *)

testsuite/tests/warnings/w53.compilers.reference

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@ File "w53.ml", line 12, characters 4-5:
66
12 | let h x = x [@inline] (* rejected *)
77
^
88
Warning 32 [unused-value-declaration]: unused value h.
9-
File "w53.ml", line 334, characters 2-33:
10-
334 | let x : int64 = 42L [@@noalloc] (* rejected *)
11-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12-
Warning 53 [misplaced-attribute]: the "noalloc" attribute cannot appear in this context
139
File "w53.ml", line 12, characters 14-20:
1410
12 | let h x = x [@inline] (* rejected *)
1511
^^^^^^
@@ -558,6 +554,10 @@ File "w53.ml", line 333, characters 19-26:
558554
333 | type s1 = Foo1 [@noalloc] (* rejected *)
559555
^^^^^^^
560556
Warning 53 [misplaced-attribute]: the "noalloc" attribute cannot appear in this context
557+
File "w53.ml", line 334, characters 25-32:
558+
334 | let x : int64 = 42L [@@noalloc] (* rejected *)
559+
^^^^^^^
560+
Warning 53 [misplaced-attribute]: the "noalloc" attribute cannot appear in this context
561561
File "w53.ml", line 336, characters 24-31:
562562
336 | external y : (int64 [@noalloc]) -> (int64 [@noalloc]) = "x" (* rejected *)
563563
^^^^^^^
@@ -590,3 +590,51 @@ File "w53.ml", line 352, characters 22-30:
590590
352 | let x : int = 42 [@@untagged] (* rejected *)
591591
^^^^^^^^
592592
Warning 53 [misplaced-attribute]: the "untagged" attribute cannot appear in this context
593+
File "w53.ml", line 359, characters 21-25:
594+
359 | type 'a t1 = 'a [@@poll error] (* rejected *)
595+
^^^^
596+
Warning 53 [misplaced-attribute]: the "poll" attribute cannot appear in this context
597+
File "w53.ml", line 360, characters 19-23:
598+
360 | type s1 = Foo1 [@poll error] (* rejected *)
599+
^^^^
600+
Warning 53 [misplaced-attribute]: the "poll" attribute cannot appear in this context
601+
File "w53.ml", line 361, characters 19-23:
602+
361 | val x : int64 [@@poll error] (* rejected *)
603+
^^^^
604+
Warning 53 [misplaced-attribute]: the "poll" attribute cannot appear in this context
605+
File "w53.ml", line 363, characters 24-28:
606+
363 | external y : (int64 [@poll error]) -> (int64 [@poll error]) = (* rejected *)
607+
^^^^
608+
Warning 53 [misplaced-attribute]: the "poll" attribute cannot appear in this context
609+
File "w53.ml", line 363, characters 49-53:
610+
363 | external y : (int64 [@poll error]) -> (int64 [@poll error]) = (* rejected *)
611+
^^^^
612+
Warning 53 [misplaced-attribute]: the "poll" attribute cannot appear in this context
613+
File "w53.ml", line 365, characters 39-43:
614+
365 | external z : int64 -> int64 = "x" [@@poll error] (* rejected *)
615+
^^^^
616+
Warning 53 [misplaced-attribute]: the "poll" attribute cannot appear in this context
617+
File "w53.ml", line 369, characters 21-25:
618+
369 | type 'a t1 = 'a [@@poll error] (* rejected *)
619+
^^^^
620+
Warning 53 [misplaced-attribute]: the "poll" attribute cannot appear in this context
621+
File "w53.ml", line 370, characters 19-23:
622+
370 | type s1 = Foo1 [@poll error] (* rejected *)
623+
^^^^
624+
Warning 53 [misplaced-attribute]: the "poll" attribute cannot appear in this context
625+
File "w53.ml", line 371, characters 25-29:
626+
371 | let x : int64 = 42L [@@poll error] (* rejected *)
627+
^^^^
628+
Warning 53 [misplaced-attribute]: the "poll" attribute cannot appear in this context
629+
File "w53.ml", line 374, characters 24-28:
630+
374 | external y : (int64 [@poll error]) -> (int64 [@poll error]) = (* rejected *)
631+
^^^^
632+
Warning 53 [misplaced-attribute]: the "poll" attribute cannot appear in this context
633+
File "w53.ml", line 374, characters 49-53:
634+
374 | external y : (int64 [@poll error]) -> (int64 [@poll error]) = (* rejected *)
635+
^^^^
636+
Warning 53 [misplaced-attribute]: the "poll" attribute cannot appear in this context
637+
File "w53.ml", line 376, characters 39-43:
638+
376 | external z : int64 -> int64 = "x" [@@poll error] (* rejected *)
639+
^^^^
640+
Warning 53 [misplaced-attribute]: the "poll" attribute cannot appear in this context

testsuite/tests/warnings/w53.ml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,3 +355,23 @@ module TestUntaggedStruct = struct
355355
external z : int -> int = "x" "y" [@@untagged] (* accepted *)
356356
end
357357

358+
module type TestPollSig = sig
359+
type 'a t1 = 'a [@@poll error] (* rejected *)
360+
type s1 = Foo1 [@poll error] (* rejected *)
361+
val x : int64 [@@poll error] (* rejected *)
362+
363+
external y : (int64 [@poll error]) -> (int64 [@poll error]) = (* rejected *)
364+
"x"
365+
external z : int64 -> int64 = "x" [@@poll error] (* rejected *)
366+
end
367+
368+
module TestPollStruct = struct
369+
type 'a t1 = 'a [@@poll error] (* rejected *)
370+
type s1 = Foo1 [@poll error] (* rejected *)
371+
let x : int64 = 42L [@@poll error] (* rejected *)
372+
let [@poll error] f x = x (* accepted *)
373+
374+
external y : (int64 [@poll error]) -> (int64 [@poll error]) = (* rejected *)
375+
"x"
376+
external z : int64 -> int64 = "x" [@@poll error] (* rejected *)
377+
end
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
open Ast_mapper
2+
3+
let replace_attr ({ Parsetree.attr_name; _} as attr) =
4+
{ attr with
5+
attr_name =
6+
if String.equal attr.attr_name.txt "test" then
7+
{ attr_name with txt = "immediate" }
8+
else attr_name
9+
}
10+
11+
let () =
12+
register "test" (fun _ ->
13+
{ default_mapper with attribute = fun _ attr -> replace_attr attr })
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
File "w53_with_ppx.ml", line 18, characters 13-17:
2+
18 | let x = 3 [@@test]
3+
^^^^
4+
Warning 53 [misplaced-attribute]: the "immediate" attribute cannot appear in this context
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
(* TEST
2+
readonly_files = "w53_ppx.ml"
3+
include ocamlcommon
4+
* setup-ocamlc.byte-build-env
5+
** ocamlc.byte
6+
program = "${test_build_directory}/w53_ppx.exe"
7+
all_modules = "w53_ppx.ml"
8+
*** ocamlc.byte
9+
module = "w53_with_ppx.ml"
10+
flags = "-ppx ${program}"
11+
**** check-ocamlc.byte-output
12+
*)
13+
14+
(* This test checks that compiler-builtin attributes inserted by a ppx still
15+
trigger the misplaced attribute warning if they are unused (and not if
16+
they are used). *)
17+
18+
let x = 3 [@@test]
19+
20+
type t = int [@@test]

0 commit comments

Comments
 (0)