Skip to content

fix(deps): update rust crate specta to v2.0.0-rc.23#4234

Open
renovate[bot] wants to merge 1 commit intomainfrom
renovate/specta-2.x
Open

fix(deps): update rust crate specta to v2.0.0-rc.23#4234
renovate[bot] wants to merge 1 commit intomainfrom
renovate/specta-2.x

Conversation

@renovate
Copy link
Contributor

@renovate renovate bot commented Mar 3, 2026

This PR contains the following updates:

Package Type Update Change
specta dependencies patch =2.0.0-rc.22=2.0.0-rc.23

Release Notes

specta-rs/specta (specta)

v2.0.0-rc.23: - Pouring the Foundation of 2.0.0

Compare Source

Specta v2.0.0-rc.23

After a lot of anticipation, Specta is back with a major update that overhauls the core to prepare the project for the upcoming 2.0.0 release. While this release includes a number of new features, much of the work has focused on building the foundations for some exciting new capabilities that will be arriving in the near future.

Work on this release started in January 2025 and was put on hold multiple times, but thanks to Flight Science's funding I have been able to dedicate time to finishing the Specta vision and getting us much closer to a stable 2.0.0 release at last. A huge debt of gratitude is owed to them for making this all possible!

Multi-file and namespace exporting for TypeScript

We have added support for the highly requested feature which allows you to export your types into TypeScript namespaces, or multiple files instead of just outputting a single flat file of types. This is incredibly useful as your project scales and your single types file starts to become out of control.

Specta's new Typescript API takes care of all the complexity for implementing the different export flows. With the Typescript API you no longer need to use the low-level primitives for generating files, worry about filesystem operations, cross-file imports, deleting no longer required type files, checking for duplicate exports in a single scope, and more. We recommend migrating all applications and frameworks built on Specta to this API but the older low-level APIs still exist in specta_typescript::primitives.

You can check out the Typescript::layout method which is used to configure this new feature!

TypeScript branded types

This release introduces experimental support for branded Typescript types to be generated from Rust.

This means you can define Rust newtypes that are exported as branded TypeScript primitives, making it possible to model values like AccountId, UserId, and similar domain-specific strings more safely in the generated bindings. We also support integrations with any Typescript branded string library, including having examples for ts-brand and EffectTS's branded strings.

The exact API may change slightly for the final 2.0.0 release but you can check out how to define branded types with branded! and how to configure integration with third-party branding libraries via Typescript::branded_type_impl.

Your feedback on this feature would be welcome! Jump in the Discord!

Rename export feature to collect

This release renames the export feature to collect. The previous name could easily be confused with exporting types when this feature actually automatically collects types with the #[derive(Type)] macro so you can get a TypeCollection containing all your types for exporting them without manually registering each type.

This feature works identically to how it previously did. This change is just to reduce confusion and make documentation easier for the feature.

This rename touches feature flags, functions, and related attribute names. If you were previously using export, the migration is the following:

  • specta::export -> specta::collect
  • export feature -> collect feature
  • #[specta(export = false)] -> #[specta(collect = false)]

Removal of the TypeScript formatter integrations

Previously Specta TypeScript had the ability to integrate with Prettier, Biome, and other custom TypeScript formatters. I decided to remove support for this as I found that in the complexity of real-world projects with different package managers, monorepo configurations, and more, the feature would rarely work well out of the box and you would end up with your own custom implementation. This was no better than just leaving the implementation up to the end-user from the get-go.

We recommend you simply using std::process::Command to spawn your formatter's CLI as a subprocess after Specta's type exporting completes.

We have also made improvements to Specta's type formatting by default so another option is to just ignore the Specta generated bindings from requiring formatting.

std feature

Specta now has a std feature, enabled by default, which makes the standard library boundary much clearer. This follows the same pattern as the feature in Serde.

Without this feature enabled, the Type implementations won't be included for std::* types, so you may need to enable it if you use default-features = false in your Cargo.toml.

Format support

Specta's core is now much more format-agnostic than before.

Previously, a lot of Serde-specific behavior was effectively baked into the derive macro. In this release, raw attributes are lowered into runtime metadata and the actual Serde interpretation lives in the new specta-serde crate so it's completly decoupled from the specta and specta-macros crates. That means Specta's core can be used with other serialization libraries than Serde and can support any data-formats.

This is an important architectural change because it opens the door for other data formats to build on the same powerful type exporting information Specta has without being forced through Serde-specific assumptions. It makes Specta more of a general purpose type-introspection library.

This work also benifits Specta users which stick with Serde (as I suspect most people will) because it also lays the groundwork for us to be able to do phase-aware handling of types in the future. This feature would allow us to export your types with the phase (serialization or deserialization) metadata attached so frameworks like Tauri Specta, TauRPC, or rspc can accept narrower types than the current types which have to be a union between both types. For example #[serde(default)] could make a field optional when passed to a Tauri Specta command but it would be required on the response from a Tauri Specta command.

