1
Fork 0

Rollup merge of #122103 - compiler-errors:taits-capture-everything, r=oli-obk

Make TAITs and ATPITs capture late-bound lifetimes in scope

This generalizes the behavior that RPITs have, where they duplicate their in-scope lifetimes so that they will always *reify* late-bound lifetimes that they capture. This allows TAITs and ATPITs to properly error when they capture in-scope late-bound lifetimes.

r? `@oli-obk` cc `@aliemjay`

Fixes #122093 and therefore https://github.com/rust-lang/rust/pull/120700#issuecomment-1981213868
This commit is contained in:
Matthias Krüger 2024-03-08 08:19:20 +01:00 committed by GitHub
commit d4d18d240b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 148 additions and 185 deletions

View file

@ -275,7 +275,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
Some(ty) => this.lower_ty( Some(ty) => this.lower_ty(
ty, ty,
ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: false }, ImplTraitContext::OpaqueTy {
origin: hir::OpaqueTyOrigin::TyAlias {
parent: this.local_def_id(id),
in_assoc_ty: false,
},
fn_kind: None,
},
), ),
}, },
); );
@ -936,7 +942,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
Some(ty) => { Some(ty) => {
let ty = this.lower_ty( let ty = this.lower_ty(
ty, ty,
ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: true }, ImplTraitContext::OpaqueTy {
origin: hir::OpaqueTyOrigin::TyAlias {
parent: this.local_def_id(i.id),
in_assoc_ty: true,
},
fn_kind: None,
},
); );
hir::ImplItemKind::Type(ty) hir::ImplItemKind::Type(ty)
} }

View file

