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

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

Closed
wants to merge 2 commits into from

Conversation

KamilaBorowska
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
Collaborator

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
Contributor

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.

@KamilaBorowska
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.

@KamilaBorowska
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 :)

@KamilaBorowska
Copy link
Contributor Author

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

@KamilaBorowska
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.

@KamilaBorowska
Copy link
Contributor Author

KamilaBorowska 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
@KamilaBorowska
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in 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.

None yet

7 participants