@@ -5165,8 +5165,50 @@ and parse_type_representation ?current_type_name_path ?inline_types_context p =
51655165 in
51665166 let kind =
51675167 match p.Parser. token with
5168- | Bar | Uident _ | DocComment _ | At ->
5168+ | Bar | Uident _ | DocComment _ ->
51695169 Parsetree. Ptype_variant (parse_type_constructor_declarations p)
5170+ | At ->
5171+ (* Attributes can prefix either a variant (constructor list), a record, or an
5172+ open/extensible variant marker (`..`). Peek past attributes and any doc
5173+ comments to decide which kind it is. *)
5174+ let after_attrs =
5175+ Parser. lookahead p (fun state ->
5176+ ignore (parse_attributes state);
5177+ let rec skip_docs () =
5178+ match state.Parser. token with
5179+ | DocComment _ -> Parser. next state; skip_docs ()
5180+ | _ -> ()
5181+ in
5182+ skip_docs () ;
5183+ state.Parser. token)
5184+ in
5185+ (match after_attrs with
5186+ | Lbrace ->
5187+ (* consume the attributes and any doc comments before the record *)
5188+ ignore (parse_attributes p);
5189+ let rec skip_docs () =
5190+ match p.Parser. token with
5191+ | DocComment _ -> Parser. next p; skip_docs ()
5192+ | _ -> ()
5193+ in
5194+ skip_docs () ;
5195+ Parsetree. Ptype_record
5196+ (parse_record_declaration ?current_type_name_path ?inline_types_context p)
5197+ | DotDot ->
5198+ (* attributes before an open variant marker; consume attrs/docs then handle `..` *)
5199+ ignore (parse_attributes p);
5200+ let rec skip_docs () =
5201+ match p.Parser. token with
5202+ | DocComment _ -> Parser. next p; skip_docs ()
5203+ | _ -> ()
5204+ in
5205+ skip_docs () ;
5206+ Parser. next p; (* consume DotDot *)
5207+ Ptype_open
5208+ | _ ->
5209+ (* fall back to variant constructor declarations; leave attributes for the
5210+ constructor parsing so they attach to the first constructor. *)
5211+ Parsetree. Ptype_variant (parse_type_constructor_declarations p))
51705212 | Lbrace ->
51715213 Parsetree. Ptype_record
51725214 (parse_record_declaration ?current_type_name_path ?inline_types_context
@@ -5727,22 +5769,42 @@ and parse_type_equation_and_representation ?current_type_name_path
57275769 let priv, kind = parse_type_representation p in
57285770 (None , priv, kind)
57295771 | At -> (
5730- (* Attribute can start a variant constructor or a type manifest.
5731- Look ahead past attributes; if a constructor -like token follows (Uident not immediately
5732- followed by a Dot, or DotDotDot/Bar/DocComment), treat as variant; otherwise manifest *)
5733- let is_variant_after_attrs =
5772+ (* Attributes can start a representation ( variant/record/open variant) or a manifest.
5773+ Look ahead past attributes (and doc comments). If a representation -like token follows,
5774+ parse it as a representation; otherwise treat as a manifest. *)
5775+ let is_representation_after_attrs =
57345776 Parser. lookahead p (fun state ->
57355777 ignore (parse_attributes state);
5778+ (* optionally skip a run of doc comments before deciding *)
5779+ let rec skip_docs () =
5780+ match state.Parser. token with
5781+ | DocComment _ -> Parser. next state; skip_docs ()
5782+ | _ -> ()
5783+ in
5784+ skip_docs () ;
57365785 match state.Parser. token with
5737- | Uident _ -> (
5786+ | Lbrace ->
5787+ (* Disambiguate record declaration vs object type.
5788+ Peek inside the braces; if it looks like an object (String/Dot/DotDot/DotDotDot),
5789+ then this is a manifest type expression, not a representation. If it looks like
5790+ a record field (e.g. Lident or attributes before one), treat as representation. *)
5791+ Parser. next state; (* consume Lbrace *)
5792+ ignore (parse_attributes state);
5793+ skip_docs () ;
5794+ (match state.Parser. token with
5795+ | String _ | Dot | DotDot | DotDotDot -> false (* object type => manifest *)
5796+ | _ -> true ) (* record decl => representation *)
5797+ | Bar -> true (* variant constructor list *)
5798+ | DotDot -> true (* extensible/open variant ".." *)
5799+ | Uident _ -> (* constructor vs module-qualified manifest *)
57385800 Parser. next state;
5739- match state.Parser. token with
5740- | Dot -> false
5741- | _ -> true )
5742- | DotDotDot | Bar | DocComment _ -> true
5801+ ( match state.Parser. token with
5802+ | Dot -> false (* M.t => manifest *)
5803+ | _ -> true ) (* Uident starting a constructor * )
5804+ | DocComment _ -> true (* doc before constructor list *)
57435805 | _ -> false )
57445806 in
5745- if is_variant_after_attrs then
5807+ if is_representation_after_attrs then
57465808 let priv, kind = parse_type_representation p in
57475809 (None , priv, kind)
57485810 else
0 commit comments