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 Jul 15, 2024
1 parent 5297907 commit 10930de
Show file tree
Hide file tree
Showing 16 changed files with 93 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
}
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() {}
4 changes: 2 additions & 2 deletions tests/ui/impl-trait/unsized_coercion3.next.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | let x = hello();
| ^^^^^^^ types differ

error[E0308]: mismatched types
--> $DIR/unsized_coercion3.rs:19:14
--> $DIR/unsized_coercion3.rs:18:14
|
LL | fn hello() -> Box<impl Trait + ?Sized> {
| ------------------- the expected opaque type
Expand All @@ -21,7 +21,7 @@ note: associated function defined here
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL

error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
--> $DIR/unsized_coercion3.rs:19:14
--> $DIR/unsized_coercion3.rs:18:14
|
LL | Box::new(1u32)
| -------- ^^^^ doesn't have a size known at compile-time
Expand Down
16 changes: 1 addition & 15 deletions tests/ui/impl-trait/unsized_coercion3.old.stderr
Original file line number Diff line number Diff line change
@@ -1,17 +1,3 @@
error: cannot check whether the hidden type of opaque type satisfies auto traits
--> $DIR/unsized_coercion3.rs:15:32
|
LL | let y: Box<dyn Send> = x;
| ^
|
= note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
note: opaque type is declared here
--> $DIR/unsized_coercion3.rs:11:19
|
LL | fn hello() -> Box<impl Trait + ?Sized> {
| ^^^^^^^^^^^^^^^^^^^
= note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Send>`

error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
--> $DIR/unsized_coercion3.rs:15:32
|
Expand All @@ -21,6 +7,6 @@ LL | let y: Box<dyn Send> = x;
= help: the trait `Sized` is not implemented for `impl Trait + ?Sized`
= note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Send>`

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
1 change: 0 additions & 1 deletion tests/ui/impl-trait/unsized_coercion3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ fn hello() -> Box<impl Trait + ?Sized> {
//[next]~^ ERROR: type mismatch resolving `impl Trait + ?Sized <: dyn Send`
let y: Box<dyn Send> = x;
//[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
//[old]~| ERROR: cannot check whether the hidden type of opaque type satisfies auto traits
}
Box::new(1u32)
//[next]~^ ERROR: mismatched types
Expand Down
16 changes: 1 addition & 15 deletions tests/ui/impl-trait/unsized_coercion5.old.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,6 @@ LL | let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
= note: expected struct `Box<dyn Send>`
found struct `Box<dyn Trait + Send>`

error: cannot check whether the hidden type of opaque type satisfies auto traits
--> $DIR/unsized_coercion5.rs:16:32
|
LL | let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
| ^
|
= note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
note: opaque type is declared here
--> $DIR/unsized_coercion5.rs:13:19
|
LL | fn hello() -> Box<impl Trait + ?Sized> {
| ^^^^^^^^^^^^^^^^^^^
= note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Trait + Send>`

error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
--> $DIR/unsized_coercion5.rs:16:32
|
Expand All @@ -32,7 +18,7 @@ LL | let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
= help: the trait `Sized` is not implemented for `impl Trait + ?Sized`
= note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Trait + Send>`

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
3 changes: 1 addition & 2 deletions tests/ui/impl-trait/unsized_coercion5.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ fn hello() -> Box<impl Trait + ?Sized> {
let x = hello();
let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
//[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
//[old]~| ERROR: cannot check whether the hidden type of opaque type satisfies auto traits
//~^^^ ERROR: mismatched types
//~^^ ERROR: mismatched types
}
Box::new(1u32)
}
Expand Down
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 @@ -10,6 +10,7 @@ where
Bar: Send,
{
[0; 1 + 2]
//~^ ERROR: type annotations needed: cannot satisfy `Bar: Send`
}

fn main() {}
21 changes: 19 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,23 @@ 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:12:9
|
LL | [0; 1 + 2]
| ^^^^^
|
= note: cannot satisfy `Bar: Send`
note: required by a bound in `foo`
--> $DIR/in-where-clause.rs:10:10
|
LL | fn foo() -> Bar
| --- required by a bound in this function
LL | where
LL | Bar: Send,
| ^^^^ required by this bound in `foo`

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`.
2 changes: 1 addition & 1 deletion tests/ui/type-alias-impl-trait/reveal_local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ fn not_gooder() -> Foo {
// while we could know this from the hidden type, it would
// need extra roundabout logic to support it.
is_send::<Foo>();
//~^ ERROR: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits
//~^ ERROR: type annotations needed: cannot satisfy `Foo: Send`

x
}
Expand Down
10 changes: 3 additions & 7 deletions tests/ui/type-alias-impl-trait/reveal_local.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,13 @@ note: required by a bound in `is_send`
LL | fn is_send<T: Send>() {}
| ^^^^ required by this bound in `is_send`

error: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits
error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
--> $DIR/reveal_local.rs:22:15
|
LL | is_send::<Foo>();
| ^^^
|
= note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
note: opaque type is declared here
--> $DIR/reveal_local.rs:5:12
|
LL | type Foo = impl Debug;
| ^^^^^^^^^^
= note: cannot satisfy `Foo: Send`
note: required by a bound in `is_send`
--> $DIR/reveal_local.rs:7:15
|
Expand All @@ -36,3 +31,4 @@ LL | fn is_send<T: Send>() {}

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0283`.

0 comments on commit 10930de

Please sign in to comment.