From e4af4e50831a23485e3e05646097bea26ff97a79 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 8 Sep 2023 03:00:59 +0000 Subject: [PATCH] Stabilize impl_trait_projections --- .../src/error_codes/E0760.md | 2 +- compiler/rustc_feature/src/accepted.rs | 2 + compiler/rustc_feature/src/active.rs | 2 - .../rustc_hir_analysis/src/check/check.rs | 135 +----------------- .../async-await/feature-self-return-type.rs | 1 - .../feature-self-return-type.stderr | 2 +- .../in-trait/async-associated-types.rs | 1 - .../issue-61949-self-return-type.rs | 28 ---- .../issue-61949-self-return-type.stderr | 26 ---- tests/ui/async-await/issues/issue-78600.rs | 2 +- .../ui/async-await/issues/issue-78600.stderr | 14 -- .../ui/impl-trait/bound-normalization-fail.rs | 3 +- .../bound-normalization-fail.stderr | 16 +-- .../impl-trait/capture-lifetime-not-in-hir.rs | 21 +++ .../capture-lifetime-not-in-hir.stderr | 14 ++ .../ui/impl-trait/feature-self-return-type.rs | 1 - .../feature-self-return-type.stderr | 6 +- 17 files changed, 50 insertions(+), 226 deletions(-) delete mode 100644 tests/ui/async-await/issue-61949-self-return-type.rs delete mode 100644 tests/ui/async-await/issue-61949-self-return-type.stderr delete mode 100644 tests/ui/async-await/issues/issue-78600.stderr create mode 100644 tests/ui/impl-trait/capture-lifetime-not-in-hir.rs create mode 100644 tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0760.md b/compiler/rustc_error_codes/src/error_codes/E0760.md index 85e5faada224e..9c4739f0df084 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0760.md +++ b/compiler/rustc_error_codes/src/error_codes/E0760.md @@ -5,7 +5,7 @@ or `Self` that references lifetimes from a parent scope. Erroneous code example: -```compile_fail,edition2018 +```ignore,edition2018 struct S<'a>(&'a i32); impl<'a> S<'a> { diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index afcf30d0b293e..6aa1e0c3e006b 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -197,6 +197,8 @@ declare_features! ( /// + `impl Iterator for &mut Iterator` /// + `impl Debug for Foo<'_>` (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), + /// Allows referencing `Self` and projections in impl-trait. + (accepted, impl_trait_projections, "CURRENT_RUSTC_VERSION", Some(103532), None), /// Allows using `a..=b` and `..=b` as inclusive range syntaxes. (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), /// Allows inferring outlives requirements (RFC 2093). diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 1941390dc4a1c..92615cc6d2a80 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -465,8 +465,6 @@ declare_features! ( (active, impl_trait_in_assoc_type, "1.70.0", Some(63063), 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, "1.67.0", Some(103532), 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 c0cf1ea34cf2d..99cfba6788756 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -5,18 +5,15 @@ use super::compare_impl_item::check_type_bounds; use super::compare_impl_item::{compare_impl_method, compare_impl_ty}; use super::*; use rustc_attr as attr; -use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; -use rustc_hir::def::{CtorKind, DefKind, Res}; +use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; -use rustc_hir::intravisit::Visitor; -use rustc_hir::{ItemKind, Node, PathSegment}; -use rustc_infer::infer::opaque_types::ConstrainOpaqueTypeRegionVisitor; +use rustc_hir::Node; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, TraitEngineExt as _}; use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS; -use rustc_middle::hir::nested_filter; use rustc_middle::middle::stability::EvalResult; use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::fold::BottomUpFolder; @@ -218,9 +215,6 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) { let args = GenericArgs::identity_for_item(tcx, item.owner_id); let span = tcx.def_span(item.owner_id.def_id); - 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).instantiate_identity().references_error() { return; } @@ -231,129 +225,6 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) { let _ = check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, &origin); } -/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result -/// in "inheriting lifetimes". -#[instrument(level = "debug", skip(tcx, span))] -pub(super) fn check_opaque_for_inheriting_lifetimes( - tcx: TyCtxt<'_>, - def_id: LocalDefId, - span: Span, -) { - let item = tcx.hir().expect_item(def_id); - debug!(?item, ?span); - - struct ProhibitOpaqueVisitor<'tcx> { - tcx: TyCtxt<'tcx>, - opaque_identity_ty: Ty<'tcx>, - parent_count: u32, - references_parent_regions: bool, - selftys: Vec<(Span, Option)>, - } - - impl<'tcx> ty::visit::TypeVisitor> for ProhibitOpaqueVisitor<'tcx> { - type BreakTy = Ty<'tcx>; - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - debug!(?t, "root_visit_ty"); - if t == self.opaque_identity_ty { - ControlFlow::Continue(()) - } else { - t.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { - tcx: self.tcx, - op: |region| { - if let ty::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = *region - && index < self.parent_count - { - self.references_parent_regions= true; - } - }, - }); - if self.references_parent_regions { - ControlFlow::Break(t) - } else { - ControlFlow::Continue(()) - } - } - } - } - - impl<'tcx> Visitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { - type NestedFilter = nested_filter::OnlyBodies; - - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() - } - - fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) { - match arg.kind { - hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments { - [PathSegment { res: Res::SelfTyParam { .. }, .. }] => { - let impl_ty_name = None; - self.selftys.push((path.span, impl_ty_name)); - } - [PathSegment { res: Res::SelfTyAlias { alias_to: def_id, .. }, .. }] => { - let impl_ty_name = Some(self.tcx.def_path_str(*def_id)); - self.selftys.push((path.span, impl_ty_name)); - } - _ => {} - }, - _ => {} - } - hir::intravisit::walk_ty(self, arg); - } - } - - if let ItemKind::OpaqueTy(&hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), - .. - }) = item.kind - { - let args = GenericArgs::identity_for_item(tcx, def_id); - let opaque_identity_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); - let mut visitor = ProhibitOpaqueVisitor { - opaque_identity_ty, - parent_count: tcx.generics_of(def_id).parent_count as u32, - references_parent_regions: false, - tcx, - selftys: vec![], - }; - let prohibit_opaque = tcx - .explicit_item_bounds(def_id) - .instantiate_identity_iter_copied() - .try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor)); - - if let Some(ty) = prohibit_opaque.break_value() { - visitor.visit_item(&item); - let is_async = match item.kind { - ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { - matches!(origin, hir::OpaqueTyOrigin::AsyncFn(..)) - } - _ => unreachable!(), - }; - - let mut err = feature_err( - &tcx.sess.parse_sess, - sym::impl_trait_projections, - 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" }, - ), - ); - for (span, name) in visitor.selftys { - err.span_suggestion( - span, - "consider spelling out the type instead", - name.unwrap_or_else(|| format!("{ty:?}")), - Applicability::MaybeIncorrect, - ); - } - err.emit(); - } - } -} - /// Checks that an opaque type does not contain cycles. pub(super) fn check_opaque_for_cycles<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/tests/ui/async-await/feature-self-return-type.rs b/tests/ui/async-await/feature-self-return-type.rs index 41f887430c1cb..ae6f766d247e6 100644 --- a/tests/ui/async-await/feature-self-return-type.rs +++ b/tests/ui/async-await/feature-self-return-type.rs @@ -1,5 +1,4 @@ // 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. diff --git a/tests/ui/async-await/feature-self-return-type.stderr b/tests/ui/async-await/feature-self-return-type.stderr index 747c54b669440..dc160bfbf6179 100644 --- a/tests/ui/async-await/feature-self-return-type.stderr +++ b/tests/ui/async-await/feature-self-return-type.stderr @@ -1,5 +1,5 @@ error[E0597]: `bar` does not live long enough - --> $DIR/feature-self-return-type.rs:22:18 + --> $DIR/feature-self-return-type.rs:21:18 | LL | let x = { | - borrow later stored here diff --git a/tests/ui/async-await/in-trait/async-associated-types.rs b/tests/ui/async-await/in-trait/async-associated-types.rs index 974f5aaff83c3..3e2739a164f17 100644 --- a/tests/ui/async-await/in-trait/async-associated-types.rs +++ b/tests/ui/async-await/in-trait/async-associated-types.rs @@ -2,7 +2,6 @@ // edition: 2021 #![feature(async_fn_in_trait)] -#![feature(impl_trait_projections)] #![allow(incomplete_features)] use std::fmt::Debug; diff --git a/tests/ui/async-await/issue-61949-self-return-type.rs b/tests/ui/async-await/issue-61949-self-return-type.rs deleted file mode 100644 index d73dbc6e828f3..0000000000000 --- a/tests/ui/async-await/issue-61949-self-return-type.rs +++ /dev/null @@ -1,28 +0,0 @@ -// edition:2018 -// gate-test-impl_trait_projections - -// 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 - //~^ ERROR `bar` does not live long enough - }; - drop(x); -} - -fn main() { } diff --git a/tests/ui/async-await/issue-61949-self-return-type.stderr b/tests/ui/async-await/issue-61949-self-return-type.stderr deleted file mode 100644 index ac85ed2887abc..0000000000000 --- a/tests/ui/async-await/issue-61949-self-return-type.stderr +++ /dev/null @@ -1,26 +0,0 @@ -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:22:18 - | -LL | let x = { - | - borrow later stored here -LL | let bar = 22; - | --- binding `bar` declared here -LL | Foo::new(&bar).await - | ^^^^ borrowed value does not live long enough -LL | -LL | }; - | - `bar` dropped here while still borrowed - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0597, E0658. -For more information about an error, try `rustc --explain E0597`. diff --git a/tests/ui/async-await/issues/issue-78600.rs b/tests/ui/async-await/issues/issue-78600.rs index 8aaeaecf3e1da..4303fc7952f2b 100644 --- a/tests/ui/async-await/issues/issue-78600.rs +++ b/tests/ui/async-await/issues/issue-78600.rs @@ -1,10 +1,10 @@ +// check-pass // edition:2018 struct S<'a>(&'a i32); impl<'a> S<'a> { async fn new(i: &'a i32) -> Result { - //~^ ERROR: `async fn` Ok(S(&22)) } } diff --git a/tests/ui/async-await/issues/issue-78600.stderr b/tests/ui/async-await/issues/issue-78600.stderr deleted file mode 100644 index 37eafa996c535..0000000000000 --- a/tests/ui/async-await/issues/issue-78600.stderr +++ /dev/null @@ -1,14 +0,0 @@ -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 E0658`. diff --git a/tests/ui/impl-trait/bound-normalization-fail.rs b/tests/ui/impl-trait/bound-normalization-fail.rs index 3329592478d6f..566a4a7adccb9 100644 --- a/tests/ui/impl-trait/bound-normalization-fail.rs +++ b/tests/ui/impl-trait/bound-normalization-fail.rs @@ -39,8 +39,7 @@ mod lifetimes { /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further. fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { - //~^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - //~| ERROR: type mismatch + //~^ ERROR: type mismatch Foo(()) } } diff --git a/tests/ui/impl-trait/bound-normalization-fail.stderr b/tests/ui/impl-trait/bound-normalization-fail.stderr index f04a753a0e8bd..fcac9ac34dbc3 100644 --- a/tests/ui/impl-trait/bound-normalization-fail.stderr +++ b/tests/ui/impl-trait/bound-normalization-fail.stderr @@ -19,21 +19,12 @@ help: consider constraining the associated type `::Assoc LL | fn foo_fail>() -> impl FooLike { | ++++++++++++ -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 | LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == >::Assoc` -... +LL | LL | Foo(()) | ------- return type was inferred to be `Foo<()>` here | @@ -49,7 +40,6 @@ help: consider constraining the associated type `>::As LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { | ++++++++++++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0271, E0658. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs b/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs new file mode 100644 index 0000000000000..9c067cb693444 --- /dev/null +++ b/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs @@ -0,0 +1,21 @@ +#![feature(rustc_attrs)] +#![rustc_variance_of_opaques] + +trait Bar<'a> { + type Assoc: From<()>; +} + +fn foo<'a, T: Bar<'a>>() -> impl Into { + //~^ ERROR [o, o] + // captures both T and 'a invariantly + () +} + +fn foo2<'a, T: Bar<'a>>() -> impl Into + 'a { + //~^ ERROR [o, o, o] + // captures both T and 'a invariantly, and also duplicates `'a` + // i.e. the opaque looks like `impl Into<>::Assoc> + 'a_duplicated` + () +} + +fn main() {} diff --git a/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr b/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr new file mode 100644 index 0000000000000..9d52001b02460 --- /dev/null +++ b/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr @@ -0,0 +1,14 @@ +error: [o, o] + --> $DIR/capture-lifetime-not-in-hir.rs:8:29 + | +LL | fn foo<'a, T: Bar<'a>>() -> impl Into { + | ^^^^^^^^^^^^^^^^^^^ + +error: [o, o, o] + --> $DIR/capture-lifetime-not-in-hir.rs:14:30 + | +LL | fn foo2<'a, T: Bar<'a>>() -> impl Into + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/impl-trait/feature-self-return-type.rs b/tests/ui/impl-trait/feature-self-return-type.rs index 51877e9cc3c43..7555df1b2c709 100644 --- a/tests/ui/impl-trait/feature-self-return-type.rs +++ b/tests/ui/impl-trait/feature-self-return-type.rs @@ -1,5 +1,4 @@ // edition:2018 -#![feature(impl_trait_projections)] // This test checks that we emit the correct borrowck error when `Self` or a projection is used as // a return type. See #61949 for context. diff --git a/tests/ui/impl-trait/feature-self-return-type.stderr b/tests/ui/impl-trait/feature-self-return-type.stderr index b9b8d00ce308b..e7113a9dfb1b9 100644 --- a/tests/ui/impl-trait/feature-self-return-type.stderr +++ b/tests/ui/impl-trait/feature-self-return-type.stderr @@ -1,5 +1,5 @@ error[E0597]: `bar` does not live long enough - --> $DIR/feature-self-return-type.rs:23:22 + --> $DIR/feature-self-return-type.rs:22:22 | LL | let x = { | - borrow later stored here @@ -12,7 +12,7 @@ LL | }; | - `bar` dropped here while still borrowed error[E0597]: `y` does not live long enough - --> $DIR/feature-self-return-type.rs:63:17 + --> $DIR/feature-self-return-type.rs:62:17 | LL | let x = { | - borrow later stored here @@ -25,7 +25,7 @@ LL | }; | - `y` dropped here while still borrowed error[E0597]: `y` does not live long enough - --> $DIR/feature-self-return-type.rs:95:17 + --> $DIR/feature-self-return-type.rs:94:17 | LL | let x = { | - borrow later stored here