1
Fork 0

Add opt_alias_variances and use it in outlives code

This commit is contained in:
Michael Goulet 2025-02-05 18:03:26 +00:00
parent 2f92f050e8
commit d17a4a7f9a
12 changed files with 117 additions and 50 deletions

View file

@ -48,7 +48,7 @@ where
return ty.super_visit_with(self);
}
match ty.kind() {
match *ty.kind() {
// We can prove that an alias is live two ways:
// 1. All the components are live.
//
@ -95,11 +95,9 @@ where
assert!(r.type_flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS));
r.visit_with(self);
} else {
// Skip lifetime parameters that are not captures.
let variances = match kind {
ty::Opaque => Some(self.tcx.variances_of(*def_id)),
_ => None,
};
// Skip lifetime parameters that are not captured, since they do
// not need to be live.
let variances = tcx.opt_alias_variances(kind, def_id);
for (idx, s) in args.iter().enumerate() {
if variances.map(|variances| variances[idx]) != Some(ty::Bivariant) {

View file

@ -392,13 +392,13 @@ where
// the problem is to add `T: 'r`, which isn't true. So, if there are no
// inference variables, we use a verify constraint instead of adding
// edges, which winds up enforcing the same condition.
let is_opaque = alias_ty.kind(self.tcx) == ty::Opaque;
let kind = alias_ty.kind(self.tcx);
if approx_env_bounds.is_empty()
&& trait_bounds.is_empty()
&& (alias_ty.has_infer_regions() || is_opaque)
&& (alias_ty.has_infer_regions() || kind == ty::Opaque)
{
debug!("no declared bounds");
let opt_variances = is_opaque.then(|| self.tcx.variances_of(alias_ty.def_id));
let opt_variances = self.tcx.opt_alias_variances(kind, alias_ty.def_id);
self.args_must_outlive(alias_ty.args, origin, region, opt_variances);
return;
}

View file

@ -102,12 +102,11 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
#[instrument(level = "debug", skip(self))]
pub(crate) fn alias_bound(&self, alias_ty: ty::AliasTy<'tcx>) -> VerifyBound<'tcx> {
let alias_ty_as_ty = alias_ty.to_ty(self.tcx);
// Search the env for where clauses like `P: 'a`.
let env_bounds = self.approx_declared_bounds_from_env(alias_ty).into_iter().map(|binder| {
if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars()
&& ty == alias_ty_as_ty
&& let ty::Alias(_, alias_ty_from_bound) = *ty.kind()
&& alias_ty_from_bound == alias_ty
{
// Micro-optimize if this is an exact match (this
// occurs often when there are no region variables
@ -127,7 +126,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
// see the extensive comment in projection_must_outlive
let recursive_bound = {
let mut components = smallvec![];
compute_alias_components_recursive(self.tcx, alias_ty_as_ty, &mut components);
let kind = alias_ty.kind(self.tcx);
compute_alias_components_recursive(self.tcx, kind, alias_ty, &mut components);
self.bound_from_components(&components)
};