1
Fork 0

Rollup merge of #105292 - JulianKnodt:no_eager_commit, r=BoxyUwU

Change a commit_if_ok call to probe

Removes an over-eager `commit_if_ok` which makes inference worse.

I'm not entirely sure whether it's ok to remove the check that types are the same, because casting seems to cause equality checks with incorrect types?

Fixes #105037

r? ```@BoxyUwU```
This commit is contained in:
fee1-dead 2023-01-09 23:35:26 +08:00 committed by GitHub
commit b7587f1867
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 221 additions and 16 deletions

View file

@ -168,24 +168,27 @@ fn satisfied_from_param_env<'tcx>(
param_env: ty::ParamEnv<'tcx>,
infcx: &'a InferCtxt<'tcx>,
single_match: Option<Result<ty::Const<'tcx>, ()>>,
}
impl<'a, 'tcx> TypeVisitor<'tcx> for Visitor<'a, 'tcx> {
type BreakTy = ();
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!("is_const_evaluatable: candidate={:?}", c);
if let Ok(()) = self.infcx.commit_if_ok(|_| {
if self.infcx.probe(|_| {
let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
if let Ok(()) = ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty())
&& let Ok(()) = ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct)
ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty()).is_ok()
&& ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok()
&& ocx.select_all_or_error().is_empty()
{
Ok(())
} else {
Err(())
}
}) {
ControlFlow::BREAK
} else if let ty::ConstKind::Expr(e) = c.kind() {
self.single_match = match self.single_match {
None => Some(Ok(c)),
Some(Ok(o)) if o == c => Some(Ok(c)),
Some(_) => Some(Err(())),
};
}
if let ty::ConstKind::Expr(e) = c.kind() {
e.visit_with(self)
} else {
// FIXME(generic_const_exprs): This doesn't recurse into `<T as Trait<U>>::ASSOC`'s substs.
@ -200,22 +203,29 @@ fn satisfied_from_param_env<'tcx>(
}
}
let mut single_match: Option<Result<ty::Const<'tcx>, ()>> = None;
for pred in param_env.caller_bounds() {
match pred.kind().skip_binder() {
ty::PredicateKind::ConstEvaluatable(ce) => {
let b_ct = tcx.expand_abstract_consts(ce);
let mut v = Visitor { ct, infcx, param_env };
let result = b_ct.visit_with(&mut v);
let mut v = Visitor { ct, infcx, param_env, single_match };
let _ = b_ct.visit_with(&mut v);
if let ControlFlow::Break(()) = result {
debug!("is_const_evaluatable: yes");
return true;
}
single_match = v.single_match;
}
_ => {} // don't care
}
}
if let Some(Ok(c)) = single_match {
let ocx = ObligationCtxt::new(infcx);
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok());
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
assert!(ocx.select_all_or_error().is_empty());
return true;
}
debug!("is_const_evaluatable: no");
false
}