Skip to content

Commit e4af4e5

Browse files
committedSep 8, 2023
Stabilize impl_trait_projections
1 parent f06b7c5 commit e4af4e5

17 files changed

+50
-226
lines changed
 

‎compiler/rustc_error_codes/src/error_codes/E0760.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ or `Self` that references lifetimes from a parent scope.
55

66
Erroneous code example:
77

8-
```compile_fail,edition2018
8+
```ignore,edition2018
99
struct S<'a>(&'a i32);
1010
1111
impl<'a> S<'a> {

‎compiler/rustc_feature/src/accepted.rs

+2
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ declare_features! (
197197
/// + `impl<I:Iterator> Iterator for &mut Iterator`
198198
/// + `impl Debug for Foo<'_>`
199199
(accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None),
200+
/// Allows referencing `Self` and projections in impl-trait.
201+
(accepted, impl_trait_projections, "CURRENT_RUSTC_VERSION", Some(103532), None),
200202
/// Allows using `a..=b` and `..=b` as inclusive range syntaxes.
201203
(accepted, inclusive_range_syntax, "1.26.0", Some(28237), None),
202204
/// Allows inferring outlives requirements (RFC 2093).

‎compiler/rustc_feature/src/active.rs

-2
Original file line numberDiff line numberDiff line change
@@ -465,8 +465,6 @@ declare_features! (
465465
(active, impl_trait_in_assoc_type, "1.70.0", Some(63063), None),
466466
/// Allows `impl Trait` as output type in `Fn` traits in return position of functions.
467467
(active, impl_trait_in_fn_trait_return, "1.64.0", Some(99697), None),
468-
/// Allows referencing `Self` and projections in impl-trait.
469-
(active, impl_trait_projections, "1.67.0", Some(103532), None),
470468
/// Allows using imported `main` function
471469
(active, imported_main, "1.53.0", Some(28937), None),
472470
/// Allows associated types in inherent impls.

‎compiler/rustc_hir_analysis/src/check/check.rs

+3-132
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,15 @@ use super::compare_impl_item::check_type_bounds;
55
use super::compare_impl_item::{compare_impl_method, compare_impl_ty};
66
use super::*;
77
use rustc_attr as attr;
8-
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan};
8+
use rustc_errors::{ErrorGuaranteed, MultiSpan};
99
use rustc_hir as hir;
10-
use rustc_hir::def::{CtorKind, DefKind, Res};
10+
use rustc_hir::def::{CtorKind, DefKind};
1111
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
12-
use rustc_hir::intravisit::Visitor;
13-
use rustc_hir::{ItemKind, Node, PathSegment};
14-
use rustc_infer::infer::opaque_types::ConstrainOpaqueTypeRegionVisitor;
12+
use rustc_hir::Node;
1513
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
1614
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
1715
use rustc_infer::traits::{Obligation, TraitEngineExt as _};
1816
use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
19-
use rustc_middle::hir::nested_filter;
2017
use rustc_middle::middle::stability::EvalResult;
2118
use rustc_middle::traits::DefiningAnchor;
2219
use rustc_middle::ty::fold::BottomUpFolder;
@@ -218,9 +215,6 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
218215
let args = GenericArgs::identity_for_item(tcx, item.owner_id);
219216
let span = tcx.def_span(item.owner_id.def_id);
220217

221-
if !tcx.features().impl_trait_projections {
222-
check_opaque_for_inheriting_lifetimes(tcx, item.owner_id.def_id, span);
223-
}
224218
if tcx.type_of(item.owner_id.def_id).instantiate_identity().references_error() {
225219
return;
226220
}
@@ -231,129 +225,6 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
231225
let _ = check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, &origin);
232226
}
233227

