rust-lang/rust · critical

Polonius output is unavailable despite `-Z polonius`

Error message

Polonius output is unavailable despite `-Z polonius`

What it means

This fires in `RegionInferenceContext::probe_*` when legacy Polonius (`-Zpolonius` without `=next`) is enabled. The code calls `check_polonius_subset_errors` and passes `polonius_output.as_ref().expect(...)`. Legacy polonius is expected to produce output (the subset errors / `child_outlives` facts). If the output is `None` despite the flag being set, the compiler panics — the analysis was requested but never ran or returned nothing.

Source

Thrown at compiler/rustc_borrowck/src/region_infer/mod.rs:516

        // eagerly erroing.
        let mut propagated_outlives_requirements =
            infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new);

        self.check_type_tests(infcx, propagated_outlives_requirements.as_mut(), &mut errors_buffer);

        debug!(?errors_buffer);
        debug!(?propagated_outlives_requirements);

        // In Polonius mode, the errors about missing universal region relations are in the output
        // and need to be emitted or propagated. Otherwise, we need to check whether the
        // constraints were too strong, and if so, emit or propagate those errors.
        if infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() {
            self.check_polonius_subset_errors(
                propagated_outlives_requirements.as_mut(),
                &mut errors_buffer,
                polonius_output
                    .as_ref()
                    .expect("Polonius output is unavailable despite `-Z polonius`"),
            );
        } else {
            self.check_universal_regions(
                propagated_outlives_requirements.as_mut(),
                &mut errors_buffer,
            );
        }

        debug!(?errors_buffer);

        let propagated_outlives_requirements = propagated_outlives_requirements.unwrap_or_default();

        if propagated_outlives_requirements.is_empty() {
            (None, errors_buffer)
        } else {
            let num_external_vids = self.universal_regions().num_global_and_external_regions();
            (
                Some(ClosureRegionRequirements {

View on GitHub (pinned to 7088e4b63a)

Solutions

  1. Switch to `-Zpolonius=next` (the in-tree successor) instead of legacy `-Zpolonius`; the legacy path is deprecated.
  2. Remove the `-Zpolonius` flag entirely to use the default NLL borrow checker.
  3. Update to the latest nightly where legacy polonius output plumbing may be fixed.
  4. If you need legacy polonius, ensure the polonius solver actually ran — check for stderr output or missing polonius binary.

Example fix

# before (legacy polonius, output unavailable)
RUSTFLAGS='-Zpolonius' cargo build

# after (next-gen in-tree polonius)
RUSTFLAGS='-Zpolonius=next' cargo build
Defensive patterns

Strategy: validation

Validate before calling

// Validate that legacy polonius is not used without its solver
// In CI:
// if echo "$RUSTFLAGS" | grep -qE '(^| )-Zpolonius( |$)'; then
//   echo "Legacy polonius requires the external solver; consider -Zpolonius=next"
//   # or: unset RUSTFLAGS to use default NLL
// fi

Prevention

When it happens

Trigger: Compiling with the legacy `-Zpolonius` flag (the datafrog-based external polonius binary approach) where the polonius computation was requested but did not produce output — e.g., the polonius binary wasn't found, the input facts weren't dumped, or the output wasn't parsed back into `polonius_output`.

Common situations: Using the legacy `-Zpolonius` mode which requires an external `polonius` binary or the built-in datafrog solver. This can fail if the polonius solver silently failed, if the crate uses a feature that triggers polonius but the solver wasn't built into the toolchain, or after a rustc refactor that changed how polonius output is plumbed.

Related errors


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/06dd6bcd5563de57. Report an issue: GitHub.