This change also necessitated a cleanup of the way attributes are handled in the Type derive macro. We have removed support for many #[specta(...)] attributes as you are now required to use #[serde(...)]. The #[serde(...)] attributes apply to both the types and runtime serialization/deserialization behavior while #[specta(...)] only applies to the types, so this change helps highlight code which is generally incorrect at compile time.

Reference overhaul

[!TIP]
A reference is used in Specta's type representation to show the value of a type refers to another one. For example if we produce type A = B<number>; the B<number> comes from a Reference.

A major change in this release is a deep overhaul of how Specta represents references internally.

The old SpectaID-based model worked really well for the #[derive(Type)] macro but it made it virtually impossible for your code to generate a type using a programmatic API at runtime. This use case is really useful for frameworks like Tauri Specta/rspc and also if you want to generate types from schemas or other runtime metadata.

Specta now also has stricter semantics around the usage of references. We have removed any public API for deleting references from the TypeCollection, making it much harder for errors to occur in the language exporters. With this change we have also split references into two types.

A named reference is just what we had in the old system. It's a reference to a NamedDataType, which is anything with #[derive(Type)] (or a runtime type built with (NamedDataTypeBuilder::build](https://docs.rs/specta/2.0.0-rc.23/specta/datatype/struct.NamedDataTypeBuilder.html#method.build)).

We have introduced a new kind of reference called an opaque reference. These have no semantic meaning to Specta's core but allow a language exporter like TypeScript to define custom behaviour when they are encountered. They are also configured to error by default if the exporter doesn't handle them. This means if you try and use a specta_typescript::Any with the specta-swift exporter your going to recieve a useful error now. This feature powers specta_typescript::{Any, Never, Unknown} and also branded types and specta_typescript::define, which allows injecting raw TypeScript code into your datatype structures.

Inline in the language exporter

[!TIP]
#[specta(inline)] is like #[serde(flatten)] at a type level. It allows the type's content to be inlined into the parent type's definition. As an end user you won't generally need this but its semantics are important to the reliability of the type export process.

One major internal shift in this release is that more of Specta's type processing now happens in the language exporter rather than in the macro expansion within the Type trait. In practice, this makes inlining much more reliable and much easier to reason about. It also prevents unsolvable stack overflows which can sometimes happen from recursive types.

With these changes the resulting fn definition implementation within the Type trait will contain DataType::Reference's to other types instead of calling <T as Type>::definition to get the DataType. This means we can't end up with infinite recursion when calling definition on a recursive type. This is really important for the collect feature as stack overflows in ctor can cause full-program crashes. The references now also contain information about whether they should be inlined which is then picked up by the language exporter (TypeScript) which is able to flatten the type definition properly.

These changes also enabled inlining to now behaves as you would expect through wrappers like Option<T> and Box<T> where it now inlines T. Older versions of Specta would apply the inline to Option<T> instead of peeking through the containiner and inlining T, which meant #[specta(inline)] Option<T> actually didn't change from a regular Option<T>.

