Use variances for defining use diag.

This commit is contained in:
Camille GILLOT 2022-10-23 12:59:40 +00:00
parent b676fc4d8e
commit 47de11f1ed

View File

@ -1345,61 +1345,13 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
// type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b;
// ```
// we may not use `'c` in the hidden type.
struct OpaqueTypeLifetimeCollector<'tcx> {
lifetimes: FxHashSet<ty::Region<'tcx>>,
}
let variances = tcx.variances_of(def_id);
debug!(?variances);
impl<'tcx> ty::TypeVisitor<'tcx> for OpaqueTypeLifetimeCollector<'tcx> {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
self.lifetimes.insert(r);
r.super_visit_with(self)
}
}
let mut collector = OpaqueTypeLifetimeCollector { lifetimes: Default::default() };
for pred in tcx.bound_explicit_item_bounds(def_id.to_def_id()).transpose_iter() {
let pred = pred.map_bound(|(pred, _)| *pred).subst(tcx, id_substs);
trace!(pred=?pred.kind());
// We only ignore opaque type substs if the opaque type is the outermost type.
// The opaque type may be nested within itself via recursion in e.g.
// type Foo<'a> = impl PartialEq<Foo<'a>>;
// which thus mentions `'a` and should thus accept hidden types that borrow 'a
// instead of requiring an additional `+ 'a`.
match pred.kind().skip_binder() {
ty::PredicateKind::Trait(TraitPredicate {
trait_ref: ty::TraitRef { def_id: _, substs },
constness: _,
polarity: _,
}) => {
trace!(?substs);
for subst in &substs[1..] {
subst.visit_with(&mut collector);
}
}
ty::PredicateKind::Projection(ty::ProjectionPredicate {
projection_ty: ty::ProjectionTy { substs, item_def_id: _ },
term,
}) => {
for subst in &substs[1..] {
subst.visit_with(&mut collector);
}
term.visit_with(&mut collector);
}
_ => {
pred.visit_with(&mut collector);
}
}
}
let lifetimes = collector.lifetimes;
trace!(?lifetimes);
map.filter(|(_, v)| {
let ty::GenericArgKind::Lifetime(lt) = v.unpack() else {
return true;
};
lifetimes.contains(&lt)
let ty::GenericArgKind::Lifetime(lt) = v.unpack() else { return true };
let ty::ReEarlyBound(ebr) = lt.kind() else { bug!() };
variances[ebr.index as usize] == ty::Variance::Invariant
})
.collect()
}