Skip to content

Commit 19423b5

Browse files
committed
Auto merge of #106910 - aliemjay:alias-ty-in-regionck, r=oli-obk
even more unify Projection/Opaque handling in region outlives code edit: This continues ate the same pace as #106829. New changes are described in #106910 (comment). ~This touches `OutlivesBound`, `Component`, `GenericKind` enums.~ r? `@oli-obk` (because of overlap with #95474)
2 parents 79335f1 + e40567b commit 19423b5

File tree

13 files changed

+108
-151
lines changed

13 files changed

+108
-151
lines changed

compiler/rustc_borrowck/src/type_check/free_region_relations.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -359,9 +359,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
359359
.insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a));
360360
}
361361

362-
OutlivesBound::RegionSubAlias(r_a, kind, alias_b) => {
362+
OutlivesBound::RegionSubAlias(r_a, alias_b) => {
363363
self.region_bound_pairs
364-
.insert(ty::OutlivesPredicate(GenericKind::Alias(kind, alias_b), r_a));
364+
.insert(ty::OutlivesPredicate(GenericKind::Alias(alias_b), r_a));
365365
}
366366
}
367367
}

compiler/rustc_hir_analysis/src/outlives/utils.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
8080
.or_insert(span);
8181
}
8282

83-
Component::Alias(kind, alias) => {
83+
Component::Alias(alias_ty) => {
8484
// This would either arise from something like:
8585
//
8686
// ```
@@ -99,13 +99,13 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
9999
//
100100
// Here we want to add an explicit `where <T as Iterator>::Item: 'a`
101101
// or `Opaque<T>: 'a` depending on the alias kind.
102-
let ty: Ty<'tcx> = tcx.mk_ty(ty::Alias(kind, alias));
102+
let ty = alias_ty.to_ty(tcx);
103103
required_predicates
104104
.entry(ty::OutlivesPredicate(ty.into(), outlived_region))
105105
.or_insert(span);
106106
}
107107

108-
Component::EscapingProjection(_) => {
108+
Component::EscapingAlias(_) => {
109109
// As above, but the projection involves
110110
// late-bound regions. Therefore, the WF
111111
// requirement is not checked in type definition

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -2272,13 +2272,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
22722272

22732273
let labeled_user_string = match bound_kind {
22742274
GenericKind::Param(ref p) => format!("the parameter type `{}`", p),
2275-
GenericKind::Alias(ty::Projection, ref p) => format!("the associated type `{}`", p),
2276-
GenericKind::Alias(ty::Opaque, ref p) => {
2277-
format!(
2278-
"the opaque type `{}`",
2279-
self.tcx.def_path_str_with_substs(p.def_id, p.substs)
2280-
)
2281-
}
2275+
GenericKind::Alias(ref p) => match p.kind(self.tcx) {
2276+
ty::AliasKind::Projection => format!("the associated type `{}`", p),
2277+
ty::AliasKind::Opaque => format!("the opaque type `{}`", p),
2278+
},
22822279
};
22832280

22842281
if let Some(SubregionOrigin::CompareImplItemObligation {

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

+6-17
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub enum Component<'tcx> {
2222
// is not in a position to judge which is the best technique, so
2323
// we just product the projection as a component and leave it to
2424
// the consumer to decide (but see `EscapingProjection` below).
25-
Alias(ty::AliasKind, ty::AliasTy<'tcx>),
25+
Alias(ty::AliasTy<'tcx>),
2626

2727
// In the case where a projection has escaping regions -- meaning
2828
// regions bound within the type itself -- we always use
@@ -44,7 +44,7 @@ pub enum Component<'tcx> {
4444
// projection, so that implied bounds code can avoid relying on
4545
// them. This gives us room to improve the regionck reasoning in
4646
// the future without breaking backwards compat.
47-
EscapingProjection(Vec<Component<'tcx>>),
47+
EscapingAlias(Vec<Component<'tcx>>),
4848
}
4949

5050
/// Push onto `out` all the things that must outlive `'a` for the condition
@@ -120,17 +120,6 @@ fn compute_components<'tcx>(
120120
out.push(Component::Param(p));
121121
}
122122

123-
// Ignore lifetimes found in opaque types. Opaque types can
124-
// have lifetimes in their substs which their hidden type doesn't
125-
// actually use. If we inferred that an opaque type is outlived by
126-
// its parameter lifetimes, then we could prove that any lifetime
127-
// outlives any other lifetime, which is unsound.
128-
// See https://github.com/rust-lang/rust/issues/84305 for
129-
// more details.
130-
ty::Alias(ty::Opaque, data) => {
131-
out.push(Component::Alias(ty::Opaque, data));
132-
},
133-
134123
// For projections, we prefer to generate an obligation like
135124
// `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
136125
// regionck more ways to prove that it holds. However,
@@ -139,23 +128,23 @@ fn compute_components<'tcx>(
139128
// trait-ref. Therefore, if we see any higher-ranked regions,
140129
// we simply fallback to the most restrictive rule, which
141130
// requires that `Pi: 'a` for all `i`.
142-
ty::Alias(ty::Projection, data) => {
143-
if !data.has_escaping_bound_vars() {
131+
ty::Alias(_, alias_ty) => {
132+
if !alias_ty.has_escaping_bound_vars() {
144133
// best case: no escaping regions, so push the
145134
// projection and skip the subtree (thus generating no
146135
// constraints for Pi). This defers the choice between
147136
// the rules OutlivesProjectionEnv,
148137
// OutlivesProjectionTraitDef, and
149138
// OutlivesProjectionComponents to regionck.
150-
out.push(Component::Alias(ty::Projection, data));
139+
out.push(Component::Alias(alias_ty));
151140
} else {
152141
// fallback case: hard code
153142
// OutlivesProjectionComponents. Continue walking
154143
// through and constrain Pi.
155144
let mut subcomponents = smallvec![];
156145
let mut subvisited = SsoHashSet::new();
157146
compute_components_recursive(tcx, ty.into(), &mut subcomponents, &mut subvisited);
158-
out.push(Component::EscapingProjection(subcomponents.into_iter().collect()));
147+
out.push(Component::EscapingAlias(subcomponents.into_iter().collect()));
159148
}
160149
}
161150

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ impl<'tcx> OutlivesEnvironmentBuilder<'tcx> {
138138
self.region_bound_pairs
139139
.insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a));
140140
}
141-
OutlivesBound::RegionSubAlias(r_a, kind, projection_b) => {
141+
OutlivesBound::RegionSubAlias(r_a, alias_b) => {
142142
self.region_bound_pairs
143-
.insert(ty::OutlivesPredicate(GenericKind::Alias(kind, projection_b), r_a));
143+
.insert(ty::OutlivesPredicate(GenericKind::Alias(alias_b), r_a));
144144
}
145145
OutlivesBound::RegionSubRegion(r_a, r_b) => {
146146
if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) {

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

+19-62
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ use crate::infer::{
6767
};
6868
use crate::traits::{ObligationCause, ObligationCauseCode};
6969
use rustc_data_structures::undo_log::UndoLogs;
70-
use rustc_hir::def_id::DefId;
7170
use rustc_middle::mir::ConstraintCategory;
7271
use rustc_middle::ty::subst::GenericArgKind;
7372
use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitable};
@@ -266,10 +265,8 @@ where
266265
Component::Param(param_ty) => {
267266
self.param_ty_must_outlive(origin, region, *param_ty);
268267
}
269-
Component::Alias(kind, data) => {
270-
self.alias_must_outlive(*kind, *data, origin, region)
271-
}
272-
Component::EscapingProjection(subcomponents) => {
268+
Component::Alias(alias_ty) => self.alias_ty_must_outlive(origin, region, *alias_ty),
269+
Component::EscapingAlias(subcomponents) => {
273270
self.components_must_outlive(origin, &subcomponents, region, category);
274271
}
275272
Component::UnresolvedInferenceVariable(v) => {
@@ -285,61 +282,26 @@ where
285282
}
286283
}
287284

285+
#[instrument(level = "debug", skip(self))]
288286
fn param_ty_must_outlive(
289287
&mut self,
290288
origin: infer::SubregionOrigin<'tcx>,
291289
region: ty::Region<'tcx>,
292290
param_ty: ty::ParamTy,
293291
) {
294-
debug!(
295-
"param_ty_must_outlive(region={:?}, param_ty={:?}, origin={:?})",
296-
region, param_ty, origin
297-
);
298-
299-
let generic = GenericKind::Param(param_ty);
300292
let verify_bound = self.verify_bound.param_bound(param_ty);
301-
self.delegate.push_verify(origin, generic, region, verify_bound);
293+
self.delegate.push_verify(origin, GenericKind::Param(param_ty), region, verify_bound);
302294
}
303295

304296
#[instrument(level = "debug", skip(self))]
305-
fn alias_must_outlive(
297+
fn alias_ty_must_outlive(
306298
&mut self,
307-
kind: ty::AliasKind,
308-
data: ty::AliasTy<'tcx>,
309299
origin: infer::SubregionOrigin<'tcx>,
310300
region: ty::Region<'tcx>,
311-
) {
312-
self.generic_must_outlive(
313-
origin,
314-
region,
315-
GenericKind::Alias(kind, data),
316-
data.def_id,
317-
data.substs,
318-
kind == ty::Opaque,
319-
|ty| match *ty.kind() {
320-
ty::Alias(filter_kind, ty::AliasTy { def_id, substs, .. })
321-
if kind == filter_kind =>
322-
{
323-
(def_id, substs)
324-
}
325-
_ => bug!("expected only projection types from env, not {:?}", ty),
326-
},
327-
);
328-
}
329-
330-
#[instrument(level = "debug", skip(self, filter))]
331-
fn generic_must_outlive(
332-
&mut self,
333-
origin: infer::SubregionOrigin<'tcx>,
334-
region: ty::Region<'tcx>,
335-
generic: GenericKind<'tcx>,
336-
def_id: DefId,
337-
substs: SubstsRef<'tcx>,
338-
is_opaque: bool,
339-
filter: impl Fn(Ty<'tcx>) -> (DefId, SubstsRef<'tcx>),
301+
alias_ty: ty::AliasTy<'tcx>,
340302
) {
341303
// An optimization for a common case with opaque types.
342-
if substs.is_empty() {
304+
if alias_ty.substs.is_empty() {
343305
return;
344306
}
345307

@@ -361,14 +323,14 @@ where
361323
// These are guaranteed to apply, no matter the inference
362324
// results.
363325
let trait_bounds: Vec<_> =
364-
self.verify_bound.declared_region_bounds(def_id, substs).collect();
326+
self.verify_bound.declared_bounds_from_definition(alias_ty).collect();
365327

366328
debug!(?trait_bounds);
367329

368330
// Compute the bounds we can derive from the environment. This
369331
// is an "approximate" match -- in some cases, these bounds
370332
// may not apply.
371-
let mut approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(generic);
333+
let mut approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(alias_ty);
372334
debug!(?approx_env_bounds);
373335

374336
// Remove outlives bounds that we get from the environment but
@@ -383,8 +345,8 @@ where
383345
// If the declaration is `trait Trait<'b> { type Item: 'b; }`, then `projection_declared_bounds_from_trait`
384346
// will be invoked with `['b => ^1]` and so we will get `^1` returned.
385347
let bound = bound_outlives.skip_binder();
386-
let (def_id, substs) = filter(bound.0);
387-
self.verify_bound.declared_region_bounds(def_id, substs).all(|r| r != bound.1)
348+
let ty::Alias(_, alias_ty) = bound.0.kind() else { bug!("expected AliasTy") };
349+
self.verify_bound.declared_bounds_from_definition(*alias_ty).all(|r| r != bound.1)
388350
});
389351

390352
// If declared bounds list is empty, the only applicable rule is
@@ -401,12 +363,12 @@ where
401363
// the problem is to add `T: 'r`, which isn't true. So, if there are no
402364
// inference variables, we use a verify constraint instead of adding
403365
// edges, which winds up enforcing the same condition.
404-
let needs_infer = substs.needs_infer();
405-
if approx_env_bounds.is_empty() && trait_bounds.is_empty() && (needs_infer || is_opaque) {
366+
if approx_env_bounds.is_empty()
367+
&& trait_bounds.is_empty()
368+
&& (alias_ty.needs_infer() || alias_ty.kind(self.tcx) == ty::Opaque)
369+
{
406370
debug!("no declared bounds");
407-
408-
self.substs_must_outlive(substs, origin, region);
409-
371+
self.substs_must_outlive(alias_ty.substs, origin, region);
410372
return;
411373
}
412374

@@ -447,14 +409,9 @@ where
447409
// projection outlive; in some cases, this may add insufficient
448410
// edges into the inference graph, leading to inference failures
449411
// even though a satisfactory solution exists.
450-
let verify_bound = self.verify_bound.projection_opaque_bounds(
451-
generic,
452-
def_id,
453-
substs,
454-
&mut Default::default(),
455-
);
456-
debug!("projection_must_outlive: pushing {:?}", verify_bound);
457-
self.delegate.push_verify(origin, generic, region, verify_bound);
412+
let verify_bound = self.verify_bound.alias_bound(alias_ty, &mut Default::default());
413+
debug!("alias_must_outlive: pushing {:?}", verify_bound);
414+
self.delegate.push_verify(origin, GenericKind::Alias(alias_ty), region, verify_bound);
458415
}
459416

460417
fn substs_must_outlive(

0 commit comments

Comments
 (0)