234-
/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
235-
/// in "inheriting lifetimes".
236-
#[instrument(level = "debug", skip(tcx, span))]
237-
pub(super) fn check_opaque_for_inheriting_lifetimes(
238-
tcx: TyCtxt<'_>,
239-
def_id: LocalDefId,
240-
span: Span,
241-
) {
242-
let item = tcx.hir().expect_item(def_id);
243-
debug!(?item, ?span);
244-
245-
struct ProhibitOpaqueVisitor<'tcx> {
246-
tcx: TyCtxt<'tcx>,
247-
opaque_identity_ty: Ty<'tcx>,
248-
parent_count: u32,
249-
references_parent_regions: bool,
250-
selftys: Vec<(Span, Option<String>)>,
251-
}
252-
253-
impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for ProhibitOpaqueVisitor<'tcx> {
254-
type BreakTy = Ty<'tcx>;
255-
256-
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
257-
debug!(?t, "root_visit_ty");
258-
if t == self.opaque_identity_ty {
259-
ControlFlow::Continue(())
260-
} else {
261-
t.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
262-
tcx: self.tcx,
263-
op: |region| {
264-
if let ty::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = *region
265-
&& index < self.parent_count
266-
{
267-
self.references_parent_regions= true;
268-
}
269-
},
270-
});
271-
if self.references_parent_regions {
272-
ControlFlow::Break(t)
273-
} else {
274-
ControlFlow::Continue(())
275-
}
276-
}
277-
}
278-
}
279-
280-
impl<'tcx> Visitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
281-
type NestedFilter = nested_filter::OnlyBodies;
282-
283-
fn nested_visit_map(&mut self) -> Self::Map {
284-
self.tcx.hir()
285-
}
286-
287-
fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
288-
match arg.kind {
289-
hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
290-
[PathSegment { res: Res::SelfTyParam { .. }, .. }] => {
291-
let impl_ty_name = None;
292-
self.selftys.push((path.span, impl_ty_name));
293-
}
294-
[PathSegment { res: Res::SelfTyAlias { alias_to: def_id, .. }, .. }] => {
295-
let impl_ty_name = Some(self.tcx.def_path_str(*def_id));
296-
self.selftys.push((path.span, impl_ty_name));
297-
}
298-
_ => {}
299-
},
300-
_ => {}
301-
}
302-
hir::intravisit::walk_ty(self, arg);
303-
}
304-
}
305-
306-
if let ItemKind::OpaqueTy(&hir::OpaqueTy {
307-
origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
308-
..
309-
}) = item.kind
310-
{
311-
let args = GenericArgs::identity_for_item(tcx, def_id);
312-
let opaque_identity_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
313-
let mut visitor = ProhibitOpaqueVisitor {
314-
opaque_identity_ty,
315-
parent_count: tcx.generics_of(def_id).parent_count as u32,
316-
references_parent_regions: false,
317-
tcx,
318-
selftys: vec![],
319-
};
320-
let prohibit_opaque = tcx
321-
.explicit_item_bounds(def_id)
322-
.instantiate_identity_iter_copied()
323-
.try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor));
324-
325-
if let Some(ty) = prohibit_opaque.break_value() {
326-
visitor.visit_item(&item);
327-
let is_async = match item.kind {
328-
ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
329-
matches!(origin, hir::OpaqueTyOrigin::AsyncFn(..))
330-
}
331-
_ => unreachable!(),
332-
};
333-
334-
let mut err = feature_err(
335-
&tcx.sess.parse_sess,
336-
sym::impl_trait_projections,
337-
span,
338-
format!(
339-
"`{}` return type cannot contain a projection or `Self` that references \
340-
lifetimes from a parent scope",
341-
if is_async { "async fn" } else { "impl Trait" },
342-
),
343-
);
344-
for (span, name) in visitor.selftys {
345-
err.span_suggestion(
346-
span,
347-
"consider spelling out the type instead",
348-
name.unwrap_or_else(|| format!("{ty:?}")),
349-
Applicability::MaybeIncorrect,
350-
);
351-
}
352-
err.emit();
353-
}
354-
}
355-
}
356-
357228
/// Checks that an opaque type does not contain cycles.
358229
pub(super) fn check_opaque_for_cycles<'tcx>(
359230
tcx: TyCtxt<'tcx>,

‎tests/ui/async-await/feature-self-return-type.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// edition:2018
2-
#![feature(impl_trait_projections)]
32

43
// This test checks that we emit the correct borrowck error when `Self` is used as a return type.
54
// See #61949 for context.

‎tests/ui/async-await/feature-self-return-type.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0597]: `bar` does not live long enough
2-
--> $DIR/feature-self-return-type.rs:22:18
2+
--> $DIR/feature-self-return-type.rs:21:18
33
|
44
LL | let x = {
55
| - borrow later stored here

‎tests/ui/async-await/in-trait/async-associated-types.rs

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// edition: 2021
33

44
#![feature(async_fn_in_trait)]
5-
#![feature(impl_trait_projections)]
65
#![allow(incomplete_features)]
76

87
use std::fmt::Debug;

‎tests/ui/async-await/issue-61949-self-return-type.rs

-28
This file was deleted.

‎tests/ui/async-await/issue-61949-self-return-type.stderr

-26
This file was deleted.

‎tests/ui/async-await/issues/issue-78600.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
// check-pass
12
// edition:2018
23

34
struct S<'a>(&'a i32);
45

