Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function with impl trait in argument position does not see all impls of trait on value returned from function with impl trait in return position #59365

Open
mwchase opened this Issue Mar 22, 2019 · 1 comment

Comments

Projects
None yet
3 participants
@mwchase
Copy link

mwchase commented Mar 22, 2019

struct A {}
struct B {}

trait Marker {}

impl Marker for A {}
impl Marker for B {}

trait Marked<M: Marker> {}

struct Singleton {}

impl<M: Marker> Marked<M> for Singleton {}

fn produce_a() -> impl Marked<A> {
    Singleton{}
}

fn produce_b() -> impl Marked<B> {
    Singleton{}
}

fn combine<M1: Marker, M2: Marker>(_t1: &impl Marked<M1>, _t2: &impl Marked<M2>) -> impl Marked<M1> + Marked<M2> {
    Singleton{}
}

fn consume_a(_: &impl Marked<A>) {}

fn main() {
    let an_a = produce_a();
    consume_a(&an_a);
    consume_a(&an_a);
    let a_b = produce_b();
    //consume_a(&a_b); // Errors, as hoped.
    let combined1 = combine(&a_b, &an_a);
    let combined2 = combine(&an_a, &a_b);
    consume_a(&combined1);
    consume_a(&combined2);
    let combined3 = combine(&combined1, &a_b);
    let combined4 = combine(&combined2, &a_b);
    consume_a(&combined3);
    //consume_a(&combined4); // Errors???
    println!("Hello, world!");
}

(Playground)

Output:

Hello, world!

Errors:

   Compiling playground v0.0.1 (/playground)
warning: unused variable: `combined4`
  --> src/main.rs:40:9
   |
40 |     let combined4 = combine(&combined2, &a_b);
   |         ^^^^^^^^^ help: consider using `_combined4` instead
   |
   = note: #[warn(unused_variables)] on by default

warning: struct is never constructed: `B`
 --> src/main.rs:2:1
  |
2 | struct B {}
  | ^^^^^^^^
  |
  = note: #[warn(dead_code)] on by default

    Finished dev [unoptimized + debuginfo] target(s) in 0.77s
     Running `target/debug/playground`

With the second commented line uncommented:

   Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `impl Marked<B>+Marked<B>: Marked<A>` is not satisfied
  --> src/main.rs:42:5
   |
42 |     consume_a(&combined4); // Errors???
   |     ^^^^^^^^^ the trait `Marked<A>` is not implemented for `impl Marked<B>+Marked<B>`
   |
note: required by `consume_a`
  --> src/main.rs:27:1
   |
27 | fn consume_a(_: &impl Marked<A>) {}
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
error: Could not compile `playground`.

To learn more, run the command again with --verbose.

I tested this across Stable, Beta, and Nightly in the playground, same behavior in all of them.

My intent with this code was to have a set of "markers" that could be associated with a type purely at a type-system level, with the actual implementation being a single concrete ZST. As the first commented-out line shows, this works in the simple case, but things get confused if you compose markers together multiple times.

@Centril

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.