Skip to content

Constructing Option<&'static dyn T>::None in a const fn requires const_fn_trait_bounds #87240

Open
@cceckman

Description

@cceckman

Thank you for filing a bug report! 🐛

Thank you for continuing to improve Rust!


Given the following code: playground

trait Irrelevant {}

struct Buffer {
    ptr: Option<&'static dyn Irrelevant>,
}

impl Buffer {
    pub const fn new() -> Self {
        Buffer {
            ptr: None,
        }
    }
}

The current output is:

error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
  --> src/lib.rs:10:18
   |
10 |             ptr: None,
   |                  ^^^^
   |
   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information

error: aborting due to previous error

For more information about this error, try `rustc --explain E0658`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

After reading this message and reading #57563, I'm not sure what trait bound is a problem. The code that is literally written here does not have any trait bounds - no syntax R: T; nor does it have any (explicit) generic const fn.

I assume there is a good reason why this doesn't immediately work - I know the Rust team has put tons of work into making all this analysis correct, so this is not a complaint about the analysis. :-) I'm just not sure how to go from the compiler's message to an action other than "switch to nightly".

(I can confirm that switching to nightly and enabling #![feature(const_fn_trait_bounds)] does quiet the warning. It's not clear to me what more-specific issue than #57563 is tracking it?)


Experiments / speculation:

I'm assuming there's some sort of desugaring here that's causing a trait bound to appear - e.g. the None constructor becoming a const fn (per #61456) , and something in the Option's generic argument turning into a trait bound. However, Option<T> itself doesn't have any trait bounds on T (...other than the default Sized, which the error message says is OK), so I'm not sure what to change.

Some experimenting shows that Option<&static T> its OK for a built-in T:

trait Irrelevant {}

struct Buffer {
    ptr: Option<&'static usize>,
}

impl Buffer {
    pub const fn new() -> Self {
        Buffer {
            ptr: None,
        }
    }
}

compiles on stable (1.53.0).

And even using a different ?Sized type - [u8] - works out alright:

trait Irrelevant {}

struct Buffer {
    ptr: Option<&'static [u8]>,
}

impl Buffer {
    pub const fn new() -> Self {
        Buffer {
            ptr: None,
        }
    }
}

compiles as well.

That's based on a not-great understanding of Sized - if I understand correctly both dyn T and [u8] are ?Sized.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions