Skip to content

Commit 99f5c85

Browse files
committed
rustc: ban registering obligations during InferCtxt snapshots.
1 parent c67cf5f commit 99f5c85

File tree

4 files changed

+31
-31
lines changed

4 files changed

+31
-31
lines changed

src/librustc/infer/mod.rs

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,8 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
199199
// `tained_by_errors`) to avoid reporting certain kinds of errors.
200200
err_count_on_creation: usize,
201201

202-
// This flag is used for debugging, and is set to true if there are
203-
// any obligations set during the current snapshot. In that case, the
204-
// snapshot can't be rolled back.
205-
pub obligations_in_snapshot: Cell<bool>,
202+
// This flag is true while there is an active snapshot.
203+
in_snapshot: Cell<bool>,
206204
}
207205

208206
/// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
@@ -507,7 +505,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
507505
projection_mode: Reveal::UserFacing,
508506
tainted_by_errors_flag: Cell::new(false),
509507
err_count_on_creation: self.sess.err_count(),
510-
obligations_in_snapshot: Cell::new(false),
508+
in_snapshot: Cell::new(false),
511509
}
512510
}
513511
}
@@ -545,7 +543,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
545543
projection_mode: projection_mode,
546544
tainted_by_errors_flag: Cell::new(false),
547545
err_count_on_creation: tcx.sess.err_count(),
548-
obligations_in_snapshot: Cell::new(false),
546+
in_snapshot: Cell::new(false),
549547
}))
550548
}
551549
}
@@ -573,7 +571,7 @@ pub struct CombinedSnapshot {
573571
int_snapshot: unify::Snapshot<ty::IntVid>,
574572
float_snapshot: unify::Snapshot<ty::FloatVid>,
575573
region_vars_snapshot: RegionSnapshot,
576-
obligations_in_snapshot: bool,
574+
was_in_snapshot: bool,
577575
}
578576

579577
/// Helper trait for shortening the lifetimes inside a
@@ -734,6 +732,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
734732
self.projection_mode
735733
}
736734

735+
pub fn is_in_snapshot(&self) -> bool {
736+
self.in_snapshot.get()
737+
}
738+
737739
pub fn freshen<T:TypeFoldable<'tcx>>(&self, t: T) -> T {
738740
t.fold_with(&mut self.freshener())
739741
}
@@ -861,46 +863,45 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
861863
result.map(move |t| InferOk { value: t, obligations: fields.obligations })
862864
}
863865

864-
// Clear the "obligations in snapshot" flag, invoke the closure,
866+
// Clear the "currently in a snapshot" flag, invoke the closure,
865867
// then restore the flag to its original value. This flag is a
866868
// debugging measure designed to detect cases where we start a
867-
// snapshot, create type variables, register obligations involving
868-
// those type variables in the fulfillment cx, and then have to
869-
// unroll the snapshot, leaving "dangling type variables" behind.
870-
// In such cases, the flag will be set by the fulfillment cx, and
871-
// an assertion will fail when rolling the snapshot back. Very
872-
// useful, much better than grovelling through megabytes of
873-
// RUST_LOG output.
869+
// snapshot, create type variables, and register obligations
870+
// which may involve those type variables in the fulfillment cx,
871+
// potentially leaving "dangling type variables" behind.
872+
// In such cases, an assertion will fail when attempting to
873+
// register obligations, within a snapshot. Very useful, much
874+
// better than grovelling through megabytes of RUST_LOG output.
874875
//
875-
// HOWEVER, in some cases the flag is wrong. In particular, we
876+
// HOWEVER, in some cases the flag is unhelpful. In particular, we
876877
// sometimes create a "mini-fulfilment-cx" in which we enroll
877878
// obligations. As long as this fulfillment cx is fully drained
878879
// before we return, this is not a problem, as there won't be any
879880
// escaping obligations in the main cx. In those cases, you can
880881
// use this function.
881-
pub fn save_and_restore_obligations_in_snapshot_flag<F, R>(&self, func: F) -> R
882+
pub fn save_and_restore_in_snapshot_flag<F, R>(&self, func: F) -> R
882883
where F: FnOnce(&Self) -> R
883884
{
884-
let flag = self.obligations_in_snapshot.get();
885-
self.obligations_in_snapshot.set(false);
885+
let flag = self.in_snapshot.get();
886+
self.in_snapshot.set(false);
886887
let result = func(self);
887-
self.obligations_in_snapshot.set(flag);
888+
self.in_snapshot.set(flag);
888889
result
889890
}
890891

