add the ability to skip leak check within a snapshot

The intention is that coherence code will skip the leak check and
determine whether two impls *would have* overlapped, and then issue a
warning.
This commit is contained in:
Niko Matsakis 2020-01-18 07:59:16 -05:00
parent 5e0197f13a
commit e9c78947dc
3 changed files with 37 additions and 12 deletions

View File

@ -128,6 +128,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
placeholder_map: &PlaceholderMap<'tcx>,
snapshot: &CombinedSnapshot<'_, 'tcx>,
) -> RelateResult<'tcx, ()> {
// If the user gave `-Zno-leak-check`, or we have been
// configured to skip the leak check, then skip the leak check
// completely. The leak check is deprecated. Any legitimate
// subtyping errors that it would have caught will now be
// caught later on, during region checking. However, we
// continue to use it for a transition period.
if self.tcx.sess.opts.debugging_opts.no_leak_check || self.skip_leak_check.get() {
return Ok(());
}
self.borrow_region_constraints().leak_check(
self.tcx,
overly_polymorphic,

View File

@ -125,6 +125,13 @@ pub struct InferCtxt<'a, 'tcx> {
/// order, represented by its upper and lower bounds.
pub type_variables: RefCell<type_variable::TypeVariableTable<'tcx>>,
/// If set, this flag causes us to skip the 'leak check' during
/// higher-ranked subtyping operations. This flag is a temporary one used
/// to manage the removal of the leak-check: for the time being, we still run the
/// leak-check, but we issue warnings. This flag can only be set to true
/// when entering a snapshot.
skip_leak_check: Cell<bool>,
/// Map from const parameter variable to the kind of const it represents.
const_unification_table: RefCell<ut::UnificationTable<ut::InPlace<ty::ConstVid<'tcx>>>>,
@ -550,6 +557,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
tainted_by_errors_flag: Cell::new(false),
err_count_on_creation: tcx.sess.err_count(),
in_snapshot: Cell::new(false),
skip_leak_check: Cell::new(false),
region_obligations: RefCell::new(vec![]),
universe: Cell::new(ty::UniverseIndex::ROOT),
})
@ -593,6 +601,7 @@ pub struct CombinedSnapshot<'a, 'tcx> {
region_obligations_snapshot: usize,
universe: ty::UniverseIndex,
was_in_snapshot: bool,
was_skip_leak_check: bool,
_in_progress_tables: Option<Ref<'a, ty::TypeckTables<'tcx>>>,
}
@ -720,6 +729,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
region_obligations_snapshot: self.region_obligations.borrow().len(),
universe: self.universe(),
was_in_snapshot: in_snapshot,
was_skip_leak_check: self.skip_leak_check.get(),
// Borrow tables "in progress" (i.e., during typeck)
// to ban writes from within a snapshot to them.
_in_progress_tables: self.in_progress_tables.map(|tables| tables.borrow()),
@ -738,11 +748,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
region_obligations_snapshot,
universe,
was_in_snapshot,
was_skip_leak_check,
_in_progress_tables,
} = snapshot;
self.in_snapshot.set(was_in_snapshot);
self.universe.set(universe);
self.skip_leak_check.set(was_skip_leak_check);
self.projection_cache.borrow_mut().rollback_to(projection_cache_snapshot);
self.type_variables.borrow_mut().rollback_to(type_snapshot);
@ -765,10 +777,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
region_obligations_snapshot: _,
universe: _,
was_in_snapshot,
was_skip_leak_check,
_in_progress_tables,
} = snapshot;
self.in_snapshot.set(was_in_snapshot);
self.skip_leak_check.set(was_skip_leak_check);
self.projection_cache.borrow_mut().commit(projection_cache_snapshot);
self.type_variables.borrow_mut().commit(type_snapshot);
@ -822,6 +836,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
r
}
/// Execute `f` then unroll any bindings it creates.
pub fn skip_leak_check<R, F>(&self, f: F) -> R
where
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
{
debug!("probe()");
let snapshot = self.start_snapshot();
self.skip_leak_check.set(true);
let r = f(&snapshot);
self.rollback_to("probe", snapshot);
r
}
/// Scan the constraints produced since `snapshot` began and returns:
///
/// - `None` -- if none of them involve "region outlives" constraints

View File

@ -33,18 +33,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
assert!(self.in_snapshot());
// If the user gave `-Zno-leak-check`, then skip the leak
// check completely. This is wildly unsound and also not
// unlikely to cause an ICE or two. It is intended for use
// only during a transition period, in which the MIR typeck
// uses the "universe-style" check, and the rest of typeck
// uses the more conservative leak check. Since the leak
// check is more conservative, we can't test the
// universe-style check without disabling it.
if tcx.sess.opts.debugging_opts.no_leak_check {
return Ok(());
}
// Go through each placeholder that we created.
for (_, &placeholder_region) in placeholder_map {
// Find the universe this placeholder inhabits.