Skip to content

Commit 7062c4e

Browse files
Add opt_alias_variances and use it in outlives code
1 parent 7b31983 commit 7062c4e

File tree

11 files changed

+100
-36
lines changed

11 files changed

+100
-36
lines changed

compiler/rustc_borrowck/src/type_check/opaque_types.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ where
284284
return;
285285
}
286286

287-
match ty.kind() {
287+
match *ty.kind() {
288288
ty::Closure(_, args) => {
289289
// Skip lifetime parameters of the enclosing item(s)
290290

@@ -316,10 +316,9 @@ where
316316
args.as_coroutine().resume_ty().visit_with(self);
317317
}
318318

319-
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
320-
// Skip lifetime parameters that are not captures.
321-
let variances = self.tcx.variances_of(*def_id);
322-
319+
ty::Alias(kind, ty::AliasTy { def_id, args, .. })
320+
if let Some(variances) = self.tcx.opt_alias_variances(kind, def_id) =>
321+
{
323322
for (v, s) in std::iter::zip(variances, args.iter()) {
324323
if *v != ty::Bivariant {
325324
s.visit_with(self);

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

+2-5
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ where
4848
return ty.super_visit_with(self);
4949
}
5050

51-
match ty.kind() {
51+
match *ty.kind() {
5252
// We can prove that an alias is live two ways:
5353
// 1. All the components are live.
5454
//
@@ -96,10 +96,7 @@ where
9696
r.visit_with(self);
9797
} else {
9898
// Skip lifetime parameters that are not captures.
99-
let variances = match kind {
100-
ty::Opaque => Some(self.tcx.variances_of(*def_id)),
101-
_ => None,
102-
};
99+
let variances = tcx.opt_alias_variances(kind, def_id);
103100

104101
for (idx, s) in args.iter().enumerate() {
105102
if variances.map(|variances| variances[idx]) != Some(ty::Bivariant) {

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

+6-3
Original file line numberDiff line numberDiff line change
@@ -392,13 +392,16 @@ where
392392
// the problem is to add `T: 'r`, which isn't true. So, if there are no
393393
// inference variables, we use a verify constraint instead of adding
394394
// edges, which winds up enforcing the same condition.
395-
let is_opaque = alias_ty.kind(self.tcx) == ty::Opaque;
395+
//
396+
// Note that this is not here for correctness; it solely affects
397+
// diagnostics.
398+
let kind = alias_ty.kind(self.tcx);
396399
if approx_env_bounds.is_empty()
397400
&& trait_bounds.is_empty()
398-
&& (alias_ty.has_infer_regions() || is_opaque)
401+
&& (alias_ty.has_infer_regions() || kind == ty::Opaque)
399402
{
400403
debug!("no declared bounds");
401-
let opt_variances = is_opaque.then(|| self.tcx.variances_of(alias_ty.def_id));
404+
let opt_variances = self.tcx.opt_alias_variances(kind, alias_ty.def_id);
402405
self.args_must_outlive(alias_ty.args, origin, region, opt_variances);
403406
return;
404407
}

compiler/rustc_middle/src/ty/context.rs

+8
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,14 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
194194
self.variances_of(def_id)
195195
}
196196

197+
fn opt_alias_variances(
198+
self,
199+
kind: impl Into<ty::AliasTermKind>,
200+
def_id: DefId,
201+
) -> Option<&'tcx [ty::Variance]> {
202+
self.opt_alias_variances(kind, def_id)
203+
}
204+
197205
fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
198206
self.type_of(def_id)
199207
}

compiler/rustc_middle/src/ty/util.rs

+23
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,29 @@ impl<'tcx> TyCtxt<'tcx> {
951951

952952
ty
953953
}
954+
955+
// Computes the variances for an alias (opaque or RPITIT) that represent
956+
// its (un)captured regions.
957+
pub fn opt_alias_variances(
958+
self,
959+
kind: impl Into<ty::AliasTermKind>,
960+
def_id: DefId,
961+
) -> Option<&'tcx [ty::Variance]> {
962+
match kind.into() {
963+
ty::AliasTermKind::ProjectionTy => {
964+
if self.is_impl_trait_in_trait(def_id) {
965+
Some(self.variances_of(def_id))
966+
} else {
967+
None
968+
}
969+
}
970+
ty::AliasTermKind::OpaqueTy => Some(self.variances_of(def_id)),
971+
ty::AliasTermKind::InherentTy
972+
| ty::AliasTermKind::WeakTy
973+
| ty::AliasTermKind::UnevaluatedConst
974+
| ty::AliasTermKind::ProjectionConst => None,
975+
}
976+
}
954977
}
955978

956979
struct OpaqueTypeExpander<'tcx> {

compiler/rustc_type_ir/src/interner.rs

+6
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,12 @@ pub trait Interner:
141141
type VariancesOf: Copy + Debug + SliceLike<Item = ty::Variance>;
142142
fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf;
143143

144+
fn opt_alias_variances(
145+
self,
146+
kind: impl Into<ty::AliasTermKind>,
147+
def_id: Self::DefId,
148+
) -> Option<Self::VariancesOf>;
149+
144150
fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder<Self, Self::Ty>;
145151

146152
type AdtDef: AdtDef<Self>;

compiler/rustc_type_ir/src/outlives.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,7 @@ pub fn compute_alias_components_recursive<I: Interner>(
230230
unreachable!("can only call `compute_alias_components_recursive` on an alias type")
231231
};
232232

233-
let opt_variances =
234-
if kind == ty::Opaque { Some(cx.variances_of(alias_ty.def_id)) } else { None };
233+
let opt_variances = cx.opt_alias_variances(kind, alias_ty.def_id);
235234

236235
let mut visitor = OutlivesCollector { cx, out, visited: Default::default() };
237236

compiler/rustc_type_ir/src/predicate.rs

+11
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,17 @@ impl AliasTermKind {
469469
}
470470
}
471471

472+
impl From<ty::AliasTyKind> for AliasTermKind {
473+
fn from(value: ty::AliasTyKind) -> Self {
474+
match value {
475+
ty::Projection => AliasTermKind::ProjectionTy,
476+
ty::Opaque => AliasTermKind::OpaqueTy,
477+
ty::Weak => AliasTermKind::WeakTy,
478+
ty::Inherent => AliasTermKind::InherentTy,
479+
}
480+
}
481+
}
482+
472483
/// Represents the unprojected term of a projection goal.
473484
///
474485
/// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.

compiler/rustc_type_ir/src/relate.rs

+7-21
Original file line numberDiff line numberDiff line change
@@ -236,28 +236,14 @@ impl<I: Interner> Relate<I> for ty::AliasTy<I> {
236236
ExpectedFound::new(a, b)
237237
}))
238238
} else {
239-
let args = match a.kind(relation.cx()) {
240-
ty::Opaque => relate_args_with_variances(
241-
relation,
242-
a.def_id,
243-
relation.cx().variances_of(a.def_id),
244-
a.args,
245-
b.args,
239+
let cx = relation.cx();
240+
let args = if let Some(variances) = cx.opt_alias_variances(a.kind(cx), a.def_id) {
241+
relate_args_with_variances(
242+
relation, a.def_id, variances, a.args, b.args,
246243
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
247-
)?,
248-
ty::Projection if relation.cx().is_impl_trait_in_trait(a.def_id) => {
249-
relate_args_with_variances(
250-
relation,
251-
a.def_id,
252-
relation.cx().variances_of(a.def_id),
253-
a.args,
254-
b.args,
255-
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
256-
)?
257-
}
258-
ty::Projection | ty::Weak | ty::Inherent => {
259-
relate_args_invariantly(relation, a.args, b.args)?
260-
}
244+
)?
245+
} else {
246+
relate_args_invariantly(relation, a.args, b.args)?
261247
};
262248
Ok(ty::AliasTy::new_from_args(relation.cx(), a.def_id, args))
263249
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//@ check-pass
2+
3+
#![feature(precise_capturing_in_traits)]
4+
5+
struct Invariant<T>(*mut T);
6+
7+
trait Foo {
8+
fn hello<'s: 's>(&'s self) -> Invariant<impl Sized + use<Self>>;
9+
}
10+
11+
fn outlives_static(_: impl Sized + 'static) {}
12+
13+
fn hello<'s, T: Foo + 'static>(x: &'s T) {
14+
outlives_static(x.hello());
15+
}
16+
17+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ check-pass
2+
3+
#![feature(precise_capturing_in_traits)]
4+
5+
struct Invariant<T>(*mut T);
6+
7+
trait Foo {
8+
fn hello<'s: 's>(&'s self) -> Invariant<impl Sized + use<Self>>;
9+
}
10+
11+
fn hello<'s, T: Foo + 'static>(x: &'s T) -> Invariant<impl Sized + 'static> {
12+
x.hello()
13+
}
14+
15+
fn main() {}

0 commit comments

Comments
 (0)