Skip to content

Upgrade Rust toolchain to nightly-2026-08-01 - #4767

Draft
feliperodri wants to merge 3 commits into
model-checking:mainfrom
feliperodri:toolchain-2026-08-01
Draft

Upgrade Rust toolchain to nightly-2026-08-01#4767
feliperodri wants to merge 3 commits into
model-checking:mainfrom
feliperodri:toolchain-2026-08-01

Conversation

@feliperodri

Copy link
Copy Markdown
Member

Important

Draft: do not review until #4764 (nightly-2026-07-01) and #4766 (cargo layout) are merged.

This branch is stacked on both, so its diff currently contains their commits too:

Commit What Where it lands from
2640178a9 Upgrade to nightly-2026-07-01 #4764
a8a58b674 Derive the cargo output directory from cargo's reported artifacts #4766
41b56947e Upgrade to nightly-2026-08-01 this PR — review only this commit

Once both land this rebases down to the single nightly-2026-08-01 commit.

Dependencies and merge order

#4760  nightly-2026-06-01   ✅ merged
  └─ #4764  nightly-2026-07-01     ← rebase on main + un-draft; its dependency has landed
       └─ #4766  cargo target layout   ← CI green, independent of any toolchain bump
            └─ THIS PR  nightly-2026-08-01

#4766 is a hard dependency, not a preference. cargo 1.99 ships with this nightly and changed the layout under target/; without that fix the entire cargo-based flow fails with error: No such file or directory (os error 2), taking out 68 of 71 cargo-kani tests and 11 script-based-pre tests. #4766 stands alone — it applies to the current toolchain and is behaviour-preserving there — which is why it is a separate PR rather than part of this one.

#4764 is a dependency only in the sense that toolchain bumps are sequential: skipping it would fold two upgrades into one review.

Description

Bumps rust-toolchain.toml from nightly-2026-07-01 to nightly-2026-08-01, the first 1.99 nightly. 91 compile errors came with it.

1. Statement/Terminator carry a SourceInfo, not a bare Span (78 of the 91 errors)

// nightly-2026-07-01
pub struct Statement<'tcx> { pub source_info: SourceInfo, .. }   // Terminator: span only
// nightly-2026-08-01 -- both carry SourceInfo (span + source scope)

A new helper in transform/body.rs keeps the choice of scope in one documented place rather than spreading a bare scope: 0 across ~78 sites:

/// The `SourceInfo` for a statement or terminator that Kani synthesizes at `span`.
///
/// As of nightly-2026-08-01 `Statement` and `Terminator` carry a `SourceInfo` (span plus source
/// scope) instead of a bare `Span`. Kani-synthesized MIR does not belong to any inlined scope, so
/// it uses the outermost one -- scope 0, which `Body::new` always allocates.
pub fn synthetic_source_info(span: Span) -> SourceInfo {
    SourceInfo { span, scope: 0 }
}

Reads become .source_info.span.

2. predicates_of became clauses_of

Returns GenericClauses (parent + clauses) instead of GenericPredicates (parent + predicates). Same shape and same instantiate, so this is a rename at four call sites — three in codegen_units.rs from #4706/#4718, one in the LLBC backend.

3. ty::FnDef's generic args are bound

Three Instance::{try,expect}_resolve call sites need .skip_binder().

4. ValueAbi::ScalarPair became a struct variant

With a new b_offset field.

5. Two new enum variants

  • AssertMessage::NullReferenceConstructed — handled like NullPointerDereference: same property class, description taken from rustc_public rather than hardcoded.
  • InstanceKind::LlvmIntrinsic — codegens like any other item, and has no Rust body for reachability to collect.

Plus LocalModDefId renamed to LocalModId, and Region::new_early_param moving to the RegionExt extension trait.

Test changes (5 files)

std::intrinsics::{size_of,align_of} are now comptime fns and cannot be called at runtime, which affected four tests:

  • tests/kani/DynTrait/{nested_boxes,vtable_size_align_drop}.rs used size_of incidentally, to compare a vtable field against a type's size — switched to std::mem::size_of.
  • tests/kani/Intrinsics/ConstEval/{size_of,align_of}.rs exist to check the intrinsics themselves, so each call is bound to a const — which is what that directory is about, and the only way now legal.

expected/issue-3571 — a genuine behaviour change worth flagging. Constructing a null reference (&*(0 as *const u32)) used to report null pointer dereference occurred; rustc now distinguishes constructing a null reference from dereferencing a null pointer and reports null reference produced. rustc also emits a new misaligned pointer to reference cast check at the same site. The UB is still caught and the harness still fails — only the wording is more precise — so the expectation follows rustc's message rather than pinning the old one.

No other test needed adjusting, and no verification behaviour changed.

Testing

