Skip to content

Commit f0411ff

Browse files
committed
Auto merge of rust-lang#111881 - lcnr:leak-check, r=nikomatsakis,jackh726
refactor and cleanup the leak check, add it to new solver ended up being a bit more involved than I wanted but is hopefully still easy enough to review as a single PR, can split it into separate ones otherwise. this can be reviewed commit by commit: a473d55cdb9284aa2b01282d1b529a2a4d26547b 31a686646534ca006d906ec757ece4e771d6f973 949039c107852a5e36361c08b62821a0613656f5 242917bf5170d9a723c6c8e23e9d9d0c2fa8dc9d ed2b25a7aa28be3184be9e3022c2796a30eaad87 are all pretty straightforward. 03dd83b4c3f4ff27558f5c8ab859bd9f83db1d04 makes it easier to refactor coherence in a later commit, see the commit description, cc `@oli-obk` 4fe311d807a77b6270f384e41689bf5d58f46aec I don't quite remember what we wanted to test here, this definitely doesn't test that the occurs check doesn't cause incorrect errors in coherence, also cc `@oli-obk` here. I may end up writing a new test for this myself later. 5c200d88a91b75bd0875b973150655bd581ef97a is the main refactor of the leak check, changing it to take the `outer_universe` instead of getting it from a snapshot. Using a snapshot requires us to be in a probe which we aren't in the new solver, it also just feels dirty as snapshots don't really have anything to do with universes. with all of this cfc230d54188d9c7ed867a9a0d1f51be77b485f9 is now kind of trivial. r? `@nikomatsakis`
2 parents a9251b6 + 0b81f99 commit f0411ff

File tree

138 files changed

+320
-244
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

138 files changed

+320
-244
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
808808
G: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
809809
{
810810
self.commit_if_ok(|snapshot| {
811+
let outer_universe = self.infcx.universe();
812+
811813
let result = if let ty::FnPtr(fn_ty_b) = b.kind()
812814
&& let (hir::Unsafety::Normal, hir::Unsafety::Unsafe) =
813815
(fn_ty_a.unsafety(), fn_ty_b.unsafety())
@@ -824,7 +826,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
824826
// want the coerced type to be the actual supertype of these two,
825827
// but for now, we want to just error to ensure we don't lock
826828
// ourselves into a specific behavior with NLL.
827-
self.leak_check(false, snapshot)?;
829+
self.leak_check(outer_universe, Some(snapshot))?;
828830

829831
result
830832
})

compiler/rustc_infer/src/infer/at.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ impl<'tcx> InferCtxt<'tcx> {
7070
tcx: self.tcx,
7171
defining_use_anchor: self.defining_use_anchor,
7272
considering_regions: self.considering_regions,
73+
skip_leak_check: self.skip_leak_check,
7374
inner: self.inner.clone(),
74-
skip_leak_check: self.skip_leak_check.clone(),
7575
lexical_region_resolutions: self.lexical_region_resolutions.clone(),
7676
selection_cache: self.selection_cache.clone(),
7777
evaluation_cache: self.evaluation_cache.clone(),

compiler/rustc_infer/src/infer/higher_ranked/mod.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -105,29 +105,31 @@ impl<'tcx> InferCtxt<'tcx> {
105105
self.tcx.replace_bound_vars_uncached(binder, delegate)
106106
}
107107

108-
/// See [RegionConstraintCollector::leak_check][1].
108+
/// See [RegionConstraintCollector::leak_check][1]. We only check placeholder
109+
/// leaking into `outer_universe`, i.e. placeholders which cannot be named by that
110+
/// universe.
109111
///
110112
/// [1]: crate::infer::region_constraints::RegionConstraintCollector::leak_check
111113
pub fn leak_check(
112114
&self,
113-
overly_polymorphic: bool,
114-
snapshot: &CombinedSnapshot<'tcx>,
115+
outer_universe: ty::UniverseIndex,
116+
only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>,
115117
) -> RelateResult<'tcx, ()> {
116118
// If the user gave `-Zno-leak-check`, or we have been
117119
// configured to skip the leak check, then skip the leak check
118120
// completely. The leak check is deprecated. Any legitimate
119121
// subtyping errors that it would have caught will now be
120122
// caught later on, during region checking. However, we
121123
// continue to use it for a transition period.
122-
if self.tcx.sess.opts.unstable_opts.no_leak_check || self.skip_leak_check.get() {
124+
if self.tcx.sess.opts.unstable_opts.no_leak_check || self.skip_leak_check {
123125
return Ok(());
124126
}
125127

126128
self.inner.borrow_mut().unwrap_region_constraints().leak_check(
127129
self.tcx,
128-
overly_polymorphic,
130+
outer_universe,
129131
self.universe(),
130-
snapshot,
132+
only_consider_snapshot,
131133
)
132134
}
133135
}

compiler/rustc_infer/src/infer/mod.rs

+22-33
Original file line numberDiff line numberDiff line change
@@ -251,14 +251,13 @@ pub struct InferCtxt<'tcx> {
251251
/// solving is left to borrowck instead.
252252
pub considering_regions: bool,
253253

254-
pub inner: RefCell<InferCtxtInner<'tcx>>,
255-
256254
/// If set, this flag causes us to skip the 'leak check' during
257255
/// higher-ranked subtyping operations. This flag is a temporary one used
258256
/// to manage the removal of the leak-check: for the time being, we still run the
259-
/// leak-check, but we issue warnings. This flag can only be set to true
260-
/// when entering a snapshot.
261-
skip_leak_check: Cell<bool>,
257+
/// leak-check, but we issue warnings.
258+
skip_leak_check: bool,
259+
260+
pub inner: RefCell<InferCtxtInner<'tcx>>,
262261

263262
/// Once region inference is done, the values for each variable.
264263
lexical_region_resolutions: RefCell<Option<LexicalRegionResolutions<'tcx>>>,
@@ -543,6 +542,7 @@ pub struct InferCtxtBuilder<'tcx> {
543542
tcx: TyCtxt<'tcx>,
544543
defining_use_anchor: DefiningAnchor,
545544
considering_regions: bool,
545+
skip_leak_check: bool,
546546
/// Whether we are in coherence mode.
547547
intercrate: bool,
548548
}
@@ -557,6 +557,7 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
557557
tcx: self,
558558
defining_use_anchor: DefiningAnchor::Error,
559559
considering_regions: true,
560+
skip_leak_check: false,
560561
intercrate: false,
561562
}
562563
}
@@ -584,6 +585,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
584585
self
585586
}
586587

