about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2021-05-07 20:00:17 +0200
committerOleksandr Babak <alexanderbabak@proton.me>2023-07-06 11:37:19 +0200
commit3adedc93a9de239a6476833841fba9c1a9796af3 (patch)
tree1c9410467ff2a4345b28b3e30d6051e01c278963
parentb112bc5529cfa8d8a9000f7a85278ece3232e579 (diff)
downloadrust-3adedc93a9de239a6476833841fba9c1a9796af3.tar.gz
rust-3adedc93a9de239a6476833841fba9c1a9796af3.zip
update auto trait handling
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs52
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs25
-rw-r--r--tests/ui/auto-traits/issue-83857-ub.rs31
-rw-r--r--tests/ui/auto-traits/issue-83857-ub.stderr22
-rw-r--r--tests/ui/generator/auto-trait-regions.rs6
-rw-r--r--tests/ui/impl-trait/auto-trait-leak0
-rw-r--r--tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking.stderr42
-rw-r--r--tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr42
-rw-r--r--tests/ui/impl-trait/recursive-impl-trait-type-indirect.no_drop_tracking.stderr42
-rw-r--r--tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs1
-rw-r--r--tests/ui/impl-traitrecursive-impl-trait-type-indirect.no_drop_tracking.stderr154
11 files changed, 339 insertions, 78 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index a0329259705..d10998cfed7 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -124,11 +124,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
             self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
-            // Auto implementations have lower priority, so we only
-            // consider triggering a default if there is no other impl that can apply.
-            if candidates.vec.is_empty() {
-                self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
-            }
+            self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
         }
         debug!("candidate list size: {}", candidates.vec.len());
         Ok(candidates)
@@ -516,7 +512,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // for an example of a test case that exercises
                     // this path.
                 }
-                ty::Infer(ty::TyVar(_)) => {
+                ty::Infer(ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_)) => {
                     // The auto impl might apply; we don't know.
                     candidates.ambiguous = true;
                 }
@@ -536,7 +532,49 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     }
                 }
 
-                _ => candidates.vec.push(AutoImplCandidate),
+               ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+                    bug!(
+                        "asked to assemble auto trait candidates of unexpected type: {:?}",
+                        self_ty
+                    );
+                }
+
+                // Only consider auto impls if there are no manual impls for the root of `self_ty`.
+                //
+                // For example, we only consider auto candidates for `&i32: Auto` if no explicit impl
+                // for `&SomeType: Auto` exists. Due to E0321 the only crate where impls
+                // for `&SomeType: Auto` can be defined is the crate where `Auto` has been defined.
+                //
+                // Generally, we have to guarantee that for all `SimplifiedType`s the only crate
+                // which may define impls for that type is either the crate defining the type
+                // or the trait. This should be guaranteed by the orphan check.
+                ty::Bool
+                | ty::Char
+                | ty::Int(_)
+                | ty::Uint(_)
+                | ty::Float(_)
+                | ty::Str
+                | ty::Array(_, _)
+                | ty::Slice(_)
+                | ty::Adt(..)
+                | ty::RawPtr(_)
+                | ty::Ref(..)
+                | ty::FnDef(..)
+                | ty::FnPtr(_)
+                | ty::Closure(_, _)
+                | ty::Generator(..)
+                | ty::Never
+                | ty::Tuple(_)
+                | ty::Alias(_, _)
+                | ty::GeneratorWitness(_)
+                | ty::GeneratorWitnessMIR(..) => {
+                    let mut has_impl = false;
+                    self.tcx().for_each_relevant_impl(def_id, self_ty, |_| has_impl = true);
+                    if !has_impl {
+                        candidates.vec.push(AutoImplCandidate)
+                    }
+                }
+                ty::Error(_) => {} // do not add an auto trait impl for `ty::Error` for now.
             }
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 26ed1481228..03f7f7dc9f2 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1814,6 +1814,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
     /// candidates and prefer where-clause candidates.
     ///
     /// See the comment for "SelectionCandidate" for more details.
