From a302055caac70f51641cdad1dfa87f134090496a Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 25 Sep 2019 12:53:28 -0700 Subject: [PATCH] Mask results from flow-sensitive resolver with `in_any_value_of_ty` We relied previously on the caller (e.g. `Q::in_operand`) to ignore `Local`s that were indirectly mutable (and thus assumed to be qualified). However, it's much clearer (and more efficient) to do this in the resolver itself. This does not yet remove the masking done in `Q::in_operand` and others for safety's sake, although I believe that should now be possible. --- .../transform/check_consts/resolver.rs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/check_consts/resolver.rs b/src/librustc_mir/transform/check_consts/resolver.rs index c23a7e98efcb..2789693ecb6e 100644 --- a/src/librustc_mir/transform/check_consts/resolver.rs +++ b/src/librustc_mir/transform/check_consts/resolver.rs @@ -188,6 +188,9 @@ where indirectly_mutable_locals: &'a RefCell>, cursor: dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'a, 'mir, 'tcx, Q>>, qualifs_per_local: BitSet, + + /// The value of `Q::in_any_value_of_ty` for each local. + qualifs_in_any_value_of_ty: BitSet, } impl FlowSensitiveResolver<'a, 'mir, 'tcx, Q> @@ -208,10 +211,18 @@ where dataflow::Engine::new(item.body, dead_unwinds, analysis).iterate_to_fixpoint(); let cursor = dataflow::ResultsCursor::new(item.body, results); + let mut qualifs_in_any_value_of_ty = BitSet::new_empty(item.body.local_decls.len()); + for (local, decl) in item.body.local_decls.iter_enumerated() { + if Q::in_any_value_of_ty(item, decl.ty) { + qualifs_in_any_value_of_ty.insert(local); + } + } + FlowSensitiveResolver { cursor, indirectly_mutable_locals, qualifs_per_local: BitSet::new_empty(item.body.local_decls.len()), + qualifs_in_any_value_of_ty, location: Location { block: mir::START_BLOCK, statement_index: 0 }, } } @@ -242,16 +253,23 @@ where self.qualifs_per_local.overwrite(indirectly_mutable_locals.get()); self.qualifs_per_local.union(self.cursor.get()); + self.qualifs_per_local.intersect(&self.qualifs_in_any_value_of_ty); &self.qualifs_per_local } fn contains(&mut self, local: Local) -> bool { + // No need to update the cursor if we know that `Local` cannot possibly be qualified. + if !self.qualifs_in_any_value_of_ty.contains(local) { + return false; + } + + // Otherwise, return `true` if this local is qualified or was indirectly mutable at any + // point before this statement. self.cursor.seek_before(self.location); if self.cursor.get().contains(local) { return true; } - let mut indirectly_mutable_locals = self.indirectly_mutable_locals.borrow_mut(); indirectly_mutable_locals.seek(self.location); indirectly_mutable_locals.get().contains(local)