Skip to content

Make BoxFuture and LocalBoxFuture a concrete type with #[must_use] #1691

New issue

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

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

Already on GitHub? # to your account

Closed
wants to merge 1 commit into from

Conversation

andll
Copy link

@andll andll commented Jun 28, 2019

Currently BoxFuture is type alias for Pin<Box<...>>, so it can not have #[must_wait]. That leads to accidental mistakes, when user does not call await/poll on result of function that returns BoxFuture. We had multiple problems with that

Some notes on PR:

  • I understand that for some projects this might be breaking change - if someone have hardcoded Pin<Box<...>> as a type of variable returned by .boxed, they would have to change it BoxedFuture once this diff lands, but I believe this is reasonable trade off.

  • I am not sure what to do with Debug implementation for BoxFuture - ok to just suppress warning for this type?

  • I don't fully understand what UnsafeFutureObj is, I mostly copied implementation from Pin<Box<...>>, but please take a look at it carefully to make sure I did not miss something.

@andll andll force-pushed the box_future_must_use branch 2 times, most recently from e5d5b07 to de0f9d6 Compare June 28, 2019 19:08
Currently BoxFuture is type alias for Pin<Box<...>>, that leads to accidental mistakes, when user does not call await/poll on result of function that returns BoxFuture. We had multiple problems with that

Some notes on PR:

* I understand that for some projects this might be breaking change - if someone have hardcoded Pin<Box<...>> as a type of variable returned by .boxed, they would have to change it BoxedFuture once this diff lands, but I believe this is reasonable trade off.

* I am not sure what to do with Debug implementation for BoxFuture - ok to just suppress warning for this type?

* I don't fully understand what UnsafeFutureObj is, I mostly copied implementation from Pin<Box<...>>, but please take a look at it carefully to make sure I did not miss something.
@andll andll force-pushed the box_future_must_use branch from de0f9d6 to 4e0d99b Compare June 28, 2019 20:33
@Nemo157
Copy link
Member

Nemo157 commented Jun 29, 2019

This seems like a big limitation in the #[must_use] for traits support, that should somehow be inherited through Box, I left a comment on the implementing issue.

@andll
Copy link
Author

andll commented Jul 1, 2019

Note that this is Pin<Box<..>>, not just Box<...>
I think (confirming with author of commit), rust-lang/rust#55506 only handles Box<..>, so it won't help our case

@andll
Copy link
Author

andll commented Jul 2, 2019

So my feeling that rust-lang/rust#62262 could take a while (and might not even happen, some people voice concerns about propagating must_use through structs).

What are your thoughts on merging this diff to solve the problem of unused boxed futures? I think pretty much all other future wrappers (AndThen, etc) already are concrete types, is there reason not to convert BoxFuture?

@andll
Copy link
Author

andll commented Jul 8, 2019

@Nemo157 what do you think? Would it make sense to merge this?

@Nemo157
Copy link
Member

Nemo157 commented Jul 9, 2019

I'm on the fence with this, it makes sense if we're not going to have must_use working on the alias soon, but it is definitely going to be annoying dealing with a concrete type in some places.

I think one thing that would help is to add

impl<'a, T: Future + 'a> BoxFuture<'a, T> {
    pub fn pin(x: T) -> Self {
        Self::new(Box::pin(x))
    }
}

that way code that is currently

Box::pin(async move { ... })

can transition to

BoxFuture::pin(async { ... })

(using .boxed() along with async { ... } results in some pretty bad formatting).

@cramertj you've probably got a better idea how badly moving this to a concrete type would affect large codebases.

@cramertj
Copy link
Member

cramertj commented Jul 9, 2019

I'm unsure about this. It does seem unfortunate that #[must_use] doesn't propagate correctly, but once we have that fixed (and I'm assuming we will fix it at some point), we would want to shift it back to a type alias. It's easy to imagine breaking existing uses of this type by shifting it back into a type alias-- there are some things we could do to try and make the APIs intercompatible like using BoxFuture::pin rather than BoxFuture::new etc., but I'm feeling pretty uneasy about it.

@andll
Copy link
Author

andll commented Jul 9, 2019

@cramertj for my education - why type alias is more preferred then concrete type, e.g. why would we want to shift back to alias?
As far as I understand, there is no allocation/performance overhead for having concrete types like this

@cramertj
Copy link
Member

cramertj commented Jul 9, 2019

Primarily that it's a simpler mental model for users-- it's more transparent, and easy to see that it's "just" a boxed trait object rather than something special.

@taiki-e
Copy link
Member

taiki-e commented Aug 29, 2019

Even if this PR is merged, considering that must_use does not work with Pin<&mut impl Future>, I think that the advantage of merging this PR is small (but thanks for finding this issue @andll).

@cramertj
Copy link
Member

I agree with @taiki-e. I'm going to go ahead and close this PR-- I don't think this is something we want to do.Thanks for the PR, though-- I appreciate you calling attention to this.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants