Common Standard Macros

todo! and unimplemented!

The todo! and unimplemented! macros are diverging placeholder macros (with return type !, the never type) that allow incomplete functions, trait methods, or match arms to type-check and compile while panicking if reached at runtime.

Semantic Distinction Between todo! and unimplemented!

Although both macros have identical runtime behavior (both panic and unwind the stack) and both coerce to any return type T, they communicate different intent to human readers, IDEs, and static analysis tools:

Macro Default Panic Message Intended Meaning
todo!() / todo!("msg") "not yet implemented" Work in progress: This code path is planned and needs to be written before the feature is finished
unimplemented!() / unimplemented!("msg") "not implemented" Intentionally unsupported: Required by a trait signature, platform interface, or legacy API, but not supported by this implementation
unreachable!() / unreachable!("msg") "internal error: entered unreachable code" Logically impossible: A code branch the programmer has proven can never be reached at runtime

Prototyping Function Signatures and match Arms with todo!

Because todo!() has the never type !, a function returning any complex type (Result<Vec<User>, DbError>, impl Iterator<Item = u64>) compiles cleanly with todo!() as its body while you test the rest of the program:

#[derive(Debug)]
enum Command {
    Ping,
    Status,
    MigrateDatabase { target_version: u32 },
}

fn execute(cmd: Command) -> String {
    match cmd {
        Command::Ping => String::from("PONG"),
        Command::Status => String::from("OK"),
        Command::MigrateDatabase { target_version } => {
            // Compiles cleanly because `todo!` has type `!`, which coerces to `String`:
            todo!("database migration to v{target_version} is not wired up yet")
        }
    }
}

fn main() {
    println!("Ping:   {}", execute(Command::Ping));
    println!("Status: {}", execute(Command::Status));
}
Ping:   PONG
Status: OK

Satisfying Unsupported Trait Methods with unimplemented!

When implementing a large trait where one operation is unsupported by design (such as a read-only storage backend implementing a combined Storage trait), use unimplemented! with an explanation:

trait BlockDevice {
    fn read_block(&self, id: u64) -> [u8; 4];
    fn write_block(&mut self, id: u64, data: [u8; 4]);
}

struct ReadOnlyRom;

impl BlockDevice for ReadOnlyRom {
    fn read_block(&self, _id: u64) -> [u8; 4] {
        [0xDE, 0xAD, 0xBE, 0xEF]
    }

    fn write_block(&mut self, _id: u64, _data: [u8; 4]) {
        unimplemented!("ReadOnlyRom does not support write_block")
    }
}

fn main() {
    let rom = ReadOnlyRom;
    println!("ROM block 0: {:02X?}", rom.read_block(0));
}
ROM block 0: [DE, AD, BE, EF]

(Tip: Enable #![warn(clippy::todo)] in CI so unfinished todo!() placeholders are flagged before merging to production.)