diff --git a/CHANGELOG.md b/CHANGELOG.md index 67a55168d3..26607be698 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - Deprecate `Stdlib_Error` and `Stdlib_Exn` modules in favor of `JsError/JsExn`. https://github.com/rescript-lang/rescript/pull/8404 - Deprecate `List.has` in favor of `List.some`. https://github.com/rescript-lang/rescript/pull/8807 - Deprecate `@deriving(abstract)` and `@deriving(jsConverter)`, which will be removed in v13. https://github.com/rescript-lang/rescript/pull/8808 +- Deprecate `@unboxed` on a variant constructor, which is an error in v13: write `@unboxed` on the type. https://github.com/rescript-lang/rescript/pull/9049 # 12.3.1 diff --git a/compiler/ml/typedecl.ml b/compiler/ml/typedecl.ml index 0f44d4595f..53f4ea33a2 100644 --- a/compiler/ml/typedecl.ml +++ b/compiler/ml/typedecl.ml @@ -591,8 +591,34 @@ let transl_declaration ~type_record_as_object ~untagged_wfc env sdecl id = in Some (tcstr, cstr) in + (* [@unboxed] on a constructor, as written, before the type's + attributes are copied to its constructors. v13 rejects it. + Constructors copied by a variant spread carry the source type's + attributes, already reported at the source. *) + let warn_unboxed_constructor scstr = + let from_spread = + Variant_type_spread.constructor_is_from_spread scstr.pcd_attributes + in + Ext_list.iter scstr.pcd_attributes (fun ({txt; loc}, _) -> + if (not from_spread) && txt = Ast_untagged_variants.untagged then + Location.deprecated loc + (if Ast_untagged_variants.has_untagged sdecl.ptype_attributes + then + Printf.sprintf + "@unboxed on constructor %s is deprecated and will be an \ + error in v13. The type is already @unboxed, so remove it \ + from the constructor." + scstr.pcd_name.txt + else + Printf.sprintf + "@unboxed on constructor %s is deprecated and will be an \ + error in v13, where @unboxed applies to a whole variant: \ + write it on the type, as in `@unboxed type t = ...`." + scstr.pcd_name.txt)) + in let make_cstr scstr = Builtin_attributes.warning_scope scstr.pcd_attributes (fun () -> + warn_unboxed_constructor scstr; make_cstr scstr) in let tcstrs, cstrs = List.split (List.filter_map make_cstr scstrs) in diff --git a/tests/build_tests/super_errors/expected/unboxed_on_constructor_deprecated.res.expected b/tests/build_tests/super_errors/expected/unboxed_on_constructor_deprecated.res.expected new file mode 100644 index 0000000000..2622fc3a2e --- /dev/null +++ b/tests/build_tests/super_errors/expected/unboxed_on_constructor_deprecated.res.expected @@ -0,0 +1,21 @@ + + Warning number 3 + /.../fixtures/unboxed_on_constructor_deprecated.res:1:16-23 + + 1 │ type mixed = | @unboxed Text(string) | Count(int) + 2 │ + 3 │ @unboxed + + deprecated: @unboxed on constructor Text is deprecated and will be an error in v13, where @unboxed applies to a whole variant: write it on the type, as in `@unboxed type t = ...`. + + + Warning number 3 + /.../fixtures/unboxed_on_constructor_deprecated.res:4:16-23 + + 2 │ + 3 │ @unboxed + 4 │ type whole = | @unboxed Name(string) | Age(int) + 5 │ + 6 │ type spreadMixed = | ...mixed | Flag(bool) + + deprecated: @unboxed on constructor Name is deprecated and will be an error in v13. The type is already @unboxed, so remove it from the constructor. \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/unboxed_on_constructor_deprecated.res b/tests/build_tests/super_errors/fixtures/unboxed_on_constructor_deprecated.res new file mode 100644 index 0000000000..dc8c855b30 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/unboxed_on_constructor_deprecated.res @@ -0,0 +1,12 @@ +type mixed = | @unboxed Text(string) | Count(int) + +@unboxed +type whole = | @unboxed Name(string) | Age(int) + +type spreadMixed = | ...mixed | Flag(bool) + +@unboxed +type plain = Plain(string) + +@unboxed +type spreadPlain = | ...plain | Num(int)