588+
pub fn skip_leak_check(mut self, skip_leak_check: bool) -> Self {
589+
self.skip_leak_check = skip_leak_check;
590+
self
591+
}
592+
587593
/// Given a canonical value `C` as a starting point, create an
588594
/// inference context that contains each of the bound values
589595
/// within instantiated as a fresh variable. The `f` closure is
@@ -605,11 +611,18 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
605611
}
606612

607613
pub fn build(&mut self) -> InferCtxt<'tcx> {
608-
let InferCtxtBuilder { tcx, defining_use_anchor, considering_regions, intercrate } = *self;
614+
let InferCtxtBuilder {
615+
tcx,
616+
defining_use_anchor,
617+
considering_regions,
618+
skip_leak_check,
619+
intercrate,
620+
} = *self;
609621
InferCtxt {
610622
tcx,
611623
defining_use_anchor,
612624
considering_regions,
625+
skip_leak_check,
613626
inner: RefCell::new(InferCtxtInner::new()),
614627
lexical_region_resolutions: RefCell::new(None),
615628
selection_cache: Default::default(),
@@ -619,7 +632,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
619632
tainted_by_errors: Cell::new(None),
620633
err_count_on_creation: tcx.sess.err_count(),
621634
in_snapshot: Cell::new(false),
622-
skip_leak_check: Cell::new(false),
623635
universe: Cell::new(ty::UniverseIndex::ROOT),
624636
intercrate,
625637
}
@@ -815,32 +827,9 @@ impl<'tcx> InferCtxt<'tcx> {
815827
r
816828
}
817829

818-
/// If `should_skip` is true, then execute `f` then unroll any bindings it creates.
819-
#[instrument(skip(self, f), level = "debug")]
820-
pub fn probe_maybe_skip_leak_check<R, F>(&self, should_skip: bool, f: F) -> R
821-
where
822-
F: FnOnce(&CombinedSnapshot<'tcx>) -> R,
823-
{
824-
let snapshot = self.start_snapshot();
825-
let was_skip_leak_check = self.skip_leak_check.get();
826-
if should_skip {
827-
self.skip_leak_check.set(true);
828-
}
829-
let r = f(&snapshot);
830-
self.rollback_to("probe", snapshot);
831-
self.skip_leak_check.set(was_skip_leak_check);
832-
r
833-
}
834-
835-
/// Scan the constraints produced since `snapshot` began and returns:
836-
///
837-
/// - `None` -- if none of them involves "region outlives" constraints.
838-
/// - `Some(true)` -- if there are `'a: 'b` constraints where `'a` or `'b` is a placeholder.
839-
/// - `Some(false)` -- if there are `'a: 'b` constraints but none involve placeholders.
840-
pub fn region_constraints_added_in_snapshot(
841-
&self,
842-
snapshot: &CombinedSnapshot<'tcx>,
843-
) -> Option<bool> {
830+
/// Scan the constraints produced since `snapshot` and check whether
831+
/// we added any region constraints.
832+
pub fn region_constraints_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool {
844833
self.inner
845834
.borrow_mut()
846835
.unwrap_region_constraints()

compiler/rustc_infer/src/infer/opaque_types.rs

+22-10
Original file line numberDiff line numberDiff line change
@@ -533,17 +533,29 @@ impl<'tcx> InferCtxt<'tcx> {
533533
// these are the same span, but not in cases like `-> (impl
534534
// Foo, impl Bar)`.
535535
let span = cause.span;
536-
let prev = self.inner.borrow_mut().opaque_types().register(
537-
opaque_type_key,
538-
OpaqueHiddenType { ty: hidden_ty, span },
539-
origin,
540-
);
541-
let mut obligations = if let Some(prev) = prev {
542-
self.at(&cause, param_env)
543-
.eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
544-
.obligations
536+
let mut obligations = if self.intercrate {
537+
// During intercrate we do not define opaque types but instead always
538+
// force ambiguity unless the hidden type is known to not implement
539+
// our trait.
540+
vec![traits::Obligation::new(
541+
self.tcx,
542+
cause.clone(),
543+
param_env,
544+
ty::PredicateKind::Ambiguous,
545+
)]
545546
} else {
546-
Vec::new()
547+
let prev = self.inner.borrow_mut().opaque_types().register(
548+
opaque_type_key,
549+
OpaqueHiddenType { ty: hidden_ty, span },
550+
origin,
551+
);
552+
if let Some(prev) = prev {
553+
self.at(&cause, param_env)
554+
.eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
555+
.obligations
556+
} else {
557+
Vec::new()
558+
}
547559
};
548560

549561
self.add_item_bounds_for_hidden_type(

0 commit comments

Comments
 (0)