Skip to content

Commit a409842

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

File tree

1 file changed

+32
-10
lines changed

1 file changed

+32
-10
lines changed

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

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
use rustc_middle::traits::solve::Goal;
2121
use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys};
2222
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
23-
use rustc_middle::ty::{self, Ty, TyCtxt, TyVar, TypeVisitableExt};
23+
use rustc_middle::ty::{self, Ty, TyCtxt, TyVar};
2424
use rustc_span::Span;
25-
use tracing::{debug, instrument};
25+
use tracing::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)]
@@ -195,6 +197,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
195197
super_combine_consts(self.infcx, self, a, b)
196198
}
197199

200+
#[instrument(level = "trace", skip(self))]
198201
fn binders<T>(
199202
&mut self,
200203
a: ty::Binder<'tcx, T>,
@@ -208,16 +211,35 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
208211
return Ok(a);
209212
}
210213

211-
debug!("binders(a={:?}, b={:?})", a, b);
212-
if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
214+
let instantiate_with_infer = |binder| {
215+
let span = self.span();
216+
let brct = BoundRegionConversionTime::HigherRankedType;
217+
self.infcx.instantiate_binder_with_fresh_vars(span, brct, binder)
218+
};
219+
let r = match (a.no_bound_vars(), b.no_bound_vars()) {
213220
// When higher-ranked types are involved, computing the GLB/LUB is
214221
// very challenging, switch to invariance. This is obviously
215222
// 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())?))
220-
}
223+
(None, None) => {
224+
self.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
225+
return Ok(a);
226+
}
227+
228+
// If we only have one type with bound vars then we convert
229+
// it to a non higher-ranked signature, This should always
230+
// be correct assuming we do not support subtyping of the form:
231+
// `fn(&'smallest ()) <: for<'a> fn(&'a ())`
232+
// but I don't think we currently do so or intend to start doing so.
233+
//
234+
// This is a bit of a special case but it was necessary for backwards
235+
// compatibility when starting to properly leak checking in coercions.
236+
(Some(a), None) => self.relate(a, instantiate_with_infer(b))?,
237+
(None, Some(b)) => self.relate(instantiate_with_infer(a), b)?,
238+
239+
(Some(a), Some(b)) => self.relate(a, b)?,
240+
};
241+
242+
Ok(ty::Binder::dummy(r))
221243
}
222244
}
223245

0 commit comments

Comments
 (0)