56
impl<'a> S<'a> {
67
async fn new(i: &'a i32) -> Result<Self, ()> {
7-
//~^ ERROR: `async fn`
88
Ok(S(&22))
99
}
1010
}

‎tests/ui/async-await/issues/issue-78600.stderr

-14
This file was deleted.

‎tests/ui/impl-trait/bound-normalization-fail.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ mod lifetimes {
3939

4040
/// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further.
4141
fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
42-
//~^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
43-
//~| ERROR: type mismatch
42+
//~^ ERROR: type mismatch
4443
Foo(())
4544
}
4645
}

‎tests/ui/impl-trait/bound-normalization-fail.stderr

+3-13
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,12 @@ 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[E0658]: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
23-
--> $DIR/bound-normalization-fail.rs:41:41
24-
|
25-
LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
26-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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
30-
3122
error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as Trait<'a>>::Assoc`
3223
--> $DIR/bound-normalization-fail.rs:41:41
3324
|
3425
LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
3526
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as Trait<'a>>::Assoc`
36-
...
27+
LL |
3728
LL | Foo(())
3829
| ------- return type was inferred to be `Foo<()>` here
3930
|
@@ -49,7 +40,6 @@ help: consider constraining the associated type `<T as lifetimes::Trait<'a>>::As
4940
LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
5041
| ++++++++++++
5142

52-
error: aborting due to 3 previous errors
43+
error: aborting due to 2 previous errors
5344

54-
Some errors have detailed explanations: E0271, E0658.
55-
For more information about an error, try `rustc --explain E0271`.
45+
For more information about this error, try `rustc --explain E0271`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#![feature(rustc_attrs)]
2+
#![rustc_variance_of_opaques]
3+
4+
trait Bar<'a> {
5+
type Assoc: From<()>;
6+
}
7+
8+
fn foo<'a, T: Bar<'a>>() -> impl Into<T::Assoc> {
9+
//~^ ERROR [o, o]
10+
// captures both T and 'a invariantly
11+
()
12+
}
13+
14+
fn foo2<'a, T: Bar<'a>>() -> impl Into<T::Assoc> + 'a {
15+
//~^ ERROR [o, o, o]
16+
// captures both T and 'a invariantly, and also duplicates `'a`
17+
// i.e. the opaque looks like `impl Into<<T as Bar<'a>>::Assoc> + 'a_duplicated`
18+
()
19+
}
20+
21+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: [o, o]
2+
--> $DIR/capture-lifetime-not-in-hir.rs:8:29
3+
|
4+
LL | fn foo<'a, T: Bar<'a>>() -> impl Into<T::Assoc> {
5+
| ^^^^^^^^^^^^^^^^^^^
6+
7+
error: [o, o, o]
8+
--> $DIR/capture-lifetime-not-in-hir.rs:14:30
9+
|
10+
LL | fn foo2<'a, T: Bar<'a>>() -> impl Into<T::Assoc> + 'a {
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to 2 previous errors
14+

‎tests/ui/impl-trait/feature-self-return-type.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// edition:2018
2-
#![feature(impl_trait_projections)]
32

43
// This test checks that we emit the correct borrowck error when `Self` or a projection is used as
54
// a return type. See #61949 for context.

‎tests/ui/impl-trait/feature-self-return-type.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0597]: `bar` does not live long enough
2-
--> $DIR/feature-self-return-type.rs:23:22
2+
--> $DIR/feature-self-return-type.rs:22:22
33
|
44
LL | let x = {
55
| - borrow later stored here
@@ -12,7 +12,7 @@ LL | };
1212
| - `bar` dropped here while still borrowed
1313

1414
error[E0597]: `y` does not live long enough
15-
--> $DIR/feature-self-return-type.rs:63:17
15+
--> $DIR/feature-self-return-type.rs:62:17
1616
|
1717
LL | let x = {
1818
| - borrow later stored here
@@ -25,7 +25,7 @@ LL | };
2525
| - `y` dropped here while still borrowed
2626

2727
error[E0597]: `y` does not live long enough
28-
--> $DIR/feature-self-return-type.rs:95:17
28+
--> $DIR/feature-self-return-type.rs:94:17
2929
|
3030
LL | let x = {
3131
| - borrow later stored here

0 commit comments

Comments
 (0)
Please sign in to comment.