Skip to content

Commit f5193a9

Browse files
committedSep 25, 2022
Auto merge of #95474 - oli-obk:tait_ub, r=jackh726
Neither require nor imply lifetime bounds on opaque type for well formedness The actual hidden type can live arbitrarily longer than any individual lifetime and arbitrarily shorter than all but one of the lifetimes. fixes #86218 fixes #84305 This is a **breaking change** but it is a necessary soundness fix
2 parents f3fafbb + 59e285f commit f5193a9

34 files changed

+697
-154
lines changed
 

‎compiler/rustc_borrowck/src/type_check/free_region_relations.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,11 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
362362
self.region_bound_pairs
363363
.insert(ty::OutlivesPredicate(GenericKind::Projection(projection_b), r_a));
364364
}
365+
366+
OutlivesBound::RegionSubOpaque(r_a, def_id, substs) => {
367+
self.region_bound_pairs
368+
.insert(ty::OutlivesPredicate(GenericKind::Opaque(def_id, substs), r_a));
369+
}
365370
}
366371
}
367372
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2481,6 +2481,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
24812481
let labeled_user_string = match bound_kind {
24822482
GenericKind::Param(ref p) => format!("the parameter type `{}`", p),
24832483
GenericKind::Projection(ref p) => format!("the associated type `{}`", p),
2484+
GenericKind::Opaque(def_id, substs) => {
2485+
format!("the opaque type `{}`", self.tcx.def_path_str_with_substs(def_id, substs))
2486+
}
24842487
};
24852488

24862489
if let Some(SubregionOrigin::CompareImplItemObligation {

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
// RFC for reference.
44

55
use rustc_data_structures::sso::SsoHashSet;
6+
use rustc_hir::def_id::DefId;
67
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
7-
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
8+
use rustc_middle::ty::{self, SubstsRef, Ty, TyCtxt, TypeVisitable};
89
use smallvec::{smallvec, SmallVec};
910

1011
#[derive(Debug)]
@@ -45,6 +46,8 @@ pub enum Component<'tcx> {
4546
// them. This gives us room to improve the regionck reasoning in
4647
// the future without breaking backwards compat.
4748
EscapingProjection(Vec<Component<'tcx>>),
49+
50+
Opaque(DefId, SubstsRef<'tcx>),
4851
}
4952

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

126+
// Ignore lifetimes found in opaque types. Opaque types can
127+
// have lifetimes in their substs which their hidden type doesn't
128+
// actually use. If we inferred that an opaque type is outlived by
129+
// its parameter lifetimes, then we could prove that any lifetime
130+
// outlives any other lifetime, which is unsound.
131+
// See https://github.com/rust-lang/rust/issues/84305 for
132+
// more details.
133+
ty::Opaque(def_id, substs) => {
134+
out.push(Component::Opaque(def_id, substs));
135+
},
136+
123137
// For projections, we prefer to generate an obligation like
124138
// `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
125139
// regionck more ways to prove that it holds. However,
@@ -168,7 +182,6 @@ fn compute_components<'tcx>(
168182
ty::Float(..) | // OutlivesScalar
169183
ty::Never | // ...
170184
ty::Adt(..) | // OutlivesNominalType
171-
ty::Opaque(..) | // OutlivesNominalType (ish)
172185
ty::Foreign(..) | // OutlivesNominalType
173186
ty::Str | // OutlivesScalar (ish)
174187
ty::Slice(..) | // ...

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> {
142142
self.region_bound_pairs
143143
.insert(ty::OutlivesPredicate(GenericKind::Projection(projection_b), r_a));
144144
}
145+
OutlivesBound::RegionSubOpaque(r_a, def_id, substs) => {
146+
self.region_bound_pairs
147+
.insert(ty::OutlivesPredicate(GenericKind::Opaque(def_id, substs), r_a));
148+
}
145149
OutlivesBound::RegionSubRegion(r_a, r_b) => {
146150
if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) {
147151
infcx

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

Lines changed: 103 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,11 @@ use crate::infer::{
6868
};
6969
use crate::traits::{ObligationCause, ObligationCauseCode};
7070
use rustc_data_structures::undo_log::UndoLogs;
71+
use rustc_hir::def_id::DefId;
7172
use rustc_hir::def_id::LocalDefId;
7273
use rustc_middle::mir::ConstraintCategory;
7374
use rustc_middle::ty::subst::GenericArgKind;
74-
use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeVisitable};
75+
use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitable};
7576
use smallvec::smallvec;
7677

7778
impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
@@ -283,6 +284,9 @@ where
283284
Component::Param(param_ty) => {
284285
self.param_ty_must_outlive(origin, region, *param_ty);
285286
}
287+
Component::Opaque(def_id, substs) => {
288+
self.opaque_must_outlive(*def_id, substs, origin, region)
289+
}
286290
Component::Projection(projection_ty) => {
287291
self.projection_must_outlive(origin, region, *projection_ty);
288292
}
@@ -314,17 +318,69 @@ where
314318
);
315319

316320
let generic = GenericKind::Param(param_ty);
317-
let verify_bound = self.verify_bound.generic_bound(generic);
321+
let verify_bound = self.verify_bound.param_bound(param_ty);
318322
self.delegate.push_verify(origin, generic, region, verify_bound);
319323
}
320324

