Add opt_alias_variances and use it in outlives code
This commit is contained in:
parent
2f92f050e8
commit
d17a4a7f9a
12 changed files with 117 additions and 50 deletions
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue