@@ -37,10 +37,11 @@ use snapshot::undo_log::InferCtxtUndoLogs;
37
37
use tracing::{debug, instrument};
38
38
use type_variable::TypeVariableOrigin;
39
39
40
- use crate::infer::region_constraints ::UndoLog;
40
+ use crate::infer::snapshot::undo_log ::UndoLog;
41
41
use crate::infer::unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey};
42
42
use crate::traits::{
43
- self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine,
43
+ self, ObligationCause, ObligationInspector, PredicateObligation, PredicateObligations,
44
+ TraitEngine,
44
45
};
45
46
46
47
pub mod at;
@@ -156,6 +157,12 @@ pub struct InferCtxtInner<'tcx> {
156
157
/// which may cause types to no longer be considered well-formed.
157
158
region_assumptions: Vec<ty::ArgOutlivesPredicate<'tcx>>,
158
159
160
+ /// `-Znext-solver`: Successfully proven goals during HIR typeck which
161
+ /// reference inference variables and get reproven after writeback.
162
+ ///
163
+ /// See the documentation of `InferCtxt::in_hir_typeck` for more details.
164
+ hir_typeck_potentially_region_dependent_goals: Vec<PredicateObligation<'tcx>>,
165
+
159
166
/// Caches for opaque type inference.
160
167
opaque_type_storage: OpaqueTypeStorage<'tcx>,
161
168
}
@@ -173,6 +180,7 @@ impl<'tcx> InferCtxtInner<'tcx> {
173
180
region_constraint_storage: Some(Default::default()),
174
181
region_obligations: Default::default(),
175
182
region_assumptions: Default::default(),
183
+ hir_typeck_potentially_region_dependent_goals: Default::default(),
176
184
opaque_type_storage: Default::default(),
177
185
}
178
186
}
@@ -247,24 +255,25 @@ pub struct InferCtxt<'tcx> {
247
255
/// the root universe. Most notably, this is used during HIR typeck as region
248
256
/// solving is left to borrowck instead.
249
257
pub considering_regions: bool,
250
- /// Whether this inference context is used by HIR typeck. If so, we uniquify regions
251
- /// with `-Znext-solver`. This is necessary as borrowck will start by replacing each
252
- /// occurance of a free region with a unique inference variable so if HIR typeck
253
- /// ends up depending on two regions being equal we'd get unexpected mismatches
254
- /// between HIR typeck and MIR typeck, resulting in an ICE.
258
+ /// `-Znext-solver`: Whether this inference context is used by HIR typeck. If so, we
259
+ /// need to make sure we don't rely on region identity in the trait solver or when
260
+ /// relating types. This is necessary as borrowck starts by replacing each occurrence of a
261
+ /// free region with a unique inference variable. If HIR typeck ends up depending on two
262
+ /// regions being equal we'd get unexpected mismatches between HIR typeck and MIR typeck,
263
+ /// resulting in an ICE.
255
264
///
256
265
/// The trait solver sometimes depends on regions being identical. As a concrete example
257
266
/// the trait solver ignores other candidates if one candidate exists without any constraints.
258
- /// The goal `&'a u32: Equals<&'a u32>` has no constraints right now, but if we replace
259
- /// each occurance of `'a` with a unique region the goal now equates these regions.
260
- ///
261
- /// See the tests in trait-system-refactor-initiative#27 for concrete examples.
267
+ /// The goal `&'a u32: Equals<&'a u32>` has no constraints right now. If we replace each
268
+ /// occurrence of `'a` with a unique region the goal now equates these regions. See
269
+ /// the tests in trait-system-refactor-initiative#27 for concrete examples.
262
270
///
263
- /// FIXME(-Znext-solver): This is insufficient in theory as a goal `T: Trait<?x, ?x>`
264
- /// may rely on the two occurances of `?x` being identical. If `?x` gets inferred to a
265
- /// type containing regions, this will no longer be the case. We can handle this case
266
- /// by storing goals which hold while still depending on inference vars and then
267
- /// reproving them before writeback.
271
+ /// We handle this by *uniquifying* region when canonicalizing root goals during HIR typeck.
272
+ /// This is still insufficient as inference variables may *hide* region variables, so e.g.
273
+ /// `dyn TwoSuper<?x, ?x>: Super<?x>` may hold but MIR typeck could end up having to prove
274
+ /// `dyn TwoSuper<&'0 (), &'1 ()>: Super<&'2 ()>` which is now ambiguous. Because of this we
275
+ /// stash all successfully proven goals which reference inference variables and then reprove
276
+ /// them after writeback.
268
277
pub in_hir_typeck: bool,
269
278
270
279
/// If set, this flag causes us to skip the 'leak check' during
@@ -1010,6 +1019,22 @@ impl<'tcx> InferCtxt<'tcx> {
1010
1019
}
1011
1020
}
1012
1021
1022
+ pub fn push_hir_typeck_potentially_region_dependent_goal(
1023
+ &self,
1024
+ goal: PredicateObligation<'tcx>,
1025
+ ) {
1026
+ let mut inner = self.inner.borrow_mut();
1027
+ inner.undo_log.push(UndoLog::PushHirTypeckPotentiallyRegionDependentGoal);
1028
+ inner.hir_typeck_potentially_region_dependent_goals.push(goal);
1029
+ }
1030
+
1031
+ pub fn take_hir_typeck_potentially_region_dependent_goals(
1032
+ &self,
1033
+ ) -> Vec<PredicateObligation<'tcx>> {
1034
+ assert!(!self.in_snapshot(), "cannot take goals in a snapshot");
1035
+ std::mem::take(&mut self.inner.borrow_mut().hir_typeck_potentially_region_dependent_goals)
1036
+ }
1037
+
1013
1038
pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
1014
1039
self.resolve_vars_if_possible(t).to_string()
1015
1040
}
0 commit comments