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) {} +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() -> 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`.