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

Implement constants using & but not ~ or @ #2317

Closed
graydon opened this issue Apr 27, 2012 · 1 comment
Closed

Implement constants using & but not ~ or @ #2317

graydon opened this issue Apr 27, 2012 · 1 comment
Labels
A-frontend Area: Compiler frontend (errors, parsing and HIR) C-enhancement Category: An issue proposing an enhancement or a PR with one.
Milestone

Comments

@graydon
Copy link
Contributor

graydon commented Apr 27, 2012

I think we have a reasonable answer for structured constant expressions now, which is to construct them using &-pointers rather than boxes. Boxes are for dynamic allocation only.

I believe issues #1272, #1417, #571 and #570 all relate to this and should probably be merged into this one. I think the correct course of action is to define two subsets of the expression language:

  • Constant expressions (a subset of expressions)
  • Integer-constant expressions (a subset of constant expressions)

The compiler should have a pass that classifies each expression as either dynamic, constant, or integer-constant, based on its operators and operands.

Only constant expressions should be legal initializers for a const item. The compiler back-end can evaluate constant expressions to read-only memory using the LLVM constant instuctions.

The compiler front-end can evaluate integer-constant expressions, in order to deduce array bounds, structure sizes, enumeration discriminators and similar "size-like" values. This is what we're currently using eval_const_expr for (in bug #1417) and it should be rigorously defined as part of the language. In particular, we might in the future permit integer-constant expressions to show up inside portions of the type grammar (particularly relating to constant sizes given for arrays).

The compiler back-end should arrive at the exact same integer values as the front-end did, when translating an integer-constant expression.

We may also wish to look into a form of const fn as in C++0x constexpr functions. At this point I think it's effectively already reserved syntax for us so we can punt for now.

It may also be useful to add sizeof(), alignof(), and similar "built-in" constant functions implemented using compiler intrinsics.

@ghost ghost assigned graydon Apr 27, 2012
@graydon
Copy link
Contributor Author

graydon commented May 10, 2012

Thought about this a bit more:

  • 'const fn' is, I think, overkill. Obliges the compiler to do a ton
    of additional work simulating runtime semantics, and gets the phases
    really mixed up, circular.
  • The scary case is integers sneaking into types, as in fixed-size
    arrays. I think the main case for this is actually C interop, where
    a syntax extension that reaches into clang, grabs C type-size
    information, and returns a literal is probably sufficient. I don't
    think it's necessary to generalize to "any constant expression can
    appear in a type". Which is good, because that would be a huge
    undertaking and very likely make the phases circular, to the point
    of total confusion.
  • Given that, sizeof/alignof/offsetof probably don't need to be
    const exprs. The other use-case for distinct integer-const exprs
    (as opposed to general const exprs) is in enum discriminant values,
    and I don't know exactly why they can't be pushed back to "some LLVM
    constant we'll get the actual value of later". I'm willing to find
    out, if someone can enlighten me!
  • Very little compiler-work is saved -- in fact I think it's more work
    -- to spill, emit a call to a visitor, and reload (and inline that),
    instead of just emitting integer-add or fp-mul. At least for types
    already well understood to the compiler, LLVM, and machine.
  • The primitive types already have privileged status in a few places,
    such as literal forms, presence in types (again, fixed vectors),
    and permitting multiple integer types for the RHS of << and [] and
    whatnot.
  • All this combines to make me think:
    • Integer, fp, raw pointer, region pointer, literal, addr-of,
      concatenation and indexing is an ok set of constant exprs.
      Evaluation happens in target mode, operands must themselves
      be constants, and we can do it in LLVM. It's just a line
      distinguishing "what we can define a 'const' as and have in
      read-only memory".
    • All such constant expressions (including literals, raw
      and region-pointer ops, fp and integer ops), have fixed
      compiler-implemented meaning. Anything more complex you want
      to do at compile time you have to shell out to a syntax
      extension for. Maybe we provide a variable-precision fp
      calculator extension for fancy math constants.
    • All nontrivial operations are routed through visitors, where
      "trivial" means that the operation could have been a constant
      expr if only it had been applied to constant operands. IOW
      anything that boils down to 0 or 1 LLVM operation, memcmp or
      memmove is trivial. Anything touching the heap or a dynamic-sized
      value is nontrivial.

I understand this is a somewhat ragged line cut through the space of constant-ness, but I think it can be defended in a principled way: the compiler does what compilers are good at -- primitives of various sorts, read-only memory slabs and addresses -- and the libraries do the rest.

This does mean that sizeof, alignof and offsetof, applied to rust types, remain "runtime" values, even though the compiler implements them as intrinsics and they wind up as emitted / inlined constants. Again, I think the main reason we'd want to have these functions evaluated much earlier -- i.e. "before types" -- has to do with C interop, and can be handled by a syntax extension that returns literals calculated by clang, but I could be wrong. Input welcome.

@graydon graydon closed this as completed in f0775d7 Aug 9, 2012
@graydon graydon removed their assignment Jun 16, 2014
bors added a commit to rust-lang-ci/rust that referenced this issue Sep 22, 2022
… r=RalfJung

move arc_drop test to miri-test-libstd

That's where we have a bunch of slow and unlikely-to-regress tests already. Miri's test suite should primarily test Miri; we sometimes add libstd tests when they are cheap and/or exercise interesting code paths in Miri. rust-lang/miri#2248 already ensures that we allow code like `Arc` with more direct tests.
celinval pushed a commit to celinval/rust-dev that referenced this issue Jun 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-frontend Area: Compiler frontend (errors, parsing and HIR) C-enhancement Category: An issue proposing an enhancement or a PR with one.
Projects
None yet
Development

No branches or pull requests

1 participant