Skip to content

chore(deps): upgrade toml to 0.9 and toml_edit to 0.24 (TOML 1.1)#8057

Merged
jdx merged 2 commits intomainfrom
chore/upgrade-toml-crate
Feb 8, 2026
Merged

chore(deps): upgrade toml to 0.9 and toml_edit to 0.24 (TOML 1.1)#8057
jdx merged 2 commits intomainfrom
chore/upgrade-toml-crate

Conversation

@jdx
Copy link
Owner

@jdx jdx commented Feb 8, 2026

Summary

  • Upgrades toml from 0.8 (spec 1.0) to 0.9 (spec 1.1)
  • Upgrades toml_edit from 0.22 to 0.24
  • Updates all call sites for breaking API changes:
    • FromStr for Value now parses single values instead of documents; switched to toml::de::from_str for document parsing
    • Deserializer::new deprecated; switched to Deserializer::parse

TOML 1.1 features now available in mise.toml

This upgrade enables TOML 1.1 syntax in all mise configuration files:

  • Newlines in inline tables — spread inline tables across multiple lines for readability:

    [tools]
    rust = { version = "1.82",
             profile = "minimal",
             components = ["rust-src", "llvm-tools"] }
  • Trailing commas in inline tables and arrays — no more editing the last line when adding entries:

    [env]
    _.path = [
      "./node_modules/.bin",
      "./bin",
    ]
  • \xHH escape sequences — hex escapes for codepoints ≤ 255 in quoted strings:

    [env]
    SEPARATOR = "\x1F"
  • \e escape — shorthand for the escape character (\x1B):

    [env]
    RED = "\e[31m"
  • Optional seconds in datetime/time values:

    # Seconds are now optional
    created = 2026-02-07T12:00

Test plan

  • cargo check --workspace passes
  • All pre-commit lints pass
  • CI passes

🤖 Generated with Claude Code


Note

Medium Risk
Touches core config parsing paths and task header/tool option TOML decoding; behavior should be equivalent but parsing/serialization differences in toml 0.9 (TOML 1.1) could surface in edge-case configs.

Overview
Upgrades TOML dependencies to TOML 1.1 support (toml 0.9 with preserve_order, toml_edit 0.24) and updates Cargo.lock accordingly (new toml_parser/toml_writer stack).

Refactors TOML parsing call sites away from str::parse() and Deserializer::new to the new toml::de::from_str and toml::Deserializer::parse APIs in config loading/codegen (build.rs), mise.toml deserialization, mise config get, Rust toolchain idiomatic file parsing, task header parsing, and nested tool option lookups.

Docs examples are reformatted to use TOML 1.1-friendly multiline inline tables (trailing commas/newlines) to match the newly supported syntax.

Written by Cursor Bugbot for commit 5bd72f8. This will update automatically on new commits. Configure here.

Upgrade toml crate from 0.8 (spec 1.0) to 0.9 (spec 1.1) and
toml_edit from 0.22 to 0.24.

Breaking API changes addressed:
- `FromStr for Value` now parses values, not documents; use
  `toml::de::from_str` for document parsing
- `Deserializer::new` replaced with `Deserializer::parse`

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 8, 2026 14:28
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @jdx, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request undertakes a significant dependency upgrade, bringing the project's TOML parsing and editing capabilities in line with the latest versions of the toml and toml_edit crates. This update not only ensures compatibility with the TOML 1.1 specification but also required several code adjustments to accommodate the new API surface, primarily around how TOML documents are parsed and deserialized, thereby ensuring continued functionality and improved parsing robustness.

Highlights

  • Dependency Upgrades: The toml crate has been upgraded from version 0.8 to 0.9, introducing support for TOML specification 1.1. Concurrently, the toml_edit crate has been updated from version 0.22 to 0.24.
  • API Adaptations for TOML Parsing: The codebase has been updated to accommodate breaking API changes in the toml crate. Specifically, the method for parsing full TOML documents from strings has shifted from FromStr for Value (i.e., .parse()) to toml::de::from_str.
  • Deserializer API Change: The deprecated toml::Deserializer::new constructor has been replaced with toml::Deserializer::parse for TOML deserialization, along with improved error handling.
