rust-lang/rust · error

not implemented

Error message

not implemented

What it means

Builder::pointercast (builder.rs:1339) only implements three of the four (src_is_pointer, dst_is_pointer) combinations. The (true, false) arm — casting a pointer-typed value to a non-pointer destination type via pointercast — is unimplemented!(). GCC's gccjit API does not expose a direct pointer-to-integer reinterpret through this path, so the backend panics instead of emitting wrong code.

Solutions

  1. Fall back to the LLVM backend for the crate that triggers it.
  2. Rewrite the reinterpretation to use an explicit ptr-to-int cast that lowers through a different builder method (e.g. inttoptr/ptrtoint intrinsics rather than pointercast).
  3. Avoid transmute between pointer and integer types; use the standard addr_of/ from/into patterns that lower to supported ops.
  4. Patch pointercast to lower (true, false) via context.new_cast through an integral type of the pointer's size.

Example fix

// before: transmute that lowers to a pointer->non-pointer pointercast
let raw: usize = std::mem::transmute(&value);

// after: use the supported cast path
let raw: usize = (&value) as *const _ as usize;
Defensive patterns

Strategy: validation

Validate before calling

# Before enabling the gcc backend, search for pointer->int reinterpretations.
grep -rn 'transmute.*&\|as \*const .* as usize\|as \*mut .* as usize' src/ || true
# Rewrite any matches to use supported cast paths before building with gcc.

Type guard

// Prefer explicit ptr-to-int casts that do not lower to pointercast's (true,false) arm.
fn ptr_to_int<T>(p: *const T) -> usize { p as usize }  // use `as`, not transmute

Try / catch

if ! RUSTFLAGS="-Zcodegen-backend=gcc" cargo build 2>err.log; then
  grep -q 'not implemented' err.log && { echo 'pointercast gap; using LLVM'; cargo build; }
fi

Prevention

When it happens

Trigger: Any Rust IR operation that lowers to BuilderMethods::pointercast where the source is a pointer and the destination is an integer/raw type — e.g. transmute/cast of a reference into a usize, ptr.addr_of()-style pointer-to-int reinterpretation generated during codegen.

Common situations: Compiling code that reinterprets pointers as integers (common in serialization, hashing of pointers, FFI marshalling, custom allocators) with the GCC backend; situations where MIR lowering calls pointercast for a ptr->int shape.

Related errors


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

Appendix: source

Thrown at compiler/rustc_codegen_gcc/src/builder.rs:1339

    fn pointercast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        let val_type = value.get_type();
        match (type_is_pointer(val_type), type_is_pointer(dest_ty)) {
            (false, true) => {
                // NOTE: Projecting a field of a pointer type will attempt a cast from a signed char to
                // a pointer, which is not supported by gccjit.
                self.cx.context.new_cast(
                    self.location,
                    self.inttoptr(value, val_type.make_pointer()),
                    dest_ty,
                )
            }
            (false, false) => {
                // When they are not pointers, we want a transmute (or reinterpret_cast).
                self.bitcast(value, dest_ty)
            }
            (true, true) => self.cx.context.new_cast(self.location, value, dest_ty),
            (true, false) => unimplemented!(),
        }
    }

    /* Comparisons */
    fn icmp(&mut self, op: IntPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
        self.gcc_icmp(op, lhs, rhs)
    }

    fn fcmp(&mut self, op: RealPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
        // LLVM has a concept of "unordered compares", where eg ULT returns true if either the two
        // arguments are unordered (i.e. either is NaN), or the lhs is less than the rhs. GCC does
        // not natively have this concept, so in some cases we must manually handle NaNs
        let must_handle_nan = match op {
            RealPredicate::RealPredicateFalse => unreachable!(),
            RealPredicate::RealOEQ => false,
            RealPredicate::RealOGT => false,
            RealPredicate::RealOGE => false,
            RealPredicate::RealOLT => false,

View on GitHub (pinned to 7088e4b63a)