diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/region.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/builder/matches/mod.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/builder/scope.rs | 14 |
3 files changed, 25 insertions, 9 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index d43ac053758..f5770b7312d 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -198,12 +198,12 @@ fn resolve_arm<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, arm: &'tcx hir: visitor.cx.var_parent = visitor.cx.parent; resolve_pat(visitor, arm.pat); - // We introduce a new scope to contain bindings and temporaries from `if let` guards, to - // ensure they're dropped before the arm's pattern's bindings. This extends to the end of - // the arm body and is the scope of its locals as well. - visitor.enter_scope(Scope { local_id: arm.hir_id.local_id, data: ScopeData::MatchGuard }); - visitor.cx.var_parent = visitor.cx.parent; if let Some(guard) = arm.guard { + // We introduce a new scope to contain bindings and temporaries from `if let` guards, to + // ensure they're dropped before the arm's pattern's bindings. This extends to the end of + // the arm body and is the scope of its locals as well. + visitor.enter_scope(Scope { local_id: arm.hir_id.local_id, data: ScopeData::MatchGuard }); + visitor.cx.var_parent = visitor.cx.parent; resolve_cond(visitor, guard); } resolve_expr(visitor, arm.body, false); diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index c9a561fc54a..d5822a65b17 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -434,12 +434,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let arm_source_info = self.source_info(arm.span); let arm_scope = (arm.scope, arm_source_info); let match_scope = self.local_scope(); + let guard_scope = arm + .guard + .map(|_| region::Scope { data: region::ScopeData::MatchGuard, ..arm.scope }); self.in_scope(arm_scope, arm.lint_level, |this| { - let guard_scope = - region::Scope { data: region::ScopeData::MatchGuard, ..arm.scope }; - this.in_scope((guard_scope, arm_source_info), LintLevel::Inherited, |this| { + this.opt_in_scope(guard_scope.map(|scope| (scope, arm_source_info)), |this| { + // `if let` guard temps needing deduplicating will be in the guard scope. let old_dedup_scope = - mem::replace(&mut this.fixed_temps_scope, Some(guard_scope)); + mem::replace(&mut this.fixed_temps_scope, guard_scope); // `try_to_place` may fail if it is unable to resolve the given // `PlaceBuilder` inside a closure. In this case, we don't want to include diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 403e7167a69..96659873622 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -697,6 +697,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.and(rv) } + /// Convenience wrapper that executes `f` either within the current scope or a new scope. + /// Used for pattern matching, which introduces an additional scope for patterns with guards. + pub(crate) fn opt_in_scope<R>( + &mut self, + opt_region_scope: Option<(region::Scope, SourceInfo)>, + f: impl FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>, + ) -> BlockAnd<R> { + if let Some(region_scope) = opt_region_scope { + self.in_scope(region_scope, LintLevel::Inherited, f) + } else { + f(self) + } + } + /// Push a scope onto the stack. You can then build code in this /// scope and call `pop_scope` afterwards. Note that these two /// calls must be paired; using `in_scope` as a convenience |
