-
Notifications
You must be signed in to change notification settings - Fork 13.6k
uniquify root goals during HIR typeck #144405
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0b323ea
64a27c2
b6cbe33
df2e543
2b065e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,10 +37,11 @@ use snapshot::undo_log::InferCtxtUndoLogs; | |
use tracing::{debug, instrument}; | ||
use type_variable::TypeVariableOrigin; | ||
|
||
use crate::infer::region_constraints::UndoLog; | ||
use crate::infer::snapshot::undo_log::UndoLog; | ||
use crate::infer::unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey}; | ||
use crate::traits::{ | ||
self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, | ||
self, ObligationCause, ObligationInspector, PredicateObligation, PredicateObligations, | ||
TraitEngine, | ||
}; | ||
|
||
pub mod at; | ||
|
@@ -156,6 +157,12 @@ pub struct InferCtxtInner<'tcx> { | |
/// which may cause types to no longer be considered well-formed. | ||
region_assumptions: Vec<ty::ArgOutlivesPredicate<'tcx>>, | ||
|
||
/// `-Znext-solver`: Successfully proven goals during HIR typeck which | ||
/// reference inference variables and get reproven after writeback. | ||
/// | ||
/// See the documentation of `InferCtxt::in_hir_typeck` for more details. | ||
hir_typeck_potentially_region_dependent_goals: Vec<PredicateObligation<'tcx>>, | ||
|
||
/// Caches for opaque type inference. | ||
opaque_type_storage: OpaqueTypeStorage<'tcx>, | ||
} | ||
|
@@ -173,6 +180,7 @@ impl<'tcx> InferCtxtInner<'tcx> { | |
region_constraint_storage: Some(Default::default()), | ||
region_obligations: Default::default(), | ||
region_assumptions: Default::default(), | ||
hir_typeck_potentially_region_dependent_goals: Default::default(), | ||
opaque_type_storage: Default::default(), | ||
} | ||
} | ||
|
@@ -244,9 +252,29 @@ pub struct InferCtxt<'tcx> { | |
typing_mode: TypingMode<'tcx>, | ||
|
||
/// Whether this inference context should care about region obligations in | ||
/// the root universe. Most notably, this is used during hir typeck as region | ||
/// the root universe. Most notably, this is used during HIR typeck as region | ||
/// solving is left to borrowck instead. | ||
pub considering_regions: bool, | ||
/// `-Znext-solver`: Whether this inference context is used by HIR typeck. If so, we | ||
/// need to make sure we don't rely on region identity in the trait solver or when | ||
/// relating types. This is necessary as borrowck starts by replacing each occurrence of a | ||
/// free region with a unique inference variable. If HIR typeck ends up depending on two | ||
/// regions being equal we'd get unexpected mismatches between HIR typeck and MIR typeck, | ||
/// resulting in an ICE. | ||
/// | ||
/// The trait solver sometimes depends on regions being identical. As a concrete example | ||
/// the trait solver ignores other candidates if one candidate exists without any constraints. | ||
/// The goal `&'a u32: Equals<&'a u32>` has no constraints right now. If we replace each | ||
/// occurrence of `'a` with a unique region the goal now equates these regions. See | ||
/// the tests in trait-system-refactor-initiative#27 for concrete examples. | ||
/// | ||
/// We handle this by *uniquifying* region when canonicalizing root goals during HIR typeck. | ||
/// This is still insufficient as inference variables may *hide* region variables, so e.g. | ||
/// `dyn TwoSuper<?x, ?x>: Super<?x>` may hold but MIR typeck could end up having to prove | ||
/// `dyn TwoSuper<&'0 (), &'1 ()>: Super<&'2 ()>` which is now ambiguous. Because of this we | ||
/// stash all successfully proven goals which reference inference variables and then reprove | ||
/// them after writeback. | ||
pub in_hir_typeck: bool, | ||
|
||
/// If set, this flag causes us to skip the 'leak check' during | ||
/// higher-ranked subtyping operations. This flag is a temporary one used | ||
|
@@ -506,6 +534,7 @@ pub struct TypeOutlivesConstraint<'tcx> { | |
pub struct InferCtxtBuilder<'tcx> { | ||
tcx: TyCtxt<'tcx>, | ||
considering_regions: bool, | ||
in_hir_typeck: bool, | ||
skip_leak_check: bool, | ||
/// Whether we should use the new trait solver in the local inference context, | ||
/// which affects things like which solver is used in `predicate_may_hold`. | ||
|
@@ -518,6 +547,7 @@ impl<'tcx> TyCtxt<'tcx> { | |
InferCtxtBuilder { | ||
tcx: self, | ||
considering_regions: true, | ||
in_hir_typeck: false, | ||
skip_leak_check: false, | ||
next_trait_solver: self.next_trait_solver_globally(), | ||
} | ||
|
@@ -535,6 +565,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> { | |
self | ||
} | ||
|
||
pub fn in_hir_typeck(mut self) -> Self { | ||
self.in_hir_typeck = true; | ||
self | ||
} | ||
|
||
pub fn skip_leak_check(mut self, skip_leak_check: bool) -> Self { | ||
self.skip_leak_check = skip_leak_check; | ||
self | ||
|
@@ -568,12 +603,18 @@ impl<'tcx> InferCtxtBuilder<'tcx> { | |
} | ||
|
||
pub fn build(&mut self, typing_mode: TypingMode<'tcx>) -> InferCtxt<'tcx> { | ||
let InferCtxtBuilder { tcx, considering_regions, skip_leak_check, next_trait_solver } = | ||
*self; | ||
let InferCtxtBuilder { | ||
tcx, | ||
considering_regions, | ||
in_hir_typeck, | ||
skip_leak_check, | ||
next_trait_solver, | ||
} = *self; | ||
InferCtxt { | ||
tcx, | ||
typing_mode, | ||
considering_regions, | ||
in_hir_typeck, | ||
skip_leak_check, | ||
inner: RefCell::new(InferCtxtInner::new()), | ||
lexical_region_resolutions: RefCell::new(None), | ||
|
@@ -978,6 +1019,22 @@ impl<'tcx> InferCtxt<'tcx> { | |
} | ||
} | ||
|
||
pub fn push_hir_typeck_potentially_region_dependent_goal( | ||
&self, | ||
goal: PredicateObligation<'tcx>, | ||
) { | ||
let mut inner = self.inner.borrow_mut(); | ||
inner.undo_log.push(UndoLog::PushHirTypeckPotentiallyRegionDependentGoal); | ||
inner.hir_typeck_potentially_region_dependent_goals.push(goal); | ||
Comment on lines
+1026
to
+1028
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. questions: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we do when using a separate fulfillment context inside of a probe |
||
} | ||
|
||
pub fn take_hir_typeck_potentially_region_dependent_goals( | ||
&self, | ||
) -> Vec<PredicateObligation<'tcx>> { | ||
assert!(!self.in_snapshot(), "cannot take goals in a snapshot"); | ||
std::mem::take(&mut self.inner.borrow_mut().hir_typeck_potentially_region_dependent_goals) | ||
} | ||
|
||
pub fn ty_to_string(&self, t: Ty<'tcx>) -> String { | ||
self.resolve_vars_if_possible(t).to_string() | ||
} | ||
|
Uh oh!
There was an error while loading. Please reload this page.