Skip to content

Commit 7fde083

Browse files
committed
Auto merge of #110399 - cjgillot:infer-variance, r=aliemjay
Account for opaque variance in outlives Fixes #108591 Fixes #108592 cc `@aliemjay`
2 parents dc73052 + 8fc1d68 commit 7fde083

File tree

5 files changed

+116
-13
lines changed

5 files changed

+116
-13
lines changed

compiler/rustc_infer/src/infer/outlives/components.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ fn compute_components<'tcx>(
143143
// through and constrain Pi.
144144
let mut subcomponents = smallvec![];
145145
let mut subvisited = SsoHashSet::new();
146-
compute_components_recursive(tcx, ty.into(), &mut subcomponents, &mut subvisited);
146+
compute_alias_components_recursive(tcx, ty, &mut subcomponents, &mut subvisited);
147147
out.push(Component::EscapingAlias(subcomponents.into_iter().collect()));
148148
}
149149
}
@@ -193,7 +193,43 @@ fn compute_components<'tcx>(
193193
///
194194
/// This should not be used to get the components of `parent` itself.
195195
/// Use [push_outlives_components] instead.
196-
pub(super) fn compute_components_recursive<'tcx>(
196+
pub(super) fn compute_alias_components_recursive<'tcx>(
197+
tcx: TyCtxt<'tcx>,
198+
alias_ty: Ty<'tcx>,
199+
out: &mut SmallVec<[Component<'tcx>; 4]>,
200+
visited: &mut SsoHashSet<GenericArg<'tcx>>,
201+
) {
202+
let ty::Alias(kind, alias_ty) = alias_ty.kind() else { bug!() };
203+
let opt_variances = if *kind == ty::Opaque { tcx.variances_of(alias_ty.def_id) } else { &[] };
204+
for (index, child) in alias_ty.substs.iter().enumerate() {
205+
if opt_variances.get(index) == Some(&ty::Bivariant) {
206+
continue;
207+
}
208+
if !visited.insert(child) {
209+
continue;
210+
}
211+
match child.unpack() {
212+
GenericArgKind::Type(ty) => {
213+
compute_components(tcx, ty, out, visited);
214+
}
215+
GenericArgKind::Lifetime(lt) => {
216+
// Ignore late-bound regions.
217+
if !lt.is_late_bound() {
218+
out.push(Component::Region(lt));
219+
}
220+
}
221+
GenericArgKind::Const(_) => {
222+
compute_components_recursive(tcx, child, out, visited);
223+
}
224+
}
225+
}
226+
}
227+
228+
/// Collect [Component]s for *all* the substs of `parent`.
229+
///
230+
/// This should not be used to get the components of `parent` itself.
231+
/// Use [push_outlives_components] instead.
232+
fn compute_components_recursive<'tcx>(
197233
tcx: TyCtxt<'tcx>,
198234
parent: GenericArg<'tcx>,
199235
out: &mut SmallVec<[Component<'tcx>; 4]>,

compiler/rustc_infer/src/infer/outlives/obligations.rs

+20-9
Original file line numberDiff line numberDiff line change
@@ -344,12 +344,14 @@ where
344344
// the problem is to add `T: 'r`, which isn't true. So, if there are no
345345
// inference variables, we use a verify constraint instead of adding
346346
// edges, which winds up enforcing the same condition.
347+
let is_opaque = alias_ty.kind(self.tcx) == ty::Opaque;
347348
if approx_env_bounds.is_empty()
348349
&& trait_bounds.is_empty()
349-
&& (alias_ty.needs_infer() || alias_ty.kind(self.tcx) == ty::Opaque)
350+
&& (alias_ty.needs_infer() || is_opaque)
350351
{
351352
debug!("no declared bounds");
352-
self.substs_must_outlive(alias_ty.substs, origin, region);
353+
let opt_variances = is_opaque.then(|| self.tcx.variances_of(alias_ty.def_id));
354+
self.substs_must_outlive(alias_ty.substs, origin, region, opt_variances);
353355
return;
354356
}
355357

@@ -395,22 +397,31 @@ where
395397
self.delegate.push_verify(origin, GenericKind::Alias(alias_ty), region, verify_bound);
396398
}
397399

