stringly-typed-field
Level: warn · Article: Primitives
The comment
// status: 'pending' | 'approved' | 'rejected'is aStatusenum 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 }
}