Skip to content

Commit af49658

Browse files
committed
Consume variant representation annotations into typed layouts
Variant representation annotations are syntax-level inputs, but their meaning is needed throughout type inclusion, coercion, printing, diagnostics, and GenType. Previously those consumers independently re-read attributes from typed declarations and constructors, leaving both the annotations and their interpreted representation live in later compiler phases. Build the canonical declaration configuration together with the variant layout after the recursive declaration group has entered the environment. Retain the declared unboxing bit and custom tag field even for shapes, such as nullary-only variants, from which those choices cannot be recovered by inspecting constructor blocks. Constructor tags and unboxed payload facts remain indexed by source position in the same completed layout. Migrate Ctype coercions, inclusion checks, Printtyp, error suggestions, and GenType to consume the typed layout and the existing type/record representations instead of parsing attributes. This also makes GenType distinguish nominal variants from polymorphic variants explicitly: nominal cases use canonical constructor tags, while polymorphic variants continue to interpret their own row-field annotations. Keep attribute interpretation only at the typing boundary that creates the layout and in the pre-typing variant-spread compatibility check, where no completed target layout exists yet. Preserve legacy single-payload unboxing through Types.type_representation and combine it with declaration-level layout configuration when an effective runtime configuration is required. Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
1 parent 71ce1d6 commit af49658

12 files changed

Lines changed: 306 additions & 179 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050

5151
#### :house: Internal
5252

53+
- Give nominal variants one canonical runtime layout: compute their JavaScript representation once after typing each declaration, replace positional constructor tags with semantic runtime descriptors, and make construction, matching, coercion, printing, diagnostics, and GenType consume the stored representation instead of reinterpreting annotations. Pattern matching keeps occurrence-specific plans local without adding another Lambda or Lam expression form. https://github.com/rescript-lang/rescript/pull/8579
5354
- Sync the platform npm package's compiler binaries (`packages/@rescript/<platform>/bin`) via dune promotion on every `dune build`, instead of Makefile/CI copy steps that only ran when make did: a plain `dune build` can no longer leave `cli/*.js` and the test harnesses running a stale compiler. https://github.com/rescript-lang/rescript/pull/8560
5455
- Remove unused compiler IR definitions, modules, helpers, error variants, and Typedtree fields. https://github.com/rescript-lang/rescript/pull/8551 https://github.com/rescript-lang/rescript/pull/8555
5556
- Make locally abstract value constraints (`let f: type a. t = value`) structural in the parsetree, remove the obsolete `Pexp_newtype` and `Texp_newtype` wrapper metadata, and keep the old encoding confined to the frozen external-PPX bridge. The CMT magic number is bumped to `Caml1999T024`. https://github.com/rescript-lang/rescript/pull/8575

compiler/gentype/translate_signature_from_types.ml

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,14 @@ open Gentype_common
33
(** Like translateTypeDeclaration but from Types not Typedtree *)
44
let translate_type_declaration_from_types ~config ~output_file_relative
55
~resolver ~type_env ~id
6-
({type_attributes; type_kind; type_loc; type_manifest; type_params} :
6+
({
7+
type_attributes;
8+
type_kind;
9+
type_loc;
10+
type_manifest;
11+
type_params;
12+
type_representation;
13+
} :
714
Types.type_declaration) : Code_item.type_declaration list =
815
type_env |> Type_env.new_type ~name:(id |> Ident.name);
916
let type_name = Ident.name id in
@@ -12,13 +19,17 @@ let translate_type_declaration_from_types ~config ~output_file_relative
1219
Log_.item "Translate Types.type_declaration %s\n" type_name;
1320
let declaration_kind =
1421
match type_kind with
15-
| Type_record (label_declarations, _) ->
16-
Translate_type_declarations.RecordDeclarationFromTypes label_declarations
17-
| Type_variant (constructor_declarations, _)
22+
| Type_record (label_declarations, representation) ->
23+
Translate_type_declarations.RecordDeclarationFromTypes
24+
(label_declarations, representation)
25+
| Type_variant (constructor_declarations, layout_ref)
1826
when not
1927
(Translate_type_declarations.has_some_gadt_leaf
2028
constructor_declarations) ->
21-
VariantDeclarationFromTypes constructor_declarations
29+
VariantDeclarationFromTypes
30+
( constructor_declarations,
31+
Variant_runtime.get_layout layout_ref,
32+
type_representation )
2233
| Type_abstract -> GeneralDeclarationFromTypes type_manifest
2334
| _ -> NoDeclaration
2435
in

compiler/gentype/translate_type_declarations.ml

Lines changed: 61 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
open Gentype_common
22

33
type declaration_kind =
4-
| RecordDeclarationFromTypes of Types.label_declaration list
4+
| RecordDeclarationFromTypes of
5+
Types.label_declaration list * Types.record_representation
56
| GeneralDeclaration of Typedtree.core_type option
67
| GeneralDeclarationFromTypes of Types.type_expr option
78
(** As the above, but from Types not Typedtree *)
8-
| VariantDeclarationFromTypes of Types.constructor_declaration list
9+
| VariantDeclarationFromTypes of
10+
Types.constructor_declaration list
11+
* Variant_runtime.layout
12+
* Types.type_representation
913
| NoDeclaration
1014

1115
let create_export_type_from_type_declaration ~annotation ~loc ~name_as ~opaque
@@ -20,7 +24,7 @@ let create_export_type_from_type_declaration ~annotation ~loc ~name_as ~opaque
2024
annotation;
2125
}
2226

