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 sizeof, alignof, offsetof and other type calculations available for use in constants #1144

Closed
nikomatsakis opened this issue Jun 2, 2015 · 21 comments
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.

Comments

@nikomatsakis
Copy link
Contributor

Currently, the standard library offers functions like size_of, but they are not available for use in constant expressions. It would be useful to be able to call such functions from constants, but it raises some interesting questions. For example:

  1. only the backend can faithfully compute the size of a type, but sometimes the front-end may need to know the actual value of a constant to decide (e.g.) if two constants are equal. (Some of these issues also arise with associated constants.)
  2. do we want keywords for these computations (like C), or should we try to adapt functions (perhaps via const fn)?
  3. etc

Related RFCs and comments:

@Mr-Byte
Copy link

Mr-Byte commented Jun 15, 2015

For consistency, I'd be in favor of these being const fn instead of actual keywords.

@eddyb
Copy link
Member

eddyb commented Dec 3, 2015

There is a compromise we can make to avoid going the static structural reflection route:

Allow dereferencing raw pointers which were cast from an integer, and produce an internal AddressLvalue(addr) constant value, equivalent to *(addr as *const _) in an unsafe context.
Only operations which are arithmetic on addr are accepted, e.g. field access, indexing, .offset.

Taking a reference to such lvalue results in Ref(AddressLvalue(addr)), which can be coerced to *const T, producing addr as *const, which can, in turn, be cast back to an integer type to retrieve addr.

At the API "membrane" level, constants (global/associated/generic const and const fn arguments/returns, maybe excluding intrinsics) have to be pure, which means no AddressLvalue present anywhere in them, and the origin of raw pointers cannot be assumed to be a safe reference, nor an integer address, so both dereferencing and casting back to integers is disallowed at that point.

This is enough to implement the "traditional" offsetof macro, with the representation logic lifted up from trans/LLVM to rustc proper.

@comex
Copy link

comex commented Mar 2, 2016

👍 was just reminded that some of my code would really benefit from this.

@kennytm
Copy link
Member

kennytm commented Jun 11, 2016

In rust-lang/rust#32021, @huonw wrote

Unfortunately, the feature has some (possibly) surprising subtleties that make it trickier than one might hope.

I'm not sure what kind of subtleties are there in making mem::size_of (not size_of_val) a const fn. It doesn't involve any kind of AddressLvalue AFAICT.

@eddyb
Copy link
Member

eddyb commented Jun 11, 2016

@kennytm FWIW I was talking about offsetof.

@nrc nrc added the T-lang Relevant to the language team, which will review and decide on the RFC. label Aug 29, 2016
@joshtriplett
Copy link
Member

For size_of and align_of, I'd like to see them as functions, not keywords. offset_of seems like it requires a macro, to accept a field name.

@burdges
Copy link

burdges commented Nov 2, 2016

Is there an issue with making these associated constants?

As an aside, I noticed the associated constants i16::MIN and i16::MAX are painful to access, while min_value() and max_value() remain easy.

@Binero
Copy link

Binero commented Nov 2, 2016

Could be made accessible through a trait so you can be generic over integers with different reaches.

@cptroot
Copy link

cptroot commented Mar 20, 2017

Is there any update on the status of offsetof? I would love to have access to it for the purpose of kernel internal linked lists.

@frehberg
Copy link

would be great to have constant variant of mem::size_of_val() for macros that allocate byte-array on stack depending on size of macro-parameter: see https://crates.io/crates/releasetag
right now compiler-plugin is required to request size of b-string during compile time.

@burdges
Copy link

burdges commented Apr 27, 2017

I'd love an associated type and/or macro that provided a type-level type_of. It would help track interface churn without without creating and importing numerous type aliases. A syntax might be :

enum Foo {
    Foo1(FooType),
}
struct AltFoo(type_of!<Foo::Foo1::0>, ..);

struct Bar { field: BarType }
struct AltBar { field: type_of!<Bar::field>, ... }

It's not as useful as say a ::LENGTH associated constant for fixed length arrays, or perhaps [S; size_of::<ArrayOfT>() / size_of::<T>], but still pretty handy.

@eddyb
Copy link
Member

eddyb commented Apr 27, 2017

@burdges We have the typeof keyword reserved for if and the compiler has "accidentally" grown an almost full implementation of it - in that it's not a hard problem in the design we're moving towards - the same design that can evaluate size_of even early on.

All of these features have been ready for an ah-hoc implementation for a few months, but someone needs to write the RFCs.

@frehberg
Copy link

frehberg commented May 1, 2017

What do you mean with "someone needs to write the RFCs"? No such RFC for size_of/typeof existing so far?? Can you give me a short sample, how the ad-hoc impl would be used in practice?

@eddyb
Copy link
Member

eddyb commented May 1, 2017

@frehberg If a RFC has been done, it has been postponed. RFCs don't stay open waiting for the technology to arrive AFAIK. The functions would be ad-hoc in the compiler but they'd be used like at runtime - just some calls to std::mem::{size_of, align_of}.

typeof if trickier because you need to come up with the syntax for it, but say, typeof(f()) would get you the type returned by calling f with no arguments.
Type-checking can proceed just as it does in regular constants/functions, but the code would never be executed or required to obey e.g. constant-checking/borrow-checking rules.

@oli-obk
Copy link
Contributor

oli-obk commented Feb 22, 2018

size_of and align_of are const fn since a few months.

@petrochenkov
Copy link
Contributor

I'm going to close this issue, MIRI will be fully merged in rustc very soon and after that making specific functions or features constexpr is better tracked by separate issues in rust-lang/rust repo.

@bstrie
Copy link
Contributor

bstrie commented Jul 24, 2019

@petrochenkov did you open equivalent issues in rust-lang/rust after closing this one? I didn't find any in my cursory search. I'm happy to create them if not.

@petrochenkov
Copy link
Contributor

did you open equivalent issues in rust-lang/rust after closing this one?

No, I didn't, IIRC.
I'm not sure what here requires opening an issue given that sizeof/alignof are stable, and offsetof is an early phase RFC material.

@bstrie
Copy link
Contributor

bstrie commented Jul 24, 2019

I was actually interested in offsetof specifically, I wasn't sure if there was any development on that front yet.

@bstrie
Copy link
Contributor

bstrie commented Jul 24, 2019

Worth mentioning that I found this issue via a link from the original RFC discussion for adding offsetof, which suggested continuing the discussion here. If there's no other place currently tracking the addition of offsetof, I might at least make an issue in the RFCs repo here.

@petrochenkov
Copy link
Contributor

@bstrie
Some recent discussions:
https://internals.rust-lang.org/t/idea-pointer-to-field/10061
https://internals.rust-lang.org/t/pre-rfc-add-a-new-offset-of-macro-to-core-mem/9273
#2708

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests