Make match discriminant reassignment check more accurate.

This commit is contained in:
Luqman Aden 2016-07-05 17:18:22 -04:00
parent ec58d0c997
commit a9c7a41576
2 changed files with 38 additions and 10 deletions

View File

@ -1495,20 +1495,27 @@ impl<'tcx> euv::Delegate<'tcx> for ReassignmentChecker {
fn decl_without_init(&mut self, _: ast::NodeId, _: Span) {}
fn mutate(&mut self, _: ast::NodeId, _: Span, cmt: mc::cmt, _: euv::MutateMode) {
let cmt_id = |cmt: &mc::cmt| match cmt.cat {
Categorization::Upvar(mc::Upvar { id: ty::UpvarId { var_id: vid, ..}, ..}) |
Categorization::Local(vid) => Some(vid),
Categorization::Interior(ref base_cmt, mc::InteriorField(_)) => Some(base_cmt.id),
_ => None
};
match cmt.cat {
Categorization::Upvar(mc::Upvar { id: ty::UpvarId { var_id: vid, .. }, .. }) |
Categorization::Local(vid) => self.reassigned |= self.node == vid,
Categorization::Interior(ref base_cmt, mc::InteriorField(field)) => {
match base_cmt.cat {
Categorization::Upvar(mc::Upvar { id: ty::UpvarId { var_id: vid, .. }, .. }) |
Categorization::Local(vid) => {
self.reassigned |= self.node == vid &&
(self.field.is_none() || Some(field) == self.field)
},
_ => {}
ref cat => {
let mut cat = cat;
while let &Categorization::Interior(ref base_cmt, mc::InteriorField(field)) = cat {
if let Some(vid) = cmt_id(base_cmt) {
if self.node == vid && (self.field.is_none() || self.field == Some(field)) {
self.reassigned = true;
return;
}
}
cat = &base_cmt.cat;
}
},
_ => {}
}
}
}
}

View File

@ -0,0 +1,21 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
let mut c = (1, (1, "".to_owned()));
match c {
c2 => { (c.1).0 = 2; assert_eq!((c2.1).0, 1); }
}
let mut c = (1, (1, (1, "".to_owned())));
match c.1 {
c2 => { ((c.1).1).0 = 3; assert_eq!((c2.1).0, 1); }
}
}