From a9c7a415763563e394e469ac88e5f6665b7b1a86 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Tue, 5 Jul 2016 17:18:22 -0400 Subject: [PATCH] Make match discriminant reassignment check more accurate. --- src/librustc_trans/_match.rs | 27 +++++++++++++++++---------- src/test/run-pass/issue-27021.rs | 21 +++++++++++++++++++++ 2 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 src/test/run-pass/issue-27021.rs diff --git a/src/librustc_trans/_match.rs b/src/librustc_trans/_match.rs index 3ef6e29a6f8..10af326be26 100644 --- a/src/librustc_trans/_match.rs +++ b/src/librustc_trans/_match.rs @@ -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; } - }, - _ => {} + } } } } diff --git a/src/test/run-pass/issue-27021.rs b/src/test/run-pass/issue-27021.rs new file mode 100644 index 00000000000..eb7d529f0ad --- /dev/null +++ b/src/test/run-pass/issue-27021.rs @@ -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 or the MIT license +// , 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); } + } +}