about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-09-08 03:00:59 +0000
committerMichael Goulet <michael@errs.io>2023-09-08 03:45:36 +0000
commite4af4e50831a23485e3e05646097bea26ff97a79 (patch)
treecf264546b23f4a6666789c93566e87756bfe8ba3
parentf06b7c59a383d51eee35470fd9cd1e0e545b5a5e (diff)
downloadrust-e4af4e50831a23485e3e05646097bea26ff97a79.tar.gz
rust-e4af4e50831a23485e3e05646097bea26ff97a79.zip
Stabilize impl_trait_projections
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0760.md2
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs135
-rw-r--r--tests/ui/async-await/feature-self-return-type.rs1
-rw-r--r--tests/ui/async-await/feature-self-return-type.stderr2
-rw-r--r--tests/ui/async-await/in-trait/async-associated-types.rs1
-rw-r--r--tests/ui/async-await/issue-61949-self-return-type.rs28
-rw-r--r--tests/ui/async-await/issue-61949-self-return-type.stderr26
-rw-r--r--tests/ui/async-await/issues/issue-78600.rs2
-rw-r--r--tests/ui/async-await/issues/issue-78600.stderr14
-rw-r--r--tests/ui/impl-trait/bound-normalization-fail.rs3
-rw-r--r--tests/ui/impl-trait/bound-normalization-fail.stderr16
-rw-r--r--tests/ui/impl-trait/capture-lifetime-not-in-hir.rs21
-rw-r--r--tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr14
-rw-r--r--tests/ui/impl-trait/feature-self-return-type.rs1
-rw-r--r--tests/ui/impl-trait/feature-self-return-type.stderr6
17 files changed, 50 insertions, 226 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes/E0760.md b/compiler/rustc_error_codes/src/error_codes/E0760.md
index 85e5faada22..9c4739f0df0 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 afcf30d0b29..6aa1e0c3e00 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -197,6 +197,8 @@ declare_features! (
     /// + `impl<I:Iterator> 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 1941390dc4a..92615cc6d2a 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 c0cf1ea34cf..99cfba67887 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<String>)>,
-    }
-
-    impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for ProhibitOpaqueVisitor<'tcx> {
-        type BreakTy = Ty<'tcx>;
-
-        fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-            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 41f887430c1..ae6f766d247 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 747c54b6694..dc160bfbf61 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 974f5aaff83..3e2739a164f 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 d73dbc6e828..00000000000
--- 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 ac85ed2887a..00000000000
--- 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 <https://github.com/rust-lang/rust/issues/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 8aaeaecf3e1..4303fc7952f 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<Self, ()> {
-        //~^ 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 37eafa996c5..00000000000
--- 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<Self, ()> {
-   |                                 ^^^^^^^----^^^^^
-   |                                        |
-   |                                        help: consider spelling out the type instead: `S<'a>`
-   |
-   = note: see issue #103532 <https://github.com/rust-lang/rust/issues/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 3329592478d..566a4a7adcc 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<Output = T::Assoc> {
-        //~^ 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 f04a753a0e8..fcac9ac34db 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 `<T as impl_trait::Trait>::Assoc
 LL |     fn foo_fail<T: Trait<Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
    |                         ++++++++++++
 
-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<Output = T::Assoc> {
-   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #103532 <https://github.com/rust-lang/rust/issues/103532> for more information
-   = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable
-
 error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as Trait<'a>>::Assoc`
   --> $DIR/bound-normalization-fail.rs:41:41
    |
 LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as Trait<'a>>::Assoc`
-...
+LL |
 LL |         Foo(())
    |         ------- return type was inferred to be `Foo<()>` here
    |
@@ -49,7 +40,6 @@ help: consider constraining the associated type `<T as lifetimes::Trait<'a>>::As
 LL |     fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
    |                                 ++++++++++++
 
-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 00000000000..9c067cb6934
--- /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<T::Assoc> {
+    //~^ ERROR [o, o]
+    // captures both T and 'a invariantly
+    ()
+}
+
+fn foo2<'a, T: Bar<'a>>() -> impl Into<T::Assoc> + 'a {
+    //~^ ERROR [o, o, o]
+    // captures both T and 'a invariantly, and also duplicates `'a`
+    // i.e. the opaque looks like `impl Into<<T as Bar<'a>>::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 00000000000..9d52001b024
--- /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<T::Assoc> {
+   |                             ^^^^^^^^^^^^^^^^^^^
+
+error: [o, o, o]
+  --> $DIR/capture-lifetime-not-in-hir.rs:14:30
+   |
+LL | fn foo2<'a, T: Bar<'a>>() -> impl Into<T::Assoc> + '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 51877e9cc3c..7555df1b2c7 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 b9b8d00ce30..e7113a9dfb1 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