Search code examples
d

What are the storage classes in D?


Up until now I was under the impression that things like immutable and const were storage classes. In a recent video (at around 11:55) Walter Bright states that immutable is not a storage class, but rather it's a type constructor. In the official documentation, immutable, const, and among many other keywords, are listed as being storage classes:

StorageClass:
abstract
auto
const
deprecated
enum
extern
final
immutable
inout
shared
nothrow
override
pure
__gshared
Property
scope
static
synchronized

Is this list wrong? Some of it doesn't make sense(e.g., deprecated, override).

I know static and ref are storage classes, but what's the rest? And which one of the keywords in D are type constructors?


Solution

  • I would point out that there is a big difference between a grammar rule named StorageClass, and what is semantically a storage class in the language. The grammar rules have to do with parsing, not the semantic phase of compilation.

    First off, TDPL, chapter 8, is explicitly about type qualifiers (for which Walter used the term type constructor). There are only 3 of them in D:

    const
    immutable
    shared

    All three of them are a part of the type that they modify. Such is not true with storage classes such as ref.

    inout is what TDPL calls a "wildcard qualifier symbol," so it's a placeholder for a type qualifier rather than really being either a type qualifer or a storage class.

    Now, as to what's a storage classes or not, I give two quotes from TDPL:

    Each function parameter (base and exponent in the example above) has, in addition to its type, an optional storage class that decides the way that arguments are passed to the function when invoked.

    (from pages 6 - 7)

    Although static is not related to passing arguments to functions, discussing it here is appropriate because, just like ref, static applied to data is a storage class, meaning an indication about a detail regarding how data is stored.

    (from page 137)

    Also, there's this line with regards to storage classes in C which seems to be used quite a bit in explanations on storage classes in C found online:

    A storage class defines the scope (visibility) and life time of variables and/or functions within a C Program.

    A storage class has no effect on the type of a variable, just how it's stored. Unfortunately, I can't find an exact list of storage classes in D, and people are quite liberal with the term storage class, using it even when it doesn't apply. Pretty much any attribute applied to a type save for access modifiers seems to get called a storage class, depending on who's talking. However, there are a few which are beyond a doubt storage classes:

    enum (when used as a manifest constant)
    extern
    lazy
    out
    ref
    scope
    static

    lazy, out, and ref can be used to modify function parameters and indicate how they're passed, whereas enum and static are used to indicate how the variables are stored (which is nowhere in the case of enum, since manifest constants are copy-pasted everywhere that they're used rather than being actual variables). extern affects linkage.

    in is a hybrid, since it's a synonym for scope const, and while scope is a storage class, const is a type qualifier.

    The online documentation also refers to auto and synchronized as storage classes, though I don't know on what basis. auto is like inout in that it's a placeholder (in its case a placeholder for a type rather than a type qualifier) and therefore indicates nothing about how a type is stored, so I wouldn't have thought that it would be a storage class. synchronized doesn't modify variables but rather classes.

    __gshared is probably a storage class as well, though it's a bit funny, since it does more or less what shared (which is a type qualifier) does, but it's not part of the type.

    Beyond that, I don't know. The fact that synchronized is listed as a storage class implies that some of the others (such as final) might be, but (like synchronized) they have nothing to do with how variables are stored or linked. So, I don't know how they could be considered storage classes.

    I'll ask on the newsgroup though and see if I can get a more definitive list.

    EDIT: It seems that there is no definitive, official list of storage classes in D. The term is used for almost any attribute used on a variable declaration which doesn't affect its type (i.e. not a type qualifier). It seems that Walter and Andrei tend to make a big point about the type qualifiers to underline which attributes actually affect the type of a variable, but the term storage class hasn't been given anywhere near the same level of importance and ends up being used informally rather than per any rigorous definition.