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?
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:
All three of them are a part of the type that they modify. Such is not true with storage classes such as
ref.inoutis 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:
(from pages 6 – 7)
(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 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:
lazy,out, andrefcan be used to modify function parameters and indicate how they’re passed, whereasenumandstaticare used to indicate how the variables are stored (which is nowhere in the case ofenum, since manifest constants are copy-pasted everywhere that they’re used rather than being actual variables).externaffects linkage.inis a hybrid, since it’s a synonym forscope const, and whilescopeis a storage class,constis a type qualifier.The online documentation also refers to
autoandsynchronizedas storage classes, though I don’t know on what basis.autois likeinoutin 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.synchronizeddoesn’t modify variables but rather classes.__gsharedis probably a storage class as well, though it’s a bit funny, since it does more or less whatshared(which is a type qualifier) does, but it’s not part of the type.Beyond that, I don’t know. The fact that
synchronizedis listed as a storage class implies that some of the others (such asfinal) might be, but (likesynchronized) 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.