From 3adedc93a9de239a6476833841fba9c1a9796af3 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 7 May 2021 20:00:17 +0200 Subject: [PATCH 1/4] update auto trait handling --- .../src/traits/select/candidate_assembly.rs | 52 +++++- .../src/traits/select/mod.rs | 25 ++- tests/ui/auto-traits/issue-83857-ub.rs | 31 ++++ tests/ui/auto-traits/issue-83857-ub.stderr | 22 +++ tests/ui/generator/auto-trait-regions.rs | 6 +- tests/ui/impl-trait/auto-trait-leak | 0 ...l-trait-type-indirect.drop_tracking.stderr | 42 ++--- ...ait-type-indirect.drop_tracking_mir.stderr | 42 ++--- ...rait-type-indirect.no_drop_tracking.stderr | 42 ++--- .../recursive-impl-trait-type-indirect.rs | 1 - ...rait-type-indirect.no_drop_tracking.stderr | 154 ++++++++++++++++++ 11 files changed, 339 insertions(+), 78 deletions(-) create mode 100644 tests/ui/auto-traits/issue-83857-ub.rs create mode 100644 tests/ui/auto-traits/issue-83857-ub.stderr create mode 100644 tests/ui/impl-trait/auto-trait-leak create mode 100644 tests/ui/impl-traitrecursive-impl-trait-type-indirect.no_drop_tracking.stderr 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 a032925970578..d10998cfed714 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 26ed1481228f9..03f7f7dc9f231 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 0000000000000..0a8865295c63f --- /dev/null +++ b/tests/ui/auto-traits/issue-83857-ub.rs @@ -0,0 +1,31 @@ +#![allow(suspicious_auto_trait_impls)] + +struct Always(T, U); +unsafe impl Send for Always {} +struct Foo(Always); + +trait False {} +unsafe impl Send for Foo {} + +trait WithAssoc { + type Output; +} +impl WithAssoc for T { + type Output = Self; +} +impl WithAssoc for Foo { + type Output = Box; +} + +fn generic(v: Foo, f: fn( as WithAssoc>::Output) -> i32) { + //~^ ERROR `Foo` cannot be sent between threads safely + f(foo(v)); +} + +fn foo(x: T) -> ::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 0000000000000..d2aef17e7f8d2 --- /dev/null +++ b/tests/ui/auto-traits/issue-83857-ub.stderr @@ -0,0 +1,22 @@ +error[E0277]: `Foo` cannot be sent between threads safely + --> $DIR/issue-83857-ub.rs:20:38 + | +LL | fn generic(v: Foo, f: fn( as WithAssoc>::Output) -> i32) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `Foo` +note: required for `Foo` to implement `WithAssoc` + --> $DIR/issue-83857-ub.rs:13:15 + | +LL | impl 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(v: Foo, f: fn( as WithAssoc>::Output) -> i32) where Foo: 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 fd13e41319f01..350f3cc34ce52 100644 --- a/tests/ui/generator/auto-trait-regions.rs +++ b/tests/ui/generator/auto-trait-regions.rs @@ -26,7 +26,7 @@ fn assert_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 0000000000000..e69de29bb2d1d 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 43118ae38540f..8b6a55558cf34 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 9c67f17e96358..0c84fa026196c 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 43118ae38540f..8b6a55558cf34 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 630372e13ed58..9d3793940c041 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 0000000000000..8b6a55558cf34 --- /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() -> 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`. From b5b3f33940f30b05c880c645b42ed1c56281981a Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 19 Jan 2022 17:35:26 +0100 Subject: [PATCH 2/4] deal with opaque types without cycling --- .../src/traits/select/candidate_assembly.rs | 34 ++-- tests/ui/impl-trait/recursive-auto-trait.rs | 10 ++ ...l-trait-type-indirect.drop_tracking.stderr | 42 +++-- ...ait-type-indirect.drop_tracking_mir.stderr | 42 +++-- ...rait-type-indirect.no_drop_tracking.stderr | 42 +++-- .../recursive-impl-trait-type-indirect.rs | 1 + ...rait-type-indirect.no_drop_tracking.stderr | 154 ------------------ 7 files changed, 95 insertions(+), 230 deletions(-) create mode 100644 tests/ui/impl-trait/recursive-auto-trait.rs delete mode 100644 tests/ui/impl-traitrecursive-impl-trait-type-indirect.no_drop_tracking.stderr 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 d10998cfed714..4330d097aa7fb 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 0000000000000..d7b68144ff6ba --- /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 8b6a55558cf34..43118ae38540f 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 0c84fa026196c..9c67f17e96358 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 8b6a55558cf34..43118ae38540f 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 9d3793940c041..630372e13ed58 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 8b6a55558cf34..0000000000000 --- 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`. From 944f237d2da706f7531f28b223fd5225e93312d3 Mon Sep 17 00:00:00 2001 From: Oleksandr Babak Date: Tue, 4 Jul 2023 11:28:19 +0200 Subject: [PATCH 3/4] always emit consider `AutoImplCandidates` for them if they don't also have a `ProjectionCandidate` --- .../src/traits/select/candidate_assembly.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 4330d097aa7fb..aff8553006439 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -552,6 +552,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Note that this is only sound as projection candidates of opaque types // are always applicable for auto traits. } + ty::Alias(_, _) => candidates.vec.push(AutoImplCandidate), ty::Bool | ty::Char @@ -570,7 +571,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Generator(..) | ty::Never | ty::Tuple(_) - | ty::Alias(_, _) | ty::GeneratorWitness(_) | ty::GeneratorWitnessMIR(..) => { // Only consider auto impls if there are no manual impls for the root of `self_ty`. From 37159345a74797316deb0b6f911d48b7243bba77 Mon Sep 17 00:00:00 2001 From: Oleksandr Babak Date: Fri, 28 Jul 2023 11:50:10 +0200 Subject: [PATCH 4/4] Change the description of `SUSPICIOUS_AUTO_TRAIT_IMPLS` --- compiler/rustc_lint_defs/src/builtin.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 87c542dc2e26a..081ec7b65622e 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4052,12 +4052,12 @@ declare_lint! { /// /// The compiler disables the automatic implementation if an explicit one /// exists for given type constructor. The exact rules governing this - /// are currently unsound, quite subtle, and will be modified in the future. - /// This change will cause the automatic implementation to be disabled in more + /// were previously unsound, quite subtle, and have been recently modified. + /// This change caused the automatic implementation to be disabled in more /// cases, potentially breaking some code. pub SUSPICIOUS_AUTO_TRAIT_IMPLS, Warn, - "the rules governing auto traits will change in the future", + "the rules governing auto traits have recently changed resulting in potential breakage", @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::FutureReleaseSemanticsChange, reference: "issue #93367 ",