325+
#[instrument(level = "debug", skip(self))]
326+
fn opaque_must_outlive(
327+
&mut self,
328+
def_id: DefId,
329+
substs: SubstsRef<'tcx>,
330+
origin: infer::SubregionOrigin<'tcx>,
331+
region: ty::Region<'tcx>,
332+
) {
333+
self.generic_must_outlive(
334+
origin,
335+
region,
336+
GenericKind::Opaque(def_id, substs),
337+
def_id,
338+
substs,
339+
true,
340+
|ty| match *ty.kind() {
341+
ty::Opaque(def_id, substs) => (def_id, substs),
342+
_ => bug!("expected only projection types from env, not {:?}", ty),
343+
},
344+
);
345+
}
346+
321347
#[instrument(level = "debug", skip(self))]
322348
fn projection_must_outlive(
323349
&mut self,
324350
origin: infer::SubregionOrigin<'tcx>,
325351
region: ty::Region<'tcx>,
326352
projection_ty: ty::ProjectionTy<'tcx>,
327353
) {
354+
self.generic_must_outlive(
355+
origin,
356+
region,
357+
GenericKind::Projection(projection_ty),
358+
projection_ty.item_def_id,
359+
projection_ty.substs,
360+
false,
361+
|ty| match ty.kind() {
362+
ty::Projection(projection_ty) => (projection_ty.item_def_id, projection_ty.substs),
363+
_ => bug!("expected only projection types from env, not {:?}", ty),
364+
},
365+
);
366+
}
367+
368+
#[instrument(level = "debug", skip(self, filter))]
369+
fn generic_must_outlive(
370+
&mut self,
371+
origin: infer::SubregionOrigin<'tcx>,
372+
region: ty::Region<'tcx>,
373+
generic: GenericKind<'tcx>,
374+
def_id: DefId,
375+
substs: SubstsRef<'tcx>,
376+
is_opaque: bool,
377+
filter: impl Fn(Ty<'tcx>) -> (DefId, SubstsRef<'tcx>),
378+
) {
379+
// An optimization for a common case with opaque types.
380+
if substs.is_empty() {
381+
return;
382+
}
383+
328384
// This case is thorny for inference. The fundamental problem is
329385
// that there are many cases where we have choice, and inference
330386
// doesn't like choice (the current region inference in
@@ -343,16 +399,15 @@ where
343399
// These are guaranteed to apply, no matter the inference
344400
// results.
345401
let trait_bounds: Vec<_> =
346-
self.verify_bound.projection_declared_bounds_from_trait(projection_ty).collect();
402+
self.verify_bound.declared_region_bounds(def_id, substs).collect();
347403

348404
debug!(?trait_bounds);
349405

350406
// Compute the bounds we can derive from the environment. This
351407
// is an "approximate" match -- in some cases, these bounds
352408
// may not apply.
353-
let mut approx_env_bounds =
354-
self.verify_bound.projection_approx_declared_bounds_from_env(projection_ty);
355-
debug!("projection_must_outlive: approx_env_bounds={:?}", approx_env_bounds);
409+
let mut approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(generic);
410+
debug!(?approx_env_bounds);
356411

357412
// Remove outlives bounds that we get from the environment but
358413
// which are also deducible from the trait. This arises (cc
@@ -366,14 +421,8 @@ where
366421
// If the declaration is `trait Trait<'b> { type Item: 'b; }`, then `projection_declared_bounds_from_trait`
367422
// will be invoked with `['b => ^1]` and so we will get `^1` returned.
368423
let bound = bound_outlives.skip_binder();
369-
match *bound.0.kind() {
370-
ty::Projection(projection_ty) => self
371-
.verify_bound
372-
.projection_declared_bounds_from_trait(projection_ty)
373-
.all(|r| r != bound.1),
374-
375-
_ => panic!("expected only projection types from env, not {:?}", bound.0),
376-
}
424+
let (def_id, substs) = filter(bound.0);
425+
self.verify_bound.declared_region_bounds(def_id, substs).all(|r| r != bound.1)
377426
});
378427

379428
// If declared bounds list is empty, the only applicable rule is
@@ -390,29 +439,11 @@ where
390439
// the problem is to add `T: 'r`, which isn't true. So, if there are no
391440
// inference variables, we use a verify constraint instead of adding
392441
// edges, which winds up enforcing the same condition.
393-
let needs_infer = projection_ty.needs_infer();
394-
if approx_env_bounds.is_empty() && trait_bounds.is_empty() && needs_infer {
395-
debug!("projection_must_outlive: no declared bounds");
396-
397-
let constraint = origin.to_constraint_category();
398-
for k in projection_ty.substs {
399-
match k.unpack() {
400-
GenericArgKind::Lifetime(lt) => {
401-
self.delegate.push_sub_region_constraint(
402-
origin.clone(),
403-
region,
404-
lt,
405-
constraint,
406-
);
407-
}
408-
GenericArgKind::Type(ty) => {
409-
self.type_must_outlive(origin.clone(), ty, region, constraint);
410-
}
411-
GenericArgKind::Const(_) => {
412-
// Const parameters don't impose constraints.
413-
}
414-
}
415-
}
442+
let needs_infer = substs.needs_infer();
443+
if approx_env_bounds.is_empty() && trait_bounds.is_empty() && (needs_infer || is_opaque) {
444+
debug!("no declared bounds");
445+
446+
self.substs_must_outlive(substs, origin, region);
416447

417448
return;
418449
}
@@ -442,8 +473,8 @@ where
442473
.all(|b| b == Some(trait_bounds[0]))
443474
{
444475
let unique_bound = trait_bounds[0];
445-
debug!("projection_must_outlive: unique trait bound = {:?}", unique_bound);
446-
debug!("projection_must_outlive: unique declared bound appears in trait ref");
476+
debug!(?unique_bound);
477+
debug!("unique declared bound appears in trait ref");
447478
let category = origin.to_constraint_category();
448479
self.delegate.push_sub_region_constraint(origin, region, unique_bound, category);
449480
return;
@@ -454,11 +485,42 @@ where
454485
// projection outlive; in some cases, this may add insufficient
455486
// edges into the inference graph, leading to inference failures
456487
// even though a satisfactory solution exists.
457-
let generic = GenericKind::Projection(projection_ty);
458-
let verify_bound = self.verify_bound.generic_bound(generic);
488+
let verify_bound = self.verify_bound.projection_opaque_bounds(
489+
generic,
490+
def_id,
491+
substs,
492+
&mut Default::default(),
493+
);
459494
debug!("projection_must_outlive: pushing {:?}", verify_bound);
460495
self.delegate.push_verify(origin, generic, region, verify_bound);
461496
}
497+
498+
fn substs_must_outlive(
499+
&mut self,
500+
substs: SubstsRef<'tcx>,
501+
origin: infer::SubregionOrigin<'tcx>,
502+
region: ty::Region<'tcx>,
503+
) {
504+
let constraint = origin.to_constraint_category();
505+
for k in substs {
506+
match k.unpack() {
507+
GenericArgKind::Lifetime(lt) => {
508+
self.delegate.push_sub_region_constraint(
509+
origin.clone(),
510+
region,
511+
lt,
512+
constraint,
513+
);
514+
}
515+
GenericArgKind::Type(ty) => {
516+
self.type_must_outlive(origin.clone(), ty, region, constraint);
517+
}
518+
GenericArgKind::Const(_) => {
519+
// Const parameters don't impose constraints.
520+
}
521+
}
522+
}
523+
}
462524
}
463525