Changelog
  • Cargo.lock
    • Updated toml version from 0.8.23 to 0.9.11+spec-1.1.0.
    • Updated toml_edit version from 0.22.27 to 0.24.0+spec-1.1.0.
    • Updated serde_spanned from 0.6.9 to 1.0.4 and changed its dependency from serde to serde_core.
    • Updated toml_datetime from 0.6.11 to 0.7.5+spec-1.1.0.
    • Introduced new transitive dependencies for toml and toml_edit, including indexmap, serde_core, toml_parser, toml_writer, and winnow, replacing the toml_write package.
  • Cargo.toml
    • Bumped toml dependency from 0.8 to 0.9.
    • Bumped toml_edit dependency from 0.22 to 0.24.
  • build.rs
    • Refactored TOML parsing logic from content.parse() to toml::de::from_str(&content) for tool_info.
    • Updated parsing of settings.toml from .parse().unwrap() to toml::de::from_str(...).unwrap().
  • crates/mise-interactive-config/Cargo.toml
    • Updated toml_edit dependency to 0.24.
  • src/cli/config/get.rs
    • Switched TOML file parsing from .parse()? to toml::de::from_str(...).
  • src/config/config_file/mise_toml.rs
    • Migrated from toml::Deserializer::new(body) to toml::Deserializer::parse(body) with added error handling.
  • src/plugins/core/rust.rs
    • Updated TOML parsing for idiomatic files from .parse::<toml::Value>()? to toml::de::from_str(&toml)?.
  • src/task/mod.rs
    • Changed TOML header parsing from .parse::<toml::Value>() to toml::de::from_str::<toml::Value>(toml).
  • src/toolset/tool_version_options.rs
    • Modified inline TOML table parsing from .parse::<toml::Value>() to toml::de::from_str::<toml::Value>(...).
Activity
  • cargo check --workspace passed successfully.
  • All pre-commit lints passed.
  • CI is expected to pass.
  • The changes were generated with Claude Code.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Upgrades toml/toml_edit to TOML 1.1-compatible versions and updates parsing/deserialization call sites to match the new APIs.

Changes:

  • Bumped toml to 0.9 and toml_edit to 0.24
  • Replaced Value::from_str usages with toml::de::from_str for document parsing
  • Switched from deprecated toml::Deserializer::new to toml::Deserializer::parse

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/toolset/tool_version_options.rs Updates inline table parsing to use toml::de::from_str
src/task/mod.rs Uses toml::de::from_str for task header TOML parsing
src/plugins/core/rust.rs Parses Rust toolchain TOML via toml::de::from_str
src/config/config_file/mise_toml.rs Migrates to toml::Deserializer::parse with custom error mapping
src/cli/config/get.rs Reads config file and deserializes via toml::de::from_str
crates/mise-interactive-config/Cargo.toml Bumps toml_edit dependency version
build.rs Switches TOML parsing to toml::de::from_str and adjusts settings parsing
Cargo.toml Bumps workspace toml/toml_edit dependency versions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +83 to +84
if let Ok(toml_value) =
toml::de::from_str::<toml::Value>(&format!("value = {value}"))
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

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

