Make TAITs capture all higher-ranked lifetimes in scope
This commit is contained in:
parent
9823f17315
commit
cf299ddb6e
17 changed files with 122 additions and 152 deletions
|
@ -275,7 +275,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
}
|
}
|
||||||
Some(ty) => this.lower_ty(
|
Some(ty) => this.lower_ty(
|
||||||
ty,
|
ty,
|
||||||
ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: false },
|
ImplTraitContext::TypeAliasesOpaqueTy {
|
||||||
|
origin: hir::OpaqueTyOrigin::TyAlias {
|
||||||
|
parent: this.local_def_id(id),
|
||||||
|
in_assoc_ty: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -936,7 +941,12 @@ 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::TypeAliasesOpaqueTy {
|
||||||
|
origin: hir::OpaqueTyOrigin::TyAlias {
|
||||||
|
parent: this.local_def_id(i.id),
|
||||||
|
in_assoc_ty: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
hir::ImplItemKind::Type(ty)
|
hir::ImplItemKind::Type(ty)
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,7 +271,10 @@ enum ImplTraitContext {
|
||||||
fn_kind: FnDeclKind,
|
fn_kind: FnDeclKind,
|
||||||
},
|
},
|
||||||
/// Impl trait in type aliases.
|
/// Impl trait in type aliases.
|
||||||
TypeAliasesOpaqueTy { in_assoc_ty: bool },
|
TypeAliasesOpaqueTy {
|
||||||
|
/// Origin: Always OpaqueTyOrigin::TypeAliasImplTrait
|
||||||
|
origin: hir::OpaqueTyOrigin,
|
||||||
|
},
|
||||||
/// `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.
|
||||||
|
@ -1426,15 +1429,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
Some(fn_kind),
|
Some(fn_kind),
|
||||||
itctx,
|
itctx,
|
||||||
),
|
),
|
||||||
ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self
|
ImplTraitContext::TypeAliasesOpaqueTy { origin } => self
|
||||||
.lower_opaque_impl_trait(
|
.lower_opaque_impl_trait(span, origin, *def_node_id, bounds, None, itctx),
|
||||||
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 +1549,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!(
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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,
|
||||||
},
|
},
|
||||||
|
|
|
@ -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_rpit_lifetime_to_fn_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);
|
||||||
|
|
|
@ -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),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 = ();
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue