rust-lang/rust · error

funnel shift on {:?}

Error message

funnel shift on {:?}

What it means

An `unimplemented!("funnel shift on {:?}", elem_type)` ICE inside `simd_funnel_shift` in rustc_codegen_gcc (master-feature path). The function lowers SIMD funnel-shift to a scalar loop but only supports vector element widths 8/16/32/64 bits. A vector whose element type is none of those (e.g. 128-bit integers, or a non-integer element) reaches the `else` branch and panics.

Source

Thrown at compiler/rustc_codegen_gcc/src/intrinsic/simd.rs:1709

    let vector_type = a_type.unqualified().dyncast_vector().expect("vector type");
    let num_units = vector_type.get_num_units();
    let elem_type = vector_type.get_element_type();

    let (new_int_type, int_shift_val, int_mask) = if elem_type.is_compatible_with(bx.u8_type)
        || elem_type.is_compatible_with(bx.i8_type)
    {
        (bx.u16_type, 8, u8::MAX as u64)
    } else if elem_type.is_compatible_with(bx.u16_type) || elem_type.is_compatible_with(bx.i16_type)
    {
        (bx.u32_type, 16, u16::MAX as u64)
    } else if elem_type.is_compatible_with(bx.u32_type) || elem_type.is_compatible_with(bx.i32_type)
    {
        (bx.u64_type, 32, u32::MAX as u64)
    } else if elem_type.is_compatible_with(bx.u64_type) || elem_type.is_compatible_with(bx.i64_type)
    {
        (bx.u128_type, 64, u64::MAX)
    } else {
        unimplemented!("funnel shift on {:?}", elem_type);
    };

    let int_mask = bx.context.new_rvalue_from_long(new_int_type, int_mask as i64);
    let int_shift_val = bx.context.new_rvalue_from_int(new_int_type, int_shift_val);
    let mut elements = vec![];
    let unsigned_type = elem_type.to_unsigned(bx);
    for i in 0..num_units {
        let index = bx.context.new_rvalue_from_int(bx.int_type, i as i32);
        let a_val = bx.context.new_vector_access(None, a, index).to_rvalue();
        let a_val = bx.context.new_bitcast(None, a_val, unsigned_type);
        let a_val = bx.gcc_int_cast(a_val, new_int_type);
        let b_val = bx.context.new_vector_access(None, b, index).to_rvalue();
        let b_val = bx.context.new_bitcast(None, b_val, unsigned_type);
        let b_val = bx.gcc_int_cast(b_val, new_int_type);
        let shift_val = bx.context.new_vector_access(None, shift, index).to_rvalue();
        let shift_val = bx.gcc_int_cast(shift_val, new_int_type);
        let mut val = a_val << int_shift_val | b_val;
        if shift_left {

View on GitHub (pinned to 7088e4b63a)

Solutions

  1. Use LLVM backend for funnel shifts on non-standard lane widths.
  2. Ensure the SIMD vector's lane type is one of i8..i64 / u8..u64 — widen/narrow explicitly before the funnel shift.
  3. If 128-bit funnel shift is required, decompose it manually into 64-bit operations so it stays within supported element widths.

Example fix

// before (cg_gcc, funnel shift on u128 lanes -> ICE)
let r: Simd<u128, 4> = unsafe { simd_shl(a, b, shift) };

// after — LLVM backend, or restrict lanes to u64
let a64 = a.cast::<u64>(); // operate on supported lane width
Defensive patterns

Strategy: validation

Validate before calling

# Funnel shift only supports i8..i64 / u8..u64 lanes in cg_gcc
# In review, reject funnel/rotate shifts on u128/i128 lanes when targeting cg_gcc
rg -n 'simd_(shl|shr)|rotate_left|rotate_right' src/  # audit lane widths

Prevention

When it happens

Trigger: Invoking a SIMD funnel-shift intrinsic (`simd_shl`/`simd_shr` funnel forms) on a SIMD vector whose lane type is `i128`/`u128`, a float, or any type not matching `u8/i8/u16/i16/u32/i32/u64/i64`, while compiling with cg_gcc (master).

Common situations: Portable-SIMD code that performs funnel/rotate-shift on unusual lane widths (128-bit integer lanes), or where type inference produces an unexpected element type, combined with the GCC backend.

Related errors


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