400+
#[instrument(level = "debug", skip(self))]
398401
fn substs_must_outlive(
399402
&mut self,
400403
substs: SubstsRef<'tcx>,
401404
origin: infer::SubregionOrigin<'tcx>,
402405
region: ty::Region<'tcx>,
406+
opt_variances: Option<&[ty::Variance]>,
403407
) {
404408
let constraint = origin.to_constraint_category();
405-
for k in substs {
409+
for (index, k) in substs.iter().enumerate() {
406410
match k.unpack() {
407411
GenericArgKind::Lifetime(lt) => {
408-
self.delegate.push_sub_region_constraint(
409-
origin.clone(),
410-
region,
411-
lt,
412-
constraint,
413-
);
412+
let variance = if let Some(variances) = opt_variances {
413+
variances[index]
414+
} else {
415+
ty::Invariant
416+
};
417+
if variance == ty::Invariant {
418+
self.delegate.push_sub_region_constraint(
419+
origin.clone(),
420+
region,
421+
lt,
422+
constraint,
423+
);
424+
}
414425
}
415426
GenericArgKind::Type(ty) => {
416427
self.type_must_outlive(origin.clone(), ty, region, constraint);

compiler/rustc_infer/src/infer/outlives/verify.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::infer::outlives::components::{compute_components_recursive, Component};
1+
use crate::infer::outlives::components::{compute_alias_components_recursive, Component};
22
use crate::infer::outlives::env::RegionBoundPairs;
33
use crate::infer::region_constraints::VerifyIfEq;
44
use crate::infer::VerifyBound;
@@ -130,7 +130,12 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
130130
// see the extensive comment in projection_must_outlive
131131
let recursive_bound = {
132132
let mut components = smallvec![];
133-
compute_components_recursive(self.tcx, alias_ty_as_ty.into(), &mut components, visited);
133+
compute_alias_components_recursive(
134+
self.tcx,
135+
alias_ty_as_ty.into(),
136+
&mut components,
137+
visited,
138+
);
134139
self.bound_from_components(&components, visited)
135140
};
136141

tests/ui/impl-trait/issue-108591.rs

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// check-pass
2+
3+
#![feature(type_alias_impl_trait)]
4+
5+
struct MyTy<'a>(Vec<u8>, &'a ());
6+
7+
impl MyTy<'_> {
8+
fn one(&mut self) -> &mut impl Sized {
9+
&mut self.0
10+
}
11+
fn two(&mut self) -> &mut (impl Sized + 'static) {
12+
self.one()
13+
}
14+
}
15+
16+
type Opaque<'a> = impl Sized;
17+
fn define<'a>() -> Opaque<'a> {}
18+
19+
fn test<'a>() {
20+
None::<&'static Opaque<'a>>;
21+
}
22+
23+
fn one<'a, 'b: 'b>() -> &'a impl Sized {
24+
&()
25+
}
26+
fn two<'a, 'b>() {
27+
one::<'a, 'b>();
28+
}
29+
30+
fn main() {}

tests/ui/impl-trait/issue-108592.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// check-pass
2+
#![feature(type_alias_impl_trait)]
3+
4+
fn opaque<'a: 'a>() -> impl Sized {}
5+
fn assert_static<T: 'static>(_: T) {}
6+
7+
fn test_closure() {
8+
let closure = |_| {
9+
assert_static(opaque());
10+
};
11+
closure(&opaque());
12+
}
13+
14+
type Opaque<'a> = impl Sized;
15+
fn define<'a>() -> Opaque<'a> {}
16+
17+
fn test_tait(_: &Opaque<'_>) {
18+
None::<&'static Opaque<'_>>;
19+
}
20+
21+
fn main() {}

0 commit comments

Comments
 (0)