Skip to content

Commit 2369a79

Browse files
committed
for<..> fn(..) lub fn(..) should lub to fn(..)
1 parent bfd1f3b commit 2369a79

File tree

1 file changed

+28
-9
lines changed

1 file changed

+28
-9
lines changed

compiler/rustc_infer/src/infer/relate/lattice.rs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ use tracing::{debug, instrument};
2626

2727
use super::StructurallyRelateAliases;
2828
use super::combine::PredicateEmittingRelation;
29-
use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin, TypeTrace};
29+
use crate::infer::{
30+
BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, SubregionOrigin, TypeTrace,
31+
};
3032
use crate::traits::{Obligation, PredicateObligations};
3133

3234
#[derive(Clone, Copy)]
@@ -209,14 +211,31 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
209211
}
210212

211213
debug!("binders(a={:?}, b={:?})", a, b);
212-
if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
213-
// When higher-ranked types are involved, computing the GLB/LUB is
214-
// very challenging, switch to invariance. This is obviously
215-
// overly conservative but works ok in practice.
216-
self.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
217-
Ok(a)
218-
} else {
219-
Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
214+
match (a.no_bound_vars().ok_or(a), b.no_bound_vars().ok_or(b)) {
215+
(Err(a), Err(b)) => {
216+
// When higher-ranked types are involved, computing the GLB/LUB is
217+
// very challenging, switch to invariance. This is obviously
218+
// overly conservative but works ok in practice.
219+
self.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
220+
Ok(a)
221+
}
222+
(Ok(non_hr), Err(hr)) | (Err(hr), Ok(non_hr)) => {
223+
// If we only have one type with bound vars then we convert
224+
// it to a non higher-ranked signature, This should always
225+
// be correct assuming we do not support subtyping of the form:
226+
// `fn(&'smallest ()) <: for<'a> fn(&'a ())`
227+
// but I don't think we currently do so or intend to start doing so.
228+
//
229+
// This is a bit of a special case but it was necessary for backwards
230+
// compatibility when starting to properly leak checking in coercions.
231+
let non_hr_2 = self.infcx.instantiate_binder_with_fresh_vars(
232+
self.span(),
233+
BoundRegionConversionTime::HigherRankedType,
234+
hr,
235+
);
236+
Ok(ty::Binder::dummy(self.relate(non_hr, non_hr_2)?))
237+
}
238+
(Ok(a), Ok(b)) => Ok(ty::Binder::dummy(self.relate(a, b)?)),
220239
}
221240
}
222241
}

0 commit comments

Comments
 (0)