-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Lazy normalization of constants #67890
Changes from all commits
23edfc3
9df3360
a479836
70ec3b5
40887eb
905e64b
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 |
---|---|---|
|
@@ -126,7 +126,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { | |
b: &'tcx ty::Const<'tcx>, | ||
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> | ||
where | ||
R: TypeRelation<'tcx>, | ||
R: ConstEquateRelation<'tcx>, | ||
{ | ||
debug!("{}.consts({:?}, {:?})", relation.tag(), a, b); | ||
if a == b { | ||
|
@@ -164,7 +164,18 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { | |
(_, ty::ConstKind::Infer(InferConst::Var(vid))) => { | ||
return self.unify_const_variable(!a_is_expected, vid, a); | ||
} | ||
|
||
(ty::ConstKind::Unevaluated(..), _) | ||
if self.tcx.features().lazy_normalization_consts => | ||
{ | ||
relation.const_equate_obligation(a, b); | ||
return Ok(b); | ||
} | ||
(_, ty::ConstKind::Unevaluated(..)) | ||
if self.tcx.features().lazy_normalization_consts => | ||
{ | ||
relation.const_equate_obligation(a, b); | ||
return Ok(a); | ||
} | ||
_ => {} | ||
} | ||
|
||
|
@@ -375,6 +386,20 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { | |
debug!("generalize: success {{ {:?}, {:?} }}", ty, needs_wf); | ||
Ok(Generalization { ty, needs_wf }) | ||
} | ||
|
||
pub fn add_const_equate_obligation( | ||
&mut self, | ||
a_is_expected: bool, | ||
a: &'tcx ty::Const<'tcx>, | ||
b: &'tcx ty::Const<'tcx>, | ||
) { | ||
let predicate = if a_is_expected { | ||
ty::Predicate::ConstEquate(a, b) | ||
} else { | ||
ty::Predicate::ConstEquate(b, a) | ||
}; | ||
self.obligations.push(Obligation::new(self.trace.cause.clone(), self.param_env, predicate)); | ||
} | ||
} | ||
|
||
struct Generalizer<'cx, 'tcx> { | ||
|
@@ -635,11 +660,21 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { | |
} | ||
} | ||
} | ||
ty::ConstKind::Unevaluated(..) if self.tcx().features().lazy_normalization_consts => { | ||
Ok(c) | ||
} | ||
_ => relate::super_relate_consts(self, c, c), | ||
} | ||
} | ||
} | ||
|
||
pub trait ConstEquateRelation<'tcx>: TypeRelation<'tcx> { | ||
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. It's not obvious to me at this moment why we have a distinct trait for this 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. There are some I slightly prefer keeping the |
||
/// Register an obligation that both constants must be equal to each other. | ||
/// | ||
/// If they aren't equal then the relation doesn't hold. | ||
fn const_equate_obligation(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>); | ||
} | ||
|
||
pub trait RelateResultCompare<'tcx, T> { | ||
fn compare<F>(&self, t: T, f: F) -> RelateResult<'tcx, T> | ||
where | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ | |
//! thing we relate in chalk are basically domain goals and their | ||
//! constituents) | ||
|
||
use crate::infer::combine::ConstEquateRelation; | ||
use crate::infer::InferCtxt; | ||
use crate::infer::{ConstVarValue, ConstVariableValue}; | ||
use crate::traits::DomainGoal; | ||
|
@@ -82,6 +83,8 @@ pub trait TypeRelatingDelegate<'tcx> { | |
/// be related. Used for lazy normalization. | ||
fn push_domain_goal(&mut self, domain_goal: DomainGoal<'tcx>); | ||
|
||
fn const_equate(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>); | ||
|
||
/// Creates a new universe index. Used when instantiating placeholders. | ||
fn create_next_universe(&mut self) -> ty::UniverseIndex; | ||
|
||
|
@@ -603,8 +606,8 @@ where | |
b = self.infcx.shallow_resolve(b); | ||
} | ||
|
||
match b.val { | ||
ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => { | ||
match (a.val, b.val) { | ||
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. Nit: seems like a useful diff? 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. Not quite sure what you mean here 🤔 This does not change the actual behavior afaict which is why I removed this change in #71973. |
||
(_, ty::ConstKind::Infer(InferConst::Var(_))) if D::forbid_inference_vars() => { | ||
// Forbid inference variables in the RHS. | ||
bug!("unexpected inference var {:?}", b) | ||
} | ||
|
@@ -726,6 +729,15 @@ where | |
} | ||
} | ||
|
||
impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D> | ||
where | ||
D: TypeRelatingDelegate<'tcx>, | ||
{ | ||
fn const_equate_obligation(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>) { | ||
self.delegate.const_equate(a, b); | ||
} | ||
} | ||
|
||
/// When we encounter a binder like `for<..> fn(..)`, we actually have | ||
/// to walk the `fn` value to find all the values bound by the `for` | ||
/// (these are not explicitly present in the ty representation right | ||
|
@@ -985,6 +997,9 @@ where | |
} | ||
} | ||
} | ||
ty::ConstKind::Unevaluated(..) if self.tcx().features().lazy_normalization_consts => { | ||
Ok(a) | ||
} | ||
_ => relate::super_relate_consts(self, a, a), | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Until we get the full universe transition happening here, I think we want to check that there are no escaping late-bound regions in these types...oh, hmm, I guess they would be substituted for placeholders already...urgh.