@@ -11,7 +11,7 @@ type wferr =
1111 | RHSLetRecMayOnlyBeFunction (Location . t )
1212 | NoLetRecMut (Location . t )
1313 | RationalZeroDenominator (Location . t )
14- | UnknownAttribute (string , Location . t )
14+ | UnknownAttribute (string , string , Location . t )
1515 | InvalidAttributeArity (string , int , Location . t )
1616 | AttributeDisallowed (string , Location . t )
1717 | LoopControlOutsideLoop (string , Location . t )
@@ -49,8 +49,8 @@ let prepare_error =
4949 errorf(~loc, "let rec may not be used with the `mut` keyword." )
5050 | RationalZeroDenominator (loc ) =>
5151 errorf(~loc, "Rational numbers may not have a denominator of zero." )
52- | UnknownAttribute (attr , loc ) =>
53- errorf(~loc, "Unknown attribute `% s `." , attr)
52+ | UnknownAttribute (attr_context , attr , loc ) =>
53+ errorf(~loc, "Unknown % s attribute `% s `." , attr_context , attr)
5454 | InvalidAttributeArity (attr , arity , loc ) =>
5555 switch (arity) {
5656 | 0 => errorf(~loc, "Attribute `% s ` expects no arguments." , attr)
@@ -300,35 +300,28 @@ type known_attribute = {
300300 arity: int ,
301301};
302302
303- let known_attributes = [
304- {name: "disableGC" , arity: 0 },
305- {name: "unsafe" , arity: 0 },
306- {name: "externalName" , arity: 1 },
307- ] ;
308-
309- let valid_attributes = (errs, super) => {
310- let enter_attribute =
311- ({Asttypes . attr_name: {txt, loc}, attr_args: args} as attr) => {
312- switch (List . find_opt(({name}) => name == txt, known_attributes)) {
313- | Some ({arity}) when List . length(args) != arity =>
314- errs := [ InvalidAttributeArity (txt, arity, loc), ... errs^ ]
315- | None => errs := [ UnknownAttribute (txt, loc), ... errs^ ]
316- | _ => ()
317- };
318- super. enter_attribute(attr);
303+ let disallowed_attributes = (errs, super) => {
304+ let validate_against_known = (attrs, known_attributes, context) => {
305+ List . iter(
306+ ({Asttypes . attr_name: {txt, loc}, attr_args: args}) => {
307+ switch (List . find_opt(({name}) => name == txt, known_attributes)) {
308+ | Some ({arity}) when List . length(args) != arity =>
309+ errs := [ InvalidAttributeArity (txt, arity, loc), ... errs^ ]
310+ | None => errs := [ UnknownAttribute (context, txt, loc), ... errs^ ]
311+ | _ => ()
312+ }
313+ },
314+ attrs,
315+ );
319316 };
320317
321- {
322- errs,
323- iter_hooks: {
324- ... super,
325- enter_attribute,
326- },
327- };
328- };
318+ let known_expr_attributes = [
319+ {name: "disableGC" , arity: 0 },
320+ {name: "unsafe" , arity: 0 },
321+ {name: "externalName" , arity: 1 },
322+ ] ;
329323
330- let disallowed_attributes = (errs, super) => {
331- let enter_expression = ({pexp_desc: desc, pexp_attributes: attrs} as e) => {
324+ let enter_expression = ({pexp_attributes: attrs} as e) => {
332325 switch (
333326 List . find_opt(
334327 ({Asttypes . attr_name: {txt}}) => txt == "externalName" ,
@@ -345,8 +338,10 @@ let disallowed_attributes = (errs, super) => {
345338 ]
346339 | None => ()
347340 };
341+ validate_against_known(attrs, known_expr_attributes, "expression" );
348342 super. enter_expression(e);
349343 };
344+
350345 let enter_toplevel_stmt =
351346 ({ptop_desc: desc, ptop_attributes: attrs} as top) => {
352347 switch (
@@ -399,15 +394,26 @@ let disallowed_attributes = (errs, super) => {
399394 }
400395 | None => ()
401396 };
397+ validate_against_known(attrs, known_expr_attributes, "top-level" );
402398 super. enter_toplevel_stmt(top);
403399 };
404400
401+ let enter_parsed_program = ({attributes} as prog) => {
402+ let known_module_attributes = [
403+ {name: "runtimeMode" , arity: 0 },
404+ {name: "noPervasives" , arity: 0 },
405+ ] ;
406+ validate_against_known(attributes, known_module_attributes, "module" );
407+ super. enter_parsed_program(prog);
408+ };
409+
405410 {
406411 errs,
407412 iter_hooks: {
408413 ... super,
409414 enter_expression,
410415 enter_toplevel_stmt,
416+ enter_parsed_program,
411417 },
412418 };
413419};
@@ -842,7 +848,6 @@ let well_formedness_checks = [
842848 only_functions_oh_rhs_letrec,
843849 no_letrec_mut,
844850 no_zero_denominator_rational,
845- valid_attributes,
846851 disallowed_attributes,
847852 no_loop_control_statement_outside_of_loop,
848853 malformed_return_statements,
0 commit comments