move the sub-unify check and extend the documentation a bit
I didn't like the sub-unify code executing when a predicate was ENQUEUED, that felt fragile. I would have preferred to move the sub-unify code so that it only occurred during generalization, but that impacted diagnostics, so having it also occur when we process subtype predicates felt pretty reasonable. (I guess we only need one or the other, but I kind of prefer both, since the generalizer ultimately feels like the *right* place to guarantee the properties we want.)
This commit is contained in:
committed by
Mark Rousskov
parent
947c0de028
commit
020655b90d
@@ -1004,23 +1004,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
predicate: ty::PolySubtypePredicate<'tcx>,
|
||||
) -> Option<InferResult<'tcx, ()>> {
|
||||
// Subtle: it's ok to skip the binder here and resolve because
|
||||
// `shallow_resolve` just ignores anything that is not a type
|
||||
// variable, and because type variable's can't (at present, at
|
||||
// Check for two unresolved inference variables, in which case we can
|
||||
// make no progress. This is partly a micro-optimization, but it's
|
||||
// also an opportunity to "sub-unify" the variables. This isn't
|
||||
// *necessary* to prevent cycles, because they would eventually be sub-unified
|
||||
// anyhow during generalization, but it helps with diagnostics (we can detect
|
||||
// earlier that they are sub-unified).
|
||||
//
|
||||
// Note that we can just skip the binders here because
|
||||
// type variables can't (at present, at
|
||||
// least) capture any of the things bound by this binder.
|
||||
//
|
||||
// NOTE(nmatsakis): really, there is no *particular* reason to do this
|
||||
// `shallow_resolve` here except as a micro-optimization.
|
||||
// Naturally I could not resist.
|
||||
let two_unbound_type_vars = {
|
||||
let a = self.shallow_resolve(predicate.skip_binder().a);
|
||||
let b = self.shallow_resolve(predicate.skip_binder().b);
|
||||
a.is_ty_var() && b.is_ty_var()
|
||||
};
|
||||
|
||||
if two_unbound_type_vars {
|
||||
// Two unbound type variables? Can't make progress.
|
||||
return None;
|
||||
// Note that this sub here is not just for diagnostics - it has semantic
|
||||
// effects as well.
|
||||
let r_a = self.shallow_resolve(predicate.skip_binder().a);
|
||||
let r_b = self.shallow_resolve(predicate.skip_binder().b);
|
||||
match (r_a.kind(), r_b.kind()) {
|
||||
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
|
||||
self.inner.borrow_mut().type_variables().sub(a_vid, b_vid);
|
||||
return None;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Some(self.commit_if_ok(|_snapshot| {
|
||||
|
||||
Reference in New Issue
Block a user