The gap
Routing (src/method.rs:22) is a public enum with no #[non_exhaustive] and no stated rationale for its absence.
Its siblings all carry it and document why: ControlMethod, ControlErrorCode, and now Category — which got it in PR#33 (b6ec6593) precisely because adding Category::Collateral in a minor would otherwise have been a compile break for any downstream exhaustive match.
Routing has the same exposure and nothing has triggered it yet.
Why now rather than later
Adding #[non_exhaustive] is itself breaking. So the cost only rises: today it is free because no consumer matches exhaustively on Routing; after the first one does, it costs a major.
That is the same reasoning that made Category cheap to fix in its window — and the window closed for Category the moment a variant was added, which is exactly when it was noticed.
Worth deciding as a rule, not a one-off
The #[non_exhaustive] boundary in this crate is currently drawn type by type, and Routing is the one that fell off. For a published contract crate, the sensible default is that every public enum a consumer might match on carries it, with an explicit rationale where it deliberately does not.
Otherwise the question gets re-answered per enum, per PR, by whoever happens to add a variant — and it will be missed again, because the miss is invisible until a variant arrives.
Scope
- Add
#[non_exhaustive] to Routing with the siblings' rationale.
- Audit the crate's other public enums for the same gap while you are there.
- State the default in
SPEC.md so the next enum is not a judgement call.
Found while fixing PR#33's gate findings.
The gap
Routing(src/method.rs:22) is a public enum with no#[non_exhaustive]and no stated rationale for its absence.Its siblings all carry it and document why:
ControlMethod,ControlErrorCode, and nowCategory— which got it in PR#33 (b6ec6593) precisely because addingCategory::Collateralin a minor would otherwise have been a compile break for any downstream exhaustive match.Routinghas the same exposure and nothing has triggered it yet.Why now rather than later
Adding
#[non_exhaustive]is itself breaking. So the cost only rises: today it is free because no consumer matches exhaustively onRouting; after the first one does, it costs a major.That is the same reasoning that made
Categorycheap to fix in its window — and the window closed forCategorythe moment a variant was added, which is exactly when it was noticed.Worth deciding as a rule, not a one-off
The
#[non_exhaustive]boundary in this crate is currently drawn type by type, andRoutingis the one that fell off. For a published contract crate, the sensible default is that every public enum a consumer might match on carries it, with an explicit rationale where it deliberately does not.Otherwise the question gets re-answered per enum, per PR, by whoever happens to add a variant — and it will be missed again, because the miss is invisible until a variant arrives.
Scope
#[non_exhaustive]toRoutingwith the siblings' rationale.SPEC.mdso the next enum is not a judgement call.Found while fixing PR#33's gate findings.