Local, macOS aarch64, CBMC 6.10.0 (cbmc-6.9.0-214-g45436eea34), on the stack rebased onto current main (which now includes #4760):

Suite Result
kani 607 passed, 0 failed
cargo-kani 71 passed, 0 failed
cargo-ui 30 passed, 0 failed
expected 471 passed, 2 failed — see below
ui 151 passed, 2 failed — environmental, see below

Also clean: both the CPROVER and LLBC builds, cargo clippy --workspace --tests -- -D warnings, RUSTFLAGS="--cfg=kani_sysroot" cargo clippy --workspace -- -D warnings, and ./scripts/kani-fmt.sh --check.

The two expected failures were run before the fix above and are accounted for:

  • expected/issue-3571 — the null-reference wording change; fixed in this PR, verified passing.
  • expected/shadow/slices/slice_split — I interrupted this one to let the suite finish. It is not an 08-01 regression: I timed it on the 07-01 branch as a control and it is equally slow there (>20 min in CBMC's SAT solver on both), so it is a slow test on this machine rather than anything this upgrade introduced. CI covers it.

The two ui failures are solver-attribute/cadical and solver-option/cadical, both expecting Solving with CaDiCaL. My local CBMC build reports The specified solver, 'cadical', is not available. The default solver will be used instead. — a missing solver in my environment, independent of the Rust toolchain.

  • Was this change tested? Yes
  • Is this a breaking change? No

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.

A much smaller upgrade than the previous two: no verification behaviour changed,
and no test needed adjusting.

**`FieldDef` moved to the `crate_def_with_ty!` macro.** Its inherent `ty()` and
`ty_with_args()` are now provided by the `CrateDefType` trait, so the 17 call
sites just need that trait in scope. This is a pure import change -- the
semantics are identical (both still resolve to `def_ty`/`def_ty_with_args`).

**`EarlyBinder::bind` takes the interner.** `bind(value)` becomes
`bind(tcx, value)` at five sites.

**`Terminator` gained MIR-level attributes** (`attributes: ThinVec<AttributeKind>`).
The stable representation has no equivalent, and Kani-synthesized terminators
carry none, so `internal_mir` passes an empty vector.

**`TerminatorKind::Drop` lost `async_fut`**, so that field is dropped from the
`internal_mir` conversion.

**Work products are an `UnordMap`, not an `FxIndexMap`**, in
`CodegenBackend::join_codegen`'s return type (both backends).

Full regression run is clean on the first attempt: kani 607/607, cargo-kani
71/71, expected, script-based-pre 68/68, std-checks, cargo-ui, coverage, prusti,
smack, kani-docs, json-handler, cargo-coverage, all unit tests, both
`-D warnings` clippy gates, the `-D warnings` build, fmt, and the LLBC build.
`cargo_build` hardcoded the compiler output directory as
`target/kani/<triple>/debug/deps`, and `cargo_project` then canonicalized
it -- so any layout that does not match becomes
`error: No such file or directory (os error 2)`.

That layout is cargo's to choose, and cargo 1.99 changes it: artifacts no
longer share `debug/deps`, each package getting its own
`debug/build/PKG/HASH/out/` instead. Artifact discovery was already
layout-agnostic (`map_kani_artifact` derives every path from the
`filenames` cargo reports), so the hardcoded directory was the only thing
tying the driver to the old layout.

Derive it from the discovered artifacts instead, and drop the
canonicalization: an artifact path is canonical already, and the
no-artifacts fallback names a directory cargo had no reason to create.

Two tests hardcoded the same layout and are now layout-agnostic:
`check-output` searches the target directory for its `--gen-c` output, and
`cargo_playback_opts` asserts only the file name of the executable whose
path cargo reports.
nightly-2026-08-01 is the first 1.99 nightly, and 91 compile errors came with it.

`Statement`/`Terminator` carry a `SourceInfo`, not a bare `Span` (78 of the 91
errors). A new `synthetic_source_info(span)` helper in `transform/body.rs`
documents the choice of the outermost source scope (scope 0, which `Body::new`
always allocates) for MIR Kani synthesizes; reads become `.source_info.span`.

`predicates_of` became `clauses_of`, returning `GenericClauses` (`parent` +
`clauses`) instead of `GenericPredicates` (`parent` + `predicates`). Same shape
and same `instantiate`, so this is a rename at the four call sites -- three in
`codegen_units.rs` from model-checking#4706/model-checking#4718, one in the LLBC backend.

`ty::FnDef`'s generic args are bound, so three `Instance::{try,expect}_resolve`
call sites need `.skip_binder()`.

`ValueAbi::ScalarPair` became a struct variant with a new `b_offset` field.

Two new enum variants: `AssertMessage::NullReferenceConstructed`, handled like
`NullPointerDereference` (same property class, description from rustc_public);
and `InstanceKind::LlvmIntrinsic`, which codegens like any other item and has no
Rust body for reachability to collect.

That new variant is why `expected/issue-3571` needed updating. Constructing a
null reference (`&*(0 as *const u32)`) used to report "null pointer dereference
occurred"; rustc now distinguishes the two and reports "null reference
produced". The UB is still caught and the harness still fails -- only the
wording is more precise -- so the expectation follows rustc's message rather
than pinning the old one.

Also adapts to `LocalModDefId` being renamed `LocalModId` and
`Region::new_early_param` moving to the `RegionExt` extension trait.

Four tests needed adjusting because `std::intrinsics::{size_of,align_of}` are
now comptime fns and cannot be called at runtime. The two `DynTrait` tests used
`size_of` incidentally, to compare a vtable field against a type's size, so they
use `std::mem::size_of`. The two `Intrinsics/ConstEval` tests exist to check the
intrinsics themselves, so each call is bound to a `const` -- which is what that
directory is about, and the only way now legal.

cargo 1.99 also ships with this nightly and changed the layout under `target/`,
which broke the whole cargo-based flow. That fix is not part of this commit: it
stands on its own, applies to the current toolchain, and is under review
separately.
@github-actions github-actions Bot added Z-EndToEndBenchCI Tag a PR to run benchmark CI Z-CompilerBenchCI Tag a PR to run benchmark CI labels Aug 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Z-CompilerBenchCI Tag a PR to run benchmark CI Z-EndToEndBenchCI Tag a PR to run benchmark CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant