Skip to content

Commit b77674d

Browse files
committed
Make impl_trait_projections a feature gate.
1 parent 47de11f commit b77674d

File tree

11 files changed

+216
-16
lines changed

11 files changed

+216
-16
lines changed

compiler/rustc_feature/src/active.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,8 @@ declare_features! (
419419
(active, if_let_guard, "1.47.0", Some(51114), None),
420420
/// Allows `impl Trait` as output type in `Fn` traits in return position of functions.
421421
(active, impl_trait_in_fn_trait_return, "1.64.0", Some(99697), None),
422+
/// Allows referencing `Self` and projections in impl-trait.
423+
(active, impl_trait_projections, "CURRENT_RUSTC_VERSION", None, None),
422424
/// Allows using imported `main` function
423425
(active, imported_main, "1.53.0", Some(28937), None),
424426
/// Allows associated types in inherent impls.

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,9 @@ fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
231231
let substs = InternalSubsts::identity_for_item(tcx, item.owner_id.to_def_id());
232232
let span = tcx.def_span(item.owner_id.def_id);
233233

234-
check_opaque_for_inheriting_lifetimes(tcx, item.owner_id.def_id, span);
234+
if !tcx.features().impl_trait_projections {
235+
check_opaque_for_inheriting_lifetimes(tcx, item.owner_id.def_id, span);
236+
}
235237
if tcx.type_of(item.owner_id.def_id).references_error() {
236238
return;
237239
}
@@ -424,15 +426,16 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
424426
_ => unreachable!(),
425427
};
426428

