Commit Graph

92 Commits

Author SHA1 Message Date
renovate[bot] d5d575c1de chore(deps): update rust to v1.98.0 (#25945)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [rust](https://rust-lang.org/)
([source](https://redirect.github.com/rust-lang/rust),
[changelog](https://redirect.github.com/rust-lang/rust/blob/main/RELEASES.md))
| toolchain | minor | `1.97.1` → `1.98.0` |

---

### Configuration

📅 **Schedule**: (in timezone Asia/Shanghai)

- Branch creation
  - "before 10am on monday"
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/oxc-project/oxc).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zNS40IiwidXBkYXRlZEluVmVyIjoiNDQuMzUuNCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Cameron <cameron.clark@hey.com>
2026-08-20 18:04:07 +00:00
leaysgur 9bf5c71ac7 refactor(formatter_core): introduce exact_line_breaks builder (#24865)
Introduce `exact_line_breaks(count)` IR builder.

This produces a line element that prints exactly `count` line breaks, exempt from the printer's hardline collapsing / empty-line capping.

Blank runs inside verbatim values (YAML block/flow scalars, GraphQL block strings) are the value itself and must not be normalized.
Previously this was emulated by emitting raw `\n` text followed by a re-arming `hard_line_break()`..., hack.

Also removed the printer behavior that trims end of line whitespaces.
2026-07-24 04:05:12 +00:00
overlookmotel 10fd38eab4 test(allocator, data_structures, str): use implements! macro in tests (#24722)
Use `implements!` macro (introduced in #24721) in various tests, including adding some new ones.

The most valuable change is replacing a `compile_fail` doctest which checks that `Arena` is not `Sync`. Using `assert!(implements!(Arena: !Sync));` is more robust.
2026-07-20 12:36:14 +00:00
overlookmotel 7e9b84a1dc feat(data_structures): add implements! macro (#24721)
Add an `implements!` macro which answers "does type X implement trait Y?".

Primarily this is useful in tests, but can also be used in macros to produce specialized code paths.

```rust
assert!(implements!(Ident: Send));
assert!(implements!(Ident: Sync));
assert!(implements!(Allocator: !Sync));
```

Also works in const context:

```rust
const U32_IS_COPY: bool = implements!(u32: Copy);
const _: () = assert!(U32_IS_COPY);
```

Particularly useful for checking that a type does _not_ implement a trait. Without this macro, that requires a `compile_fail` doctest, which is fragile - when code changes, the doctest can easily start failing for _different_ reasons, which means it's no longer testing what it's meant to, and there's no way to spot that.

This is a primitive required for forthcoming `MultiVec` SoA vec type. Putting it in `oxc_data_structures` as it can be useful in other places too.
2026-07-20 12:36:14 +00:00
overlookmotel 39e141b85c feat(data_structures): add const_str_eq function (#24720)
Add a `const_str_eq` function to `oxc_data_structures`, which allows comparing two strings in const context.

```rust
const IS_SAME: bool = const_str_eq("foo", "bar");
const _: () = assert!(!IS_SAME);
```

This is a primitive required for forthcoming `MultiVec` SoA vec type. Putting it in `oxc_data_structures` as it can be useful in other places too.
2026-07-20 12:36:13 +00:00
overlookmotel ddab89a66c feat(data_structures): add likely and unlikely functions (#24368)
[#24359](https://github.com/oxc-project/oxc/pull/24359) bumped our MSRV to 1.95.0.

Now *at last* we have a decent way to guide branch layout: [`std::hint::cold_path`](https://doc.rust-lang.org/stable/core/hint/fn.cold_path.html). 🍾

Add the `likely` and `unlikely` functions that Rust's docs suggest as simple ways to use this capability.
2026-07-10 20:20:47 +00:00
overlookmotel 2e62012a1f feat(data_structures): add StringExt trait (#24006)
Introduce a `StringExt` trait which adds 2 unsafe methods to `String`:

- `push_unchecked`
- `push_str_unchecked`

Both push to the string without checking there's sufficient capacity for it. The caller guarantees the push cannot cause the `String`'s length to exceed its capacity.

Both methods call the corresponding safe methods of `String` internally, with `assert_unchecked!`s preceding those calls to allow compiler to remove the bounds check. The shape of these assertions matches the code in `String`'s methods exactly.

Examination of generated assembly confirms that the optimizations work.
2026-07-01 12:17:56 +00:00
overlookmotel f68641e09d docs(data_structures): improve docs on safety contract (#23575)
Follow-on after #23571. Improve docs related to the safety of `as_str` and `into_string` methods.
2026-06-17 23:22:36 +00:00
overlookmotel 556cc6d565 feat(data_structures): add CodeBuffer::as_str method (#23571)
Add an `as_str` method to `CodeBuffer` to get the contents of the buffer as a `&str`, without consuming the `CodeBuffer`.
2026-06-17 22:40:13 +00:00
overlookmotel 851891bd18 test(data_structures): remove duplicate test (#23570)
This test does the same as `into_string` test just below. Remove it.
2026-06-17 22:40:13 +00:00
overlookmotel ce65070882 docs(data_structures): document why as_ref and as_mut on NonNullConst and NonNullMut take self (#21800)
Docs-only change. Document why `NonNullConst` and `NonNullMut`'s `as_ref` / `as_mut` methods take `self`, not `&self` / `&mut self`  as `NonNull`'s methods do. See the comment for the rationale.
2026-04-26 22:16:08 +00:00
overlookmotel 24b03ded48 feat(data_structures): introduce NonNullConst and NonNullMut pointer types (#21425)
Most of our low-level data structures e.g. `Arena`, `Vec`, `Box`, and `Stack` types use `NonNull` pointers.

`NonNull` is fundamentally dangerous. A `NonNull` can be created from a `&T`, and so only has read permissions. Yet you can call `as_mut()` on such a pointer to gain a `&mut T`, and that's instant undefined behavior. The onus is on the author to manually track how pointers were created and so whether they have write permissions or not, to avoid this hazard.

In complex code like the arena allocator, pointers are created in various different places, stored in structs, and passed around, so it is not trivial to track their permissions, and neither the type system nor Clippy gives you any help.

In comparison, raw pointers `*const T` and `*mut T` *do* make such a distinction between read-only and write-enabled pointers, but they have other shortcomings - they lack the non-null guarantee of `NonNull` (which can improve perf in some cases), and `*mut T` is not covariant, so it is unsuitable for use in types like `Vec`.

This PR intoduces 2 new pointer types `NonNullConst` and `NonNullMut`. Both are just wrappers around `NonNull` and are equivalent to `NonNull` at runtime. What they add is type system-level guarantees of the read/write permissions that these pointers have. i.e. they bring together the const/mut distinction of raw `*const` / `*mut` pointers, and the advantages of `NonNull`.

This PR only introduces these new pointer types, but does not use them in the codebase yet. It is my intention to migrate `Arena` allocator over to these new pointer types, to make it harder to blunder into causing UB while reworking the implementation. Other types like `Vec`, `Box`, `Stack`, and lexer's `Source` could also be migrated over later on.
2026-04-14 13:42:18 +00:00
overlookmotel b1da75024e docs(allocator, data_structures): correct comments (#20966)
Follow on after #18172.

That PR made changes to comments to remove references to `bumpalo` from the codebase. Correct a few of those comments which were incorrect.
2026-04-02 15:09:52 +00:00
overlookmotel b3dceae895 feat(data_structures): add fieldless_enum! macro (#19876)
Add a `fieldless_enum!` macro. This macro generates a `VARIANTS` constant on the type that lists all the enum's variants.

```rs
fieldless_enum! {
    enum Foo {
        A,
        B,
        C,
    }
}

assert_eq!(Foo::VARIANTS, [Foo::A, Foo::B, Foo::C]);
```

This is useful for code which interacts with the enum, and needs to take some action on each variant.
2026-03-01 17:40:04 +00:00
overlookmotel 46994986e9 feat(data_structures): add CodeBuffer::print_strs_array (#19760)
Add a method `CodeBuffer::print_strs_array`. This works much like `StringBuilder::from_strs_array_in` and `Atom::from_strs_array_in`. It takes an array of `&str`s, computes the total length required to print them all, reserves space for the total number of bytes for all together, and then writes all the strings one after another.

The result is that it's much faster than a series of `print_str` calls, which incur the cost of a bounds check and branch for each string. Instead you only do 1 bounds check for the whole batch.

Like `StringBuilder::from_strs_array_in` there have to be additional checks when computing the total length to ensure the sum of lengths does not exceed `usize::MAX` and wrap around. But when some of the strings are statically known (e.g. `buffer.print_strs_array(["foo", dynamic, "bar"])`) and so it's impossible for overflow to occur, these checks can usually be removed by compiler.
2026-02-26 23:53:31 +00:00
leaysgur 93bb861dc3 fix(formatter): Trim trailing whitespace before breaking line (#19740)
This doesn't seem to be an issue with native js/ts format paths, but it appears to cause problems when converting Prettier Docs, such as with gql-in-js.

Without this change,

```gql
type Mutation {
    create__TYPE_NAME__(input: Create__TYPE_NAME__Input!): __TYPE_NAME__!
      @skipAuth
```

will be formatted:

```gql
type Mutation {
    create__TYPE_NAME__(input: Create__TYPE_NAME__Input!): __TYPE_NAME__!
      @skipAuth
```

See trailing ` ` after `__TYPE_NAME__!`.
2026-02-26 15:24:02 +00:00
Sysix e8140495cd feat(oxc_data_structure/rope): add get_offset_from_line_and_column (#18133)
> This PR adds a new function get_offset_from_line_and_column that performs the inverse operation of the existing get_line_column function, converting UTF-16 line and column coordinates to a UTF-8 byte offset in source text.
2026-02-16 20:17:59 +00:00
Boshen 569aa6138d docs(rust): add missing rustdocs and remove missing_docs lint attrs (#19306)
## Summary
- add rustdoc comments for remaining public APIs in:
  - `oxc_transformer`
  - `oxc_isolated_declarations`
  - `oxc_semantic`
- remove all `#![warn(missing_docs)]` crate attributes
- remove all `#![expect(missing_docs)]` and `#[expect(missing_docs)]` attributes
- update AST kind generator template and regenerate so generated code no longer reintroduces missing-doc lint expectations

## Validation
- `just fmt`
- `just ast`
- `cargo rustc -p oxc_ast --lib -- -Dmissing-docs`
- `cargo rustc -p oxc_codegen --lib -- -Dmissing-docs`
- `cargo rustc -p oxc_transformer --lib -- -Dmissing-docs`
- `cargo rustc -p oxc_isolated_declarations --lib -- -Dmissing-docs`
- `cargo rustc -p oxc_semantic --lib -- -Dmissing-docs`
- `cargo rustc -p oxc_span --lib -- -Dmissing-docs`
- `cargo check -p oxc_transformer -p oxc_isolated_declarations -p oxc_semantic`
- `cargo check -p oxc_ast -p oxc_syntax -p oxc_str -p oxc_parser -p oxc_codegen -p oxc_span -p oxc_allocator -p oxc_data_structures -p oxc_macros`

## AI usage disclosure
This PR was prepared with AI assistance (Codex / GPT-5). I reviewed and validated the generated changes and take responsibility for the final content.
2026-02-12 08:41:48 +00:00
Boshen 08da7bd29a refactor(allocator): clean up obsolete bumpalo references (#18172)
## Summary

Now that bumpalo has been inlined into oxc_allocator (#18168), this PR cleans up comments and documentation that still reference bumpalo as an external dependency.

- Update module docs in `bump.rs` and `bumpalo_alloc.rs` to say "originally derived from" instead of "ported from"
- Remove obsolete comments about bumpalo version pinning in `from_raw_parts.rs`
- Update inline comments in `allocator.rs` from "delegates to bumpalo" to "it's a small function"
- Remove outdated TODO about replacing bumpalo in `tracking.rs`
- Update `ARCHITECTURE.md` and parser docs to reference `oxc_allocator` instead of bumpalo
- Clean up bumpalo references in other crates (`oxc_semantic`, `oxc_data_structures`, `apps/oxlint`, `napi/parser`, `tasks/ast_tools`)

## Test plan

- [x] `cargo check -p oxc_allocator` passes
- [x] `cargo test -p oxc_allocator` passes
- [x] Changes are documentation/comment only - no functional changes

🤖 Generated with [Claude Code](https://claude.ai/code)
2026-01-18 08:47:25 +00:00
overlookmotel 36e08efc4e feat(data_structures): implement conversion traits for stack types (#17141)
Implement methods and traits for converting stacks to/from `Vec`s, and from iterators:

* `Stack::into_vec`
* `From<Stack> for Vec`
* `From<Vec> for Stack`
* `NonEmptyStack::into_vec`
* `From<NonEmptyStack> for Vec`
* `TryFrom<Vec> for NonEmptyStack`
* `FromIterator for Stack` (infallible)
* `FromIterator for NonEmptyStack` (fallible)
2025-12-19 21:57:50 +00:00
overlookmotel 0e177f47ef feat(data_structures): implement Send and Sync for stack types (#17135)
Implement `Send` and `Sync` for `Stack<T>` and `NonEmptyStack<T>` where `T` is `Send` / `Sync`.

This also makes `SparseStack<T>` implement `Send` / `Sync` with same bounds.

`Vec` also implements `Send` / `Sync` in the same way, and the stack types are all essentially the same as `Vec`, just with a different internal implementations, so it makes sense to follow `Vec`.
2025-12-19 21:33:43 +00:00
renovate 1da3dc1920 chore(deps): update dependency rust to v1.92.0 (#16758)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [rust](https://redirect.github.com/rust-lang/rust) | minor | `1.91.1` -> `1.92.0` |

---

<details>
<summary>rust-lang/rust (rust)</summary>

[Compare Source](https://redirect.github.com/rust-lang/rust/compare/1.91.1...1.92.0)

\==========================

<a id="1.92.0-Language"></a>

- [Document `MaybeUninit` representation and validity](https://redirect.github.com/rust-lang/rust/pull/140463)
- [Allow `&raw [mut | const]` for union field in safe code](https://redirect.github.com/rust-lang/rust/pull/141469)
- [Prefer item bounds of associated types over where-bounds for auto-traits and `Sized`](https://redirect.github.com/rust-lang/rust/pull/144064)
- [Do not materialize `X` in `[X; 0]` when `X` is unsizing a const](https://redirect.github.com/rust-lang/rust/pull/145277)
- [Support combining `#[track_caller]` and `#[no_mangle]` (requires every declaration specifying `#[track_caller]` as well)](https://redirect.github.com/rust-lang/rust/pull/145724)
- [Make never type lints `never_type_fallback_flowing_into_unsafe` and `dependency_on_unit_never_type_fallback` deny-by-default](https://redirect.github.com/rust-lang/rust/pull/146167)
- [Allow specifying multiple bounds for same associated item, except in trait objects](https://redirect.github.com/rust-lang/rust/pull/146593)
- [Slightly strengthen higher-ranked region handling in coherence](https://redirect.github.com/rust-lang/rust/pull/146725)
- [The `unused_must_use` lint no longer warns on `Result<(), Uninhabited>` (for instance, `Result<(), !>`), or `ControlFlow<Uninhabited, ()>`](https://redirect.github.com/rust-lang/rust/pull/147382). This avoids having to check for an error that can never happen.

<a id="1.92.0-Compiler"></a>

- [Make `mips64el-unknown-linux-muslabi64` link dynamically](https://redirect.github.com/rust-lang/rust/pull/146858)
- [Remove current code for embedding command-line args in PDB](https://redirect.github.com/rust-lang/rust/pull/147022)
  Command-line information is typically not needed by debugging tools, and the removed code
  was causing problems for incremental builds even on targets that don't use PDB debuginfo.

<a id="1.92.0-Libraries"></a>

- [Specialize `Iterator::eq{_by}` for `TrustedLen` iterators](https://redirect.github.com/rust-lang/rust/pull/137122)
- [Simplify `Extend` for tuples](https://redirect.github.com/rust-lang/rust/pull/138799)
- [Added details to `Debug` for `EncodeWide`](https://redirect.github.com/rust-lang/rust/pull/140153).
- [`iter::Repeat::last`](https://redirect.github.com/rust-lang/rust/pull/147258) and [`count`](https://redirect.github.com/rust-lang/rust/pull/146410) will now panic, rather than looping infinitely.

<a id="1.92.0-Stabilized-APIs"></a>

- [`NonZero<u{N}>::div_ceil`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.div_ceil)
- [`Location::file_as_c_str`](https://doc.rust-lang.org/stable/std/panic/struct.Location.html#method.file_as_c_str)
- [`RwLockWriteGuard::downgrade`](https://doc.rust-lang.org/stable/std/sync/struct.RwLockWriteGuard.html#method.downgrade)
- [`Box::new_zeroed`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.new_zeroed)
- [`Box::new_zeroed_slice`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.new_zeroed_slice)
- [`Rc::new_zeroed`](https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#method.new_zeroed)
- [`Rc::new_zeroed_slice`](https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#method.new_zeroed_slice)
- [`Arc::new_zeroed`](https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#method.new_zeroed)
- [`Arc::new_zeroed_slice`](https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#method.new_zeroed_slice)
- [`btree_map::Entry::insert_entry`](https://doc.rust-lang.org/stable/std/collections/btree_map/enum.Entry.html#method.insert_entry)
- [`btree_map::VacantEntry::insert_entry`](https://doc.rust-lang.org/stable/std/collections/btree_map/struct.VacantEntry.html#method.insert_entry)
- [`impl Extend<proc_macro::Group> for proc_macro::TokenStream`](https://doc.rust-lang.org/stable/proc_macro/struct.TokenStream.html#impl-Extend%3CGroup%3E-for-TokenStream)
- [`impl Extend<proc_macro::Literal> for proc_macro::TokenStream`](https://doc.rust-lang.org/stable/proc_macro/struct.TokenStream.html#impl-Extend%3CLiteral%3E-for-TokenStream)
- [`impl Extend<proc_macro::Punct> for proc_macro::TokenStream`](https://doc.rust-lang.org/stable/proc_macro/struct.TokenStream.html#impl-Extend%3CPunct%3E-for-TokenStream)
- [`impl Extend<proc_macro::Ident> for proc_macro::TokenStream`](https://doc.rust-lang.org/stable/proc_macro/struct.TokenStream.html#impl-Extend%3CIdent%3E-for-TokenStream)

These previously stable APIs are now stable in const contexts:

- [`<[_]>::rotate_left`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.rotate_left)
- [`<[_]>::rotate_right`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.rotate_right)

<a id="1.92.0-Cargo"></a>

- [Added a new chapter](https://redirect.github.com/rust-lang/cargo/issues/16119) to the Cargo book, ["Optimizing Build Performance"](https://doc.rust-lang.org/stable/cargo/guide/build-performance.html).

<a id="1.92.0-Rustdoc"></a>

- [If a trait item appears in rustdoc search, hide the corresponding impl items](https://redirect.github.com/rust-lang/rust/pull/145898).  Previously a search for "last" would show both `Iterator::last` as well as impl methods like `std::vec::IntoIter::last`.  Now these impl methods will be hidden, freeing up space for inherent methods like `BTreeSet::last`.
- [Relax rules for identifiers in search](https://redirect.github.com/rust-lang/rust/pull/147860).  Previously you could only search for identifiers that were valid in rust code, now searches only need to be valid as part of an identifier.  For example, you can now perform a search that starts with a digit.

<a id="1.92.0-Compatibility-Notes"></a>

- [Fix backtraces with `-C panic=abort` on Linux by generating unwind tables by default](https://redirect.github.com/rust-lang/rust/pull/143613). Build with `-C force-unwind-tables=no` to keep omitting unwind tables.

* As part of the larger effort refactoring compiler built-in attributes and their diagnostics, [the future-compatibility lint `invalid_macro_export_arguments` is upgraded to deny-by-default and will be reported in dependencies too.](https://redirect.github.com/rust-lang/rust/pull/143857)
* [Update the minimum external LLVM to 20](https://redirect.github.com/rust-lang/rust/pull/145071)
* [Prevent downstream `impl DerefMut for Pin<LocalType>`](https://redirect.github.com/rust-lang/rust/pull/145608)
* [Don't apply temporary lifetime extension rules to the arguments of non-extended `pin!` and formatting macros](https://redirect.github.com/rust-lang/rust/pull/145838)

</details>

---

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi40Mi4yIiwidXBkYXRlZEluVmVyIjoiNDIuNDIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

---------

Co-authored-by: Cameron Clark <cameron.clark@hey.com>
2025-12-11 19:05:53 +00:00
overlookmotel 32f4fdd9a4 refactor(data_structures): add PhantomData field to Stack and NonEmptyStack (#15794)
Data structures which own `T`s should contain a `PhantomData<T>` field to signal to compiler the ownership semantics. For example `std::vec::Vec` does this.

Add `PhantomData` field to `Stack` and `NonEmptyStack`.

It's unclear to me if this is actually required for soundness or not. In the case of `std::vec::Vec`, it definitely is, but `Vec` uses `#[may_dangle]` in its `Drop` impl. Ideally we would use `#[may_dangle]` in these `Stack` types too, to loosen the borrow-checker's restrictions, but we're not able to as it's not available in stable Rust.

Given that we're not using `#[may_dangle]`, maybe `PhantomData` is not required either, but it costs nothing, so it's better to be on safe side and add it.
2025-11-17 16:02:28 +00:00
overlookmotel c81a3312a7 docs(data_structures): doc comments on fields of Stack (#15793)
Convert normal comments on `Stack`'s struct fields to doc comments. Add doc comments on fields of `SparseStack`.
2025-11-17 16:02:28 +00:00
overlookmotel 19086c469e refactor(various): use size_of and align_of from prelude (#15471)
Pure refactor. `std::mem::size_of` and `std::mem::align_of` are now part of the standard prelude. Shorten code by using them from the prelude, instead of importing from `std::mem`.
2025-11-08 11:41:56 +00:00
overlookmotel 801ce9590f refactor(data_structures): use unchecked_add (#15308)
Tiny refactor. Replace `.checked_add(1).unwrap_unchecked()` with the method designed for this use case `.unchecked_add(1)` (added in Rust 1.79.0).
2025-11-05 11:03:53 +00:00
sapphi-red 1521a1f98a feat(data_structures): add Stack::clear (#14028)
Added `Stack::clear` for #14029.
2025-09-24 11:10:36 +00:00
overlookmotel f8feed1205 feat(data_structures): add advance_to_end method to SliceIter trait (#13947)
Add `advance_to_end` method to `SliceIter` trait. This allows calling `advance_to_end` on any slice iterator.

(this stack of 3 PRs is work I did as part of first attempt to build an ESTree walker, which I abandoned, but the APIs are useful for other tasks in `oxc_ast_tools`).
2025-09-20 12:08:26 +00:00
renovate 5ebe4d6760 chore(deps): update dependency rust to v1.90.0 (#13906)
Coming soon: The Renovate bot (GitHub App) will be renamed to Mend. PRs from Renovate will soon appear from 'Mend'. Learn more [here](https://redirect.github.com/renovatebot/renovate/discussions/37842).

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [rust](https://redirect.github.com/rust-lang/rust) | minor | `1.89.0` -> `1.90.0` |

---

### Release Notes

<details>
<summary>rust-lang/rust (rust)</summary>

### [`v1.90.0`](https://redirect.github.com/rust-lang/rust/compare/1.89.0...1.90.0)

[Compare Source](https://redirect.github.com/rust-lang/rust/compare/1.89.0...1.90.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS45Ny4xMCIsInVwZGF0ZWRJblZlciI6IjQxLjk3LjEwIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
2025-09-19 01:10:29 +00:00
overlookmotel e433633ecb refactor(data_structures)!: make NonEmptyStack::is_empty a compile-time error (#13673)
Continuation from #13672.

Calling `NonEmptyStack::is_empty` is always a logic error. `NonEmptyStack` can never be empty, and `NonEmptyStack::is_exhausted` is very likely what was intended.

Make calling `NonEmptyStack::is_empty` a compile-time error, to prevent this erroneous usage.

Ideally, we'd remove the method entirely, but `&NonEmptyStack<T>` derefs to `&[T]`, so without defining `is_empty` method on `NonEmptyStack`, `stack.is_empty()` falls through to `[T]::is_empty`, which is not what we want.
2025-09-11 06:06:37 +00:00
overlookmotel 1a58e9908d feat(data_structures): add is_exhausted method to NonEmptyStack and SparseStack (#13672)
When using stacks, typically you create a stack at start of AST traversal, and then `debug_assert!` that the stack has been emptied again at the end of traversal, to make sure that the stack has not got out of sync - that every `push` is followed by a corresponding `pop`.

With `NonEmptyStack` and `SparseStack` it's a little confusing how to do this, because these stacks can never be empty. `stack.is_empty()` is not correct. `stack.len() == 1` is correct, but it's unclear when reading that code what exactly this is testing.

Add `is_exhausted` methods to `NonEmptyStack` and `SparseStack` to fulfil this role.

Naming: `is_exhausted` is perhaps not the best name, but I couldn't come up with a better one. I considered `is_emptied`, which is more descriptive, but I think it's too close to `is_empty`.

(prompted by #13632)
2025-09-11 06:06:37 +00:00
overlookmotel 2db32eb6ef feat(data_structures): add boxed_slice! and boxed_array! macros (#13596)
Add `boxed_slice!` and `boxed_array!` macros, similar to std lib's `vec!` macro.

```rs
// Box<[u64]>
let box_slice = boxed_slice![0u64; 10];
// Box<[u64; 10]>
let box_array = boxed_array![0u64; 10];
```

Use `boxed_array!` in linter to shorten code.

These macros could probably be made more efficient by using `MaybeUninit` and emplacement, but can leave that until later.
2025-09-09 01:41:37 +00:00
Boshen 34d3cde705 fix(rust): fix clippy issues (#13540) 2025-09-04 07:00:33 +00:00
overlookmotel edeebc6380 refactor(data_structures)!: rename SliceIterExt to SliceIter (#13439)
Pure refactor. Rename:

* `SliceIterExt` -> `SliceIter`
* `SliceIterMutExt` -> `SliceIterMut`
* `slice_iter_ext` module -> `slice_iter`
* `slice_iter_ext` Cargo feature -> `slice_iter`

I don't think "ext" added any value. There is no `SliceIter` trait in std library, so no naming clash.
2025-08-31 01:44:54 +01:00
overlookmotel 475205fdf2 perf(data_structures): reduce IterMut::advance_unchecked to 1 instruction (#13438)
Use `as_mut_slice` method (introduced in #13437) to optimize `advance_unchecked` method on `slice::IterMut`. Previously it had a branch, now it's only 1 instruction.
2025-08-31 01:44:54 +01:00
overlookmotel d0479e9916 feat(data_structures): add as_mut_slice method to IterMut via SliceIterMutExt trait (#13437)
Add a new extension trait for mutable slice iterators, `SliceIterMutExt`.

This trait provides an `as_mut_slice` method for `slice::IterMut`, which [exists in std library](https://doc.rust-lang.org/std/slice/struct.IterMut.html#method.as_mut_slice), but requires nightly Rust.
2025-08-31 01:44:54 +01:00
overlookmotel 5b139aa4ee feat(data_structures): add ptr and end_ptr methods to SliceIterExt (#13435)
Add `ptr` and `end_ptr` methods to `SliceIterExt`. These methods get pointers to the start and end of slice iterators, using the minimum possible number of instructions (1).

`end_ptr` also avoids unsafe code, unlike `iter.as_slice().as_ptr().add(iter.as_slice().len())`, which we used previously.

Use these methods in codegen.
2025-08-31 00:31:03 +00:00
overlookmotel d8b027f1af feat(data_structures): add SliceIterExt::peek method (#13434)
Add `peek` and `peek_copy` methods to `SliceIterExt`.

This is just syntax sugar, but it makes code easier to understand - it's clear what `bytes.peek()` does, whereas `bytes.clone().next()` is a bit less obvious.

Use these methods in codegen.

Unclear to me why this has +4% perf impact on codegen. My best guess is it's pushing compiler to make better inlining decisions, as `peek` is marked `#[inline(always)]`.
2025-08-30 22:32:48 +00:00
overlookmotel 51919c2390 refactor(data_structures): rename lifetime in SliceIterExt (#13433)
Pure refactor. Give lifetime a more descriptive name, so it's clearer what we're borrowing.
2025-08-30 17:50:59 +00:00
overlookmotel 128b527a06 refactor(data_structures)!: remove PointerExt trait (#12903)
`PointerExt` trait was introduced to allow using `NonNull::offset_from_unsigned` (and similar APIs) on Rust v1.87.0 and above, without breaking code on earlier Rust versions where these APIs did not exist.

Our MSRV is now v1.87.0 (#12900), so we can just use these methods directly, and `PointerExt` is not required any more. Remove it.
2025-08-08 11:38:51 +00:00
overlookmotel 6d94216e8d chore(deps): raise MSRV to 1.87.0 (#12900)
#12873 bumped Rust version to 1.89.0. In line with our N-2 MSRV policy, raise MSRV to 1.87.0.
2025-08-08 11:06:47 +00:00
overlookmotel e8ac1a567d perf(codegen): write indent in chunks of 32 bytes (#12745)
#12691 added the option to write indentation as either tabs or spaces.

This changed 2 things about writing indentation:

1. On x86_64, it now takes 3 SIMD instructions to "splat" the indent character across a 16-byte XMM register. Previously it was a 16-byte XMM read from a static.

2. If using spaces as indent, it'll usually be in width of 2 or 4. The indent printer has a fast path for writing less than 16 bytes of indentation. When using a single tab as indent, it's rare you'd write more than 16 bytes, because code is rarely that deeply nested. But if using 4 spaces as indent, depth only needs to get to 5 to exceed 16 bytes, which is not uncommon. This makes hitting the slow path far more likely.

Therefore, increase the size of chunks of indentation that's written on the fast path to 32 bytes. This adds only one more XMM write, because it can reuse the "splatted" XMM register, and makes it less likely to hit the slow path.

It's not possible to optimize for all cases because tabs and spaces indentation are quite different in this respect, but I think increasing the chunk size to 32 is probably a decent "middle of the road" option.

Seems to have no ill effects on our benchmarks, which use tabs for indentation. So this seems not to hurt the tabs case, but should help the 4 x spaces case significantly.
2025-08-05 07:13:56 +00:00
Copilot af4d5582bf feat(codegen): add options to control indentation (#12691)
Add ability to control indentation style (tabs/spaces) and width (e.g. 2 / 4).

## Usage

```rust
use oxc_codegen::{Codegen, CodegenOptions, IndentChar};

// Tabs with default width
let options = CodegenOptions::default();

// Spaces with width 4
let options = CodegenOptions {
    indent_char: IndentChar::Space,
    indent_width: 4,
    ..CodegenOptions::default()
};

// Tabs with width 2
let options = CodegenOptions {
    indent_char: IndentChar::Tab,
    indent_width: 2,
    ..CodegenOptions::default()
};
```

All existing functionality is preserved with backward compatibility maintained. The updated system enables new use cases like multi-tab indentation.

---------

Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
2025-08-02 00:56:59 +01:00
Copilot 45e2fe8851 docs(rust): Fix typos and grammar mistakes in Rust documentation comments (#12715) 2025-08-01 21:25:28 +08:00
overlookmotel 7cb4d22244 feat(data_structures): SliceIterExt extension trait (#12294)
Introduce `SliceIterExt` extension trait, to add methods to `std::slice::Iter` and `std::slice::IterMut` for advancing the iterators.

* `next_unchecked` - Get next item from iterator without checking if iterator is empty.
* `advance` - Move iterator forwards by a number of items.
* `advance_unchecked` - Move iterator forwards by a number of items, without bounds checks.

We have various implementations of these in various places in the codebase (and slightly different implementations of them each time), so it's better to centralize the implementation in one place.
2025-07-16 01:31:51 +00:00
overlookmotel f8fac4e45d perf(data_structures): inline all methods in PointerExt (#11149)
Add `#[inline(always)]` to one method that I missed.
2025-05-19 09:44:54 +00:00
overlookmotel bb8bde3e9c refactor(various): update macros to use expr fragment specifier (#11113)
Pure refactor. `expr_2021` fragment specifier was I assume introduced in these macros by a codemod when we updated to Rust 2024 edition. None of these macros are used with input where there's any difference between `expr_2021` and `expr`, so just use `expr`.
2025-05-18 10:26:51 +00:00
overlookmotel c79a7d0433 feat(data_structures): introduce PointerExt trait (#11095)
Rust v1.87.0 introduced new methods for pointers, notably `offset_from_unsigned` which calculates the distance between 2 pointers.

https://doc.rust-lang.org/std/primitive.pointer.html#method.offset_from_unsigned

`offset_from_unsigned` is the same as `offset_from`, except it require the source pointer to be before the target, and so returns a `usize` rather than an `isize`. In return for this restriction, the compiler is able to generate more efficient code in some cases.

We want to use these methods, but our MSRV won't hit 1.87.0 for 3 months.

This PR introduces a `PointerExt` trait which provides similar methods `offset_from_usize` and `byte_offset_from_usize`.

On versions of Rust >= 1.87.0, these delegate directly to the native Rust methods `offset_from_unsigned` and `byte_offset_from_unsigned`. On earlier versions of Rust, they use a fallback implementation.

This PR replaces all use of `offset_from` with `offset_from_usize` in our crates.

This will probably make little difference to perf, as we don't use these methods much, and the perf advantage is small anyway. But reason I'm making this PR now is that allocator will make liberal use of them on very hot paths.
2025-05-18 07:01:20 +00:00
Boshen 5d9344fbfa refactor(rust)!: clippy avoid-breaking-exported-api = false (#11088) 2025-05-17 02:21:26 +00:00
overlookmotel 05bf1be10f feat(data_structures): add InlineString::as_mut_str method (#10856)
Add `InlineString::as_mut_str` method, to accompany `as_str`. Not including this method was an oversight when I wrote `InlineString`.
2025-05-07 12:32:38 +00:00