value.trim() is called multiple times in the surrounding conditional, and format!(\"value = {value}\") allocates a new String for each parse attempt. Consider binding let trimmed = value.trim(); once and formatting from trimmed (or reusing a prebuilt String) to reduce repeated work in these hot-path helpers.

Copilot uses AI. Check for mistakes.
src/task/mod.rs Outdated
.map(|[toml]| {
toml.parse::<toml::Value>()
toml::de::from_str::<toml::Value>(toml)
.map_err(|e| eyre::eyre!("failed to parse task header TOML '{}': {}", toml, e))
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

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

The error message embeds the raw toml snippet in single quotes, which can produce noisy/multiline logs (and confusing output if it contains quotes/newlines). Prefer Debug formatting ({toml:?}) and/or truncating/sanitizing (e.g., replacing newlines) in the message so parse errors remain readable.

Suggested change
.map_err(|e| eyre::eyre!("failed to parse task header TOML '{}': {}", toml, e))
.map_err(|e| eyre::eyre!("failed to parse task header TOML {toml:?}: {e}"))

Copilot uses AI. Check for mistakes.
build.rs Outdated
Comment on lines +302 to +303
let settings: toml::Table =
toml::de::from_str(&fs::read_to_string("settings.toml").unwrap()).unwrap();
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

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

This nested unwrap() chain makes failures harder to diagnose and is difficult to read. Please split into separate steps and use expect(...)/unwrap_or_else(...) with context (file path + parse error) similar to load_registry_tools() above.

Suggested change
let settings: toml::Table =
toml::de::from_str(&fs::read_to_string("settings.toml").unwrap()).unwrap();
let settings_toml = fs::read_to_string("settings.toml")
.unwrap_or_else(|err| panic!("Failed to read settings.toml: {err}"));
let settings: toml::Table =
toml::de::from_str(&settings_toml)
.unwrap_or_else(|err| panic!("Failed to parse settings.toml: {err}"));

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request successfully upgrades the toml and toml_edit dependencies and updates the call sites to align with the new APIs. The changes are generally correct. I've included a few suggestions to enhance code readability and maintainability by separating file reading from parsing and avoiding variable shadowing.

build.rs Outdated
Comment on lines +302 to +303
let settings: toml::Table =
toml::de::from_str(&fs::read_to_string("settings.toml").unwrap()).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

For better readability and easier debugging, consider separating the file reading and TOML parsing into two distinct steps. This avoids chaining unwrap() calls on a single line.

Suggested change
let settings: toml::Table =
toml::de::from_str(&fs::read_to_string("settings.toml").unwrap()).unwrap();
let content = fs::read_to_string("settings.toml").unwrap();
let settings: toml::Table = toml::de::from_str(&content).unwrap();

}
if let Some(file) = file {
let config: toml::Value = std::fs::read_to_string(&file)?.parse()?;
let config: toml::Value = toml::de::from_str(&std::fs::read_to_string(&file)?)?;
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

To improve readability, it's a good practice to separate file reading from TOML parsing. This makes the code easier to follow and debug.

Suggested change
let config: toml::Value = toml::de::from_str(&std::fs::read_to_string(&file)?)?;
let content = std::fs::read_to_string(&file)?;
let config: toml::Value = toml::de::from_str(&content)?;

Comment on lines +275 to +276
let toml = file::read_to_string(path)?;
let toml = toml.parse::<toml::Value>()?;
let toml: toml::Value = toml::de::from_str(&toml)?;
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

To avoid confusion from variable shadowing with different types, consider using a different variable name for the file content before parsing it into a TOML value.

Suggested change
let toml = file::read_to_string(path)?;
let toml = toml.parse::<toml::Value>()?;
let toml: toml::Value = toml::de::from_str(&toml)?;
let content = file::read_to_string(path)?;
let toml: toml::Value = toml::de::from_str(&content)?;

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is ON, but a Cloud Agent failed to start.

@jdx jdx enabled auto-merge (squash) February 8, 2026 14:50
@github-actions
Copy link

github-actions bot commented Feb 8, 2026

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.7 x -- echo 17.7 ± 0.5 16.6 20.2 1.00
mise x -- echo 18.1 ± 0.7 16.5 24.0 1.02 ± 0.05

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.7 env 17.9 ± 0.8 16.2 24.3 1.00
mise env 18.7 ± 0.7 16.8 23.6 1.04 ± 0.06

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.7 hook-env 19.1 ± 0.8 17.8 26.2 1.00
mise hook-env 19.2 ± 0.5 17.3 21.7 1.01 ± 0.05

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.7 ls 18.0 ± 1.6 16.7 41.8 1.00
mise ls 18.1 ± 0.8 17.0 27.4 1.00 ± 0.10

xtasks/test/perf

Command mise-2026.2.7 mise Variance
install (cached) 95ms 93ms +2%
ls (cached) 63ms 62ms +1%
bin-paths (cached) 64ms 65ms -1%
task-ls (cached) 495ms 501ms -1%

- Fix two missed .parse::<toml::Value>() calls in tool_version_options.rs
  that broke nested TOML document parsing (e.g., platform-specific configs)
- Separate file reading from TOML parsing for better debuggability
- Use Debug formatting for TOML error messages to handle newlines
- Use expect() with context in build.rs instead of bare unwrap()
- Use multiline inline tables in docs (TOML 1.1 syntax)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jdx jdx force-pushed the chore/upgrade-toml-crate branch from d750e9f to 5bd72f8 Compare February 8, 2026 15:04
@jdx jdx merged commit 27dccaa into main Feb 8, 2026
36 checks passed
@jdx jdx deleted the chore/upgrade-toml-crate branch February 8, 2026 15:19
mise-en-dev added a commit that referenced this pull request Feb 9, 2026
### 🚀 Features

- **(node)** support package.json as idiomatic version file by @jdx in
[#8059](#8059)
- **(ruby)** graduate precompiled ruby from experimental (gradual
rollout) by @jdx in [#8052](#8052)
- add --dry-run-code flag to exit non-zero when there is work to do by
@jdx in [#8063](#8063)

### 🐛 Bug Fixes

- **(core)** respect MISE_ARCH override in bun and erlang plugins by
@jdx in [#8062](#8062)
- **(hooks)** resolve 12 community-reported hooks issues by @jdx in
[#8058](#8058)
- accept key=value format in set/add subcommands by @jdx in
[#8053](#8053)

### 📚 Documentation

- bump action versions in GitHub Actions examples by @muzimuzhi in
[#8065](#8065)
- add opengraph meta tags by @jdx in
[#8066](#8066)

### 📦️ Dependency Updates

- upgrade toml to 0.9 and toml_edit to 0.24 (TOML 1.1) by @jdx in
[#8057](#8057)

### 📦 Registry

- add quicktype (npm:quicktype) by @zdunecki in
[#8054](#8054)
- use inline table for test definitions by @jdx in
[#8056](#8056)
lucasew pushed a commit to lucasew/CONTRIB-mise that referenced this pull request Feb 18, 2026
…x#8057)

## Summary
- Upgrades `toml` from 0.8 (spec 1.0) to 0.9 (spec 1.1)
- Upgrades `toml_edit` from 0.22 to 0.24
- Updates all call sites for breaking API changes:
- `FromStr for Value` now parses single values instead of documents;
switched to `toml::de::from_str` for document parsing
  - `Deserializer::new` deprecated; switched to `Deserializer::parse`

## TOML 1.1 features now available in `mise.toml`

This upgrade enables TOML 1.1 syntax in all mise configuration files:

- **Newlines in inline tables** — spread inline tables across multiple
lines for readability:
  ```toml
  [tools]
  rust = { version = "1.82",
           profile = "minimal",
           components = ["rust-src", "llvm-tools"] }
  ```

- **Trailing commas in inline tables and arrays** — no more editing the
last line when adding entries:
  ```toml
  [env]
  _.path = [
    "./node_modules/.bin",
    "./bin",
  ]
  ```

- **`\xHH` escape sequences** — hex escapes for codepoints ≤ 255 in
quoted strings:
  ```toml
  [env]
  SEPARATOR = "\x1F"
  ```

- **`\e` escape** — shorthand for the escape character (`\x1B`):
  ```toml
  [env]
  RED = "\e[31m"
  ```

- **Optional seconds in datetime/time values**:
  ```toml
  # Seconds are now optional
  created = 2026-02-07T12:00
  ```

## Test plan
- [x] `cargo check --workspace` passes
- [x] All pre-commit lints pass
- [x] CI passes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches core config parsing paths (including `mise.toml`
deserialization) and build-time codegen, so any subtle parsing/serde
behavior changes could impact config compatibility despite the changes
being largely mechanical.
> 
> **Overview**
> Upgrades the Rust `toml` ecosystem to TOML 1.1 support by bumping
`toml` to `0.9` and `toml_edit` to `0.24` (including lockfile updates
that replace older `toml_*` crates with `toml_parser`/`toml_writer` and
newer `serde_spanned`).
> 
> Updates TOML parsing call sites to match the new APIs by switching
document parsing from `str::parse()` to `toml::de::from_str()` and
replacing `toml::Deserializer::new` with `toml::Deserializer::parse`
(affecting `build.rs`, `mise.toml` parsing, `mise config get`, rust
toolchain file parsing, task header parsing, and nested tool option
lookup).
> 
> Refreshes docs examples to use multi-line inline-table formatting that
TOML 1.1 permits (primarily readability changes).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d750e9f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
lucasew pushed a commit to lucasew/CONTRIB-mise that referenced this pull request Feb 18, 2026
### 🚀 Features

- **(node)** support package.json as idiomatic version file by @jdx in
[jdx#8059](jdx#8059)
- **(ruby)** graduate precompiled ruby from experimental (gradual
rollout) by @jdx in [jdx#8052](jdx#8052)
- add --dry-run-code flag to exit non-zero when there is work to do by
@jdx in [jdx#8063](jdx#8063)

### 🐛 Bug Fixes

- **(core)** respect MISE_ARCH override in bun and erlang plugins by
@jdx in [jdx#8062](jdx#8062)
- **(hooks)** resolve 12 community-reported hooks issues by @jdx in
[jdx#8058](jdx#8058)
- accept key=value format in set/add subcommands by @jdx in
[jdx#8053](jdx#8053)

### 📚 Documentation

- bump action versions in GitHub Actions examples by @muzimuzhi in
[jdx#8065](jdx#8065)
- add opengraph meta tags by @jdx in
[jdx#8066](jdx#8066)

### 📦️ Dependency Updates

- upgrade toml to 0.9 and toml_edit to 0.24 (TOML 1.1) by @jdx in
[jdx#8057](jdx#8057)

### 📦 Registry

- add quicktype (npm:quicktype) by @zdunecki in
[jdx#8054](jdx#8054)
- use inline table for test definitions by @jdx in
[jdx#8056](jdx#8056)
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