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

Option + impl Trait = uncompilable code (?) #37454

Open
japaric opened this Issue Oct 28, 2016 · 3 comments

Comments

Projects
None yet
5 participants
@japaric
Copy link
Member

japaric commented Oct 28, 2016

STR

#![feature(conservative_impl_trait)]

trait Foo {
    fn foo(&self);
}

struct FooStruct {}

impl Foo for FooStruct {
    fn foo(&self) {
        println!("foo");
    }
}

fn mk_foo() -> impl Foo {
    FooStruct {}
}

fn main() {
    let mut maybe_foo = None;

    loop {
        if some_condition() {
            maybe_foo.take().map(|f| f.foo());

            maybe_foo = Some(mk_foo());
        }

        // .. more code ..
    }
}

fn some_condition() -> bool {
    true
}
rustc foo.rs
error: the type of this value must be known in this context
  --> foo.rs:24:38
   |
24 |             maybe_foo.take().map(|f| f.foo());
   |                                      ^^^^^^^

error: aborting due to previous error

This works:

     loop {
         if true {
-            maybe_foo.take().map(|f| f.foo());
-
             maybe_foo = Some(mk_foo());
+
+            maybe_foo.take().map(|f| f.foo());
         }

but changes the behaviour of the code.

My first attempt to fix this was:

 fn main() {
-    let mut maybe_foo = None;
+    let mut maybe_foo: Option<impl Foo> = None;

     loop {

but:

error[E0562]: `impl Trait` not allowed outside of function and inherent method return types

My second attempt was:

+fn init_maybe_foo() -> Option<impl Foo> {
+    None::<FooStruct>
+}
+
 fn main() {
-    let mut maybe_foo = None;
+    let mut maybe_foo = init_maybe_foo();

     loop {

but:

$ rustc foo.rs
error[E0308]: mismatched types
  --> foo.rs:30:30
   |
30 |             maybe_foo = Some(mk_foo());
   |                              ^^^^^^^^ expected anonymized type, found a different anonymized type
   |
   = note: expected type `impl Foo` (anonymized type)
   = note:    found type `impl Foo` (anonymized type)

error: aborting due to previous error

What? They have the same type.

Are impl Trait types in let statements planned? Or can type inference be ... improved (?) to handle the last case? Or does anyone know how to work around this? 😄

cc @eddyb

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Oct 28, 2016

fn hint_none<R, F: FnOnce() -> R>(_: F) -> Option<T> {None}
...
let mut maybe_foo = hint_none(mk_foo);
@mister-walter

This comment has been minimized.

Copy link

mister-walter commented Dec 30, 2017

Is this blocked on the implemention of rust-lang/rfcs#2071 ?

@cramertj

This comment has been minimized.

Copy link
Member

cramertj commented Jan 5, 2018

This isn't a full solution, but the code in the original issue report can be fixed using UFCS: Foo::foo(&f) works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment