Changes the ad-hoc closure adjustment into using adjustment info instead
of being separately driven from types, and likewise for autoderef.
Also takes care of autoref (the cases we should be seeing in consts,
at least, since we can't be doing method calls which would need the
ref-to-vec mode), which didn't quite work right previously.
However, "dereference" of a newtype isn't handled yet....
Also converts const cast-from-enum, because it used the same routine to
get the discriminant as what's renovated to construct the enums.
Also fixes ICE on struct-like variants as consts, and provides a slightly
less bad ICE for functional-update-like struct expressions in consts.
Later changes on this branch adapt the rest of rustc::middle::trans
to use this module instead of scattered hard-coded knowledge of
representations; a few of them also have improvements or cleanup for
adt.rs (and many added comments) that weren't drastic enough to justify
changing history to move them into this commit.
If an enum is isomorphic to unit, there's no need to use any bits to
represent it. The only obvious reason this wasn't the case was because
the enum could be C-like and have a user-specified discriminant -- but
that value is constant, so it doesn't need to be stored.
This change means that all newtype-like enums have the same size (and
layout) as their underlying type, which might be a useful property to
have, at least in terms of making programs' low-level behavior less
surprising.
The number of operands of the LLVM node initializing the array
underlying a const vector isn't always the array length -- if the
array is of a sufficiently primitive type and all the elements' values
are known (or something like that), LLVM uses a specialized Constant
subclass that stores the data packed, and thus has no operands. Oops.
But, because llsize_of now gives us a ConstantInt, we can just fix
mozilla/rust#3169 and this all goes away.
This is wasted space if the const is just an enum, but optimizing that
case without breaking everything else is an issue that can be addressed
separately.
Loosening the connection between the LLVM type and the Rust type
is necessary to use non-nullary enum constructors as const initializers,
because the const needs to be initialized with data of the actual type of
the variant in question, which is (generally) not the same as the u8
array in the `type_of` type.
Thus, referring to a const now requires casting the LLVM global to the
expected pointer type instead of using it as-is.