23-
let create_case (label, attributes) ~poly =
27+
let create_polyvariant_case (label, attributes) =
2428
{
2529
label_js =
2630
(match
@@ -32,10 +36,20 @@ let create_case (label, attributes) ~poly =
3236
| Some (_, FloatPayload s) -> FloatLabel s
3337
| Some (_, IntPayload i) -> IntLabel i
3438
| Some (_, StringPayload as_label) -> StringLabel as_label
35-
| _ ->
36-
if poly && is_number label then IntLabel label else StringLabel label);
39+
| _ -> if is_number label then IntLabel label else StringLabel label);
3740
}
3841

42+
let create_variant_case label = function
43+
| Some (Variant_runtime.String label) -> {label_js = StringLabel label}
44+
| Some (Variant_runtime.Int label) ->
45+
{label_js = IntLabel (string_of_int label)}
46+
| Some (Variant_runtime.Float label) -> {label_js = FloatLabel label}
47+
| Some (Variant_runtime.BigInt label) -> {label_js = IntLabel label}
48+
| Some (Variant_runtime.Bool label) -> {label_js = BoolLabel label}
49+
| Some Variant_runtime.Null -> {label_js = NullLabel}
50+
| Some Variant_runtime.Undefined -> {label_js = UndefinedLabel}
51+
| Some (Variant_runtime.Untagged _) | None -> {label_js = StringLabel label}
52+
3953
(**
4054
* Rename record fields.
4155
* If @genType.as is used, perform renaming conversion.
@@ -65,10 +79,6 @@ let traslate_declaration_kind ~config ~loc ~output_file_relative ~resolver
6579
let import_string_opt, name_as =
6680
type_attributes |> Annotation.get_attribute_import_renaming
6781
in
68-
let unboxed_annotation =
69-
type_attributes |> Annotation.has_attribute Annotation.tag_is_unboxed
70-
in
71-
let tag_annotation = type_attributes |> Annotation.get_tag in
7282
let return_type_declaration (type_declaration : Code_item.type_declaration) =
7383
match opaque = Some true with
7484
| true -> [{type_declaration with import_types = []}]
@@ -88,7 +98,8 @@ let traslate_declaration_kind ~config ~loc ~output_file_relative ~resolver
8898
in
8999
{Code_item.import_types; export_from_type_declaration}
90100
in
91-
let translate_label_declarations ?(inline = false) label_declarations =
101+
let translate_label_declarations ?(inline = false) ?(unboxed = false)
102+
label_declarations =
92103
let field_translations =
93104
label_declarations
94105
|> List.map
@@ -137,7 +148,7 @@ let traslate_declaration_kind ~config ~loc ~output_file_relative ~resolver
137148
in
138149
let type_ =
139150
match fields with
140-
| [field] when unboxed_annotation -> field.type_
151+
| [field] when unboxed -> field.type_
141152
| _ -> Object ((if inline then Inline else Closed), fields)
142153
in
143154
{Translate_type_expr_from_types.dependencies; type_}
@@ -201,7 +212,7 @@ let traslate_declaration_kind ~config ~loc ~output_file_relative ~resolver
201212
row_fields |> Translate_core_type.process_variant
202213
in
203214
let no_payloads =
204-
row_fields_variants.no_payloads |> List.map (create_case ~poly:true)
215+
row_fields_variants.no_payloads |> List.map create_polyvariant_case
205216
in
206217
let payloads =
207218
if
@@ -211,7 +222,7 @@ let traslate_declaration_kind ~config ~loc ~output_file_relative ~resolver
211222
(List.combine variant.payloads row_fields_variants.payloads
212223
[@doesNotRaise])
213224
|> List.map (fun (payload, (label, attributes, _)) ->
214-
let case = (label, attributes) |> create_case ~poly:true in
225+
let case = create_polyvariant_case (label, attributes) in
215226
{payload with case})
216227
else variant.payloads
217228
in
@@ -221,9 +232,15 @@ let traslate_declaration_kind ~config ~loc ~output_file_relative ~resolver
221232
in
222233
{translation with type_} |> handle_general_declaration
223234
|> return_type_declaration
224-
| RecordDeclarationFromTypes label_declarations, None ->
235+
| RecordDeclarationFromTypes (label_declarations, representation), None ->
236+
let unboxed =
237+
match representation with
238+
| Record_unboxed _ -> true
239+
| Record_regular | Record_inlined _ | Record_extension -> false
240+
| Record_float_unused -> assert false
241+
in
225242
let {Translate_type_expr_from_types.dependencies; type_} =
226-
label_declarations |> translate_label_declarations
243+
label_declarations |> translate_label_declarations ~unboxed
227244
in
228245
let import_types =
229246
dependencies
@@ -238,13 +255,16 @@ let traslate_declaration_kind ~config ~loc ~output_file_relative ~resolver
238255
~name_as ~opaque ~type_ ~type_env ~type_vars;
239256
}
240257
|> return_type_declaration
241-
| VariantDeclarationFromTypes constructor_declarations, None ->
258+
| ( VariantDeclarationFromTypes
259+
(constructor_declarations, layout, type_representation),
260+
None ) ->
261+
let {Variant_runtime.tag_name} = Variant_runtime.matching_facts layout in
242262
let variants =
243263
constructor_declarations
244-
|> List.map (fun constructor_declaration ->
264+
|> List.mapi (fun position constructor_declaration ->
245265
let constructor_args = constructor_declaration.Types.cd_args in
246-
let attributes = constructor_declaration.cd_attributes in
247266
let name = constructor_declaration.cd_id |> Ident.name in
267+
let tag = Variant_runtime.constructor_tag layout position in
248268
let args_translation =
249269
match constructor_args with
250270
| Cstr_tuple type_exprs ->
@@ -254,7 +274,11 @@ let traslate_declaration_kind ~config ~loc ~output_file_relative ~resolver
254274
| Cstr_record label_declarations ->
255275
[
256276
label_declarations
257-
|> translate_label_declarations ~inline:true;
277+
|> translate_label_declarations ~inline:true
278+
~unboxed:
279+
(type_representation = Unboxed
280+
|| Variant_runtime.constructor_is_untagged layout
281+
position);
258282
]
259283
in
260284
let arg_types =
@@ -269,29 +293,34 @@ let traslate_declaration_kind ~config ~loc ~output_file_relative ~resolver
269293
|> Translation.translate_dependencies ~config
270294
~output_file_relative ~resolver
271295
in
272-
(name, attributes, arg_types, import_types))
296+
(name, tag, arg_types, import_types))
273297
in
274298
let variants_no_payload, variants_with_payload =
275299
variants |> List.partition (fun (_, _, arg_types, _) -> arg_types = [])
276300
in
277301
let no_payloads =
278302
variants_no_payload
279-
|> List.map (fun (name, attributes, _argTypes, _importTypes) ->
280-
(name, attributes) |> create_case ~poly:false)
303+
|> List.map (fun (name, tag, _argTypes, _importTypes) ->
304+
create_variant_case name tag)
281305
in
282306
let payloads =
283307
variants_with_payload
284-
|> List.map (fun (name, attributes, arg_types, _importTypes) ->
308+
|> List.map (fun (name, tag, arg_types, _importTypes) ->
285309
let type_ =
286310
match arg_types with
287311
| [type_] -> type_
288312
| _ -> Tuple arg_types
289313
in
290-
{case = (name, attributes) |> create_case ~poly:false; t = type_})
314+
{case = create_variant_case name tag; t = type_})
291315
in
292316
let variant_typ =
317+
let unboxed =
318+
match type_representation with
319+
| Unboxed -> true
320+
| Boxed -> (Variant_runtime.configuration layout).unboxed
321+
in
293322
create_variant ~inherits:[] ~no_payloads ~payloads ~polymorphic:false
294-
~tag:tag_annotation ~unboxed:unboxed_annotation
323+
~tag:tag_name ~unboxed
295324
in
296325
let resolved_type_name =
297326
type_name |> sanitize_type_name |> Type_env.add_module_path ~type_env
@@ -339,10 +368,13 @@ let translate_type_declaration ~config ~output_file_relative ~resolver ~type_env
339368
in
340369
let declaration_kind =
341370
match typ_type.type_kind with
342-
| Type_record (label_declarations, _) ->
343-
RecordDeclarationFromTypes label_declarations
344-
| Type_variant (constructor_declarations, _) ->
345-
VariantDeclarationFromTypes constructor_declarations
371+
| Type_record (label_declarations, representation) ->
372+
RecordDeclarationFromTypes (label_declarations, representation)
373+
| Type_variant (constructor_declarations, layout_ref) ->
374+
VariantDeclarationFromTypes
375+
( constructor_declarations,
376+
Variant_runtime.get_layout layout_ref,
377+
typ_type.type_representation )
346378
| Type_abstract -> GeneralDeclaration typ_manifest
347379
| _ -> NoDeclaration
348380
in

0 commit comments

Comments
 (0)