Skip to content

[tracking issue] const fn: count_zeros, count_ones, leading_zeros, trailing_zeros #51267

Closed
@glandium

Description

@glandium
Contributor

One thing that I would like to do is to compile-time assert that the log2 of an alignment is less a given size. A simple way to do log2 of a power of 2 is to use trailing_zeros. But trailing_zeros is not const, so it's not possible to do a compile-time check.

The equivalent __builtins in clang are const (example: https://godbolt.org/g/RxWczn) so llvm should be able to handle that.

However, adding const to the functions in core::num requires adding const to the corresponding intrinsics, and that is not supported (extern items cannot be 'const')

Activity

hanna-kruppe

hanna-kruppe commented on Jun 1, 2018

@hanna-kruppe
Contributor

The underlying intrinsics are const as of #51171, now we just need to make the stable wrapper functions const (possibly #[rustc_const_unstable]).

The equivalent __builtins in clang are const (example: https://godbolt.org/g/RxWczn) so llvm should be able to handle that.

LLVM is irrelevant. Clang is evaluating the built-in in the frontend (check the generated IR at -O0), and rustc is doing it in miri. Both have to do that since the value of a constant can be needed during type checking.

glandium

glandium commented on Jun 1, 2018

@glandium
ContributorAuthor

hah, I tried an hour too early!

glandium

glandium commented on Jun 1, 2018

@glandium
ContributorAuthor

There's a bootstrapping problem, though. stage0 doesn't have support for those const intrinsics, so it won't accept the const keyword even behind a #[cfg(not(stage0))]. So it's either macro pain or wait for 1.29.

nagisa

nagisa commented on Jun 1, 2018

@nagisa
Member

One thing that I would like to do is to compile-time assert that the log2 of an alignment is less a given size. A simple way to do log2 of a power of 2 is to use trailing_zeros. But trailing_zeros is not const, so it's not possible to do a compile-time check.

Is const fn assert(x: usize) -> bool { x < (1 << LOG2) } not enough to do this check?

Not disagreeing, though, that it would be nice to have these operations be const fn :)

oli-obk

oli-obk commented on Jun 1, 2018

@oli-obk
Contributor
added
C-feature-requestCategory: A feature request, i.e: not implemented / a PR.
A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)
on Jun 1, 2018
faern

faern commented on Jun 1, 2018

@faern
Contributor

Yes. I created #51171 in order to then make swap_bytes, to_le, to_be, trailing_zeros, count_ones etc const. Was planning on doing this as soon as the stage0 compiler is bumped. I already have the code for it done :)

faern

faern commented on Jun 1, 2018

@faern
Contributor

Initially I only planned on making swap_bytes and the endianess conversion const fns. But since we also merged making cttz, ctlz and ctpop constant intrinsics this could very well be extended to the integer methods using these intrinsics as well.

I made the appropriate methods on integers constant and pushed a feature branch to my fork, the diff can be viewed at https://github.com/rust-lang/rust/compare/master...faern:const-int-ops?expand=1. Please check if it makes all the methods you need const fns. To try that branch one must first point to a very new nightly rustc for stage0 in config.toml.

I'm going to try to get that feature branch merged into nightly as soon as Rust 1.27 comes out and the stage0 compiler is bumped. But yes, if I understand the way the stage0 compiler is bumped, this can't hit stable before Rust 1.29.

glandium

glandium commented on Jun 1, 2018

@glandium
ContributorAuthor

(unless #51171 is uplifted to beta)

oli-obk

oli-obk commented on Jun 1, 2018

@oli-obk
Contributor

unless #51171 is uplifted to beta

There is no motivation to do so. This is a feature, not a bugfix.

To try that branch one must first point to a very new nightly rustc for stage0 in config.toml.

Idk what the policy on that is, but maybe we can just bump the stage0 now?

Mark-Simulacrum

Mark-Simulacrum commented on Jun 1, 2018

@Mark-Simulacrum
Member

stage0 must always be a beta compiler, but otherwise we can bump whenever. I'm not opposed to uplifting #51171 if it make some other patch possible, but that should ~never be the case. AFAICT, the correct approach here is to have the relevant methods (count_*) be made const fn with #[cfg(not(stage0)] and left as-is in stage0, which should permit landing this change whenever.

glandium

glandium commented on Jun 1, 2018

@glandium
ContributorAuthor

You can't do something like:

#[cfg(stage0)]
fn foo() {}
#[cfg(not(stage0))]
const fn foo() {}

The stage0 compiler still barfs about the const. So the only way to do this without a stage0 that has #51171 is a macro that can parse all kinds of function declarations.

Mark-Simulacrum

Mark-Simulacrum commented on Jun 1, 2018

@Mark-Simulacrum
Member

I am somewhat surprised by that? Do you happen to have an error message?

25 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)C-feature-requestCategory: A feature request, i.e: not implemented / a PR.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @fbstj@oli-obk@faern@nagisa@Centril

        Issue actions

          [tracking issue] const fn: count_zeros, count_ones, leading_zeros, trailing_zeros · Issue #51267 · rust-lang/rust