Handle the visibility/lint scope distinction better
* Don't generate an extra lint scope for each `let` statement. * Place match guards inside the visiblility scope of the bindings for their arm.
This commit is contained in:
parent
e784595c28
commit
af6a9a2c62
|
@ -1313,10 +1313,8 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
|
||||
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm {
|
||||
let LoweredNodeId { node_id: _, hir_id } = self.next_id();
|
||||
|
||||
hir::Arm {
|
||||
hir_id,
|
||||
hir_id: self.next_id(),
|
||||
attrs: self.lower_attrs(&arm.attrs),
|
||||
pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(),
|
||||
guard: match arm.guard {
|
||||
|
@ -5027,10 +5025,8 @@ impl<'a> LoweringContext<'a> {
|
|||
// Helper methods for building HIR.
|
||||
|
||||
fn arm(&mut self, pats: hir::HirVec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm {
|
||||
let LoweredNodeId { node_id: _, hir_id } = self.next_id();
|
||||
|
||||
hir::Arm {
|
||||
hir_id,
|
||||
hir_id: self.next_id(),
|
||||
attrs: hir_vec![],
|
||||
pats,
|
||||
guard: None,
|
||||
|
|
|
@ -113,31 +113,39 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
let remainder_span = remainder_scope.span(this.hir.tcx(),
|
||||
&this.hir.region_scope_tree);
|
||||
|
||||
let scope;
|
||||
let visibility_scope =
|
||||
Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None));
|
||||
|
||||
// Evaluate the initializer, if present.
|
||||
if let Some(init) = initializer {
|
||||
let initializer_span = init.span();
|
||||
|
||||
scope = this.declare_bindings(
|
||||
None,
|
||||
remainder_span,
|
||||
lint_level,
|
||||
&pattern,
|
||||
ArmHasGuard(false),
|
||||
Some((None, initializer_span)),
|
||||
);
|
||||
unpack!(block = this.in_opt_scope(
|
||||
opt_destruction_scope.map(|de|(de, source_info)), |this| {
|
||||
let scope = (init_scope, source_info);
|
||||
this.in_scope(scope, lint_level, |this| {
|
||||
this.declare_bindings(
|
||||
visibility_scope,
|
||||
remainder_span,
|
||||
&pattern,
|
||||
ArmHasGuard(false),
|
||||
Some((None, initializer_span)),
|
||||
);
|
||||
this.expr_into_pattern(block, pattern, init)
|
||||
})
|
||||
}));
|
||||
} else {
|
||||
scope = this.declare_bindings(
|
||||
None, remainder_span, lint_level, &pattern,
|
||||
ArmHasGuard(false), None);
|
||||
let scope = (init_scope, source_info);
|
||||
unpack!(this.in_scope(scope, lint_level, |this| {
|
||||
this.declare_bindings(
|
||||
visibility_scope,
|
||||
remainder_span,
|
||||
&pattern,
|
||||
ArmHasGuard(false),
|
||||
None,
|
||||
);
|
||||
block.unit()
|
||||
}));
|
||||
|
||||
debug!("ast_block_stmts: pattern={:?}", pattern);
|
||||
this.visit_bindings(
|
||||
|
@ -149,8 +157,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
// Enter the source scope, after evaluating the initializer.
|
||||
if let Some(source_scope) = scope {
|
||||
// Enter the visibility scope, after evaluating the initializer.
|
||||
if let Some(source_scope) = visibility_scope {
|
||||
this.source_scope = source_scope;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -259,12 +259,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
let scope = self.declare_bindings(
|
||||
None,
|
||||
body.span,
|
||||
LintLevel::Inherited,
|
||||
&arm.patterns[0],
|
||||
ArmHasGuard(arm.guard.is_some()),
|
||||
Some((Some(&scrutinee_place), scrutinee_span)),
|
||||
);
|
||||
|
||||
if let Some(source_scope) = scope {
|
||||
this.source_scope = source_scope;
|
||||
}
|
||||
|
||||
for candidate in candidates {
|
||||
self.bind_and_guard_matched_candidate(
|
||||
candidate,
|
||||
|
@ -275,9 +278,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
if let Some(source_scope) = scope {
|
||||
self.source_scope = source_scope;
|
||||
}
|
||||
|
||||
unpack!(arm_block = self.into(destination, arm_block, body));
|
||||
|
||||
|
@ -489,33 +489,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
&mut self,
|
||||
mut visibility_scope: Option<SourceScope>,
|
||||
scope_span: Span,
|
||||
lint_level: LintLevel,
|
||||
pattern: &Pattern<'tcx>,
|
||||
has_guard: ArmHasGuard,
|
||||
opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
|
||||
) -> Option<SourceScope> {
|
||||
assert!(
|
||||
!(visibility_scope.is_some() && lint_level.is_explicit()),
|
||||
"can't have both a visibility and a lint scope at the same time"
|
||||
);
|
||||
let mut scope = self.source_scope;
|
||||
debug!("declare_bindings: pattern={:?}", pattern);
|
||||
self.visit_bindings(
|
||||
&pattern,
|
||||
UserTypeProjections::none(),
|
||||
&mut |this, mutability, name, mode, var, span, ty, user_ty| {
|
||||
if visibility_scope.is_none() {
|
||||
// If we have lints, create a new source scope
|
||||
// that marks the lints for the locals. See the comment
|
||||
// on the `source_info` field for why this is needed.
|
||||
if lint_level.is_explicit() {
|
||||
scope = this.new_source_scope(scope_span, lint_level, None);
|
||||
visibility_scope =
|
||||
Some(this.new_source_scope(scope_span, LintLevel::Inherited, None));
|
||||
}
|
||||
visibility_scope = Some(this.new_source_scope(scope_span,
|
||||
LintLevel::Inherited,
|
||||
None));
|
||||
}
|
||||
let source_info = SourceInfo { span, scope };
|
||||
let source_info = SourceInfo { span, this.source_scope };
|
||||
let visibility_scope = visibility_scope.unwrap();
|
||||
this.declare_binding(
|
||||
source_info,
|
||||
|
|
|
@ -945,10 +945,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
self.var_indices.insert(var, LocalsForNode::One(local));
|
||||
}
|
||||
_ => {
|
||||
scope = self.declare_bindings(scope, ast_body.span,
|
||||
LintLevel::Inherited, &pattern,
|
||||
scope = self.declare_bindings(
|
||||
scope,
|
||||
ast_body.span,
|
||||
&pattern,
|
||||
matches::ArmHasGuard(false),
|
||||
Some((Some(&place), span)));
|
||||
Some((Some(&place), span)),
|
||||
);
|
||||
unpack!(block = self.place_into_pattern(block, pattern, &place, false));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,15 +31,6 @@ pub enum LintLevel {
|
|||
Explicit(hir::HirId)
|
||||
}
|
||||
|
||||
impl LintLevel {
|
||||
pub fn is_explicit(self) -> bool {
|
||||
match self {
|
||||
LintLevel::Inherited => false,
|
||||
LintLevel::Explicit(_) => true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Block<'tcx> {
|
||||
pub targeted_by_break: bool,
|
||||
|
@ -311,6 +302,8 @@ pub struct Arm<'tcx> {
|
|||
pub guard: Option<Guard<'tcx>>,
|
||||
pub body: ExprRef<'tcx>,
|
||||
pub lint_level: LintLevel,
|
||||
pub scope: region::Scope,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
|
@ -22,13 +22,11 @@ impl Drop for S {
|
|||
// END RUST SOURCE
|
||||
// START rustc.main.ElaborateDrops.before.mir
|
||||
// let mut _0: ();
|
||||
// let _1: std::boxed::Box<S>;
|
||||
// let mut _2: std::boxed::Box<S>;
|
||||
// let mut _3: ();
|
||||
// let mut _4: std::boxed::Box<S>;
|
||||
// scope 1 {
|
||||
// let _1: std::boxed::Box<S>;
|
||||
// }
|
||||
// scope 2 {
|
||||
// }
|
||||
// bb0: {
|
||||
// StorageLive(_1);
|
||||
|
|
|
@ -29,27 +29,24 @@ impl S {
|
|||
// END RUST SOURCE
|
||||
// START rustc.main.ElaborateDrops.after.mir
|
||||
// let mut _0: ();
|
||||
// let _1: ();
|
||||
// let mut _2: S;
|
||||
// let mut _3: S;
|
||||
// let mut _4: S;
|
||||
// let mut _5: bool;
|
||||
// scope 1 {
|
||||
// let _1: ();
|
||||
// }
|
||||
// scope 2 {
|
||||
// }
|
||||
// ...
|
||||
// bb0: {
|
||||
// END rustc.main.ElaborateDrops.after.mir
|
||||
// START rustc.test.ElaborateDrops.after.mir
|
||||
// let mut _0: ();
|
||||
// let _1: S;
|
||||
// let mut _3: ();
|
||||
// let mut _4: S;
|
||||
// let mut _5: S;
|
||||
// let mut _6: bool;
|
||||
// ...
|
||||
// let _1: S;
|
||||
// ...
|
||||
// let mut _2: S;
|
||||
// ...
|
||||
// bb0: {
|
||||
|
|
|
@ -18,14 +18,12 @@ fn main() {
|
|||
// fn main() -> (){
|
||||
// let mut _0: ();
|
||||
// let mut _1: ();
|
||||
// let _2: i32;
|
||||
// let mut _3: bool;
|
||||
// let mut _4: !;
|
||||
// let mut _5: ();
|
||||
// let mut _6: &i32;
|
||||
// scope 1 {
|
||||
// let _2: i32;
|
||||
// }
|
||||
// scope 2 {
|
||||
// }
|
||||
// bb0: {
|
||||
// goto -> bb1;
|
||||
|
|
|
@ -18,15 +18,13 @@ impl Drop for Droppy {
|
|||
// START rustc.main.EraseRegions.before.mir
|
||||
// fn main() -> () {
|
||||
// let mut _0: ();
|
||||
// let mut _1: Packed;
|
||||
// let mut _2: Aligned;
|
||||
// let mut _3: Droppy;
|
||||
// let mut _4: Aligned;
|
||||
// let mut _5: Droppy;
|
||||
// let mut _6: Aligned;
|
||||
// scope 1 {
|
||||
// let mut _1: Packed;
|
||||
// }
|
||||
// scope 2 {
|
||||
// }
|
||||
//
|
||||
// bb0: {
|
||||
|
|
Loading…
Reference in New Issue