From b77674d25467f521786cbfd450259b07bd2c378a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 24 Oct 2022 16:06:25 +0000 Subject: [PATCH] Make impl_trait_projections a feature gate. --- compiler/rustc_feature/src/active.rs | 2 + .../rustc_hir_analysis/src/check/check.rs | 19 ++-- compiler/rustc_span/src/symbol.rs | 1 + .../async-await/feature-self-return-type.rs | 28 +++++ .../feature-self-return-type.stderr | 15 +++ .../issue-61949-self-return-type.rs | 1 + .../issue-61949-self-return-type.stderr | 11 +- .../ui/async-await/issues/issue-78600.stderr | 7 +- .../bound-normalization-fail.stderr | 7 +- .../ui/impl-trait/feature-self-return-type.rs | 102 ++++++++++++++++++ .../feature-self-return-type.stderr | 39 +++++++ 11 files changed, 216 insertions(+), 16 deletions(-) create mode 100644 src/test/ui/async-await/feature-self-return-type.rs create mode 100644 src/test/ui/async-await/feature-self-return-type.stderr create mode 100644 src/test/ui/impl-trait/feature-self-return-type.rs create mode 100644 src/test/ui/impl-trait/feature-self-return-type.stderr diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index e94e038f928..56eaefc88e1 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -419,6 +419,8 @@ pub fn set(&self, features: &mut Features, span: Span) { (active, if_let_guard, "1.47.0", Some(51114), None), /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. (active, impl_trait_in_fn_trait_return, "1.64.0", Some(99697), None), + /// Allows referencing `Self` and projections in impl-trait. + (active, impl_trait_projections, "CURRENT_RUSTC_VERSION", None, None), /// Allows using imported `main` function (active, imported_main, "1.53.0", Some(28937), None), /// Allows associated types in inherent impls. diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index eddc7e0e055..256ecc60516 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -231,7 +231,9 @@ fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { let substs = InternalSubsts::identity_for_item(tcx, item.owner_id.to_def_id()); let span = tcx.def_span(item.owner_id.def_id); - check_opaque_for_inheriting_lifetimes(tcx, item.owner_id.def_id, span); + if !tcx.features().impl_trait_projections { + check_opaque_for_inheriting_lifetimes(tcx, item.owner_id.def_id, span); + } if tcx.type_of(item.owner_id.def_id).references_error() { return; } @@ -424,15 +426,16 @@ fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) { _ => unreachable!(), }; - let mut err = struct_span_err!( - tcx.sess, + let mut err = feature_err( + &tcx.sess.parse_sess, + sym::impl_trait_projections, span, - E0760, - "`{}` return type cannot contain a projection or `Self` that references lifetimes from \ - a parent scope", - if is_async { "async fn" } else { "impl Trait" }, + &format!( + "`{}` return type cannot contain a projection or `Self` that references \ + lifetimes from a parent scope", + if is_async { "async fn" } else { "impl Trait" }, + ), ); - for (span, name) in visitor.selftys { err.span_suggestion( span, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 54a61483a11..fd7456e8c9d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -816,6 +816,7 @@ impl_macros, impl_trait_in_bindings, impl_trait_in_fn_trait_return, + impl_trait_projections, implied_by, import, import_name_type, diff --git a/src/test/ui/async-await/feature-self-return-type.rs b/src/test/ui/async-await/feature-self-return-type.rs new file mode 100644 index 00000000000..41f887430c1 --- /dev/null +++ b/src/test/ui/async-await/feature-self-return-type.rs @@ -0,0 +1,28 @@ +// edition:2018 +#![feature(impl_trait_projections)] + +// This test checks that we emit the correct borrowck error when `Self` is used 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 { + Foo { + bar: &22 + } + } +} + +pub async fn foo() { + let x = { + let bar = 22; + Foo::new(&bar).await + //~^ ERROR `bar` does not live long enough + }; + drop(x); +} + +fn main() { } diff --git a/src/test/ui/async-await/feature-self-return-type.stderr b/src/test/ui/async-await/feature-self-return-type.stderr new file mode 100644 index 00000000000..8924683684f --- /dev/null +++ b/src/test/ui/async-await/feature-self-return-type.stderr @@ -0,0 +1,15 @@ +error[E0597]: `bar` does not live long enough + --> $DIR/feature-self-return-type.rs:22:18 + | +LL | let x = { + | - borrow later stored here +LL | let bar = 22; +LL | Foo::new(&bar).await + | ^^^^ borrowed value does not live long enough +LL | +LL | }; + | - `bar` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/async-await/issue-61949-self-return-type.rs b/src/test/ui/async-await/issue-61949-self-return-type.rs index d7bf34a4795..d73dbc6e828 100644 --- a/src/test/ui/async-await/issue-61949-self-return-type.rs +++ b/src/test/ui/async-await/issue-61949-self-return-type.rs @@ -1,4 +1,5 @@ // edition:2018 +// gate-test-impl_trait_projections // This test checks that `Self` is prohibited as a return type. See #61949 for context. diff --git a/src/test/ui/async-await/issue-61949-self-return-type.stderr b/src/test/ui/async-await/issue-61949-self-return-type.stderr index 5a769115989..638b197bc02 100644 --- a/src/test/ui/async-await/issue-61949-self-return-type.stderr +++ b/src/test/ui/async-await/issue-61949-self-return-type.stderr @@ -1,11 +1,14 @@ -error[E0760]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - --> $DIR/issue-61949-self-return-type.rs:10:40 +error[E0658]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope + --> $DIR/issue-61949-self-return-type.rs:11:40 | LL | pub async fn new(_bar: &'a i32) -> Self { | ^^^^ help: consider spelling out the type instead: `Foo<'a>` + | + = note: see issue #103532 for more information + = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable error[E0597]: `bar` does not live long enough - --> $DIR/issue-61949-self-return-type.rs:21:18 + --> $DIR/issue-61949-self-return-type.rs:22:18 | LL | let x = { | - borrow later stored here @@ -18,5 +21,5 @@ LL | }; error: aborting due to 2 previous errors -Some errors have detailed explanations: E0597, E0760. +Some errors have detailed explanations: E0597, E0658. For more information about an error, try `rustc --explain E0597`. diff --git a/src/test/ui/async-await/issues/issue-78600.stderr b/src/test/ui/async-await/issues/issue-78600.stderr index 92b66147106..37eafa996c5 100644 --- a/src/test/ui/async-await/issues/issue-78600.stderr +++ b/src/test/ui/async-await/issues/issue-78600.stderr @@ -1,11 +1,14 @@ -error[E0760]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope +error[E0658]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope --> $DIR/issue-78600.rs:6:33 | LL | async fn new(i: &'a i32) -> Result { | ^^^^^^^----^^^^^ | | | help: consider spelling out the type instead: `S<'a>` + | + = note: see issue #103532 for more information + = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable error: aborting due to previous error -For more information about this error, try `rustc --explain E0760`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index 2bccfd6cf11..a9fa2da569f 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -19,11 +19,14 @@ help: consider constraining the associated type `::Assoc LL | fn foo_fail>() -> impl FooLike { | ++++++++++++ -error[E0760]: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope +error[E0658]: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope --> $DIR/bound-normalization-fail.rs:41:41 | LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #103532 for more information + = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable error[E0271]: type mismatch resolving ` as FooLike>::Output == >::Assoc` --> $DIR/bound-normalization-fail.rs:41:41 @@ -48,5 +51,5 @@ LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { + pub bar: &'a i32, + } + + impl<'a> Foo<'a> { + pub fn new(_bar: &'a i32) -> impl Into { + Foo { + bar: &22 + } + } + } + + fn foo() { + let x = { + let bar = 22; + Foo::new(&bar).into() + //~^ ERROR `bar` does not live long enough + }; + drop(x); + } +} + +struct Foo(T); + +trait FooLike { + type Output; +} + +impl FooLike for Foo { + type Output = T; +} + +mod impl_trait { + use super::*; + + trait Trait { + type Assoc; + + fn make_assoc(self) -> Self::Assoc; + } + + /// `T::Assoc` can't be normalized any further here. + fn foo(x: T) -> impl FooLike { + Foo(x.make_assoc()) + } + + impl<'a> Trait for &'a () { + type Assoc = &'a (); + + fn make_assoc(self) -> &'a () { &() } + } + + fn usage() { + let x = { + let y = (); + foo(&y) + //~^ ERROR `y` does not live long enough + }; + drop(x); + } +} + +// Same with lifetimes in the trait + +mod lifetimes { + use super::*; + + trait Trait<'a> { + type Assoc; + + fn make_assoc(self) -> Self::Assoc; + } + + /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further. + fn foo<'a, T: Trait<'a>>(x: T) -> impl FooLike { + Foo(x.make_assoc()) + } + + impl<'a> Trait<'a> for &'a () { + type Assoc = &'a (); + + fn make_assoc(self) -> &'a () { &() } + } + + fn usage() { + let x = { + let y = (); + foo(&y) + //~^ ERROR `y` does not live long enough + }; + drop(x); + } +} + +fn main() { } diff --git a/src/test/ui/impl-trait/feature-self-return-type.stderr b/src/test/ui/impl-trait/feature-self-return-type.stderr new file mode 100644 index 00000000000..601e53b7694 --- /dev/null +++ b/src/test/ui/impl-trait/feature-self-return-type.stderr @@ -0,0 +1,39 @@ +error[E0597]: `bar` does not live long enough + --> $DIR/feature-self-return-type.rs:23:22 + | +LL | let x = { + | - borrow later stored here +LL | let bar = 22; +LL | Foo::new(&bar).into() + | ^^^^ borrowed value does not live long enough +LL | +LL | }; + | - `bar` dropped here while still borrowed + +error[E0597]: `y` does not live long enough + --> $DIR/feature-self-return-type.rs:63:17 + | +LL | let x = { + | - borrow later stored here +LL | let y = (); +LL | foo(&y) + | ^^ borrowed value does not live long enough +LL | +LL | }; + | - `y` dropped here while still borrowed + +error[E0597]: `y` does not live long enough + --> $DIR/feature-self-return-type.rs:95:17 + | +LL | let x = { + | - borrow later stored here +LL | let y = (); +LL | foo(&y) + | ^^ borrowed value does not live long enough +LL | +LL | }; + | - `y` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. -- 2.44.0