Auto merge of #110399 - cjgillot:infer-variance, r=aliemjay
Account for opaque variance in outlives Fixes https://github.com/rust-lang/rust/issues/108591 Fixes https://github.com/rust-lang/rust/issues/108592 cc `@aliemjay`
This commit is contained in:
commit
7fde08365c
5 changed files with 116 additions and 13 deletions
|
@ -143,7 +143,7 @@ fn compute_components<'tcx>(
|
|||
// through and constrain Pi.
|
||||
let mut subcomponents = smallvec![];
|
||||
let mut subvisited = SsoHashSet::new();
|
||||
compute_components_recursive(tcx, ty.into(), &mut subcomponents, &mut subvisited);
|
||||
compute_alias_components_recursive(tcx, ty, &mut subcomponents, &mut subvisited);
|
||||
out.push(Component::EscapingAlias(subcomponents.into_iter().collect()));
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +193,43 @@ fn compute_components<'tcx>(
|
|||
///
|
||||
/// This should not be used to get the components of `parent` itself.
|
||||
/// Use [push_outlives_components] instead.
|
||||
pub(super) fn compute_components_recursive<'tcx>(
|
||||
pub(super) fn compute_alias_components_recursive<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
alias_ty: Ty<'tcx>,
|
||||
out: &mut SmallVec<[Component<'tcx>; 4]>,
|
||||
visited: &mut SsoHashSet<GenericArg<'tcx>>,
|
||||
) {
|
||||
let ty::Alias(kind, alias_ty) = alias_ty.kind() else { bug!() };
|
||||
let opt_variances = if *kind == ty::Opaque { tcx.variances_of(alias_ty.def_id) } else { &[] };
|
||||
for (index, child) in alias_ty.substs.iter().enumerate() {
|
||||
if opt_variances.get(index) == Some(&ty::Bivariant) {
|
||||
continue;
|
||||
}
|
||||
if !visited.insert(child) {
|
||||
continue;
|
||||
}
|
||||
match child.unpack() {
|
||||
GenericArgKind::Type(ty) => {
|
||||
compute_components(tcx, ty, out, visited);
|
||||
}
|
||||
GenericArgKind::Lifetime(lt) => {
|
||||
// Ignore late-bound regions.
|
||||
if !lt.is_late_bound() {
|
||||
out.push(Component::Region(lt));
|
||||
}
|
||||
}
|
||||
GenericArgKind::Const(_) => {
|
||||
compute_components_recursive(tcx, child, out, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect [Component]s for *all* the substs of `parent`.
|
||||
///
|
||||
/// This should not be used to get the components of `parent` itself.
|
||||
/// Use [push_outlives_components] instead.
|
||||
fn compute_components_recursive<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
parent: GenericArg<'tcx>,
|
||||
out: &mut SmallVec<[Component<'tcx>; 4]>,
|
||||
|
|
|
@ -344,12 +344,14 @@ 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;
|
||||
if approx_env_bounds.is_empty()
|
||||
&& trait_bounds.is_empty()
|
||||
&& (alias_ty.needs_infer() || alias_ty.kind(self.tcx) == ty::Opaque)
|
||||
&& (alias_ty.needs_infer() || is_opaque)
|
||||
{
|
||||
debug!("no declared bounds");
|
||||
self.substs_must_outlive(alias_ty.substs, origin, region);
|
||||
let opt_variances = is_opaque.then(|| self.tcx.variances_of(alias_ty.def_id));
|
||||
self.substs_must_outlive(alias_ty.substs, origin, region, opt_variances);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -395,22 +397,31 @@ where
|
|||
self.delegate.push_verify(origin, GenericKind::Alias(alias_ty), region, verify_bound);
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn substs_must_outlive(
|
||||
&mut self,
|
||||
substs: SubstsRef<'tcx>,
|
||||
origin: infer::SubregionOrigin<'tcx>,
|
||||
region: ty::Region<'tcx>,
|
||||
opt_variances: Option<&[ty::Variance]>,
|
||||
) {
|
||||
let constraint = origin.to_constraint_category();
|
||||
for k in substs {
|
||||
for (index, k) in substs.iter().enumerate() {
|
||||
match k.unpack() {
|
||||
GenericArgKind::Lifetime(lt) => {
|
||||
self.delegate.push_sub_region_constraint(
|
||||
origin.clone(),
|
||||
region,
|
||||
lt,
|
||||
constraint,
|
||||
);
|
||||
let variance = if let Some(variances) = opt_variances {
|
||||
variances[index]
|
||||
} else {
|
||||
ty::Invariant
|
||||
};
|
||||
if variance == ty::Invariant {
|
||||
self.delegate.push_sub_region_constraint(
|
||||
origin.clone(),
|
||||
region,
|
||||
lt,
|
||||
constraint,
|
||||
);
|
||||
}
|
||||
}
|
||||
GenericArgKind::Type(ty) => {
|
||||
self.type_must_outlive(origin.clone(), ty, region, constraint);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::infer::outlives::components::{compute_components_recursive, Component};
|
||||
use crate::infer::outlives::components::{compute_alias_components_recursive, Component};
|
||||
use crate::infer::outlives::env::RegionBoundPairs;
|
||||
use crate::infer::region_constraints::VerifyIfEq;
|
||||
use crate::infer::VerifyBound;
|
||||
|
@ -130,7 +130,12 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
|
|||
// see the extensive comment in projection_must_outlive
|
||||
let recursive_bound = {
|
||||
let mut components = smallvec![];
|
||||
compute_components_recursive(self.tcx, alias_ty_as_ty.into(), &mut components, visited);
|
||||
compute_alias_components_recursive(
|
||||
self.tcx,
|
||||
alias_ty_as_ty.into(),
|
||||
&mut components,
|
||||
visited,
|
||||
);
|
||||
self.bound_from_components(&components, visited)
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue