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:
Matthew Jasper 2019-04-02 22:29:28 +01:00
parent e784595c28
commit af6a9a2c62
9 changed files with 45 additions and 67 deletions

View File

@ -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,

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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,
matches::ArmHasGuard(false),
Some((Some(&place), span)));
scope = self.declare_bindings(
scope,
ast_body.span,
&pattern,
matches::ArmHasGuard(false),
Some((Some(&place), span)),
);
unpack!(block = self.place_into_pattern(block, pattern, &place, false));
}
}

View File

@ -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)]

View File

@ -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);

View File

@ -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: {

View File

@ -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;

View File

@ -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: {