891892
fn start_snapshot(&self) -> CombinedSnapshot {
892893
debug!("start_snapshot()");
893894

894-
let obligations_in_snapshot = self.obligations_in_snapshot.get();
895-
self.obligations_in_snapshot.set(false);
895+
let in_snapshot = self.in_snapshot.get();
896+
self.in_snapshot.set(true);
896897

897898
CombinedSnapshot {
898899
projection_cache_snapshot: self.projection_cache.borrow_mut().snapshot(),
899900
type_snapshot: self.type_variables.borrow_mut().snapshot(),
900901
int_snapshot: self.int_unification_table.borrow_mut().snapshot(),
901902
float_snapshot: self.float_unification_table.borrow_mut().snapshot(),
902903
region_vars_snapshot: self.region_vars.start_snapshot(),
903-
obligations_in_snapshot: obligations_in_snapshot,
904+
was_in_snapshot: in_snapshot,
904905
}
905906
}
906907

@@ -911,10 +912,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
911912
int_snapshot,
912913
float_snapshot,
913914
region_vars_snapshot,
914-
obligations_in_snapshot } = snapshot;
915+
was_in_snapshot } = snapshot;
915916

916-
assert!(!self.obligations_in_snapshot.get());
917-
self.obligations_in_snapshot.set(obligations_in_snapshot);
917+
self.in_snapshot.set(was_in_snapshot);
918918

919919
self.projection_cache
920920
.borrow_mut()
@@ -939,9 +939,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
939939
int_snapshot,
940940
float_snapshot,
941941
region_vars_snapshot,
942-
obligations_in_snapshot } = snapshot;
942+
was_in_snapshot } = snapshot;
943943

944-
self.obligations_in_snapshot.set(obligations_in_snapshot);
944+
self.in_snapshot.set(was_in_snapshot);
945945

946946
self.projection_cache
947947
.borrow_mut()

src/librustc/traits/fulfill.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
171171

172172
debug!("register_predicate_obligation(obligation={:?})", obligation);
173173

174-
infcx.obligations_in_snapshot.set(true);
174+
assert!(!infcx.is_in_snapshot());
175175

176176
if infcx.tcx.fulfilled_predicates.borrow().check_duplicate(&obligation.predicate) {
177177
debug!("register_predicate_obligation: duplicate");

src/librustc/traits/specialize/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
242242
// attempt to prove all of the predicates for impl2 given those for impl1
243243
// (which are packed up in penv)
244244

245-
infcx.save_and_restore_obligations_in_snapshot_flag(|infcx| {
245+
infcx.save_and_restore_in_snapshot_flag(|infcx| {
246246
let mut fulfill_cx = FulfillmentContext::new();
247247
for oblig in obligations.into_iter() {
248248
fulfill_cx.register_predicate_obligation(&infcx, oblig);

src/librustc_typeck/check/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2588,7 +2588,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
25882588
// we can. We don't care if some things turn
25892589
// out unconstrained or ambiguous, as we're
25902590
// just trying to get hints here.
2591-
let result = self.save_and_restore_obligations_in_snapshot_flag(|_| {
2591+
let result = self.save_and_restore_in_snapshot_flag(|_| {
25922592
let mut fulfill = FulfillmentContext::new();
25932593
let ok = ok; // FIXME(#30046)
25942594
for obligation in ok.obligations {

0 commit comments

Comments
 (0)