Skip to content

Remove OCaml attribute aliases and the features only OCaml used - #8928

Merged
cknitt merged 5 commits into
masterfrom
remove-ocaml-attribute-aliases
Oct 20, 2026
Merged

cknitt merged 5 commits into
masterfrom
remove-ocaml-attribute-aliases

Conversation

@cknitt

@cknitt cknitt commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

v13 cleanup: the compiler reads builtin attributes only by their bare names. Hand-written OCaml spellings (@ocaml.deprecated, @ocaml.unboxed, @ocaml.immediate, @ocaml.warnerror, @ocaml.warning, @ocaml.ppwarning, @ocaml.boxed, @ocaml.deprecated_mutable, @ocaml.text, %ocaml.error) fail with an error naming the bare attribute.

PPX output keeps working: the v0 bridge renames ocaml.warning, ocaml.ppwarning and ocaml.error (what ppxlib emits) to the bare names, and Ast_mapper.extension_of_error emits error. The internal ocaml.warn_on_literal_pattern is now warn_on_literal_pattern.

The OCaml-only @boxed and @deprecated_mutable are no longer interpreted (ignored like any unknown attribute), and %extension_constructor is removed with Texp_extension_constructor, the predefined type extension_constructor and their errors. The CMT magic is bumped. @immediate, @warnerror and @ppwarning stay.

New tests: ounit tests for the bridge renaming and for rejecting hand-written spellings before an external PPX, and super_errors fixtures for @ocaml.unboxed, %ocaml.error and %extension_constructor.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Kr4cjoUi2f5VpMvE6wT9bo

Why:
    The compiler still accepted OCaml spellings of builtin attributes that
    nothing in ReScript produces, and some of them only half worked:
    `@ocaml.unboxed` changed the type's representation but was ignored by
    untagged variants. `@boxed`, `@deprecated_mutable` and
    `%extension_constructor` are OCaml features with no use in ReScript.

The `ocaml.*` spellings are now rejected with the bare name to use instead.
`@boxed` and `@deprecated_mutable` are reported as unused attributes, and
`%extension_constructor` as an uninterpreted extension. With it go the
typed tree node `Texp_extension_constructor`, the predefined type
`extension_constructor`, the error "A type cannot be boxed and unboxed at
the same time." and the deprecated-mutation checks. The CMT magic number is
bumped.

Diagnostic added (removed OCaml spelling):
Example:
    @ocaml.unboxed
    type t = Name(string)
Before (diagnostic): (none, the type is unboxed)
After (diagnostic):
    `@ocaml.unboxed` is no longer supported, use `@unboxed` instead.

Diagnostic modified (boxed and unboxed):
Example:
    @unboxed @boxed
    type t = One(int)
Before (diagnostic):
    A type cannot be boxed and unboxed at the same time.
After (diagnostic):
    Warning number 101
    Unused attribute: @boxed
    This attribute has no effect here.

Diagnostic modified (extension constructor):
Example:
    exception A
    let _ = %extension_constructor(A)
