Skip to content

Make iter::Empty<T> Send and Sync for any T #57682

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 2 commits into from

Conversation

LunaBorowska
Copy link
Contributor

Just because it can be. Likely nobody will be using that property of iter::empty, but at the same time, there is no reason to not allow it.

@rust-highfive
Copy link
Contributor

r? @dtolnay

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 16, 2019
Copy link
Member

@dtolnay dtolnay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@dtolnay
Copy link
Member

dtolnay commented Jan 16, 2019

@rust-lang/libs FYI

@bors r+

@bors
Copy link
Collaborator

bors commented Jan 16, 2019

📌 Commit f973f37165249e18671306f4d380973647355f4c has been approved by dtolnay

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 16, 2019
@rust-highfive

This comment has been minimized.

@LunaBorowska
Copy link
Contributor Author

Hm, I guess it cannot be done currently, as for const fn, a PhantomData<fn() -> T> is considered to be a function pointer, and I don't feel like putting unsafe impl<T> Send for Empty<T> {}.

@dtolnay
Copy link
Member

dtolnay commented Jan 16, 2019

@bors r-

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Jan 16, 2019
@dtolnay
Copy link
Member

dtolnay commented Jan 16, 2019

error: function pointers in const fn are unstable
   --> src/libcore/iter/sources.rs:277:11
    |
277 |     Empty(marker::PhantomData)
    |           ^^^^^^^^^^^^^^^^^^^

Strange. I guess an unsafe impl would be the way to go.

@LunaBorowska
Copy link
Contributor Author

I wonder if special casing PhantomData in const fn check would make sense, but doing so would be way out of scope of this pull request.

@dtolnay
Copy link
Member

dtolnay commented Jan 16, 2019

function pointers in const fn are unstable

It sounds like this has been implemented already but not stabilized yet. Adding #![feature(const_fn)] makes the same error disappear in the playground. But libcore/lib.rs already has #![feature(const_fn)]:

#![feature(const_fn)]

Any suggestions @oli-obk?

@Centril
Copy link
Contributor

Centril commented Jan 17, 2019

@dtolnay For #[stable] items in the standard library we impose an additional restriction that it must conform to min_const_fn and if it doesn't we emit an error. Having #![feature(const_fn)] does not affect that. You can see this by enabling #![feature(staged_api)].

The recourse you have here is to use something other than fn(T) to get the covariance and auto trait behavior you want. I think &'static T should work here but I would double check.

@dtolnay
Copy link
Member

dtolnay commented Jan 17, 2019

&'static T would impose T: 'static, and is only Send if T is Sync. playground

@xfix -- I would go ahead and add unsafe impls. playground

@Centril
Copy link
Contributor

Centril commented Jan 17, 2019

@dtolnay oh right; yeah, unsafe impls it is :)

@LunaBorowska
Copy link
Contributor Author

Or, I have another idea how to do it without unsafe.

@LunaBorowska
Copy link
Contributor Author

Arguably abusing a bug, but IMO PhantomData<fn() -> T> should be allowed, even in minimal const fn.

@Centril
Copy link
Contributor

Centril commented Jan 17, 2019

@xfix That's not a bug; an intentional choice was made in min_const_fn to not recurse into data types.

@LunaBorowska
Copy link
Contributor Author

LunaBorowska commented Jan 17, 2019

@Centril I don't know, compiler rejecting PhantomData<fn() -> T> but being fine with PhantomData<PhantomFnWorkaround<T>> sounds inconsistent to me. Like, I understand why the rule is what it is - it's necessary for instance for Vec::<fn()>::new() to be const fn, as on the lowest levels, Vec<T> is using PhantomData<T>. And this is fine, except I don't understand why reject PhantomData<fn() -> T> in const fn subset.

@Centril
Copy link
Contributor

Centril commented Jan 17, 2019

@xfix It's an intentional inconsistency ;) (see #53604 (review), #53604 (comment)) and doesn't really have to do with Vec::<fn()>::new(). Anyways, I'm fine with the solution here.

@rust-highfive

This comment has been minimized.

Copy link
Member

@dtolnay dtolnay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a little crazy for my taste. I would prefer to see plain old unsafe impls over this.

Or, add a more readable and better tested mechanism internal to libcore for establishing variance and auto traits. By standardizing on something like this over PhantomData<T> / PhantomData<fn() -> T> / PhantomData<PhantomFnWorkaround<T>>, the variance and auto trait impls become clearly visible during code reviews and we are more likely to catch when they are wrong for some type.

pub struct Empty<T>(phantom_data![T, Covariant + AlwaysSendSync]);

We would want to support any combination of {Covariant, Contravariant, Invariant} × {AlwaysSendSync, NeverSendSync, InheritSendSync}.

@Centril
Copy link
Contributor

Centril commented Jan 25, 2019

Ping from triage @xfix, can you update to the unsafe impls as requested?

@Dylan-DPC-zz
Copy link

ping from triage @xfix any updates on this?

@Dylan-DPC-zz
Copy link

ping from triage @xfix Unfortunately we haven't heard from you on this in a while, so I'm closing the PR to keep things tidy. Don't worry though, if you'll have time again in the future please reopen this PR, we'll be happy to review it again!

@Dylan-DPC-zz Dylan-DPC-zz added S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 25, 2019
@LunaBorowska
Copy link
Contributor Author

Please re-open this merge request.

That's pretty funny. I said this a year ago.

Likely nobody will be using that property of iter::empty, but at the same time, there is no reason to not allow it.

And then now I'm writing code that went

= help: the trait `std::marker::Sync` is not implemented for `dyn postgres_types::ToSql`
...
= note: required because it appears within the type `std::iter::Empty<&dyn postgres_types::ToSql>`
...

The code looks like this.

    pub async fn fetch_fortunes(&self) -> Vec<Fortune> {
        self.client
            .query_raw(&self.fortune, iter::empty())
            .await
            .unwrap()
            .map(|row| row.unwrap())
            .map(|row| Fortune {
                id: row.get(0),
                message: Cow::Owned(row.get(1)),
            })
            .collect::<Vec<_>>()
            .await
    }

Empty<T> not being Sync is the only issue.

@Dylan-DPC-zz
Copy link

@xfix given the difference between when the PR was closed and now, it would be easier to create a new PR :)

@Mark-Simulacrum
Copy link
Member

Notably, we cannot reopen this merge request due to GitHub limitations. We would be happy to review a new version!

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Jan 19, 2020
Make iter::Empty<T> Send and Sync for any T

Continuing from rust-lang#57682

It's quite funny, when I initially submitted this pull request, I said "Likely nobody will be using that property of `iter::empty`", but then a year later I got a compilation error because it wasn't `Send` and `Sync`.

Unfortunately, `PhantomData<fn() -> T>` still errors out. Oh well. I proposed `
struct PhantomFnWorkaround<T>(fn() -> T);`, but dtolnay did not like it, so using explicit implementations.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Jan 19, 2020
Make iter::Empty<T> Send and Sync for any T

Continuing from rust-lang#57682

It's quite funny, when I initially submitted this pull request, I said "Likely nobody will be using that property of `iter::empty`", but then a year later I got a compilation error because it wasn't `Send` and `Sync`.

Unfortunately, `PhantomData<fn() -> T>` still errors out. Oh well. I proposed `
struct PhantomFnWorkaround<T>(fn() -> T);`, but dtolnay did not like it, so using explicit implementations.
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants