- let Builder { ref mut hir, ref mut cfg, ref mut scopes, .. } = *self;
-
- // Given an array of scopes, we generate these from the outermost scope to the innermost
- // one. Thus for array [S0, S1, S2] with corresponding cleanup blocks [B0, B1, B2], we will
- // generate B0 <- B1 <- B2 in left-to-right order. Control flow of the generated blocks
- // always ends up at a block with the Resume terminator.
- if scopes.iter().any(|scope| !scope.drops.is_empty() || scope.free.is_some()) {
- Some(build_diverge_scope(hir.tcx(), self.fn_span, cfg, &unit_temp, scopes))
+ let Builder { ref mut hir, ref mut cfg, ref mut scopes,
+ ref mut cached_resume_block, .. } = *self;
+
+ // Build up the drops in **reverse** order. The end result will
+ // look like:
+ //
+ // scopes[n] -> scopes[n-1] -> ... -> scopes[0]
+ //
+ // However, we build this in **reverse order**. That is, we
+ // process scopes[0], then scopes[1], etc, pointing each one at
+ // the result generates from the one before. Along the way, we
+ // store caches. If everything is cached, we'll just walk right
+ // to left reading the cached results but never created anything.
+
+ // To start, create the resume terminator.
+ let mut target = if let Some(target) = *cached_resume_block {
+ target