Before (diagnostic): (none, the constructor's slot)
After (diagnostic):
    Uninterpreted extension 'extension_constructor'.

Typedtree removed (Texp_extension_constructor):
Before (typed):
    expression
      Texp_extension_constructor "A"
After (typed): (removed)

Breaking: `@ocaml.deprecated`, `@ocaml.unboxed`, `@ocaml.immediate` and `@ocaml.warnerror` are errors; use `@deprecated`, `@unboxed`, `@immediate` and `@warnerror`. `@ocaml.boxed`, `@ocaml.deprecated_mutable` and `@ocaml.text` are errors; remove them (use a doc comment for `@ocaml.text`). `@boxed` and `@deprecated_mutable` are unused attributes (warning 101, an error by default); remove them. `%extension_constructor` and the type `extension_constructor` are gone.
Review: Why keep `@ocaml.ppwarning`? ppxlib's driver emits `[@@@ocaml.ppwarning]` for lint warnings, so PPXs built with ppxlib still produce it.
Review: Why keep `@immediate`, `@warnerror` and `@ppwarning`? `@immediate` on an abstract type makes comparisons on it compile to `===`/`<`; `@warnerror` turns warnings into errors in a scope; `@ppwarning` is how PPXs report warnings.
Review: Does removing a typed tree constructor break reading older CMTs? The CMT magic is bumped; older CMTs were already unreadable since `Texp_dict` was inserted mid-variant.

Area: compiler/ml, compiler/frontend, analysis
Output: unchanged for programs that use none of the removed spellings
Tests: super_errors fixtures for the removed spellings, unused `@boxed`/`@deprecated_mutable` and `%extension_constructor`; three obsolete fixtures removed; `@ocaml.unboxed` in the reanalyze and gentype tests switched to `@unboxed`
PPX: v0 wire unchanged; `ocaml.error`, `ocaml.warning`, `ocaml.ppwarning` and `ocaml.explicit_arity` still accepted
Editor: hover no longer reads `@ocaml.text` as documentation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kr4cjoUi2f5VpMvE6wT9bo
Signed-off-by: Christoph Knittel <ck@cca.io>
@codecov

codecov Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.69565% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.11%. Comparing base (f79ec1f) to head (5294809).

Files with missing lines Patch % Lines
compiler/frontend/bs_ast_invariant.ml 75.86% 7 Missing ⚠️
tests/ounit_tests/ounit_compiler_request_tests.ml 91.66% 2 Missing ⚠️
analysis/reanalyze/src/arnold.ml 0.00% 1 Missing ⚠️
compiler/ml/depend.ml 0.00% 1 Missing ⚠️
compiler/ml/rec_check.ml 0.00% 1 Missing ⚠️
compiler/ml/typedtree_iter.ml 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #8928      +/-   ##
==========================================
+ Coverage   81.03%   81.11%   +0.08%     
==========================================
  Files         455      455              
  Lines       63640    63672      +32     
==========================================
+ Hits        51573    51650      +77     
+ Misses      12067    12022      -45     
Files with missing lines Coverage Δ
analysis/reanalyze/src/annotation.ml 51.78% <100.00%> (-0.85%) ⬇️
analysis/reanalyze/src/side_effects.ml 80.64% <ø> (+2.52%) ⬆️
analysis/src/process_attributes.ml 86.84% <100.00%> (+2.63%) ⬆️
compiler/core/cmd_ppx_apply.ml 80.64% <ø> (+0.64%) ⬆️
compiler/ext/config.ml 100.00% <ø> (ø)
compiler/ml/ast_mapper.ml 98.45% <100.00%> (ø)
compiler/ml/ast_mapper_from0.ml 78.70% <100.00%> (+0.99%) ⬆️
compiler/ml/builtin_attributes.ml 81.25% <100.00%> (+10.45%) ⬆️
compiler/ml/includecore.ml 77.25% <100.00%> (-0.18%) ⬇️
compiler/ml/includemod.ml 75.88% <100.00%> (ø)
... and 15 more

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pkg-pr-new

pkg-pr-new Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

rescript

npm i https://pkg.pr.new/rescript@8928

@rescript/belt

npm i https://pkg.pr.new/@rescript/belt@8928

@rescript/darwin-arm64

npm i https://pkg.pr.new/@rescript/darwin-arm64@8928

@rescript/linux-arm64

npm i https://pkg.pr.new/@rescript/linux-arm64@8928

@rescript/linux-x64

npm i https://pkg.pr.new/@rescript/linux-x64@8928

@rescript/runtime

npm i https://pkg.pr.new/@rescript/runtime@8928

@rescript/win32-x64

npm i https://pkg.pr.new/@rescript/win32-x64@8928

commit: 5294809

@github-actions

Copy link
Copy Markdown

cknitt and others added 2 commits October 20, 2026 07:04
Why:
    `ocaml.warning`, `ocaml.ppwarning` and `ocaml.error` were still read
    everywhere because PPXs built on OCaml tooling emit them (ppxlib reports
    errors as `[%ocaml.error]` and lint warnings as `[@@@ocaml.ppwarning]`).
    Renaming them once, where PPX output enters the compiler, lets every
    other reader use the bare name.

The PPX bridge (`Ast_mapper_from0`) renames the three names in its default
attribute and extension mappers, so they are renamed at any depth,
payloads included. `Ast_mapper.extension_of_error` emits `error`, and the
internal `ocaml.warn_on_literal_pattern` that `Predef` puts on `Failure`
and `Invalid_argument` is now `warn_on_literal_pattern`. Written by hand in
source, the prefixed spellings are rejected like the other removed
aliases; the check now also sees attributes on constants.

AST modified (PPX output):
Example:
    %%ocaml.error("ppx error")
    let x = @ocaml.warning("-3") 1
Before (parse):
    structure_item
      Pstr_extension "ocaml.error"
    attribute "ocaml.warning"
After (parse):
    structure_item
      Pstr_extension "error"
    attribute "warning"

Diagnostic added (written by hand):
Example:
    @@ocaml.warning("-32")
Before (diagnostic): (none, warning 32 disabled)
After (diagnostic):
    `@ocaml.warning` is no longer supported, use `@warning` instead.

Breaking: `@ocaml.warning`, `@ocaml.ppwarning` and `%ocaml.error` in source are errors; use `@warning`, `@ppwarning` and `%error`. A hand-written `@ocaml.warn_on_literal_pattern` no longer has an effect. PPX output that uses the prefixed names keeps working.
Review: Can a PPX's `ocaml.warning` still reach the error check? Only if the bridge skipped an attribute position; the ounit test covers structure and signature items, type declarations, expressions and attribute payloads, and the ast-mapping fixture covers the parser round trip.
Review: Does warning 52 still fire on `Failure("boom")`? Yes, a new super_errors fixture covers it.

Area: compiler/ml, compiler/frontend, analysis
Output: unchanged
Tests: ounit tests for the bridge renaming and `extension_of_error`; ast-mapping fixture OcamlPrefixedBuiltins; super_errors fixtures for hand-written `@ocaml.warning`, `@ocaml.ppwarning`, `%ocaml.error` and warning 52 on `Failure`; the reanalyze test's `@@ocaml.warning` switched to `@@warning`
PPX: v0 wire unchanged; `ocaml.warning`, `ocaml.ppwarning` and `ocaml.error` from a PPX are renamed to the bare names; `ocaml.explicit_arity` still read by the bridge
Editor: reanalyze reads only `@warning`
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kr4cjoUi2f5VpMvE6wT9bo
Signed-off-by: Christoph Knittel <ck@cca.io>
Why:
    Reporting them as unused attributes (warning 101, an error by default)
    broke builds over attributes that never changed anything in ReScript.

Diagnostic removed (unused boxed):
Example:
    @boxed
    type t = One(int)
Before (diagnostic):
    Warning number 101
    Unused attribute: @boxed
    This attribute has no effect here.
After (diagnostic): (none, the attribute is ignored)

Breaking: `@boxed` and `@deprecated_mutable` are no longer interpreted and are silently ignored; remove them.

Area: compiler/frontend
Output: unchanged
Tests: the unused_boxed_deprecated_mutable super_errors fixture is removed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kr4cjoUi2f5VpMvE6wT9bo
Signed-off-by: Christoph Knittel <ck@cca.io>
@cknitt

cknitt commented Oct 20, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-20T07:42:07.890117Z d0055c9 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: faaa6bdef0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread compiler/ext/config.ml
Comment thread compiler/ml/ast_mapper_from0.ml
…CMI magic

Why:
    With a `-ppx`, the source tree went through the PPX bridge, which
    renames `ocaml.warning`, `ocaml.ppwarning` and `ocaml.error` to the bare
    names, before the removed-spelling check ran, so hand-written
    `@@ocaml.warning("-32")` was silently accepted. Removing the predefined
    type `extension_constructor` shifted the stamps of later predefined
    types, but `.cmi` files from before the change were still accepted.

`Cmd_ppx_apply` now runs the removed-spelling check from `Bs_ast_invariant`
on the source before handing it to external PPXs; the check after the PPXs
is unchanged. The CMI magic number is bumped to `Caml1999I039`.

Diagnostic added (with an external PPX):
Example:
    @@ocaml.warning("-32")
    let value = 1
Before (diagnostic): (none, accepted as `@@warning("-32")`)
After (diagnostic):
    `@ocaml.warning` is no longer supported, use `@warning` instead.

Breaking: `.cmi` files built by an earlier compiler are rejected; rebuild them.

Area: compiler/core, compiler/frontend, compiler/ext
Output: unchanged
Tests: ounit test ppx_removed_ocaml_spelling compiles `@@ocaml.warning`, `@ocaml.ppwarning` in an interface and `%ocaml.error` through an identity PPX and expects the errors, and `@@warning` to compile
PPX: v0 wire unchanged; source is checked before it is sent to a PPX, and PPX output is still renamed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kr4cjoUi2f5VpMvE6wT9bo
Signed-off-by: Christoph Knittel <ck@cca.io>
@cknitt

cknitt commented Oct 20, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d0055c90e0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread compiler/core/cmd_ppx_apply.ml
The removed `ocaml.*` attributes share one table lookup, which the
`@ocaml.unboxed` fixture already covers. Warning 52 on predefined
exceptions is covered by `warning_52_fragile_literal_pattern`, and the
bridge renaming by the ounit test.

Area: tests
Output: unchanged
Tests: removed super_errors fixtures removed_ocaml_deprecated, removed_ocaml_boxed, removed_ocaml_warning, removed_ocaml_ppwarning and warning_52_failure_literal_pattern, and the ast-mapping fixture OcamlPrefixedBuiltins, each with its expected file
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kr4cjoUi2f5VpMvE6wT9bo
Signed-off-by: Christoph Knittel <ck@cca.io>
@github-actions

Copy link
Copy Markdown

@cknitt
cknitt marked this pull request as ready for review October 20, 2026 07:54
@cknitt
cknitt requested a review from cristianoc October 20, 2026 07:54

@cristianoc cristianoc left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing that these are still around after all the rounds of cleanup.

@cknitt
cknitt merged commit b7c67d2 into master Oct 20, 2026
28 checks passed
@cknitt
cknitt deleted the remove-ocaml-attribute-aliases branch October 20, 2026 08:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants