mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-27 06:14:55 +00:00
Rollup merge of #62849 - davidtwco:prohibit-inheriting-lifetimes, r=nikomatsakis
typeck: Prohibit RPIT types that inherit lifetimes Part of #61949. This PR prohibits return position `impl Trait` types that "inherit lifetimes" from the parent scope. The intent is to forbid cases that are challenging until they can be addressed properly. cc @nikomatsakis
This commit is contained in:
commit
3f18112079
@ -1325,12 +1325,94 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
|
|||||||
check_packed(tcx, span, def_id);
|
check_packed(tcx, span, def_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
|
||||||
|
/// projections that would result in "inheriting lifetimes".
|
||||||
fn check_opaque<'tcx>(
|
fn check_opaque<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
substs: SubstsRef<'tcx>,
|
substs: SubstsRef<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
origin: &hir::OpaqueTyOrigin
|
origin: &hir::OpaqueTyOrigin,
|
||||||
|
) {
|
||||||
|
check_opaque_for_inheriting_lifetimes(tcx, def_id, span);
|
||||||
|
check_opaque_for_cycles(tcx, def_id, substs, span, origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
|
||||||
|
/// in "inheriting lifetimes".
|
||||||
|
fn check_opaque_for_inheriting_lifetimes(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
def_id: DefId,
|
||||||
|
span: Span,
|
||||||
|
) {
|
||||||
|
let item = tcx.hir().expect_item(
|
||||||
|
tcx.hir().as_local_hir_id(def_id).expect("opaque type is not local"));
|
||||||
|
debug!("check_opaque_for_inheriting_lifetimes: def_id={:?} span={:?} item={:?}",
|
||||||
|
def_id, span, item);
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct ProhibitOpaqueVisitor<'tcx> {
|
||||||
|
opaque_identity_ty: Ty<'tcx>,
|
||||||
|
generics: &'tcx ty::Generics,
|
||||||
|
};
|
||||||
|
|
||||||
|
impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
|
||||||
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
|
||||||
|
debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t);
|
||||||
|
if t == self.opaque_identity_ty { false } else { t.super_visit_with(self) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
|
||||||
|
debug!("check_opaque_for_inheriting_lifetimes: (visit_region) r={:?}", r);
|
||||||
|
if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r {
|
||||||
|
return *index < self.generics.parent_count as u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
r.super_visit_with(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let prohibit_opaque = match item.node {
|
||||||
|
ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::AsyncFn, .. }) |
|
||||||
|
ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn, .. }) => {
|
||||||
|
let mut visitor = ProhibitOpaqueVisitor {
|
||||||
|
opaque_identity_ty: tcx.mk_opaque(
|
||||||
|
def_id, InternalSubsts::identity_for_item(tcx, def_id)),
|
||||||
|
generics: tcx.generics_of(def_id),
|
||||||
|
};
|
||||||
|
debug!("check_opaque_for_inheriting_lifetimes: visitor={:?}", visitor);
|
||||||
|
|
||||||
|
tcx.predicates_of(def_id).predicates.iter().any(
|
||||||
|
|(predicate, _)| predicate.visit_with(&mut visitor))
|
||||||
|
},
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!("check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}", prohibit_opaque);
|
||||||
|
if prohibit_opaque {
|
||||||
|
let is_async = match item.node {
|
||||||
|
ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => match origin {
|
||||||
|
hir::OpaqueTyOrigin::AsyncFn => true,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
tcx.sess.span_err(span, &format!(
|
||||||
|
"`{}` return type cannot contain a projection or `Self` that references lifetimes from \
|
||||||
|
a parent scope",
|
||||||
|
if is_async { "async fn" } else { "impl Trait" },
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks that an opaque type does not contain cycles.
|
||||||
|
fn check_opaque_for_cycles<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
def_id: DefId,
|
||||||
|
substs: SubstsRef<'tcx>,
|
||||||
|
span: Span,
|
||||||
|
origin: &hir::OpaqueTyOrigin,
|
||||||
) {
|
) {
|
||||||
if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id, substs) {
|
if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id, substs) {
|
||||||
if let hir::OpaqueTyOrigin::AsyncFn = origin {
|
if let hir::OpaqueTyOrigin::AsyncFn = origin {
|
||||||
|
28
src/test/ui/async-await/issue-61949-self-return-type.rs
Normal file
28
src/test/ui/async-await/issue-61949-self-return-type.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// ignore-tidy-linelength
|
||||||
|
// edition:2018
|
||||||
|
#![feature(async_await)]
|
||||||
|
|
||||||
|
// This test checks that `Self` is prohibited as a return type. See #61949 for context.
|
||||||
|
|
||||||
|
pub struct Foo<'a> {
|
||||||
|
pub bar: &'a i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Foo<'a> {
|
||||||
|
pub async fn new(_bar: &'a i32) -> Self {
|
||||||
|
//~^ ERROR `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
|
||||||
|
Foo {
|
||||||
|
bar: &22
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn foo() {
|
||||||
|
let x = {
|
||||||
|
let bar = 22;
|
||||||
|
Foo::new(&bar).await
|
||||||
|
};
|
||||||
|
drop(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() { }
|
@ -0,0 +1,8 @@
|
|||||||
|
error: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
|
||||||
|
--> $DIR/issue-61949-self-return-type.rs:12:40
|
||||||
|
|
|
||||||
|
LL | pub async fn new(_bar: &'a i32) -> Self {
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
@ -1,4 +1,5 @@
|
|||||||
// compile-fail
|
// compile-fail
|
||||||
|
// ignore-tidy-linelength
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
#![feature(async_await)]
|
#![feature(async_await)]
|
||||||
@ -44,7 +45,8 @@ mod lifetimes {
|
|||||||
|
|
||||||
/// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further.
|
/// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further.
|
||||||
fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
|
fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
|
||||||
//~^ ERROR: type mismatch
|
//~^ ERROR: type mismatch
|
||||||
|
//~^^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
|
||||||
Foo(())
|
Foo(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash
|
warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash
|
||||||
--> $DIR/bound-normalization-fail.rs:5:12
|
--> $DIR/bound-normalization-fail.rs:6:12
|
||||||
|
|
|
|
||||||
LL | #![feature(impl_trait_in_bindings)]
|
LL | #![feature(impl_trait_in_bindings)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -7,7 +7,7 @@ LL | #![feature(impl_trait_in_bindings)]
|
|||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
|
error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
|
||||||
--> $DIR/bound-normalization-fail.rs:29:32
|
--> $DIR/bound-normalization-fail.rs:30:32
|
||||||
|
|
|
|
||||||
LL | fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> {
|
LL | fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found associated type
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found associated type
|
||||||
@ -16,8 +16,14 @@ LL | fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> {
|
|||||||
found type `<T as impl_trait::Trait>::Assoc`
|
found type `<T as impl_trait::Trait>::Assoc`
|
||||||
= note: the return type of a function must have a statically known size
|
= note: the return type of a function must have a statically known size
|
||||||
|
|
||||||
|
error: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
|
||||||
|
--> $DIR/bound-normalization-fail.rs:47:41
|
||||||
|
|
|
||||||
|
LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'static>>::Assoc`
|
error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'static>>::Assoc`
|
||||||
--> $DIR/bound-normalization-fail.rs:46:41
|
--> $DIR/bound-normalization-fail.rs:47:41
|
||||||
|
|
|
|
||||||
LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
|
LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found associated type
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found associated type
|
||||||
@ -26,6 +32,6 @@ LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
|
|||||||
found type `<T as lifetimes::Trait<'static>>::Assoc`
|
found type `<T as lifetimes::Trait<'static>>::Assoc`
|
||||||
= note: the return type of a function must have a statically known size
|
= note: the return type of a function must have a statically known size
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0271`.
|
For more information about this error, try `rustc --explain E0271`.
|
||||||
|
Loading…
Reference in New Issue
Block a user