diff options
| author | Dylan MacKenzie <ecstaticmorse@gmail.com> | 2019-09-25 12:53:28 -0700 |
|---|---|---|
| committer | Dylan MacKenzie <ecstaticmorse@gmail.com> | 2019-09-28 07:06:52 -0700 |
| commit | a302055caac70f51641cdad1dfa87f134090496a (patch) | |
| tree | 0fb0a2f6c59f7b80041cd51670804f94e17838c2 | |
| parent | ff6faabda7840db86b90663f239bac909bae3a18 (diff) | |
| download | rust-a302055caac70f51641cdad1dfa87f134090496a.tar.gz rust-a302055caac70f51641cdad1dfa87f134090496a.zip | |
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.
| -rw-r--r-- | src/librustc_mir/transform/check_consts/resolver.rs | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/src/librustc_mir/transform/check_consts/resolver.rs b/src/librustc_mir/transform/check_consts/resolver.rs index c23a7e98efc..2789693ecb6 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<IndirectlyMutableResults<'mir, 'tcx>>, cursor: dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'a, 'mir, 'tcx, Q>>, qualifs_per_local: BitSet<Local>, + + /// The value of `Q::in_any_value_of_ty` for each local. + qualifs_in_any_value_of_ty: BitSet<Local>, } impl<Q> 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) |