427-
let mut err = struct_span_err!(
428-
tcx.sess,
429+
let mut err = feature_err(
430+
&tcx.sess.parse_sess,
431+
sym::impl_trait_projections,
429432
span,
430-
E0760,
431-
"`{}` return type cannot contain a projection or `Self` that references lifetimes from \
432-
a parent scope",
433-
if is_async { "async fn" } else { "impl Trait" },
433+
&format!(
434+
"`{}` return type cannot contain a projection or `Self` that references \
435+
lifetimes from a parent scope",
436+
if is_async { "async fn" } else { "impl Trait" },
437+
),
434438
);
435-
436439
for (span, name) in visitor.selftys {
437440
err.span_suggestion(
438441
span,

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,7 @@ symbols! {
816816
impl_macros,
817817
impl_trait_in_bindings,
818818
impl_trait_in_fn_trait_return,
819+
impl_trait_projections,
819820
implied_by,
820821
import,
821822
import_name_type,
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// edition:2018
2+
#![feature(impl_trait_projections)]
3+
4+
// This test checks that we emit the correct borrowck error when `Self` is used as a return type.
5+
// See #61949 for context.
6+
7+
pub struct Foo<'a> {
8+
pub bar: &'a i32,
9+
}
10+
11+
impl<'a> Foo<'a> {
12+
pub async fn new(_bar: &'a i32) -> Self {
13+
Foo {
14+
bar: &22
15+
}
16+
}
17+
}
18+
19+
pub async fn foo() {
20+
let x = {
21+
let bar = 22;
22+
Foo::new(&bar).await
23+
//~^ ERROR `bar` does not live long enough
24+
};
25+
drop(x);
26+
}
27+
28+
fn main() { }
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0597]: `bar` does not live long enough
2+
--> $DIR/feature-self-return-type.rs:22:18
3+
|
4+
LL | let x = {
5+
| - borrow later stored here
6+
LL | let bar = 22;
7+
LL | Foo::new(&bar).await
8+
| ^^^^ borrowed value does not live long enough
9+
LL |
10+
LL | };
11+
| - `bar` dropped here while still borrowed
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0597`.

src/test/ui/async-await/issue-61949-self-return-type.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// edition:2018
2+
// gate-test-impl_trait_projections
23

34
// This test checks that `Self` is prohibited as a return type. See #61949 for context.
45

src/test/ui/async-await/issue-61949-self-return-type.stderr

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
error[E0760]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
2-
--> $DIR/issue-61949-self-return-type.rs:10:40
1+
error[E0658]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
2+
--> $DIR/issue-61949-self-return-type.rs:11:40
33
|
44
LL | pub async fn new(_bar: &'a i32) -> Self {
55
| ^^^^ help: consider spelling out the type instead: `Foo<'a>`
6+
|
7+
= note: see issue #103532 <https://github.com/rust-lang/rust/issues/103532> for more information
8+
= help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable
69

710
error[E0597]: `bar` does not live long enough
8-
--> $DIR/issue-61949-self-return-type.rs:21:18
11+
--> $DIR/issue-61949-self-return-type.rs:22:18
912
|
1013
LL | let x = {
1114
| - borrow later stored here
@@ -18,5 +21,5 @@ LL | };
1821

1922
error: aborting due to 2 previous errors
2023

21-
Some errors have detailed explanations: E0597, E0760.
24+
Some errors have detailed explanations: E0597, E0658.
2225
For more information about an error, try `rustc --explain E0597`.
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
error[E0760]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
1+
error[E0658]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
22
--> $DIR/issue-78600.rs:6:33
33
|
44
LL | async fn new(i: &'a i32) -> Result<Self, ()> {
55
| ^^^^^^^----^^^^^
66
| |
77
| help: consider spelling out the type instead: `S<'a>`
8+
|
9+
= note: see issue #103532 <https://github.com/rust-lang/rust/issues/103532> for more information
10+
= help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable
811

912
error: aborting due to previous error
1013

11-
For more information about this error, try `rustc --explain E0760`.
14+
For more information about this error, try `rustc --explain E0658`.

src/test/ui/impl-trait/bound-normalization-fail.stderr

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,14 @@ help: consider constraining the associated type `<T as impl_trait::Trait>::Assoc
1919
LL | fn foo_fail<T: Trait<Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
2020
| ++++++++++++
2121

22-
error[E0760]: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
22+
error[E0658]: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
2323
--> $DIR/bound-normalization-fail.rs:41:41
2424
|
2525
LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
2626
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
27+
|
28+
= note: see issue #103532 <https://github.com/rust-lang/rust/issues/103532> for more information
29+
= help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable
2730

2831
error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'a>>::Assoc`
2932
--> $DIR/bound-normalization-fail.rs:41:41
@@ -48,5 +51,5 @@ LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output = T
4851

4952
error: aborting due to 3 previous errors
5053

51-
Some errors have detailed explanations: E0271, E0760.
54+
Some errors have detailed explanations: E0271, E0658.
5255
For more information about an error, try `rustc --explain E0271`.
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// edition:2018
2+
#![feature(impl_trait_projections)]
3+
4+
// This test checks that we emit the correct borrowck error when `Self` or a projection is used as
5+
// a return type. See #61949 for context.
6+
7+
mod with_self {
8+
pub struct Foo<'a> {
9+
pub bar: &'a i32,
10+
}
11+
12+
impl<'a> Foo<'a> {
13+
pub fn new(_bar: &'a i32) -> impl Into<Self> {
14+
Foo {
15+
bar: &22
16+
}
17+
}
18+
}
19+
20+
fn foo() {
21+
let x = {
22+
let bar = 22;
23+
Foo::new(&bar).into()
24+
//~^ ERROR `bar` does not live long enough
25+
};
26+
drop(x);
27+
}
28+
}
29+
30+
struct Foo<T>(T);
31+
32+
trait FooLike {
33+
type Output;
34+
}
35+
36+
impl<T> FooLike for Foo<T> {
37+
type Output = T;
38+
}
39+
40+
mod impl_trait {
41+
use super::*;
42+
43+
trait Trait {
44+
type Assoc;
45+
46+
fn make_assoc(self) -> Self::Assoc;
47+
}
48+
49+
/// `T::Assoc` can't be normalized any further here.
50+
fn foo<T: Trait>(x: T) -> impl FooLike<Output = T::Assoc> {
51+
Foo(x.make_assoc())
52+
}
53+
54+
impl<'a> Trait for &'a () {
55+
type Assoc = &'a ();
56+
57+
fn make_assoc(self) -> &'a () { &() }
58+
}
59+
60+
fn usage() {
61+
let x = {
62+
let y = ();
63+
foo(&y)
64+
//~^ ERROR `y` does not live long enough
65+
};
66+
drop(x);
67+
}
68+
}
69+
70+
// Same with lifetimes in the trait
71+
72+
mod lifetimes {
73+
use super::*;
74+
75+
trait Trait<'a> {
76+
type Assoc;
77+
78+
fn make_assoc(self) -> Self::Assoc;
79+
}
80+
81+
/// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further.
82+
fn foo<'a, T: Trait<'a>>(x: T) -> impl FooLike<Output = T::Assoc> {
83+
Foo(x.make_assoc())
84+
}
85+
86+
impl<'a> Trait<'a> for &'a () {
87+
type Assoc = &'a ();
88+
89+
fn make_assoc(self) -> &'a () { &() }
90+
}
91+
92+
fn usage() {
93+
let x = {
94+
let y = ();
95+
foo(&y)
96+
//~^ ERROR `y` does not live long enough
97+
};
98+
drop(x);
99+
}
100+
}
101+
102+
fn main() { }
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error[E0597]: `bar` does not live long enough
2+
--> $DIR/feature-self-return-type.rs:23:22
3+
|
4+
LL | let x = {
5+
| - borrow later stored here
6+
LL | let bar = 22;
7+
LL | Foo::new(&bar).into()
8+
| ^^^^ borrowed value does not live long enough
9+
LL |
10+
LL | };
11+
| - `bar` dropped here while still borrowed
12+
13+
error[E0597]: `y` does not live long enough
14+
--> $DIR/feature-self-return-type.rs:63:17
15+
|
16+
LL | let x = {
17+
| - borrow later stored here
18+
LL | let y = ();
19+
LL | foo(&y)
20+
| ^^ borrowed value does not live long enough
21+
LL |
22+
LL | };
23+
| - `y` dropped here while still borrowed
24+
25+
error[E0597]: `y` does not live long enough
26+
--> $DIR/feature-self-return-type.rs:95:17
27+
|
28+
LL | let x = {
29+
| - borrow later stored here
30+
LL | let y = ();
31+
LL | foo(&y)
32+
| ^^ borrowed value does not live long enough
33+
LL |
34+
LL | };
35+
| - `y` dropped here while still borrowed
36+
37+
error: aborting due to 3 previous errors
38+
39+
For more information about this error, try `rustc --explain E0597`.

0 commit comments

Comments
 (0)