464526
impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'cx, 'tcx> {

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

Lines changed: 37 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@ use crate::infer::outlives::components::{compute_components_recursive, Component
22
use crate::infer::outlives::env::RegionBoundPairs;
33
use crate::infer::region_constraints::VerifyIfEq;
44
use crate::infer::{GenericKind, VerifyBound};
5-
use rustc_data_structures::captures::Captures;
65
use rustc_data_structures::sso::SsoHashSet;
76
use rustc_hir::def_id::DefId;
87
use rustc_middle::ty::GenericArg;
9-
use rustc_middle::ty::{self, EarlyBinder, OutlivesPredicate, Ty, TyCtxt};
8+
use rustc_middle::ty::{self, EarlyBinder, OutlivesPredicate, SubstsRef, Ty, TyCtxt};
109

1110
use smallvec::smallvec;
1211

@@ -38,20 +37,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
3837
Self { tcx, region_bound_pairs, implicit_region_bound, param_env }
3938
}
4039

41-
/// Returns a "verify bound" that encodes what we know about
42-
/// `generic` and the regions it outlives.
43-
pub fn generic_bound(&self, generic: GenericKind<'tcx>) -> VerifyBound<'tcx> {
44-
let mut visited = SsoHashSet::new();
45-
match generic {
46-
GenericKind::Param(param_ty) => self.param_bound(param_ty),
47-
GenericKind::Projection(projection_ty) => {
48-
self.projection_bound(projection_ty, &mut visited)
49-
}
50-
}
51-
}
52-
5340
#[instrument(level = "debug", skip(self))]
54-
fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
41+
pub fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
5542
// Start with anything like `T: 'a` we can scrape from the
5643
// environment. If the environment contains something like
5744
// `for<'a> T: 'a`, then we know that `T` outlives everything.
@@ -105,41 +92,31 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
10592
/// the clause from the environment only applies if `'0 = 'a`,
10693
/// which we don't know yet. But we would still include `'b` in
10794
/// this list.
108-
pub fn projection_approx_declared_bounds_from_env(
95+
pub fn approx_declared_bounds_from_env(
10996
&self,
110-
projection_ty: ty::ProjectionTy<'tcx>,
97+
generic: GenericKind<'tcx>,
11198
) -> Vec<ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>> {
112-
let projection_ty = GenericKind::Projection(projection_ty).to_ty(self.tcx);
99+
let projection_ty = generic.to_ty(self.tcx);
113100
let erased_projection_ty = self.tcx.erase_regions(projection_ty);
114101
self.declared_generic_bounds_from_env_for_erased_ty(erased_projection_ty)
115102
}
116103

117-
/// Searches the where-clauses in scope for regions that
118-
/// `projection_ty` is known to outlive. Currently requires an
119-
/// exact match.
120-
pub fn projection_declared_bounds_from_trait(
104+
#[instrument(level = "debug", skip(self, visited))]
105+
pub fn projection_opaque_bounds(
121106
&self,
122-
projection_ty: ty::ProjectionTy<'tcx>,
123-
) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> {
124-
self.declared_projection_bounds_from_trait(projection_ty)
125-
}
126-
127-
pub fn projection_bound(
128-
&self,
129-
projection_ty: ty::ProjectionTy<'tcx>,
107+
generic: GenericKind<'tcx>,
108+
def_id: DefId,
109+
substs: SubstsRef<'tcx>,
130110
visited: &mut SsoHashSet<GenericArg<'tcx>>,
131111
) -> VerifyBound<'tcx> {
132-
debug!("projection_bound(projection_ty={:?})", projection_ty);
133-
134-
let projection_ty_as_ty =
135-
self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs);
112+
let generic_ty = generic.to_ty(self.tcx);
136113

137114
// Search the env for where clauses like `P: 'a`.
138-
let env_bounds = self
139-
.projection_approx_declared_bounds_from_env(projection_ty)
115+
let projection_opaque_bounds = self
116+
.approx_declared_bounds_from_env(generic)
140117
.into_iter()
141118
.map(|binder| {
142-
if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == projection_ty_as_ty {
119+
if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == generic_ty {
143120
// Micro-optimize if this is an exact match (this
144121
// occurs often when there are no region variables
145122
// involved).
@@ -149,21 +126,19 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
149126
VerifyBound::IfEq(verify_if_eq_b)
150127
}
151128
});
152-
153129
// Extend with bounds that we can find from the trait.
154-
let trait_bounds = self
155-
.projection_declared_bounds_from_trait(projection_ty)
156-
.map(|r| VerifyBound::OutlivedBy(r));
130+
let trait_bounds =
131+
self.declared_region_bounds(def_id, substs).map(|r| VerifyBound::OutlivedBy(r));
157132

158133
// see the extensive comment in projection_must_outlive
159134
let recursive_bound = {
160135
let mut components = smallvec![];
161-
let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs);
162-
compute_components_recursive(self.tcx, ty.into(), &mut components, visited);
136+
compute_components_recursive(self.tcx, generic_ty.into(), &mut components, visited);
163137
self.bound_from_components(&components, visited)
164138
};
165139

166-
VerifyBound::AnyBound(env_bounds.chain(trait_bounds).collect()).or(recursive_bound)
140+
VerifyBound::AnyBound(projection_opaque_bounds.chain(trait_bounds).collect())
141+
.or(recursive_bound)
167142
}
168143

169144
fn bound_from_components(
@@ -195,7 +170,18 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
195170
match *component {
196171
Component::Region(lt) => VerifyBound::OutlivedBy(lt),
197172
Component::Param(param_ty) => self.param_bound(param_ty),
198-
Component::Projection(projection_ty) => self.projection_bound(projection_ty, visited),
173+
Component::Opaque(did, substs) => self.projection_opaque_bounds(
174+
GenericKind::Opaque(did, substs),
175+
did,
176+
substs,
177+
visited,
178+
),
179+
Component::Projection(projection_ty) => self.projection_opaque_bounds(
180+
GenericKind::Projection(projection_ty),
181+
projection_ty.item_def_id,
182+
projection_ty.substs,
183+
visited,
184+
),
199185
Component::EscapingProjection(ref components) => {
200186
self.bound_from_components(components, visited)
201187
}
@@ -293,30 +279,6 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
293279
/// }
294280
/// ```
295281
///
296-
/// then this function would return `'x`. This is subject to the
297-
/// limitations around higher-ranked bounds described in
298-
/// `region_bounds_declared_on_associated_item`.
299-
fn declared_projection_bounds_from_trait(
300-
&self,
301-
projection_ty: ty::ProjectionTy<'tcx>,
302-
) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> {
303-
debug!("projection_bounds(projection_ty={:?})", projection_ty);
304-
let tcx = self.tcx;
305-
self.region_bounds_declared_on_associated_item(projection_ty.item_def_id)
306-
.map(move |r| EarlyBinder(r).subst(tcx, projection_ty.substs))
307-
}
308-
309-
/// Given the `DefId` of an associated item, returns any region
310-
/// bounds attached to that associated item from the trait definition.
311-
///
312-
/// For example:
313-
///
314-
/// ```rust
315-
/// trait Foo<'a> {
316-
/// type Bar: 'a;
317-
/// }
318-
/// ```
319-
///
320282
/// If we were given the `DefId` of `Foo::Bar`, we would return
321283
/// `'a`. You could then apply the substitutions from the
322284
/// projection to convert this into your namespace. This also
@@ -336,17 +298,20 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
336298
///
337299
/// This is for simplicity, and because we are not really smart
338300
/// enough to cope with such bounds anywhere.
339-
fn region_bounds_declared_on_associated_item(
301+
pub fn declared_region_bounds(
340302
&self,
341-
assoc_item_def_id: DefId,
303+
def_id: DefId,
304+
substs: SubstsRef<'tcx>,
342305
) -> impl Iterator<Item = ty::Region<'tcx>> {
343306
let tcx = self.tcx;
344-
let bounds = tcx.item_bounds(assoc_item_def_id);
307+
let bounds = tcx.item_bounds(def_id);
308+
trace!("{:#?}", bounds);
345309
bounds
346310
.into_iter()
347311
.filter_map(|p| p.to_opt_type_outlives())
348312
.filter_map(|p| p.no_bound_vars())
349313
.map(|b| b.1)
314+
.map(move |r| EarlyBinder(r).subst(tcx, substs))
350315
}
351316

352317
/// Searches through a predicate list for a predicate `T: 'a`.

‎compiler/rustc_infer/src/infer/region_constraints/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ use rustc_data_structures::intern::Interned;
1212
use rustc_data_structures::sync::Lrc;
1313
use rustc_data_structures::undo_log::UndoLogs;
1414
use rustc_data_structures::unify as ut;
15+
use rustc_hir::def_id::DefId;
1516
use rustc_index::vec::IndexVec;
1617
use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion};
18+
use rustc_middle::ty::subst::SubstsRef;
1719
use rustc_middle::ty::ReStatic;
1820
use rustc_middle::ty::{self, Ty, TyCtxt};
1921
use rustc_middle::ty::{ReLateBound, ReVar};
@@ -168,6 +170,7 @@ pub struct Verify<'tcx> {
168170
pub enum GenericKind<'tcx> {
169171
Param(ty::ParamTy),
170172
Projection(ty::ProjectionTy<'tcx>),
173+
Opaque(DefId, SubstsRef<'tcx>),
171174
}
172175

173176
/// Describes the things that some `GenericKind` value `G` is known to
@@ -747,6 +750,9 @@ impl<'tcx> fmt::Debug for GenericKind<'tcx> {
747750
match *self {
748751
GenericKind::Param(ref p) => write!(f, "{:?}", p),
749752
GenericKind::Projection(ref p) => write!(f, "{:?}", p),
753+
GenericKind::Opaque(def_id, substs) => ty::tls::with(|tcx| {
754+
write!(f, "{}", tcx.def_path_str_with_substs(def_id, tcx.lift(substs).unwrap()))
755+
}),
750756
}
751757
}
752758
}
@@ -756,6 +762,9 @@ impl<'tcx> fmt::Display for GenericKind<'tcx> {
756762
match *self {
757763
GenericKind::Param(ref p) => write!(f, "{}", p),
758764
GenericKind::Projection(ref p) => write!(f, "{}", p),
765+
GenericKind::Opaque(def_id, substs) => ty::tls::with(|tcx| {
766+
write!(f, "{}", tcx.def_path_str_with_substs(def_id, tcx.lift(substs).unwrap()))
767+
}),
759768
}
760769
}
761770
}
@@ -765,6 +774,7 @@ impl<'tcx> GenericKind<'tcx> {
765774
match *self {
766775
GenericKind::Param(ref p) => p.to_ty(tcx),
767776
GenericKind::Projection(ref p) => tcx.mk_projection(p.item_def_id, p.substs),
777+
GenericKind::Opaque(def_id, substs) => tcx.mk_opaque(def_id, substs),
768778
}
769779
}
770780
}

‎compiler/rustc_infer/src/traits/util.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,13 @@ impl<'tcx> Elaborator<'tcx> {
246246

247247
Component::UnresolvedInferenceVariable(_) => None,
248248

249+
Component::Opaque(def_id, substs) => {
250+
let ty = tcx.mk_opaque(def_id, substs);
251+
Some(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
252+
ty, r_min,
253+
)))
254+
}
255+
249256
Component::Projection(projection) => {
250257
// We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`.
251258
// With this, we can deduce that `<Bar as Baz>::Assoc: 'a`.
@@ -262,8 +269,9 @@ impl<'tcx> Elaborator<'tcx> {
262269
None
263270
}
264271
})
265-
.map(ty::Binder::dummy)
266-
.map(|predicate_kind| predicate_kind.to_predicate(tcx))
272+
.map(|predicate_kind| {
273+
bound_predicate.rebind(predicate_kind).to_predicate(tcx)
274+
})
267275
.filter(|&predicate| visited.insert(predicate))
268276
.map(|predicate| {
269277
predicate_obligation(

‎compiler/rustc_middle/src/traits/query.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
use crate::error::DropCheckOverflow;
99
use crate::infer::canonical::{Canonical, QueryResponse};
1010
use crate::ty::error::TypeError;
11-
use crate::ty::subst::GenericArg;
11+
use crate::ty::subst::{GenericArg, SubstsRef};
1212
use crate::ty::{self, Ty, TyCtxt};
13+
use rustc_hir::def_id::DefId;
1314
use rustc_span::source_map::Span;
1415
use std::iter::FromIterator;
1516

@@ -219,4 +220,5 @@ pub enum OutlivesBound<'tcx> {
219220
RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
220221
RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
221222
RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
223+
RegionSubOpaque(ty::Region<'tcx>, DefId, SubstsRef<'tcx>),
222224
}

‎compiler/rustc_traits/src/implied_outlives_bounds.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ fn implied_bounds_from_components<'tcx>(
156156
Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)),
157157
Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)),
158158
Component::Projection(p) => Some(OutlivesBound::RegionSubProjection(sub_region, p)),
159+
Component::Opaque(def_id, substs) => {
160+
Some(OutlivesBound::RegionSubOpaque(sub_region, def_id, substs))
161+
}
159162
Component::EscapingProjection(_) =>
160163
// If the projection has escaping regions, don't
161164
// try to infer any implied bounds even for its

