about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2022-01-19 17:35:26 +0100
committerOleksandr Babak <alexanderbabak@proton.me>2023-07-06 11:37:21 +0200
commitb5b3f33940f30b05c880c645b42ed1c56281981a (patch)
tree6ea1c8bb71b104e28ea14ed7e1d8609fdb20a42c
parent3adedc93a9de239a6476833841fba9c1a9796af3 (diff)
downloadrust-b5b3f33940f30b05c880c645b42ed1c56281981a.tar.gz
rust-b5b3f33940f30b05c880c645b42ed1c56281981a.zip
deal with opaque types without cycling
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs34
-rw-r--r--tests/ui/impl-trait/recursive-auto-trait.rs10
-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
7 files changed, 95 insertions, 230 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 d10998cfed7..4330d097aa7 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -532,22 +532,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     }
                 }
 
-               ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+                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::Alias(_, _)
+                    if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(..))) =>
+                {
+                    // We do not generate an auto impl candidate for `impl Trait`s which already
+                    // reference our auto trait.
+                    //
+                    // For example during candidate assembly for `impl Send: Send`, we don't have
+                    // to look at the constituent types for this opaque types to figure out that this
+                    // trivially holds.
+                    //
+                    // Note that this is only sound as projection candidates of opaque types
+                    // are always applicable for auto traits.
+                }
+
                 ty::Bool
                 | ty::Char
                 | ty::Int(_)
@@ -568,6 +573,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | ty::Alias(_, _)
                 | ty::GeneratorWitness(_)
                 | ty::GeneratorWitnessMIR(..) => {
+                    // 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.
                     let mut has_impl = false;
                     self.tcx().for_each_relevant_impl(def_id, self_ty, |_| has_impl = true);
                     if !has_impl {
diff --git a/tests/ui/impl-trait/recursive-auto-trait.rs b/tests/ui/impl-trait/recursive-auto-trait.rs
new file mode 100644
index 00000000000..d7b68144ff6
--- /dev/null
+++ b/tests/ui/impl-trait/recursive-auto-trait.rs
@@ -0,0 +1,10 @@
+// check-pass
+fn is_send<T: Send>(_: T) {}
+fn foo() -> impl Send {
+    if false {
+        is_send(foo());
+    }
+    ()
+}
+
+fn main() {}
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 8b6a55558cf..43118ae3854 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,32 +123,30 @@ 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}`
+error[E0720]: cannot resolve opaque type
   --> $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
+   |                          ^^^^^^^^^ 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
    |
 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() {}
-   | |____________^
+   |                          --------- 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`
 
-error: aborting due to 13 previous errors
+error: aborting due to 14 previous errors
 
-Some errors have detailed explanations: E0391, E0720.
-For more information about an error, try `rustc --explain E0391`.
+For more information about this error, try `rustc --explain E0720`.
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 0c84fa02619..9c67f17e963 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,32 +118,30 @@ LL | fn generator_hold() -> impl Sized {
 LL |         let x = generator_hold();
    |             - generator captures itself here
 
-error[E0391]: cycle detected when computing type of `mutual_recursion::{opaque#0}`
+error[E0720]: cannot resolve opaque type
   --> $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
+   |                          ^^^^^^^^^ 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
    |
 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() {}
-   | |____________^
+   |                          --------- 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`
 
-error: aborting due to 13 previous errors
+error: aborting due to 14 previous errors
 
-Some errors have detailed explanations: E0391, E0720.
-For more information about an error, try `rustc --explain E0391`.
+For more information about this error, try `rustc --explain E0720`.
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 8b6a55558cf..43118ae3854 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,32 +123,30 @@ 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}`
+error[E0720]: cannot resolve opaque type
   --> $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
+   |                          ^^^^^^^^^ 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
    |
 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() {}
-   | |____________^
+   |                          --------- 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`
 
-error: aborting due to 13 previous errors
+error: aborting due to 14 previous errors
 
-Some errors have detailed explanations: E0391, E0720.
-For more information about an error, try `rustc --explain E0391`.
+For more information about this error, try `rustc --explain E0720`.
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 9d3793940c0..630372e13ed 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
@@ -93,6 +93,7 @@ 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
deleted file mode 100644
index 8b6a55558cf..00000000000
--- a/tests/ui/impl-traitrecursive-impl-trait-type-indirect.no_drop_tracking.stderr
+++ /dev/null
@@ -1,154 +0,0 @@
-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`.