rust-lang/rust · critical

unsupported float: {self:?}

Error message

unsupported float: {self:?}

What it means

This panic fires in `Reg::align` for a `RegKind::Float` whose bit width is not 16/32/64/128 — the only float sizes the data layout has alignment entries for (`f16_align`, `f32_align`, `f64_align`, `f128_align`). It is an internal invariant: the float register constructors (`Reg::f32`, `f64`, `f128`) always produce supported widths, so an unsupported size means a codegen or target-spec bug rather than user-level input.

Source

Thrown at compiler/rustc_abi/src/callconv/reg.rs:70

impl Reg {
    pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
        let dl = cx.data_layout();
        match self.kind {
            RegKind::Integer => match self.size.bits() {
                1 => dl.i1_align,
                2..=8 => dl.i8_align,
                9..=16 => dl.i16_align,
                17..=32 => dl.i32_align,
                33..=64 => dl.i64_align,
                65..=128 => dl.i128_align,
                _ => panic!("unsupported integer: {self:?}"),
            },
            RegKind::Float => match self.size.bits() {
                16 => dl.f16_align,
                32 => dl.f32_align,
                64 => dl.f64_align,
                128 => dl.f128_align,
                _ => panic!("unsupported float: {self:?}"),
            },
            RegKind::Vector { .. } => dl.rust_vector_align(self.size),
        }
    }
}

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Confirm the target's `data_layout` declares float alignments for 16/32/64/128 bits and that the target actually supports the float width you intend to pass.
  2. Trace the caller building the float `Reg` (search for `RegKind::Float` and `Reg::f*`) and ensure it uses the canonical constructors rather than a hand-built size.
  3. If a genuinely new float width is required, first add the matching `fN_align` field to `TargetDataLayout` and a match arm here.
  4. Report an ICE with the backtrace if it reproduces on stock `rustc` with a built-in target.

Example fix

// before
let f = Reg { kind: RegKind::Float, size: Size::from_bits(80) };
let a = f.align(&dl); // panic: unsupported float

// after — use a supported width, or model 80-bit as a memory/Primitive::Float(F64) slot
let f = Reg::f64();
let a = f.align(&dl);
Defensive patterns

Strategy: validation

Validate before calling

// Reg::align panics on float sizes outside {16, 32, 64, 128} bits.
use rustc_abi::{Reg, RegKind};
fn supported_float_align(reg: &Reg) -> bool {
    if !matches!(reg.kind, RegKind::Float) { return true; }
    matches!(reg.size.bits(), 16 | 32 | 64 | 128)
}
// caller: if supported_float_align(&reg) { reg.align(cx) } else { /* skip / report */ }

Type guard

fn is_supported_float_reg(reg: &Reg) -> bool {
    matches!(reg.kind, RegKind::Float) && supported_float_align(reg)
}

Try / catch

let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| reg.align(cx)));
match result {
    Ok(align) => { /* use align */ }
    Err(_) => { eprintln!("unsupported float reg: {:?}", &reg); /* recover */ }
}

Prevention

When it happens

Trigger: Constructing `Reg { kind: RegKind::Float, size }` with a size whose `.bits()` is not in {16,32,64,128} and then calling `.align(cx)` against any `HasDataLayout` (e.g. while computing a calling-convention slot for a float argument).

Common situations: A target data layout missing or misordering float alignment fields, a custom backend introducing a non-standard float width (e.g. 80-bit x87 extended, 64-byte vectors reported as floats), or an internal refactor that changed how float primitives map to `Reg` sizes.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/9e92111d5dae63a1.json. Report an issue: GitHub.