‎compiler/rustc_typeck/src/mem_categorization.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
265265
self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment)
266266
}
267267

268+
#[instrument(level = "debug", skip(self, previous))]
268269
fn cat_expr_adjusted_with<F>(
269270
&self,
270271
expr: &hir::Expr<'_>,
@@ -274,7 +275,6 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
274275
where
275276
F: FnOnce() -> McResult<PlaceWithHirId<'tcx>>,
276277
{
277-
debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr);
278278
let target = self.resolve_vars_if_possible(adjustment.target);
279279
match adjustment.kind {
280280
adjustment::Adjust::Deref(overloaded) => {
@@ -299,6 +299,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
299299
}
300300
}
301301

302+
#[instrument(level = "debug", skip(self))]
302303
pub(crate) fn cat_expr_unadjusted(
303304
&self,
304305
expr: &hir::Expr<'_>,
@@ -387,15 +388,14 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
387388
}
388389
}
389390

391+
#[instrument(level = "debug", skip(self, span))]
390392
pub(crate) fn cat_res(
391393
&self,
392394
hir_id: hir::HirId,
393395
span: Span,
394396
expr_ty: Ty<'tcx>,
395397
res: Res,
396398
) -> McResult<PlaceWithHirId<'tcx>> {
397-
debug!("cat_res: id={:?} expr={:?} def={:?}", hir_id, expr_ty, res);
398-
399399
match res {
400400
Res::Def(
401401
DefKind::Ctor(..)
@@ -475,13 +475,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
475475
ret
476476
}
477477

478+
#[instrument(level = "debug", skip(self))]
478479
fn cat_overloaded_place(
479480
&self,
480481
expr: &hir::Expr<'_>,
481482
base: &hir::Expr<'_>,
482483
) -> McResult<PlaceWithHirId<'tcx>> {
483-
debug!("cat_overloaded_place(expr={:?}, base={:?})", expr, base);
484-
485484
// Reconstruct the output assuming it's a reference with the
486485
// same region and mutability as the receiver. This holds for
487486
// `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
@@ -497,13 +496,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
497496
self.cat_deref(expr, base)
498497
}
499498

