Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

stringly-typed-field

Level: warn · Article: Primitives

The comment // status: 'pending' | 'approved' | 'rejected' is a Status enum that hasn’t been written yet. Write it. Delete the comment.

What it checks

A named field called status, state, kind, role, mode, level, phase, stage, category or type whose type is String, &str or Option<String>. A value with a handful of valid spellings is an enum, and the compiler checks every match on an enum.

Wire shapes (*Request, *Row, …) are skipped, like primitive-field.

Don’t

#![allow(unused)]
fn main() {
struct Order {
    status: String, // "pending" | "approved" | "rejected"
}

impl Order {
    fn ship_if_approved(self, warehouse: &Warehouse) {
        if self.status == "aproved" {
            warehouse.ship(self); // never ships
        }
    }
}
}

Do

#![allow(unused)]
fn main() {
enum OrderStatus {
    Approved,
    Pending,
    Rejected,
}

struct Order {
    status: OrderStatus,
}

impl Order {
    fn ship_if_approved(self, warehouse: &Warehouse) {
        match self.status {
            OrderStatus::Approved => warehouse.ship(self),
            OrderStatus::Pending | OrderStatus::Rejected => {}
        }
    }
}
}

Parse the string once, where it enters. A typo is now a compile error, and adding a variant makes every match that forgot it fail to build.

Options

[naming]
enum-fields = ["category", "kind", "level", "mode", "phase", "role", "stage", "state", "status"]

Silence it

#![allow(unused)]
fn main() {
// rabot: allow(stringly-typed-field) free-form user label, not a closed set
struct Tag { kind: String }
}