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(
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) => {
let ty = this.lower_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)
}

View File

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

View File

@ -367,14 +367,17 @@ fn check_opaque_type_parameter_valid(
span: Span,
) -> Result<(), ErrorGuaranteed> {
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 {
OpaqueTyOrigin::TyAlias { .. } => true,
OpaqueTyOrigin::AsyncFn(..) | OpaqueTyOrigin::FnReturn(..) => false,
let (parent, is_ty_alias) = match opaque_ty_hir.expect_opaque_ty().origin {
OpaqueTyOrigin::TyAlias { parent, .. } => (parent, true),
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();
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() {
return Err(guar);
}
@ -395,7 +398,7 @@ fn check_opaque_type_parameter_valid(
seen_params.entry(arg).or_default().push(i);
} else {
// 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();
return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam {
@ -409,10 +412,10 @@ fn check_opaque_type_parameter_valid(
for (_, indices) in seen_params {
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
.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();
#[allow(rustc::diagnostic_outside_of_impl)]
#[allow(rustc::untranslatable_diagnostic)]

View File

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

View File

@ -339,8 +339,9 @@ fn check_opaque_meets_bounds<'tcx>(
origin: &hir::OpaqueTyOrigin,
) -> Result<(), ErrorGuaranteed> {
let defining_use_anchor = match *origin {
hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did,
hir::OpaqueTyOrigin::TyAlias { .. } => tcx.impl_trait_parent(def_id),
hir::OpaqueTyOrigin::FnReturn(did)
| hir::OpaqueTyOrigin::AsyncFn(did)
| hir::OpaqueTyOrigin::TyAlias { parent: did, .. } => did,
};
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 args = match *origin {
hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => {
GenericArgs::identity_for_item(tcx, parent).extend_to(
tcx,
def_id.to_def_id(),
|param, _| tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local()).into(),
)
}
hir::OpaqueTyOrigin::TyAlias { .. } => GenericArgs::identity_for_item(tcx, def_id),
hir::OpaqueTyOrigin::FnReturn(parent)
| hir::OpaqueTyOrigin::AsyncFn(parent)
| hir::OpaqueTyOrigin::TyAlias { parent, .. } => GenericArgs::identity_for_item(
tcx, parent,
)
.extend_to(tcx, def_id.to_def_id(), |param, _| {
tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into()
}),
};
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)>,
) {
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 {
let dup_lifetime = ty::Region::new_early_param(
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.
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 {
origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent),
origin:
hir::OpaqueTyOrigin::FnReturn(parent)
| hir::OpaqueTyOrigin::AsyncFn(parent)
| hir::OpaqueTyOrigin::TyAlias { parent, .. },
generics,
..
}) => {
@ -683,26 +656,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
// the opaque_ty generics
let opaque_ty = self.tcx.hir().item(item_id);
match &opaque_ty.kind {
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
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(..),
..
}) => {}
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin: _, .. }) => {}
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) {
Node::Item(item) => match item.kind {
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),
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 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
// lifetime generics.
let variances = std::iter::repeat(ty::Invariant).take(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),
};
let mut variances = vec![ty::Invariant; generics.count()];
// Mark all lifetimes from parent generics as unused (Bivariant).
// This will be overridden later if required.

View File

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

View File

@ -1254,7 +1254,7 @@ impl<'tcx> TyCtxt<'tcx> {
if self.def_kind(scope) == DefKind::OpaqueTy {
// Lifetime params of opaque types are synthetic and thus irrelevant to
// 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;
}
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
/// lifetime of the function from which it originally as captured. If it is
/// a late-bound lifetime, this will represent the liberated (`ReLateParam`) lifetime
/// of the signature.
// 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.
pub fn map_rpit_lifetime_to_fn_lifetime(
pub fn map_opaque_lifetime_to_parent_lifetime(
self,
mut rpit_lifetime_param_def_id: LocalDefId,
mut opaque_lifetime_param_def_id: LocalDefId,
) -> ty::Region<'tcx> {
debug_assert!(
matches!(self.def_kind(rpit_lifetime_param_def_id), DefKind::LifetimeParam),
"{rpit_lifetime_param_def_id:?} is a {}",
self.def_descr(rpit_lifetime_param_def_id.to_def_id())
matches!(self.def_kind(opaque_lifetime_param_def_id), DefKind::LifetimeParam),
"{opaque_lifetime_param_def_id:?} is a {}",
self.def_descr(opaque_lifetime_param_def_id.to_def_id())
);
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, .. } =
self.hir_node_by_def_id(parent).expect_item().expect_opaque_ty();
let Some((lifetime, _)) = lifetime_mapping
.iter()
.find(|(_, duplicated_param)| *duplicated_param == rpit_lifetime_param_def_id)
.find(|(_, duplicated_param)| *duplicated_param == opaque_lifetime_param_def_id)
else {
bug!("duplicated lifetime param should be present");
};
@ -2256,7 +2256,7 @@ impl<'tcx> TyCtxt<'tcx> {
// of the opaque we mapped from. Continue mapping.
if matches!(self.def_kind(new_parent), DefKind::OpaqueTy) {
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;
}

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))
}
/// 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 {
if self.def_kind(def_id) != DefKind::AssocFn {
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.
for param in &generics.params[tcx.generics_of(fn_def_id).params.len()..] {
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(..)) {
mapping.insert(
orig_lt,

View File

@ -141,7 +141,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
trace!(?origin);
match origin {
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 !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) {
return;

View File

@ -7,7 +7,7 @@ pub trait Trait<'a> {
trait 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 () {
type Assoc = ();

View File

@ -1,8 +1,14 @@
error: cannot capture late-bound lifetime in type alias impl trait
--> $DIR/escaping-bound-var.rs:9:57
error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/escaping-bound-var.rs:9:25
|
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

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);
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)
}
type Moo<'a, 'b> = (i32, impl PartialEq<Moo<'b, 'a>> + std::fmt::Debug);
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)
}

View File

@ -10,28 +10,28 @@ LL | i
= help: the trait `PartialEq<Bar<'b, 'a>>` is not 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
|
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 | (42, i)
| ------- 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`
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
|
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 | (42, i)
| ------- 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`
error: aborting due to 3 previous errors

View File

@ -5,21 +5,21 @@
trait Captures<'a> {}
impl<T> Captures<'_> for T {}
type NotCapturedEarly<'a> = impl Sized; //~ [o]
type NotCapturedEarly<'a> = impl Sized; //~ [*, o]
//~^ ERROR: unconstrained opaque type
type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [o]
type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [*, o]
//~^ ERROR: unconstrained opaque type
// TAIT does *not* capture `'b`
type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ [o]
//~^ ERROR: unconstrained opaque type
type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ [*, o, o]
//~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level
//~| ERROR: unconstrained opaque type
// TAIT does *not* capture `'b`
type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; //~ [o]
//~^ ERROR: unconstrained opaque type
type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; //~ [*, o, o]
//~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level
//~| 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
trait Foo<'i> {
@ -31,24 +31,24 @@ trait Foo<'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
type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [o, o]
type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [*, *, o, o]
//~^ 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
}
impl<'i> Foo<'i> for () {
type ImplicitCapture<'a> = impl Sized; //~ [o, o]
type ImplicitCapture<'a> = impl Sized; //~ [*, *, o, o]
//~^ 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
type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [o, o]
type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [*, *, o, o]
//~^ 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
--> $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
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>;
| ^^^^^^^^^^
@ -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
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>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -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
error: [o]
error: [*, o]
--> $DIR/variance.rs:8:29
|
LL | type NotCapturedEarly<'a> = impl Sized;
| ^^^^^^^^^^
error: [o]
error: [*, o]
--> $DIR/variance.rs:11:26
|
LL | type CapturedEarly<'a> = impl Sized + Captures<'a>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: [o]
--> $DIR/variance.rs:15:56
error: [*, o, o]
--> $DIR/variance.rs:14:56
|
LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
| ^^^^^^^^^^
error: [o]
--> $DIR/variance.rs:19:49
error: [*, o, o]
--> $DIR/variance.rs:18:49
|
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
|
LL | type Bar<'a, 'b: 'b, T> = impl Sized;
| ^^^^^^^^^^
error: [o, o]
error: [*, *, o, o]
--> $DIR/variance.rs:34:32
|
LL | type ImplicitCapture<'a> = impl Sized;
| ^^^^^^^^^^
error: [o, o]
error: [*, *, o, o]
--> $DIR/variance.rs:37:42
|
LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: [o, o]
error: [*, *, o, o]
--> $DIR/variance.rs:40:39
|
LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: [o, o]
error: [*, *, o, o]
--> $DIR/variance.rs:45:32
|
LL | type ImplicitCapture<'a> = impl Sized;
| ^^^^^^^^^^
error: [o, o]
error: [*, *, o, o]
--> $DIR/variance.rs:48:42
|
LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: [o, o]
error: [*, *, o, o]
--> $DIR/variance.rs:51:39
|
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`.