Skip to content

Commit

Permalink
Do not assemble candidates for auto traits of opaque types in their d…
Browse files Browse the repository at this point in the history
…efining scope
  • Loading branch information
oli-obk committed Jun 4, 2024
1 parent 4f47342 commit ad6e85b
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,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.
Expand All @@ -792,6 +792,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)
}
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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<T: Trait<U>, U: Default>(_: T) -> U {
| ^^^^^^^^ required by this bound in `is_trait`
Expand Down
26 changes: 26 additions & 0 deletions tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr
Original file line number Diff line number Diff line change
@@ -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<T: Freeze> Trait<u32> for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | impl<T> Trait<i32> for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `is_trait`
--> $DIR/auto-trait-selection-freeze.rs:11:16
|
LL | fn is_trait<T: Trait<U>, 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`.
3 changes: 1 addition & 2 deletions tests/ui/impl-trait/auto-trait-selection-freeze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
//@ revisions: next old
//@[next] compile-flags: -Znext-solver
//@[old]check-pass

#![feature(freeze)]

Expand All @@ -18,7 +17,7 @@ impl<T: Freeze> Trait<u32> for T {}
impl<T> Trait<i32> 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() {}
4 changes: 2 additions & 2 deletions tests/ui/impl-trait/auto-trait-selection.next.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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<T: Trait<U>, U: Default>(_: T) -> U {
| ^^^^^^^^ required by this bound in `is_trait`
Expand Down
26 changes: 26 additions & 0 deletions tests/ui/impl-trait/auto-trait-selection.old.stderr
Original file line number Diff line number Diff line change
@@ -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<T: Send> Trait<u32> for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | impl<T> Trait<i32> for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `is_trait`
--> $DIR/auto-trait-selection.rs:7:16
|
LL | fn is_trait<T: Trait<U>, 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`.
3 changes: 1 addition & 2 deletions tests/ui/impl-trait/auto-trait-selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
//@ revisions: next old
//@[next] compile-flags: -Znext-solver
//@[old]check-pass

fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
Default::default()
Expand All @@ -14,7 +13,7 @@ impl<T: Send> Trait<u32> for T {}
impl<T> Trait<i32> 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() {}
1 change: 1 addition & 0 deletions tests/ui/type-alias-impl-trait/in-where-clause.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type Bar = impl Sized;
fn foo() -> Bar
where
Bar: Send,
//~^ ERROR: type annotations needed
{
[0; 1 + 2]
}
Expand Down
13 changes: 11 additions & 2 deletions tests/ui/type-alias-impl-trait/in-where-clause.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`.

0 comments on commit ad6e85b

Please sign in to comment.