From dd96364e6594932ef79f97a1b51a3cdf805f5b72 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 4 Jun 2024 16:20:01 +0000 Subject: [PATCH] Do not assemble candidates for auto traits of opaque types in their defining scope --- .../src/traits/select/candidate_assembly.rs | 7 ++++- .../auto-trait-selection-freeze.next.stderr | 4 +-- .../auto-trait-selection-freeze.old.stderr | 26 +++++++++++++++++++ .../impl-trait/auto-trait-selection-freeze.rs | 3 +-- .../auto-trait-selection.next.stderr | 4 +-- .../auto-trait-selection.old.stderr | 26 +++++++++++++++++++ tests/ui/impl-trait/auto-trait-selection.rs | 3 +-- .../type-alias-impl-trait/in-where-clause.rs | 1 + .../in-where-clause.stderr | 13 ++++++++-- 9 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr create mode 100644 tests/ui/impl-trait/auto-trait-selection.old.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 4c3d833b0f90f..06b79ea63ca47 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -772,7 +772,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); } - ty::Alias(ty::Opaque, _) => { + ty::Alias(ty::Opaque, 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. @@ -787,6 +787,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // We do not emit auto trait candidates for opaque types in coherence. // Doing so can result in weird dependency cycles. candidates.ambiguous = true; + } else if self.infcx.can_define_opaque_ty(alias.def_id) { + // We do not emit auto trait candidates for opaque types in their defining scope, as + // we need to know the hidden type first, which we can't reliably know within the defining + // scope. + candidates.ambiguous = true; } else { candidates.vec.push(AutoImplCandidate) } diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr index d9192e854971f..5caf0eb2fd4e3 100644 --- a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr +++ b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr @@ -1,5 +1,5 @@ error[E0283]: type annotations needed - --> $DIR/auto-trait-selection-freeze.rs:20:16 + --> $DIR/auto-trait-selection-freeze.rs:19:16 | LL | if false { is_trait(foo()) } else { Default::default() } | ^^^^^^^^ ----- type must be known at this point @@ -8,7 +8,7 @@ LL | if false { is_trait(foo()) } else { Default::default() } | = note: cannot satisfy `_: Trait<_>` note: required by a bound in `is_trait` - --> $DIR/auto-trait-selection-freeze.rs:12:16 + --> $DIR/auto-trait-selection-freeze.rs:11:16 | LL | fn is_trait, U: Default>(_: T) -> U { | ^^^^^^^^ required by this bound in `is_trait` diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr b/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr new file mode 100644 index 0000000000000..b4d2229d408d2 --- /dev/null +++ b/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr @@ -0,0 +1,26 @@ +error[E0283]: type annotations needed + --> $DIR/auto-trait-selection-freeze.rs:19:16 + | +LL | if false { is_trait(foo()) } else { Default::default() } + | ^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `is_trait` + | +note: multiple `impl`s satisfying `impl Sized: Trait<_>` found + --> $DIR/auto-trait-selection-freeze.rs:16:1 + | +LL | impl Trait for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Trait for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `is_trait` + --> $DIR/auto-trait-selection-freeze.rs:11:16 + | +LL | fn is_trait, U: Default>(_: T) -> U { + | ^^^^^^^^ required by this bound in `is_trait` +help: consider specifying the generic arguments + | +LL | if false { is_trait::<_, U>(foo()) } else { Default::default() } + | ++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.rs b/tests/ui/impl-trait/auto-trait-selection-freeze.rs index 72c24c5196221..7306a1c41f746 100644 --- a/tests/ui/impl-trait/auto-trait-selection-freeze.rs +++ b/tests/ui/impl-trait/auto-trait-selection-freeze.rs @@ -3,7 +3,6 @@ //@ revisions: next old //@[next] compile-flags: -Znext-solver -//@[old]check-pass #![feature(freeze)] @@ -18,7 +17,7 @@ impl Trait for T {} impl Trait for T {} fn foo() -> impl Sized { if false { is_trait(foo()) } else { Default::default() } - //[next]~^ ERROR: type annotations needed + //~^ ERROR: type annotations needed } fn main() {} diff --git a/tests/ui/impl-trait/auto-trait-selection.next.stderr b/tests/ui/impl-trait/auto-trait-selection.next.stderr index 2e8d7ad99b290..d34fdcc44967f 100644 --- a/tests/ui/impl-trait/auto-trait-selection.next.stderr +++ b/tests/ui/impl-trait/auto-trait-selection.next.stderr @@ -1,5 +1,5 @@ error[E0283]: type annotations needed - --> $DIR/auto-trait-selection.rs:16:16 + --> $DIR/auto-trait-selection.rs:15:16 | LL | if false { is_trait(foo()) } else { Default::default() } | ^^^^^^^^ ----- type must be known at this point @@ -8,7 +8,7 @@ LL | if false { is_trait(foo()) } else { Default::default() } | = note: cannot satisfy `_: Trait<_>` note: required by a bound in `is_trait` - --> $DIR/auto-trait-selection.rs:8:16 + --> $DIR/auto-trait-selection.rs:7:16 | LL | fn is_trait, U: Default>(_: T) -> U { | ^^^^^^^^ required by this bound in `is_trait` diff --git a/tests/ui/impl-trait/auto-trait-selection.old.stderr b/tests/ui/impl-trait/auto-trait-selection.old.stderr new file mode 100644 index 0000000000000..1b5fd95fdf903 --- /dev/null +++ b/tests/ui/impl-trait/auto-trait-selection.old.stderr @@ -0,0 +1,26 @@ +error[E0283]: type annotations needed + --> $DIR/auto-trait-selection.rs:15:16 + | +LL | if false { is_trait(foo()) } else { Default::default() } + | ^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `is_trait` + | +note: multiple `impl`s satisfying `impl Sized: Trait<_>` found + --> $DIR/auto-trait-selection.rs:12:1 + | +LL | impl Trait for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Trait for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `is_trait` + --> $DIR/auto-trait-selection.rs:7:16 + | +LL | fn is_trait, U: Default>(_: T) -> U { + | ^^^^^^^^ required by this bound in `is_trait` +help: consider specifying the generic arguments + | +LL | if false { is_trait::<_, U>(foo()) } else { Default::default() } + | ++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/impl-trait/auto-trait-selection.rs b/tests/ui/impl-trait/auto-trait-selection.rs index beb0b189fd7f7..ee5612459c257 100644 --- a/tests/ui/impl-trait/auto-trait-selection.rs +++ b/tests/ui/impl-trait/auto-trait-selection.rs @@ -3,7 +3,6 @@ //@ revisions: next old //@[next] compile-flags: -Znext-solver -//@[old]check-pass fn is_trait, U: Default>(_: T) -> U { Default::default() @@ -14,7 +13,7 @@ impl Trait for T {} impl Trait for T {} fn foo() -> impl Sized { if false { is_trait(foo()) } else { Default::default() } - //[next]~^ ERROR: type annotations needed + //~^ ERROR: type annotations needed } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.rs b/tests/ui/type-alias-impl-trait/in-where-clause.rs index 6e104781d84f3..8fc05023147fd 100644 --- a/tests/ui/type-alias-impl-trait/in-where-clause.rs +++ b/tests/ui/type-alias-impl-trait/in-where-clause.rs @@ -8,6 +8,7 @@ type Bar = impl Sized; fn foo() -> Bar where Bar: Send, + //~^ ERROR: type annotations needed { [0; 1 + 2] } diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.stderr b/tests/ui/type-alias-impl-trait/in-where-clause.stderr index c486013f8874a..197e0fc2c79ec 100644 --- a/tests/ui/type-alias-impl-trait/in-where-clause.stderr +++ b/tests/ui/type-alias-impl-trait/in-where-clause.stderr @@ -25,6 +25,15 @@ LL | type Bar = impl Sized; | ^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 1 previous error +error[E0283]: type annotations needed: cannot satisfy `Bar: Send` + --> $DIR/in-where-clause.rs:10:10 + | +LL | Bar: Send, + | ^^^^ + | + = note: cannot satisfy `Bar: Send` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0391`. +Some errors have detailed explanations: E0283, E0391. +For more information about an error, try `rustc --explain E0283`.