This work also improved how Specta decides whether a type actually needs to be emitted as a referenceable export. Types that can only ever be inlined (Eg. #[specta(inline)] on the container) no longer produce pointless named exports in the resulting bindings file.

For downstream frameworks like Tauri Specta and TauRPC, this release also improves the TypeScript exporting pipeline so that frameworks can include their own runtime TypeScript code via Exporter::framework_runtime while allows them to take advantage of Specta's new multi-file exporting without needing to reimplement all of it's logic into their own crate. This also reduce the amount of filesystem and type wrangling code frameworks need to maintain and allows the ecosystem to work on a single battle tested implementation of the logic.

Published new language exporter crates

We have published all of the crates in the Specta monorepo to crates.io. These include some beta and some unfinished language exporter crates. Most of them are not ready for prime time at the moment, but hopefully work on them can begin soon.

Swift should be usable and Go is coming in the next release thanks to the work of @​philocalyst in #​448. If your use case requires one feel free to reach out or open a PR!

For the foreseeable future the Typescript exporter is the recommended language exporter as it receives the majority of the development effort. If your want to sponsor work on or maintain a specific language exporter I would love to hear from you!

Breaking changes

As expected for a release with this much stuff it includes a number of breaking changes, especially for advanced users, framework authors, and anyone using low-level Specta APIs directly. Most end-users won't see as much of an impact.

Some changes include:

  • export has been renamed to collect, including feature flags and related APIs.
  • SpectaID has been removed from the public model.
  • NamedType, Flatten, and Language have been removed from core.
  • DataType::Any, DataType::Unknown, and DataType::Literal have been removed.
  • Older public datatype items such as EnumVariants, StructFields, LiteralType, PrimitiveType, GenericType, EnumType, StructType, TupleType, DataTypeReference, and reference::Reference were removed or reworked.
  • Type::inline and Type::reference were removed from the Type trait in favor of the newer definition/reference model.
  • TypeCollection changed significantly, including the removal of methods like insert, extend, remove, and get, and register now takes ownership of Self instead of &mut Self.
  • The export, serde, and interop features were removed from specta.
  • specta-jsdoc has been folded into specta-typescript as specta_typescript::JSDoc.
  • specta-rust has been removed for now.
  • specta::json has been removed.
  • Serde-style behavior is no longer accepted through deprecated #[specta(...)] forms; Serde attributes now belong to Serde and are handled through specta-serde.
  • specta-typescript had its API restructured heavily: the old root-level export, export_ref, inline, inline_ref, export_named_datatype, and datatype helpers are gone in favor of Typescript, JSDoc, Exporter, and primitives::* APIs.
  • specta_typescript::ExportError and related types were removed in favor of the newer sealed specta_typescript::Error model.
  • The function feature was removed from specta-typescript.

If you see any issues upgrading jump in the Discord and we can help you out!

What's next?

Much of the work in this release is foundational work for the next stage of Specta.

We can now start working on:

  • handling for special datatypes like BigInt, Date, UInt8Array, etc.
  • handling types differently across each phase (serialization vs deserialization) with Serde
  • stronger support for Serde attributes (we don't implement a handful of them yet)
  • reliability (you can never have enough tests!)
  • and lots more!

This release is a major milestone in the path towards the stable release Specta v2. We are now in a place where I can see the final release is in sight which is very exciting.

New Contributors

A huge thanks to all the people who contributed to this release!

Full Changelog: specta-rs/specta@v2.0.0-rc.22...v2.0.0-rc.23


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.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate
Copy link
Contributor Author

renovate bot commented Mar 3, 2026

⚠️ Artifact update problem

Renovate failed to update artifacts related to this branch. You probably do not want to merge this PR as-is.

♻ Renovate will retry this branch, including artifacts, only when one of the following happens:

  • any of the package files in this branch needs updating, or
  • the branch becomes conflicted, or
  • you click the rebase/retry checkbox if found above, or
  • you rename this PR's title to start with "rebase!" to trigger it manually

The artifact failure details are included below:

File name: backend/nyanpasu-egui/Cargo.lock
Command failed: cargo update --config net.git-fetch-with-cli=true --manifest-path backend/nyanpasu-egui/Cargo.toml --workspace
    Updating crates.io index
error: failed to select a version for `specta`.
    ... required by package `nyanpasu-egui v0.1.0 (/tmp/renovate/repos/github/libnyanpasu/clash-nyanpasu/backend/nyanpasu-egui)`
    ... which satisfies path dependency `nyanpasu-egui` (locked to 0.1.0) of package `clash-nyanpasu v0.1.0 (/tmp/renovate/repos/github/libnyanpasu/clash-nyanpasu/backend/tauri)`
versions that meet the requirements `=2.0.0-rc.23` are: 2.0.0-rc.23

package `nyanpasu-egui` depends on `specta` with feature `serde` but `specta` does not have that feature.
 A required dependency with that name exists, but only optional dependencies can be used as features.


failed to select a version for `specta` which could resolve this conflict

File name: backend/Cargo.lock
Command failed: cargo update --config net.git-fetch-with-cli=true --manifest-path backend/tauri/Cargo.toml --workspace
    Updating crates.io index
error: failed to select a version for `specta`.
    ... required by package `nyanpasu-egui v0.1.0 (/tmp/renovate/repos/github/libnyanpasu/clash-nyanpasu/backend/nyanpasu-egui)`
    ... which satisfies path dependency `nyanpasu-egui` (locked to 0.1.0) of package `clash-nyanpasu v0.1.0 (/tmp/renovate/repos/github/libnyanpasu/clash-nyanpasu/backend/tauri)`
versions that meet the requirements `=2.0.0-rc.23` are: 2.0.0-rc.23

package `nyanpasu-egui` depends on `specta` with feature `serde` but `specta` does not have that feature.
 A required dependency with that name exists, but only optional dependencies can be used as features.


failed to select a version for `specta` which could resolve this conflict

@renovate renovate bot force-pushed the renovate/specta-2.x branch 29 times, most recently from 2f1c5fe to cab2ddd Compare March 9, 2026 12:03
@renovate renovate bot force-pushed the renovate/specta-2.x branch 14 times, most recently from 5200b76 to fb2448b Compare March 12, 2026 07:28
@renovate renovate bot force-pushed the renovate/specta-2.x branch 6 times, most recently from 5d309a5 to 0690399 Compare March 12, 2026 17:54
@renovate renovate bot changed the title fix(deps): update rust crate specta to v2.0.0-rc.23 fix(deps): update rust crate specta to v2.0.0-rc.23 [skip ci] Mar 12, 2026
@renovate renovate bot force-pushed the renovate/specta-2.x branch from 0690399 to 16d5d05 Compare March 13, 2026 06:50
@renovate renovate bot changed the title fix(deps): update rust crate specta to v2.0.0-rc.23 [skip ci] fix(deps): update rust crate specta to v2.0.0-rc.23 Mar 13, 2026
@renovate renovate bot force-pushed the renovate/specta-2.x branch 4 times, most recently from d40800b to 1d9ba88 Compare March 13, 2026 11:32
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.

0 participants