499+
#[instrument(level = "debug", skip(self, node))]
500500
fn cat_deref(
501501
&self,
502502
node: &impl HirNode,
503503
base_place: PlaceWithHirId<'tcx>,
504504
) -> McResult<PlaceWithHirId<'tcx>> {
505-
debug!("cat_deref: base_place={:?}", base_place);
506-
507505
let base_curr_ty = base_place.place.ty();
508506
let deref_ty = match base_curr_ty.builtin_deref(true) {
509507
Some(mt) => mt.ty,

‎compiler/rustc_typeck/src/outlives/utils.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,23 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
9696
.or_insert(span);
9797
}
9898

99+
Component::Opaque(def_id, substs) => {
100+
// This would arise from something like:
101+
//
102+
// ```rust
103+
// type Opaque<T> = impl Sized;
104+
// fn defining<T>() -> Opaque<T> {}
105+
// struct Ss<'a, T>(&'a Opaque<T>);
106+
// ```
107+
//
108+
// Here we want to have an implied bound `Opaque<T>: 'a`
109+
110+
let ty = tcx.mk_opaque(def_id, substs);
111+
required_predicates
112+
.entry(ty::OutlivesPredicate(ty.into(), outlived_region))
113+
.or_insert(span);
114+
}
115+
99116
Component::EscapingProjection(_) => {
100117
// As above, but the projection involves
101118
// late-bound regions. Therefore, the WF

‎src/test/ui/generic-associated-types/bugs/issue-86218.stderr

Lines changed: 0 additions & 23 deletions
This file was deleted.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// check-pass
2+
3+
#![feature(type_alias_impl_trait)]
4+
5+
pub trait Stream {
6+
type Item;
7+
}
8+
9+
impl Stream for () {
10+
type Item = i32;
11+
}
12+
13+
trait Yay<AdditionalValue> {
14+
type InnerStream<'s>: Stream<Item = i32> + 's;
15+
fn foo<'s>() -> Self::InnerStream<'s>;
16+
}
17+
18+
impl<T> Yay<T> for () {
19+
type InnerStream<'s> = impl Stream<Item = i32> + 's;
20+
fn foo<'s>() -> Self::InnerStream<'s> { () }
21+
}
22+
23+
fn main() {}

‎src/test/ui/generic-associated-types/bugs/issue-86218.rs renamed to ‎src/test/ui/generic-associated-types/issue-86218.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
// check-fail
2-
// known-bug: #86218
3-
4-
// This should pass, but seems to run into a TAIT issue.
1+
// check-pass
52

63
#![feature(type_alias_impl_trait)]
74

@@ -20,7 +17,8 @@ trait Yay<AdditionalValue> {
2017

2118
impl<'a> Yay<&'a ()> for () {
2219
type InnerStream<'s> = impl Stream<Item = i32> + 's;
23-
fn foo<'s>() -> Self::InnerStream<'s> { todo!() }
20+
//^ ERROR does not fulfill the required lifetime
21+
fn foo<'s>() -> Self::InnerStream<'s> { () }
2422
}
2523

2624
fn main() {}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// run-rustfix
2+
3+
pub trait Trait {}
4+
5+
pub struct Foo;
6+
7+
impl Trait for Foo {}
8+
9+
fn foo<'x, P>(
10+
_post: P,
11+
x: &'x Foo,
12+
) -> &'x impl Trait {
13+
x
14+
}
15+
16+
pub fn bar<'t, T: 't>(
17+
//~^ HELP: consider adding an explicit lifetime bound...
18+
post: T,
19+
x: &'t Foo,
20+
) -> &'t impl Trait {
21+
foo(post, x)
22+
//~^ ERROR: the parameter type `T` may not live long enough
23+
}
24+
25+
fn main() {}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// run-rustfix
2+
3+
pub trait Trait {}
4+
5+
pub struct Foo;
6+
7+
impl Trait for Foo {}
8+
9+
fn foo<'x, P>(
10+
_post: P,
11+
x: &'x Foo,
12+
) -> &'x impl Trait {
13+
x
14+
}
15+
16+
pub fn bar<'t, T>(
17+
//~^ HELP: consider adding an explicit lifetime bound...
18+
post: T,
19+
x: &'t Foo,
20+
) -> &'t impl Trait {
21+
foo(post, x)
22+
//~^ ERROR: the parameter type `T` may not live long enough
23+
}
24+
25+
fn main() {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0309]: the parameter type `T` may not live long enough
2+
--> $DIR/unactionable_diagnostic.rs:21:5
3+
|
4+
LL | foo(post, x)
5+
| ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
6+
|
7+
help: consider adding an explicit lifetime bound...
8+
|
9+
LL | pub fn bar<'t, T: 't>(
10+
| ++++
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0309`.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#![feature(type_alias_impl_trait)]
2+
3+
type WithLifetime<'a> = impl Equals<SelfType = ()>;
4+
fn _defining_use<'a>() -> WithLifetime<'a> {}
5+
6+
trait Convert<'a> {
7+
type Witness;
8+
fn convert<'b, T: ?Sized>(_proof: &'b Self::Witness, x: &'a T) -> &'b T;
9+
}
10+
11+
impl<'a> Convert<'a> for () {
12+
type Witness = WithLifetime<'a>;
13+
14+
fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<'a>, x: &'a T) -> &'b T {
15+
// compiler used to think it gets to assume 'a: 'b here because
16+
// of the `&'b WithLifetime<'a>` argument
17+
x
18+
//~^ ERROR lifetime may not live long enough
19+
}
20+
}
21+
22+
fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T {
23+
WithLifetime::<'a>::convert_helper::<(), T>(&(), x)
24+
}
25+
26+
trait Equals {
27+
type SelfType;
28+
fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>(
29+
proof: &'b Self::SelfType,
30+
x: &'a T,
31+
) -> &'b T;
32+
}
33+
34+
impl<S> Equals for S {
35+
type SelfType = Self;
36+
fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>(
37+
proof: &'b Self,
38+
x: &'a T,
39+
) -> &'b T {
40+
W::convert(proof, x)
41+
}
42+
}
43+
44+
fn main() {
45+
let r;
46+
{
47+
let x = String::from("Hello World?");
48+
r = extend_lifetime(&x);
49+
}
50+
println!("{}", r);
51+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/implied_bounds.rs:17:9
3+
|
4+
LL | impl<'a> Convert<'a> for () {
5+
| -- lifetime `'a` defined here
6+
...
7+
LL | fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<'a>, x: &'a T) -> &'b T {
8+
| -- lifetime `'b` defined here
9+
...
10+
LL | x
11+
| ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
12+
|
13+
= help: consider adding the following bound: `'a: 'b`
14+
15+
error: aborting due to previous error
16+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// check-pass
2+
3+
#![feature(type_alias_impl_trait)]
4+
5+
type Ty<'a, A> = impl Sized + 'a;
6+
fn defining<'a, A>() -> Ty<'a, A> {}
7+
fn assert_static<T: 'static>() {}
8+
fn test<'a, A>() where Ty<'a, A>: 'static, { assert_static::<Ty<'a, A>>() }
9+
10+
fn main() {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// check-pass
2+
3+
fn foo<F>(_: F)
4+
where
5+
F: 'static,
6+
{
7+
}
8+
9+
fn from<F: Send>(f: F) -> impl Send {
10+
f
11+
}
12+
13+
fn bar<T>() {
14+
foo(from(|| ()))
15+
}
16+
17+
fn main() {
18+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
trait StaticDefaultRef: 'static {
2+
fn default_ref() -> &'static Self;
3+
}
4+
5+
impl StaticDefaultRef for str {
6+
fn default_ref() -> &'static str {
7+
""
8+
}
9+
}
10+
11+
fn into_impl(x: &str) -> &(impl ?Sized + AsRef<str> + StaticDefaultRef + '_) {
12+
x
13+
}
14+
15+
fn extend_lifetime<'a>(x: &'a str) -> &'static str {
16+
let t = into_impl(x);
17+
helper(|_| t) //~ ERROR lifetime may not live long enough
18+
}
19+
20+
fn helper<T: ?Sized + AsRef<str> + StaticDefaultRef>(f: impl FnOnce(&T) -> &T) -> &'static str {
21+
f(T::default_ref()).as_ref()
22+
}
23+
24+
fn main() {
25+
let r;
26+
{
27+
let x = String::from("Hello World?");
28+
r = extend_lifetime(&x);
29+
}
30+
println!("{}", r);
31+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/implied_bounds_closure.rs:17:16
3+
|
4+
LL | fn extend_lifetime<'a>(x: &'a str) -> &'static str {
5+
| -- lifetime `'a` defined here
6+
LL | let t = into_impl(x);
7+
LL | helper(|_| t)
8+
| ^ returning this value requires that `'a` must outlive `'static`
9+
10+
error: aborting due to previous error
11+
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#![feature(type_alias_impl_trait)]
2+
3+
type WithLifetime<T> = impl Equals<SelfType = ()>;
4+
fn _defining_use<T>() -> WithLifetime<T> {}
5+
6+
trait Convert<'a> {
7+
type Witness;
8+
fn convert<'b, T: ?Sized>(_proof: &'b Self::Witness, x: &'a T) -> &'b T;
9+
}
10+
11+
impl<'a> Convert<'a> for () {
12+
type Witness = WithLifetime<&'a ()>;
13+
14+
fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T {
15+
// compiler used to think it gets to assume 'a: 'b here because
16+
// of the `&'b WithLifetime<&'a ()>` argument
17+
x
18+
//~^ ERROR lifetime may not live long enough
19+
}
20+
}
21+
22+
fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T {
23+
WithLifetime::<&'a ()>::convert_helper::<(), T>(&(), x)
24+
}
25+
26+
trait Equals {
27+
type SelfType;
28+
fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>(
29+
proof: &'b Self::SelfType,
30+
x: &'a T,
31+
) -> &'b T;
32+
}
33+
34+
impl<S> Equals for S {
35+
type SelfType = Self;
36+
fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>(
37+
proof: &'b Self,
38+
x: &'a T,
39+
) -> &'b T {
40+
W::convert(proof, x)
41+
}
42+
}
43+
44+
fn main() {
45+
let r;
46+
{
47+
let x = String::from("Hello World?");
48+
r = extend_lifetime(&x);
49+
}
50+
println!("{}", r);
51+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/implied_bounds_from_types.rs:17:9
3+
|
4+
LL | impl<'a> Convert<'a> for () {
5+
| -- lifetime `'a` defined here
6+
...
7+
LL | fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T {
8+
| -- lifetime `'b` defined here
9+
...
10+
LL | x
11+
| ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
12+
|
13+
= help: consider adding the following bound: `'a: 'b`
14+
15+
error: aborting due to previous error
16+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#![feature(type_alias_impl_trait)]
2+
3+
// known-bug: #99840
4+
// this should not compile
5+
// check-pass
6+
7+
type Alias = impl Sized;
8+
9+
fn constrain() -> Alias {
10+
1i32
11+
}
12+
13+
trait HideIt {
14+
type Assoc;
15+
}
16+
17+
impl HideIt for () {
18+
type Assoc = Alias;
19+
}
20+
21+
pub trait Yay {}
22+
23+
impl Yay for <() as HideIt>::Assoc {}
24+
// impl Yay for i32 {} // this already errors
25+
// impl Yay for u32 {} // this also already errors
26+
27+
fn main() {}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#![feature(type_alias_impl_trait)]
2+
3+
mod test_lifetime_param {
4+
type Ty<'a> = impl Sized;
5+
fn defining(a: &str) -> Ty<'_> { a }
6+
fn assert_static<'a: 'static>() {}
7+
//~^ WARN: unnecessary lifetime parameter `'a`
8+
fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() }
9+
//~^ ERROR: lifetime may not live long enough
10+
}
11+
12+
mod test_higher_kinded_lifetime_param {
13+
type Ty<'a> = impl Sized;
14+
fn defining(a: &str) -> Ty<'_> { a }
15+
fn assert_static<'a: 'static>() {}
16+
//~^ WARN: unnecessary lifetime parameter `'a`
17+
fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() }
18+
//~^ ERROR: lifetime may not live long enough
19+
}
20+
21+
mod test_higher_kinded_lifetime_param2 {
22+
fn assert_static<'a: 'static>() {}
23+
//~^ WARN: unnecessary lifetime parameter `'a`
24+
fn test<'a>() { assert_static::<'a>() }
25+
//~^ ERROR: lifetime may not live long enough
26+
}
27+
28+
mod test_type_param {
29+
type Ty<A> = impl Sized;
30+
fn defining<A>(s: A) -> Ty<A> { s }
31+
fn assert_static<A: 'static>() {}
32+
fn test<A>() where Ty<A>: 'static { assert_static::<A>() }
33+
//~^ ERROR: parameter type `A` may not live long enough
34+
}
35+
36+
mod test_implied_from_fn_sig {
37+
type Opaque<T: 'static> = impl Sized;
38+
fn defining<T: 'static>() -> Opaque<T> {}
39+
fn assert_static<T: 'static>() {}
40+
fn test<T>(_: Opaque<T>) { assert_static::<T>(); }
41+
}
42+
43+
fn main() {}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
warning: unnecessary lifetime parameter `'a`
2+
--> $DIR/implied_lifetime_wf_check3.rs:6:22
3+
|
4+
LL | fn assert_static<'a: 'static>() {}
5+
| ^^
6+
|
7+
= help: you can use the `'static` lifetime directly, in place of `'a`
8+
9+
warning: unnecessary lifetime parameter `'a`
10+
--> $DIR/implied_lifetime_wf_check3.rs:15:22
11+
|
12+
LL | fn assert_static<'a: 'static>() {}
13+
| ^^
14+
|
15+
= help: you can use the `'static` lifetime directly, in place of `'a`
16+
17+
warning: unnecessary lifetime parameter `'a`
18+
--> $DIR/implied_lifetime_wf_check3.rs:22:22
19+
|
20+
LL | fn assert_static<'a: 'static>() {}
21+
| ^^
22+
|
23+
= help: you can use the `'static` lifetime directly, in place of `'a`
24+
25+
error: lifetime may not live long enough
26+
--> $DIR/implied_lifetime_wf_check3.rs:8:43
27+
|
28+
LL | fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() }
29+
| -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
30+
31+
error: lifetime may not live long enough
32+
--> $DIR/implied_lifetime_wf_check3.rs:17:46
33+
|
34+
LL | fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() }
35+
| -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
36+
37+
error: lifetime may not live long enough
38+
--> $DIR/implied_lifetime_wf_check3.rs:24:21
39+
|
40+
LL | fn test<'a>() { assert_static::<'a>() }
41+
| -- ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
42+
| |
43+
| lifetime `'a` defined here
44+
45+
error[E0310]: the parameter type `A` may not live long enough
46+
--> $DIR/implied_lifetime_wf_check3.rs:32:41
47+
|
48+
LL | fn test<A>() where Ty<A>: 'static { assert_static::<A>() }
49+
| ^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
50+
|
51+
help: consider adding an explicit lifetime bound...
52+
|
53+
LL | fn test<A: 'static>() where Ty<A>: 'static { assert_static::<A>() }
54+
| +++++++++
55+
56+
error: aborting due to 4 previous errors; 3 warnings emitted
57+
58+
For more information about this error, try `rustc --explain E0310`.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(type_alias_impl_trait)]
2+
3+
mod test_type_param_static {
4+
type Ty<A> = impl Sized + 'static;
5+
//~^ ERROR: the parameter type `A` may not live long enough
6+
fn defining<A: 'static>(s: A) -> Ty<A> { s }
7+
fn assert_static<A: 'static>() {}
8+
fn test<A>() where Ty<A>: 'static { assert_static::<A>() }
9+
}
10+
11+
fn main() {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0310]: the parameter type `A` may not live long enough
2+
--> $DIR/implied_lifetime_wf_check4_static.rs:4:18
3+
|
4+
LL | type Ty<A> = impl Sized + 'static;
5+
| ^^^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
6+
|
7+
help: consider adding an explicit lifetime bound...
8+
|
9+
LL | type Ty<A: 'static> = impl Sized + 'static;
10+
| +++++++++
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0310`.

‎src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ fn rand_generator<'a>(rng: &'a ()) -> RandGenerator<'a> {
1616
}
1717
}
1818

19-
pub type RandGeneratorWithIndirection<'a> = impl Generator<Return = (), Yield = u64> + 'a;
19+
pub type RandGeneratorWithIndirection<'c> = impl Generator<Return = (), Yield = u64> + 'c;
2020
pub fn rand_generator_with_indirection<'a>(rng: &'a ()) -> RandGeneratorWithIndirection<'a> {
2121
fn helper<'b>(rng: &'b ()) -> impl 'b + Generator<Return = (), Yield = u64> {
2222
move || {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// check-pass
2+
3+
#![feature(generators, generator_trait)]
4+
#![feature(type_alias_impl_trait)]
5+
6+
trait Trait {}
7+
8+
impl<T> Trait for T {}
9+
10+
type Foo<'c> = impl Trait + 'c;
11+
fn foo<'a>(rng: &'a ()) -> Foo<'a> {
12+
fn helper<'b>(rng: &'b ()) -> impl 'b + Trait {
13+
rng
14+
}
15+
16+
helper(rng)
17+
}
18+
19+
fn main() {
20+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// check-pass
2+
3+
#![feature(type_alias_impl_trait)]
4+
type Opaque<T> = impl Sized;
5+
fn defining<T>() -> Opaque<T> {}
6+
struct Ss<'a, T>(&'a Opaque<T>);
7+
8+
9+
fn test<'a, T>(_: Ss<'a, T>) {
10+
// test that we have an implied bound `Opaque<T>: 'a` from fn signature
11+
None::<&'a Opaque<T>>;
12+
}
13+
14+
fn main() {}

0 commit comments

Comments
 (0)
Please sign in to comment.