Today, the finish/rollback logic of variant builders is ad hoc and spread over many call sites. It's quite likely that not all state is reliably rolled back in all cases, because some changes happen eagerly (to be rolled back on failure) while others are lazy (applied only at finish). Even if the current behavior is correct, it is brittle and future changes could easily break it. The logic is also convoluted and difficult to follow.
To combat these issues, builders should use ParentState more consistently (today, used only for nested builders), and the ParentState should encapsulate the finish/rollback logic for each of its enum variants. It also becomes fully eager -- apply all changes up front, and roll them all back on failure.