OCaml - Language extensions (original) (raw)

☰The OCaml language

Chapter 12 Language extensions

12 Attributes

(Introduced in OCaml 4.02, infix notations for constructs other than expressions added in 4.03)

Attributes are “decorations” of the syntax tree which are mostly ignored by the type-checker but can be used by external tools. An attribute is made of an identifier and a payload, which can be a structure, a type expression (prefixed with :), a signature (prefixed with :) or a pattern (prefixed with ?) optionally followed by a when clause:

The first form of attributes is attached with a postfix notation on “algebraic” categories:

This form of attributes can also be inserted after the `tag-namein polymorphic variant type expressions (tag-spec-first, tag-spec,tag-spec-full) or after the method-name in method-type.

The same syntactic form is also used to attach attributes to labels and constructors in type declarations:

Note: when a label declaration is followed by a semi-colon, attributes can also be put after the semi-colon (in which case they are merged to those specified before).

The second form of attributes are attached to “blocks” such as type declarations, class fields, etc:

A third form of attributes appears as stand-alone structure or signature items in the module or class sub-languages. They are not attached to any specific node in the syntax tree:

(Note: contrary to what the grammar above describes, item-attributescannot be attached to these floating attributes in class-field-specand class-field.)

It is also possible to specify attributes using an infix syntax. For instance:

let[@foo] x = 2 in x + 1 === (let x = 2 [@@foo] in x + 1) begin[@foo][@bar x] ... end === (begin ... end)[@foo][@bar x] module[@foo] M = ... === module M = ... [@@foo] type[@foo] t = T === type t = T [@@foo] method[@foo] m = ... === method m = ... [@@foo]

For let, the attributes are applied to each bindings:

let[@foo] x = 2 and y = 3 in x + y === (let x = 2 [@@foo] and y = 3 in x + y) let[@foo] x = 2 and[@bar] y = 3 in x + y === (let x = 2 [@@foo] and y = 3 [@@bar] in x + y)

12.1 Built-in attributes

Some attributes are understood by the compiler:

module X = struct [@@@warning "+9"] …end[@@deprecated "Please use module 'Y' instead."]let x = begin[@warning "+9"] […] end type t = A | B [@@deprecated "Please use type 's' instead."]

let fires_warning_22 x =assert (x >= 0) [@ppwarning "TODO: remove this later"]

Warning 22 [preprocessor]: TODO: remove this later

let rec is_a_tail_call = function | [] -> () | _ :: q -> (is_a_tail_call[@tailcall]) qlet rec not_a_tail_call = function | [] -> [] | x :: q -> x :: (not_a_tail_call[@tailcall]) q

Warning 51 [wrong-tailcall-expectation]: expected tailcall

let f x = x [@@inline]let () = (f[@inlined]) ()

type fragile = | Int of int [@warn_on_literal_pattern] | String of string [@warn_on_literal_pattern]

let fragile_match_1 = function| Int 0 -> () | _ -> ()

Warning 52 [fragile-literal-pattern]: Code should not depend on the actual values of this constructor's arguments. They are only for information and may change in future versions. (see manual section 13.5.3) val fragile_match_1 : fragile -> unit =

let fragile_match_2 = function| String "constant" -> () | _ -> ()

Warning 52 [fragile-literal-pattern]: Code should not depend on the actual values of this constructor's arguments. They are only for information and may change in future versions. (see manual section 13.5.3) val fragile_match_2 : fragile -> unit =

module Immediate: sig type t [@@immediate]val x: t ref end = struct type t = A | Blet x = ref Aend

module Int_or_int64 : sig type t [@@immediate64]val zero : tval one : tval add : t -> t -> tend = struct include Sys.Immediate64.Make(Int)(Int64)module type S = sig val zero : tval one : tval add : t -> t -> tend let impl : (module S) =match repr with | Immediate -> (module Int : S) | Non_immediate -> (module Int64 : S)include (val impl : S)end

Copyright © 2025 Institut National de Recherche en Informatique et en Automatique