Rust: `PhantomData<fn()>` is unstable in `const fn`

Created on 25 Feb 2020  路  5Comments  路  Source: rust-lang/rust

I tried this code:

use core::marker::PhantomData;

const fn test() {
    let _: PhantomData<fn()> = PhantomData;
}

(playground)

I expected it to work, but it doesn't work.

Error:

error[E0723]: function pointers in const fn are unstable
 --> src/lib.rs:4:32
  |
4 |     let _: PhantomData<fn()> = PhantomData;
  |                                ^^^^^^^^^^^
  |
  = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
  = help: add `#![feature(const_fn)]` to the crate attributes to enable

I use PhantomData<fn(T) -> T> to make type invariant over T & mark that I don't own T. I see no reason for this code to be unstable.

Meta

rustc --version --verbose:

rustc 1.43.0-nightly (433aae93e 2020-02-14)
binary: rustc
commit-hash: 433aae93e4ef866a1fdfefad136b32ed89acd3e7
commit-date: 2020-02-14
host: x86_64-unknown-linux-gnu
release: 1.43.0-nightly
LLVM version: 9.0
A-const-fn C-feature-request T-lang

All 5 comments

To add to this, the only stable way to achieve const friendly non-owning invariance is with PhantomData<*mut T> which means that you must implement Send and Sync manually. This is unfortunate.

There is a similar issue with PhantomData<dyn Fn(T)> (I was trying to find a workaround...):

error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
  --> src/dimensions.rs:94:14
   |
94 |         Self(PhantomData)
   |              ^^^^^^^^^^^
   |
   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
   = help: add `#![feature(const_fn)]` to the crate attributes to enable

I've found a workaround for my case (generic struct with PhantomData inside + const fn new) 馃帀

pub struct Generic<T>(core::marker::PhantomData<fn(T) -> T>);

impl<T> Generic<T> {
    const NEW: Self = Self(core::marker::PhantomData);
}

impl<T> Generic<T> {
    pub const fn new() -> Self {
        Self::NEW
    }
}

(playgrond)

Here is another workaround,

struct Invariant<T>(fn(T) -> T);
pub struct Generic<T>(core::marker::PhantomData<Invariant<T>>);

impl<T> Generic<T> {
    pub const fn new() -> Self {
        Self(PhantomData)
    }
}
Was this page helpful?
0 / 5 - 0 ratings