@ -265,13 +265,12 @@ enum ImplTraitContext {
/// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
/// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`. /// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`.
/// ///
ReturnPositionOpaqueTy { OpaqueTy {
/// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
origin: hir::OpaqueTyOrigin, origin: hir::OpaqueTyOrigin,
fn_kind: FnDeclKind, /// Only used to change the lifetime capture rules, since
/// RPITIT captures all in scope, RPIT does not.
fn_kind: Option<FnDeclKind>,
}, },
/// Impl trait in type aliases.
TypeAliasesOpaqueTy { in_assoc_ty: bool },
/// `impl Trait` is unstably accepted in this position. /// `impl Trait` is unstably accepted in this position.
FeatureGated(ImplTraitPosition, Symbol), FeatureGated(ImplTraitPosition, Symbol),
/// `impl Trait` is not accepted in this position. /// `impl Trait` is not accepted in this position.
@ -1075,9 +1074,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Disallow ATB in dyn types // Disallow ATB in dyn types
if self.is_in_dyn_type { if self.is_in_dyn_type {
let suggestion = match itctx { let suggestion = match itctx {
ImplTraitContext::ReturnPositionOpaqueTy { .. } ImplTraitContext::OpaqueTy { .. } | ImplTraitContext::Universal => {
| ImplTraitContext::TypeAliasesOpaqueTy { .. }
| ImplTraitContext::Universal => {
let bound_end_span = constraint let bound_end_span = constraint
.gen_args .gen_args
.as_ref() .as_ref()
@ -1417,24 +1414,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
TyKind::ImplTrait(def_node_id, bounds) => { TyKind::ImplTrait(def_node_id, bounds) => {
let span = t.span; let span = t.span;
match itctx { match itctx {
ImplTraitContext::ReturnPositionOpaqueTy { origin, fn_kind } => self ImplTraitContext::OpaqueTy { origin, fn_kind } => self.lower_opaque_impl_trait(
.lower_opaque_impl_trait( span,
span, origin,
origin, *def_node_id,
*def_node_id, bounds,
bounds, fn_kind,
Some(fn_kind), itctx,
itctx, ),
),
ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self
.lower_opaque_impl_trait(
span,
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty },
*def_node_id,
bounds,
None,
itctx,
),
ImplTraitContext::Universal => { ImplTraitContext::Universal => {
let span = t.span; let span = t.span;
@ -1553,9 +1540,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let captured_lifetimes_to_duplicate = match origin { let captured_lifetimes_to_duplicate = match origin {
hir::OpaqueTyOrigin::TyAlias { .. } => { hir::OpaqueTyOrigin::TyAlias { .. } => {
// in a TAIT like `type Foo<'a> = impl Foo<'a>`, we don't duplicate any // type alias impl trait and associated type position impl trait were
// lifetimes, since we don't have the issue that any are late-bound. // decided to capture all in-scope lifetimes, which we collect for
Vec::new() // all opaques during resolution.
self.resolver
.take_extra_lifetime_params(opaque_ty_node_id)
.into_iter()
.map(|(ident, id, _)| Lifetime { id, ident })
.collect()
} }
hir::OpaqueTyOrigin::FnReturn(..) => { hir::OpaqueTyOrigin::FnReturn(..) => {
if matches!( if matches!(
@ -1823,9 +1815,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
FnDeclKind::Fn FnDeclKind::Fn
| FnDeclKind::Inherent | FnDeclKind::Inherent
| FnDeclKind::Trait | FnDeclKind::Trait
| FnDeclKind::Impl => ImplTraitContext::ReturnPositionOpaqueTy { | FnDeclKind::Impl => ImplTraitContext::OpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(self.local_def_id(fn_node_id)), origin: hir::OpaqueTyOrigin::FnReturn(self.local_def_id(fn_node_id)),
fn_kind: kind, fn_kind: Some(kind),
}, },
FnDeclKind::ExternFn => { FnDeclKind::ExternFn => {
ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnReturn) ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnReturn)
@ -1919,9 +1911,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
output, output,
coro, coro,
opaque_ty_span, opaque_ty_span,
ImplTraitContext::ReturnPositionOpaqueTy { ImplTraitContext::OpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
fn_kind, fn_kind: Some(fn_kind),
}, },
); );
arena_vec![this; bound] arena_vec![this; bound]

View file

@ -423,7 +423,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug // fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug
// // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^ // // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^
// ``` // ```
FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => { FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::OpaqueTy { .. }) => {
if self.tcx.features().impl_trait_in_fn_trait_return { if self.tcx.features().impl_trait_in_fn_trait_return {
self.lower_ty(ty, itctx) self.lower_ty(ty, itctx)
} else { } else {

View file

@ -367,14 +367,17 @@ fn check_opaque_type_parameter_valid(
span: Span, span: Span,
) -> Result<(), ErrorGuaranteed> { ) -> Result<(), ErrorGuaranteed> {
let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id); let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id);
let is_ty_alias = match opaque_ty_hir.expect_opaque_ty().origin { let (parent, is_ty_alias) = match opaque_ty_hir.expect_opaque_ty().origin {
OpaqueTyOrigin::TyAlias { .. } => true, OpaqueTyOrigin::TyAlias { parent, .. } => (parent, true),
OpaqueTyOrigin::AsyncFn(..) | OpaqueTyOrigin::FnReturn(..) => false, OpaqueTyOrigin::AsyncFn(parent) | OpaqueTyOrigin::FnReturn(parent) => (parent, false),
}; };
let opaque_generics = tcx.generics_of(opaque_type_key.def_id); let parent_generics = tcx.generics_of(parent);
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default(); let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
for (i, arg) in opaque_type_key.args.iter().enumerate() {
// Only check the parent generics, which will ignore any of the
// duplicated lifetime args that come from reifying late-bounds.
for (i, arg) in opaque_type_key.args.iter().take(parent_generics.count()).enumerate() {
if let Err(guar) = arg.error_reported() { if let Err(guar) = arg.error_reported() {
return Err(guar); return Err(guar);
} }
@ -395,7 +398,7 @@ fn check_opaque_type_parameter_valid(
seen_params.entry(arg).or_default().push(i); seen_params.entry(arg).or_default().push(i);
} else { } else {
// Prevent `fn foo() -> Foo<u32>` from being defining. // Prevent `fn foo() -> Foo<u32>` from being defining.
let opaque_param = opaque_generics.param_at(i, tcx); let opaque_param = parent_generics.param_at(i, tcx);
let kind = opaque_param.kind.descr(); let kind = opaque_param.kind.descr();
return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam { return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam {
@ -409,10 +412,10 @@ fn check_opaque_type_parameter_valid(
for (_, indices) in seen_params { for (_, indices) in seen_params {
if indices.len() > 1 { if indices.len() > 1 {
let descr = opaque_generics.param_at(indices[0], tcx).kind.descr(); let descr = parent_generics.param_at(indices[0], tcx).kind.descr();
let spans: Vec<_> = indices let spans: Vec<_> = indices
.into_iter() .into_iter()
.map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) .map(|i| tcx.def_span(parent_generics.param_at(i, tcx).def_id))
.collect(); .collect();
#[allow(rustc::diagnostic_outside_of_impl)] #[allow(rustc::diagnostic_outside_of_impl)]
#[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::untranslatable_diagnostic)]

View file

@ -2562,6 +2562,8 @@ pub enum OpaqueTyOrigin {
AsyncFn(LocalDefId), AsyncFn(LocalDefId),
/// type aliases: `type Foo = impl Trait;` /// type aliases: `type Foo = impl Trait;`
TyAlias { TyAlias {
/// The type alias or associated type parent of the TAIT/ATPIT
parent: LocalDefId,
/// associated types in impl blocks for traits. /// associated types in impl blocks for traits.
in_assoc_ty: bool, in_assoc_ty: bool,
}, },

View file

@ -339,8 +339,9 @@ fn check_opaque_meets_bounds<'tcx>(
origin: &hir::OpaqueTyOrigin, origin: &hir::OpaqueTyOrigin,
) -> Result<(), ErrorGuaranteed> { ) -> Result<(), ErrorGuaranteed> {
let defining_use_anchor = match *origin { let defining_use_anchor = match *origin {
hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did, hir::OpaqueTyOrigin::FnReturn(did)
hir::OpaqueTyOrigin::TyAlias { .. } => tcx.impl_trait_parent(def_id), | hir::OpaqueTyOrigin::AsyncFn(did)
| hir::OpaqueTyOrigin::TyAlias { parent: did, .. } => did,
}; };
let param_env = tcx.param_env(defining_use_anchor); let param_env = tcx.param_env(defining_use_anchor);
@ -351,14 +352,14 @@ fn check_opaque_meets_bounds<'tcx>(
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let args = match *origin { let args = match *origin {
hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => { hir::OpaqueTyOrigin::FnReturn(parent)
GenericArgs::identity_for_item(tcx, parent).extend_to( | hir::OpaqueTyOrigin::AsyncFn(parent)
tcx, | hir::OpaqueTyOrigin::TyAlias { parent, .. } => GenericArgs::identity_for_item(
def_id.to_def_id(), tcx, parent,
|param, _| tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local()).into(), )
) .extend_to(tcx, def_id.to_def_id(), |param, _| {
} tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into()
hir::OpaqueTyOrigin::TyAlias { .. } => GenericArgs::identity_for_item(tcx, def_id), }),
}; };
let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);

View file

@ -339,7 +339,7 @@ fn compute_bidirectional_outlives_predicates<'tcx>(
predicates: &mut Vec<(ty::Clause<'tcx>, Span)>, predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
) { ) {
for param in opaque_own_params { for param in opaque_own_params {
let orig_lifetime = tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local()); let orig_lifetime = tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local());
if let ty::ReEarlyParam(..) = *orig_lifetime { if let ty::ReEarlyParam(..) = *orig_lifetime {
let dup_lifetime = ty::Region::new_early_param( let dup_lifetime = ty::Region::new_early_param(
tcx, tcx,

View file

@ -514,38 +514,11 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
// These sorts of items have no lifetime parameters at all. // These sorts of items have no lifetime parameters at all.
intravisit::walk_item(self, item); intravisit::walk_item(self, item);
} }
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::TyAlias { .. },
..
}) => {
// Opaque types are visited when we visit the
// `TyKind::OpaqueDef`, so that they have the lifetimes from
// their parent opaque_ty in scope.
//
// The core idea here is that since OpaqueTys are generated with the impl Trait as
// their owner, we can keep going until we find the Item that owns that. We then
// conservatively add all resolved lifetimes. Otherwise we run into problems in
// cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
let parent_item = self.tcx.hir().get_parent_item(item.hir_id());
let resolved_lifetimes: &ResolveBoundVars =
self.tcx.resolve_bound_vars(parent_item);
// We need to add *all* deps, since opaque tys may want them from *us*
for (&owner, defs) in resolved_lifetimes.defs.iter() {
defs.iter().for_each(|(&local_id, region)| {
self.map.defs.insert(hir::HirId { owner, local_id }, *region);
});
}
for (&owner, late_bound_vars) in resolved_lifetimes.late_bound_vars.iter() {
late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| {
self.record_late_bound_vars(
hir::HirId { owner, local_id },
late_bound_vars.clone(),
);
});
}
}
hir::ItemKind::OpaqueTy(&hir::OpaqueTy { hir::ItemKind::OpaqueTy(&hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent), origin:
hir::OpaqueTyOrigin::FnReturn(parent)
| hir::OpaqueTyOrigin::AsyncFn(parent)
| hir::OpaqueTyOrigin::TyAlias { parent, .. },
generics, generics,
.. ..
}) => { }) => {
@ -683,26 +656,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
// the opaque_ty generics // the opaque_ty generics
let opaque_ty = self.tcx.hir().item(item_id); let opaque_ty = self.tcx.hir().item(item_id);
match &opaque_ty.kind { match &opaque_ty.kind {
hir::ItemKind::OpaqueTy(hir::OpaqueTy { hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin: _, .. }) => {}
origin: hir::OpaqueTyOrigin::TyAlias { .. },
..
}) => {
intravisit::walk_ty(self, ty);
// Elided lifetimes and late-bound lifetimes (from the parent)
// are not allowed in non-return position impl Trait
let scope = Scope::LateBoundary {
s: &Scope::TraitRefBoundary { s: self.scope },
what: "type alias impl trait",
};
self.with(scope, |this| intravisit::walk_item(this, opaque_ty));
return;
}
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..),
..
}) => {}
i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
}; };

View file

@ -553,11 +553,11 @@ pub(super) fn type_of_opaque(
Ok(ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id) { Ok(ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id) {
Node::Item(item) => match item.kind { Node::Item(item) => match item.kind {
ItemKind::OpaqueTy(OpaqueTy { ItemKind::OpaqueTy(OpaqueTy {
origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false }, origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. },
.. ..
}) => opaque::find_opaque_ty_constraints_for_tait(tcx, def_id), }) => opaque::find_opaque_ty_constraints_for_tait(tcx, def_id),
ItemKind::OpaqueTy(OpaqueTy { ItemKind::OpaqueTy(OpaqueTy {
origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true }, origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true, .. },
.. ..
}) => opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type(tcx, def_id), }) => opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type(tcx, def_id),
// Opaque types desugared from `impl Trait`. // Opaque types desugared from `impl Trait`.

View file

@ -125,15 +125,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
// By default, RPIT are invariant wrt type and const generics, but they are bivariant wrt // By default, RPIT are invariant wrt type and const generics, but they are bivariant wrt
// lifetime generics. // lifetime generics.
let variances = std::iter::repeat(ty::Invariant).take(generics.count()); let mut variances = vec![ty::Invariant; generics.count()];
let mut variances: Vec<_> = match tcx.opaque_type_origin(item_def_id) {
rustc_hir::OpaqueTyOrigin::FnReturn(_) | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {
variances.collect()
}
// But TAIT are invariant for all generics
rustc_hir::OpaqueTyOrigin::TyAlias { .. } => return tcx.arena.alloc_from_iter(variances),
};
// Mark all lifetimes from parent generics as unused (Bivariant). // Mark all lifetimes from parent generics as unused (Bivariant).
// This will be overridden later if required. // This will be overridden later if required.

View file

@ -391,7 +391,7 @@ impl<'tcx> InferCtxt<'tcx> {
// Anonymous `impl Trait` // Anonymous `impl Trait`
hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id, hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id,
// Named `type Foo = impl Bar;` // Named `type Foo = impl Bar;`
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => { hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => {
if in_assoc_ty { if in_assoc_ty {
self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id) self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id)
} else { } else {

View file

@ -1254,7 +1254,7 @@ impl<'tcx> TyCtxt<'tcx> {
if self.def_kind(scope) == DefKind::OpaqueTy { if self.def_kind(scope) == DefKind::OpaqueTy {
// Lifetime params of opaque types are synthetic and thus irrelevant to // Lifetime params of opaque types are synthetic and thus irrelevant to
// diagnostics. Map them back to their origin! // diagnostics. Map them back to their origin!
region = self.map_rpit_lifetime_to_fn_lifetime(def_id); region = self.map_opaque_lifetime_to_parent_lifetime(def_id);
continue; continue;
} }
break (scope, ty::BrNamed(def_id.into(), self.item_name(def_id.into()))); break (scope, ty::BrNamed(def_id.into(), self.item_name(def_id.into())));
@ -2219,31 +2219,31 @@ impl<'tcx> TyCtxt<'tcx> {
) )
} }
/// Given the def-id of an early-bound lifetime on an RPIT corresponding to /// Given the def-id of an early-bound lifetime on an opaque corresponding to
/// a duplicated captured lifetime, map it back to the early- or late-bound /// a duplicated captured lifetime, map it back to the early- or late-bound
/// lifetime of the function from which it originally as captured. If it is /// lifetime of the function from which it originally as captured. If it is
/// a late-bound lifetime, this will represent the liberated (`ReLateParam`) lifetime /// a late-bound lifetime, this will represent the liberated (`ReLateParam`) lifetime
/// of the signature. /// of the signature.
// FIXME(RPITIT): if we ever synthesize new lifetimes for RPITITs and not just // FIXME(RPITIT): if we ever synthesize new lifetimes for RPITITs and not just
// re-use the generics of the opaque, this function will need to be tweaked slightly. // re-use the generics of the opaque, this function will need to be tweaked slightly.
pub fn map_rpit_lifetime_to_fn_lifetime( pub fn map_opaque_lifetime_to_parent_lifetime(
self, self,
mut rpit_lifetime_param_def_id: LocalDefId, mut opaque_lifetime_param_def_id: LocalDefId,
) -> ty::Region<'tcx> { ) -> ty::Region<'tcx> {
debug_assert!( debug_assert!(
matches!(self.def_kind(rpit_lifetime_param_def_id), DefKind::LifetimeParam), matches!(self.def_kind(opaque_lifetime_param_def_id), DefKind::LifetimeParam),
"{rpit_lifetime_param_def_id:?} is a {}", "{opaque_lifetime_param_def_id:?} is a {}",
self.def_descr(rpit_lifetime_param_def_id.to_def_id()) self.def_descr(opaque_lifetime_param_def_id.to_def_id())
); );
loop { loop {
let parent = self.local_parent(rpit_lifetime_param_def_id); let parent = self.local_parent(opaque_lifetime_param_def_id);
let hir::OpaqueTy { lifetime_mapping, .. } = let hir::OpaqueTy { lifetime_mapping, .. } =
self.hir_node_by_def_id(parent).expect_item().expect_opaque_ty(); self.hir_node_by_def_id(parent).expect_item().expect_opaque_ty();
let Some((lifetime, _)) = lifetime_mapping let Some((lifetime, _)) = lifetime_mapping
.iter() .iter()
.find(|(_, duplicated_param)| *duplicated_param == rpit_lifetime_param_def_id) .find(|(_, duplicated_param)| *duplicated_param == opaque_lifetime_param_def_id)
else { else {
bug!("duplicated lifetime param should be present"); bug!("duplicated lifetime param should be present");
}; };
@ -2256,7 +2256,7 @@ impl<'tcx> TyCtxt<'tcx> {
// of the opaque we mapped from. Continue mapping. // of the opaque we mapped from. Continue mapping.
if matches!(self.def_kind(new_parent), DefKind::OpaqueTy) { if matches!(self.def_kind(new_parent), DefKind::OpaqueTy) {
debug_assert_eq!(self.parent(parent.to_def_id()), new_parent); debug_assert_eq!(self.parent(parent.to_def_id()), new_parent);
rpit_lifetime_param_def_id = ebv.expect_local(); opaque_lifetime_param_def_id = ebv.expect_local();
continue; continue;
} }

View file

@ -1940,18 +1940,6 @@ impl<'tcx> TyCtxt<'tcx> {
matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait)) matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait))
} }
/// Returns the `DefId` of the item within which the `impl Trait` is declared.
/// For type-alias-impl-trait this is the `type` alias.
/// For impl-trait-in-assoc-type this is the assoc type.
/// For return-position-impl-trait this is the function.
pub fn impl_trait_parent(self, mut def_id: LocalDefId) -> LocalDefId {
// Find the surrounding item (type alias or assoc type)
while let DefKind::OpaqueTy = self.def_kind(def_id) {
def_id = self.local_parent(def_id);
}
def_id
}
pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool { pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool {
if self.def_kind(def_id) != DefKind::AssocFn { if self.def_kind(def_id) != DefKind::AssocFn {
return false; return false;

View file

@ -71,7 +71,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
// the end of the list corresponding to the opaque's generics. // the end of the list corresponding to the opaque's generics.
for param in &generics.params[tcx.generics_of(fn_def_id).params.len()..] { for param in &generics.params[tcx.generics_of(fn_def_id).params.len()..] {
let orig_lt = let orig_lt =
tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local()); tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local());
if matches!(*orig_lt, ty::ReLateParam(..)) { if matches!(*orig_lt, ty::ReLateParam(..)) {
mapping.insert( mapping.insert(
orig_lt, orig_lt,

View file

@ -141,7 +141,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
trace!(?origin); trace!(?origin);
match origin { match origin {
rustc_hir::OpaqueTyOrigin::FnReturn(_) | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {} rustc_hir::OpaqueTyOrigin::FnReturn(_) | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {}
rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => { rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => {
if !in_assoc_ty { if !in_assoc_ty {
if !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) { if !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) {
return; return;

View file

@ -7,7 +7,7 @@ pub trait Trait<'a> {
trait Test<'a> {} trait Test<'a> {}
pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>; pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
//~^ ERROR cannot capture late-bound lifetime in type alias impl trait //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
impl Trait<'_> for () { impl Trait<'_> for () {
type Assoc = (); type Assoc = ();

View file

@ -1,8 +1,14 @@
error: cannot capture late-bound lifetime in type alias impl trait error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/escaping-bound-var.rs:9:57 --> $DIR/escaping-bound-var.rs:9:25
| |
LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>; LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
| -- lifetime defined here ^^ | ^^
|
note: lifetime declared here
--> $DIR/escaping-bound-var.rs:9:25
|
LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
| ^^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -12,14 +12,14 @@ fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
type Foo<'a, 'b> = (i32, impl PartialEq<Foo<'a, 'b>> + std::fmt::Debug); type Foo<'a, 'b> = (i32, impl PartialEq<Foo<'a, 'b>> + std::fmt::Debug);
fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> {
//~^ ERROR can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0})` //~^ ERROR can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)`
(42, i) (42, i)
} }
type Moo<'a, 'b> = (i32, impl PartialEq<Moo<'b, 'a>> + std::fmt::Debug); type Moo<'a, 'b> = (i32, impl PartialEq<Moo<'b, 'a>> + std::fmt::Debug);
fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> {
//~^ ERROR can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` //~^ ERROR can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)`
(42, i) (42, i)
} }

View file

@ -10,28 +10,28 @@ LL | i
= help: the trait `PartialEq<Bar<'b, 'a>>` is not implemented for `&i32` = help: the trait `PartialEq<Bar<'b, 'a>>` is not implemented for `&i32`
= help: the trait `PartialEq` is implemented for `i32` = help: the trait `PartialEq` is implemented for `i32`
error[E0277]: can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0})` error[E0277]: can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)`
--> $DIR/self-referential.rs:14:31 --> $DIR/self-referential.rs:14:31
| |
LL | fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { LL | fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> {
| ^^^^^^^^^^^ no implementation for `&i32 == (i32, Foo<'a, 'b>::{opaque#0})` | ^^^^^^^^^^^ no implementation for `&i32 == (i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)`
LL | LL |
LL | (42, i) LL | (42, i)
| ------- return type was inferred to be `(i32, &i32)` here | ------- return type was inferred to be `(i32, &i32)` here
| |
= help: the trait `PartialEq<(i32, Foo<'a, 'b>::{opaque#0})>` is not implemented for `&i32` = help: the trait `PartialEq<(i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)>` is not implemented for `&i32`
= help: the trait `PartialEq` is implemented for `i32` = help: the trait `PartialEq` is implemented for `i32`
error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)`
--> $DIR/self-referential.rs:21:31 --> $DIR/self-referential.rs:21:31
| |
LL | fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { LL | fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> {
| ^^^^^^^^^^^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0})` | ^^^^^^^^^^^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)`
LL | LL |
LL | (42, i) LL | (42, i)
| ------- return type was inferred to be `(i32, &i32)` here | ------- return type was inferred to be `(i32, &i32)` here
| |
= help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0})>` is not implemented for `&i32` = help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)>` is not implemented for `&i32`
= help: the trait `PartialEq` is implemented for `i32` = help: the trait `PartialEq` is implemented for `i32`
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -5,21 +5,21 @@
trait Captures<'a> {} trait Captures<'a> {}
impl<T> Captures<'_> for T {} impl<T> Captures<'_> for T {}
type NotCapturedEarly<'a> = impl Sized; //~ [o] type NotCapturedEarly<'a> = impl Sized; //~ [*, o]
//~^ ERROR: unconstrained opaque type //~^ ERROR: unconstrained opaque type
type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [o] type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [*, o]
//~^ ERROR: unconstrained opaque type //~^ ERROR: unconstrained opaque type
// TAIT does *not* capture `'b` type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ [*, o, o]
type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ [o] //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level
//~^ ERROR: unconstrained opaque type //~| ERROR: unconstrained opaque type
// TAIT does *not* capture `'b` type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; //~ [*, o, o]
type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; //~ [o] //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level
//~^ ERROR: unconstrained opaque type //~| ERROR: unconstrained opaque type
type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR [o, o, o] type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR [*, *, o, o, o]
//~^ ERROR: unconstrained opaque type //~^ ERROR: unconstrained opaque type
trait Foo<'i> { trait Foo<'i> {
@ -31,24 +31,24 @@ trait Foo<'i> {
} }
impl<'i> Foo<'i> for &'i () { impl<'i> Foo<'i> for &'i () {
type ImplicitCapture<'a> = impl Sized; //~ [o, o] type ImplicitCapture<'a> = impl Sized; //~ [*, *, o, o]
//~^ ERROR: unconstrained opaque type //~^ ERROR: unconstrained opaque type
type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [o, o] type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [*, *, o, o]
//~^ ERROR: unconstrained opaque type //~^ ERROR: unconstrained opaque type
type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [o, o] type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [*, *, o, o]
//~^ ERROR: unconstrained opaque type //~^ ERROR: unconstrained opaque type
} }
impl<'i> Foo<'i> for () { impl<'i> Foo<'i> for () {
type ImplicitCapture<'a> = impl Sized; //~ [o, o] type ImplicitCapture<'a> = impl Sized; //~ [*, *, o, o]
//~^ ERROR: unconstrained opaque type //~^ ERROR: unconstrained opaque type
type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [o, o] type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [*, *, o, o]
//~^ ERROR: unconstrained opaque type //~^ ERROR: unconstrained opaque type
type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [o, o] type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [*, *, o, o]
//~^ ERROR: unconstrained opaque type //~^ ERROR: unconstrained opaque type
} }

View file

@ -1,3 +1,15 @@
error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
--> $DIR/variance.rs:14:36
|
LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
| ^^
error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
--> $DIR/variance.rs:18:29
|
LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;
| ^^
error: unconstrained opaque type error: unconstrained opaque type
--> $DIR/variance.rs:8:29 --> $DIR/variance.rs:8:29
| |
@ -15,7 +27,7 @@ LL | type CapturedEarly<'a> = impl Sized + Captures<'a>;
= note: `CapturedEarly` must be used in combination with a concrete type within the same module = note: `CapturedEarly` must be used in combination with a concrete type within the same module
error: unconstrained opaque type error: unconstrained opaque type
--> $DIR/variance.rs:15:56 --> $DIR/variance.rs:14:56
| |
LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
| ^^^^^^^^^^ | ^^^^^^^^^^
@ -23,7 +35,7 @@ LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
= note: `NotCapturedLate` must be used in combination with a concrete type within the same module = note: `NotCapturedLate` must be used in combination with a concrete type within the same module
error: unconstrained opaque type error: unconstrained opaque type
--> $DIR/variance.rs:19:49 --> $DIR/variance.rs:18:49
| |
LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -86,71 +98,72 @@ LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
| |
= note: `ExplicitCaptureFromGat` must be used in combination with a concrete type within the same impl = note: `ExplicitCaptureFromGat` must be used in combination with a concrete type within the same impl
error: [o] error: [*, o]
--> $DIR/variance.rs:8:29 --> $DIR/variance.rs:8:29
| |
LL | type NotCapturedEarly<'a> = impl Sized; LL | type NotCapturedEarly<'a> = impl Sized;
| ^^^^^^^^^^ | ^^^^^^^^^^
error: [o] error: [*, o]
--> $DIR/variance.rs:11:26 --> $DIR/variance.rs:11:26
| |
LL | type CapturedEarly<'a> = impl Sized + Captures<'a>; LL | type CapturedEarly<'a> = impl Sized + Captures<'a>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: [o] error: [*, o, o]
--> $DIR/variance.rs:15:56 --> $DIR/variance.rs:14:56
| |
LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
| ^^^^^^^^^^ | ^^^^^^^^^^
error: [o] error: [*, o, o]
--> $DIR/variance.rs:19:49 --> $DIR/variance.rs:18:49
| |
LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: [o, o, o] error: [*, *, o, o, o]
--> $DIR/variance.rs:22:27 --> $DIR/variance.rs:22:27
| |
LL | type Bar<'a, 'b: 'b, T> = impl Sized; LL | type Bar<'a, 'b: 'b, T> = impl Sized;
| ^^^^^^^^^^ | ^^^^^^^^^^
error: [o, o] error: [*, *, o, o]
--> $DIR/variance.rs:34:32 --> $DIR/variance.rs:34:32
| |
LL | type ImplicitCapture<'a> = impl Sized; LL | type ImplicitCapture<'a> = impl Sized;
| ^^^^^^^^^^ | ^^^^^^^^^^
error: [o, o] error: [*, *, o, o]
--> $DIR/variance.rs:37:42 --> $DIR/variance.rs:37:42
| |
LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: [o, o] error: [*, *, o, o]
--> $DIR/variance.rs:40:39 --> $DIR/variance.rs:40:39
| |
LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: [o, o] error: [*, *, o, o]
--> $DIR/variance.rs:45:32 --> $DIR/variance.rs:45:32
| |
LL | type ImplicitCapture<'a> = impl Sized; LL | type ImplicitCapture<'a> = impl Sized;
| ^^^^^^^^^^ | ^^^^^^^^^^
error: [o, o] error: [*, *, o, o]
--> $DIR/variance.rs:48:42 --> $DIR/variance.rs:48:42
| |
LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: [o, o] error: [*, *, o, o]
--> $DIR/variance.rs:51:39 --> $DIR/variance.rs:51:39
| |
LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 22 previous errors error: aborting due to 24 previous errors
For more information about this error, try `rustc --explain E0657`.