+    #[instrument(level = "debug", skip(self))]
     fn candidate_should_be_dropped_in_favor_of(
         &mut self,
         victim: &EvaluatedCandidate<'tcx>,
@@ -1837,13 +1838,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         // This is a fix for #53123 and prevents winnowing from accidentally extending the
         // lifetime of a variable.
         match (&other.candidate, &victim.candidate) {
-            (_, AutoImplCandidate) | (AutoImplCandidate, _) => {
-                bug!(
-                    "default implementations shouldn't be recorded \
-                    when there are other valid candidates"
-                );
-            }
-
             // FIXME(@jswrenn): this should probably be more sophisticated
             (TransmutabilityCandidate, _) | (_, TransmutabilityCandidate) => DropVictim::No,
 
@@ -1885,6 +1879,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             (
                 ParamCandidate(ref other_cand),
                 ImplCandidate(..)
+                | AutoImplCandidate
                 | ClosureCandidate { .. }
                 | GeneratorCandidate
                 | FutureCandidate
@@ -1912,6 +1907,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             }
             (
                 ImplCandidate(_)
+                | AutoImplCandidate
                 | ClosureCandidate { .. }
                 | GeneratorCandidate
                 | FutureCandidate
@@ -1945,6 +1941,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             (
                 ObjectCandidate(_) | ProjectionCandidate(..),
                 ImplCandidate(..)
+                | AutoImplCandidate
                 | ClosureCandidate { .. }
                 | GeneratorCandidate
                 | FutureCandidate
@@ -1958,6 +1955,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
 
             (
                 ImplCandidate(..)
+                | AutoImplCandidate
                 | ClosureCandidate { .. }
                 | GeneratorCandidate
                 | FutureCandidate
@@ -2048,6 +2046,19 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 }
             }
 
+            (AutoImplCandidate, ImplCandidate(_)) | (ImplCandidate(_), AutoImplCandidate) => {
+                DropVictim::No
+            }
+
+            (AutoImplCandidate, _) | (_, AutoImplCandidate) => {
+                bug!(
+                    "default implementations shouldn't be recorded \
+                    when there are other global candidates: {:?} {:?}",
+                    other,
+                    victim
+                );
+            }
+
             // Everything else is ambiguous
             (
                 ImplCandidate(_)
diff --git a/tests/ui/auto-traits/issue-83857-ub.rs b/tests/ui/auto-traits/issue-83857-ub.rs
new file mode 100644
index 00000000000..0a8865295c6
--- /dev/null
+++ b/tests/ui/auto-traits/issue-83857-ub.rs
@@ -0,0 +1,31 @@
+#![allow(suspicious_auto_trait_impls)]
+
+struct Always<T, U>(T, U);
+unsafe impl<T, U> Send for Always<T, U> {}
+struct Foo<T, U>(Always<T, U>);
+
+trait False {}
+unsafe impl<U: False> Send for Foo<u32, U> {}
+
+trait WithAssoc {
+    type Output;
+}
+impl<T: Send> WithAssoc for T {
+    type Output = Self;
+}
+impl WithAssoc for Foo<u32, ()> {
+    type Output = Box<i32>;
+}
+
+fn generic<T, U>(v: Foo<T, U>, f: fn(<Foo<T, U> as WithAssoc>::Output) -> i32) {
+    //~^ ERROR `Foo<T, U>` cannot be sent between threads safely
+    f(foo(v));
+}
+
+fn foo<T: Send>(x: T) -> <T as WithAssoc>::Output {
+    x
+}
+
+fn main() {
+    generic(Foo(Always(0, ())), |b| *b);
+}
diff --git a/tests/ui/auto-traits/issue-83857-ub.stderr b/tests/ui/auto-traits/issue-83857-ub.stderr
new file mode 100644
index 00000000000..d2aef17e7f8
--- /dev/null
+++ b/tests/ui/auto-traits/issue-83857-ub.stderr
@@ -0,0 +1,22 @@
+error[E0277]: `Foo<T, U>` cannot be sent between threads safely
+  --> $DIR/issue-83857-ub.rs:20:38
+   |
+LL | fn generic<T, U>(v: Foo<T, U>, f: fn(<Foo<T, U> as WithAssoc>::Output) -> i32) {
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo<T, U>` cannot be sent between threads safely
+   |
+   = help: the trait `Send` is not implemented for `Foo<T, U>`
+note: required for `Foo<T, U>` to implement `WithAssoc`
+  --> $DIR/issue-83857-ub.rs:13:15
+   |
+LL | impl<T: Send> WithAssoc for T {
+   |         ----  ^^^^^^^^^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | fn generic<T, U>(v: Foo<T, U>, f: fn(<Foo<T, U> as WithAssoc>::Output) -> i32) where Foo<T, U>: Send {
+   |                                                                                +++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/generator/auto-trait-regions.rs b/tests/ui/generator/auto-trait-regions.rs
index fd13e41319f..350f3cc34ce 100644
--- a/tests/ui/generator/auto-trait-regions.rs
+++ b/tests/ui/generator/auto-trait-regions.rs
@@ -26,7 +26,7 @@ fn assert_foo<T: Foo>(f: T) {}
 fn main() {
     // Make sure 'static is erased for generator interiors so we can't match it in trait selection
     let x: &'static _ = &OnlyFooIfStaticRef(No);
-    let gen = || {
+    let gen = move || {
         let x = x;
         yield;
         assert_foo(x);
@@ -36,7 +36,7 @@ fn main() {
 
     // Allow impls which matches any lifetime
     let x = &OnlyFooIfRef(No);
-    let gen = || {
+    let gen = move || {
         let x = x;
         yield;
         assert_foo(x);
@@ -44,7 +44,7 @@ fn main() {
     assert_foo(gen); // ok
 
     // Disallow impls which relates lifetimes in the generator interior
-    let gen = || {
+    let gen = move || {
         let a = A(&mut true, &mut true, No);
         //~^ temporary value dropped while borrowed
         //~| temporary value dropped while borrowed
diff --git a/tests/ui/impl-trait/auto-trait-leak b/tests/ui/impl-trait/auto-trait-leak
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/ui/impl-trait/auto-trait-leak
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking.stderr
index 43118ae3854..8b6a55558cf 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking.stderr
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking.stderr
@@ -123,30 +123,32 @@ LL | |         x;
 LL | |     }
    | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:78:5: 78:12]`
 
-error[E0720]: cannot resolve opaque type
+error[E0391]: cycle detected when computing type of `mutual_recursion::{opaque#0}`
   --> $DIR/recursive-impl-trait-type-indirect.rs:90:26
    |
 LL | fn mutual_recursion() -> impl Sync {
-   |                          ^^^^^^^^^ recursive opaque type
-LL |
-LL |     mutual_recursion_b()
-   |     -------------------- returning here with type `impl Sized`
-...
-LL | fn mutual_recursion_b() -> impl Sized {
-   |                            ---------- returning this opaque type `impl Sized`
-
-error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:95:28
+   |                          ^^^^^^^^^
+   |
+note: ...which requires type-checking `mutual_recursion`...
+  --> $DIR/recursive-impl-trait-type-indirect.rs:90:26
    |
 LL | fn mutual_recursion() -> impl Sync {
-   |                          --------- returning this opaque type `impl Sync`
-...
-LL | fn mutual_recursion_b() -> impl Sized {
-   |                            ^^^^^^^^^^ recursive opaque type
-LL |
-LL |     mutual_recursion()
-   |     ------------------ returning here with type `impl Sync`
+   |                          ^^^^^^^^^
+   = note: ...which requires evaluating trait selection obligation `mutual_recursion_b::{opaque#0}: core::marker::Sync`...
+   = note: ...which again requires computing type of `mutual_recursion::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/recursive-impl-trait-type-indirect.rs:8:1
+   |
+LL | / #![feature(generators)]
+LL | | #![allow(unconditional_recursion)]
+LL | |
+LL | | fn option(i: i32) -> impl Sized {
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
 
-error: aborting due to 14 previous errors
+error: aborting due to 13 previous errors
 
-For more information about this error, try `rustc --explain E0720`.
+Some errors have detailed explanations: E0391, E0720.
+For more information about an error, try `rustc --explain E0391`.
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr
index 9c67f17e963..0c84fa02619 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr
@@ -118,30 +118,32 @@ LL | fn generator_hold() -> impl Sized {
 LL |         let x = generator_hold();
    |             - generator captures itself here
 
-error[E0720]: cannot resolve opaque type
+error[E0391]: cycle detected when computing type of `mutual_recursion::{opaque#0}`
   --> $DIR/recursive-impl-trait-type-indirect.rs:90:26
    |
 LL | fn mutual_recursion() -> impl Sync {
-   |                          ^^^^^^^^^ recursive opaque type
-LL |
-LL |     mutual_recursion_b()
-   |     -------------------- returning here with type `impl Sized`
-...
-LL | fn mutual_recursion_b() -> impl Sized {
-   |                            ---------- returning this opaque type `impl Sized`
-
-error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:95:28
+   |                          ^^^^^^^^^
+   |
+note: ...which requires type-checking `mutual_recursion`...
+  --> $DIR/recursive-impl-trait-type-indirect.rs:90:26
    |
 LL | fn mutual_recursion() -> impl Sync {
-   |                          --------- returning this opaque type `impl Sync`
-...
-LL | fn mutual_recursion_b() -> impl Sized {
-   |                            ^^^^^^^^^^ recursive opaque type
-LL |
-LL |     mutual_recursion()
-   |     ------------------ returning here with type `impl Sync`
+   |                          ^^^^^^^^^
+   = note: ...which requires evaluating trait selection obligation `mutual_recursion_b::{opaque#0}: core::marker::Sync`...
+   = note: ...which again requires computing type of `mutual_recursion::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/recursive-impl-trait-type-indirect.rs:8:1
+   |
+LL | / #![feature(generators)]
+LL | | #![allow(unconditional_recursion)]
+LL | |
+LL | | fn option(i: i32) -> impl Sized {
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
 
-error: aborting due to 14 previous errors
+error: aborting due to 13 previous errors
 
-For more information about this error, try `rustc --explain E0720`.
+Some errors have detailed explanations: E0391, E0720.
+For more information about an error, try `rustc --explain E0391`.
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.no_drop_tracking.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.no_drop_tracking.stderr
index 43118ae3854..8b6a55558cf 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.no_drop_tracking.stderr
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.no_drop_tracking.stderr
@@ -123,30 +123,32 @@ LL | |         x;
 LL | |     }
    | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:78:5: 78:12]`
 
-error[E0720]: cannot resolve opaque type
+error[E0391]: cycle detected when computing type of `mutual_recursion::{opaque#0}`
   --> $DIR/recursive-impl-trait-type-indirect.rs:90:26
    |
 LL | fn mutual_recursion() -> impl Sync {
-   |                          ^^^^^^^^^ recursive opaque type
-LL |
-LL |     mutual_recursion_b()
-   |     -------------------- returning here with type `impl Sized`
-...
-LL | fn mutual_recursion_b() -> impl Sized {
-   |                            ---------- returning this opaque type `impl Sized`
-
-error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:95:28
+   |                          ^^^^^^^^^
+   |
+note: ...which requires type-checking `mutual_recursion`...
+  --> $DIR/recursive-impl-trait-type-indirect.rs:90:26
    |
 LL | fn mutual_recursion() -> impl Sync {
-   |                          --------- returning this opaque type `impl Sync`
-...
-LL | fn mutual_recursion_b() -> impl Sized {
-   |                            ^^^^^^^^^^ recursive opaque type
-LL |
-LL |     mutual_recursion()
-   |     ------------------ returning here with type `impl Sync`
+   |                          ^^^^^^^^^
+   = note: ...which requires evaluating trait selection obligation `mutual_recursion_b::{opaque#0}: core::marker::Sync`...
+   = note: ...which again requires computing type of `mutual_recursion::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/recursive-impl-trait-type-indirect.rs:8:1
+   |
+LL | / #![feature(generators)]
+LL | | #![allow(unconditional_recursion)]
+LL | |
+LL | | fn option(i: i32) -> impl Sized {
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
 
-error: aborting due to 14 previous errors
+error: aborting due to 13 previous errors
 
-For more information about this error, try `rustc --explain E0720`.
+Some errors have detailed explanations: E0391, E0720.
+For more information about an error, try `rustc --explain E0391`.
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
index 630372e13ed..9d3793940c0 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
@@ -93,7 +93,6 @@ fn mutual_recursion() -> impl Sync {
 }
 
 fn mutual_recursion_b() -> impl Sized {
-    //~^ ERROR
     mutual_recursion()
 }
 
diff --git a/tests/ui/impl-traitrecursive-impl-trait-type-indirect.no_drop_tracking.stderr b/tests/ui/impl-traitrecursive-impl-trait-type-indirect.no_drop_tracking.stderr
new file mode 100644
index 00000000000..8b6a55558cf
--- /dev/null
+++ b/tests/ui/impl-traitrecursive-impl-trait-type-indirect.no_drop_tracking.stderr
@@ -0,0 +1,154 @@
+error[E0720]: cannot resolve opaque type
+  --> $DIR/recursive-impl-trait-type-indirect.rs:11:22
+   |
+LL | fn option(i: i32) -> impl Sized {
+   |                      ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     if i < 0 { None } else { Some((option(i - 1), i)) }
+   |                ----          ------------------------ returning here with type `Option<(impl Sized, i32)>`
+   |                |
+   |                returning here with type `Option<(impl Sized, i32)>`
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/recursive-impl-trait-type-indirect.rs:16:15
+   |
+LL | fn tuple() -> impl Sized {
+   |               ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     (tuple(),)
+   |     ---------- returning here with type `(impl Sized,)`
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/recursive-impl-trait-type-indirect.rs:21:15
+   |
+LL | fn array() -> impl Sized {
+   |               ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     [array()]
+   |     --------- returning here with type `[impl Sized; 1]`
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/recursive-impl-trait-type-indirect.rs:26:13
+   |
+LL | fn ptr() -> impl Sized {
+   |             ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     &ptr() as *const _
+   |     ------------------ returning here with type `*const impl Sized`
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/recursive-impl-trait-type-indirect.rs:31:16
+   |
+LL | fn fn_ptr() -> impl Sized {
+   |                ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     fn_ptr as fn() -> _
+   |     ------------------- returning here with type `fn() -> impl Sized`
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/recursive-impl-trait-type-indirect.rs:36:25
+   |
+LL |   fn closure_capture() -> impl Sized {
+   |                           ^^^^^^^^^^ recursive opaque type
+...
+LL | /     move || {
+LL | |         x;
+   | |         - closure captures itself here
+LL | |     }
+   | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:39:5: 39:12]`
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/recursive-impl-trait-type-indirect.rs:44:29
+   |
+LL |   fn closure_ref_capture() -> impl Sized {
+   |                               ^^^^^^^^^^ recursive opaque type
+...
+LL | /     move || {
+LL | |         &x;
+   | |          - closure captures itself here
+LL | |     }
+   | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:47:5: 47:12]`
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/recursive-impl-trait-type-indirect.rs:52:21
+   |
+LL | fn closure_sig() -> impl Sized {
+   |                     ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     || closure_sig()
+   |     ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:54:5: 54:7]`
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/recursive-impl-trait-type-indirect.rs:57:23
+   |
+LL | fn generator_sig() -> impl Sized {
+   |                       ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     || generator_sig()
+   |     ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:59:5: 59:7]`
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/recursive-impl-trait-type-indirect.rs:62:27
+   |
+LL |   fn generator_capture() -> impl Sized {
+   |                             ^^^^^^^^^^ recursive opaque type
+...
+LL | /     move || {
+LL | |         yield;
+LL | |         x;
+   | |         - generator captures itself here
+LL | |     }
+   | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:65:5: 65:12]`
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/recursive-impl-trait-type-indirect.rs:71:35
+   |
+LL | fn substs_change<T: 'static>() -> impl Sized {
+   |                                   ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     (substs_change::<&T>(),)
+   |     ------------------------ returning here with type `(impl Sized,)`
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/recursive-impl-trait-type-indirect.rs:76:24
+   |
+LL |   fn generator_hold() -> impl Sized {
+   |                          ^^^^^^^^^^ recursive opaque type
+LL |
+LL | /     move || {
+LL | |         let x = generator_hold();
+   | |             - generator captures itself here
+LL | |         yield;
+LL | |         x;
+LL | |     }
+   | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:78:5: 78:12]`
+
+error[E0391]: cycle detected when computing type of `mutual_recursion::{opaque#0}`
+  --> $DIR/recursive-impl-trait-type-indirect.rs:90:26
+   |
+LL | fn mutual_recursion() -> impl Sync {
+   |                          ^^^^^^^^^
+   |
+note: ...which requires type-checking `mutual_recursion`...
+  --> $DIR/recursive-impl-trait-type-indirect.rs:90:26
+   |
+LL | fn mutual_recursion() -> impl Sync {
+   |                          ^^^^^^^^^
+   = note: ...which requires evaluating trait selection obligation `mutual_recursion_b::{opaque#0}: core::marker::Sync`...
+   = note: ...which again requires computing type of `mutual_recursion::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/recursive-impl-trait-type-indirect.rs:8:1
+   |
+LL | / #![feature(generators)]
+LL | | #![allow(unconditional_recursion)]
+LL | |
+LL | | fn option(i: i32) -> impl Sized {
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error: aborting due to 13 previous errors
+
+Some errors have detailed explanations: E0391, E0720.
+For more information about an error, try `rustc --explain E0391`.