diff dmd/Type.d @ 135:af1bebfd96a4 dmd2037

dmd 2.038
author Eldar Insafutdinov <e.insafutdinov@gmail.com>
date Mon, 13 Sep 2010 22:19:42 +0100
parents 206db751bd4c
children 31c086f76669
line wrap: on
line diff
--- a/dmd/Type.d	Sat Sep 11 13:03:39 2010 +0100
+++ b/dmd/Type.d	Mon Sep 13 22:19:42 2010 +0100
@@ -59,6 +59,8 @@
 import dmd.DotIdExp;
 import dmd.AggregateDeclaration;
 import dmd.DotTemplateInstanceExp;
+import dmd.Token;
+import dmd.TypeInfoWildDeclaration;
 
 import dmd.expression.Util;
 
@@ -127,6 +129,102 @@
     return -1;
 }
 
+/***************************
+ * Return !=0 if modfrom can be implicitly converted to modto
+ */
+int MODimplicitConv(MOD modfrom, MOD modto)
+{
+    if (modfrom == modto)
+	return 1;
+
+    //printf("MODimplicitConv(from = %x, to = %x)\n", modfrom, modto);
+	static uint X(MOD m, MOD n)
+	{
+		return (((m) << 4) | (n));
+	}
+    switch (X(modfrom, modto))
+    {
+	    case X(MOD.MODundefined, MOD.MODconst):
+	    case X(MOD.MODimmutable, MOD.MODconst):
+	    case X(MOD.MODwild,      MOD.MODconst):
+	    case X(MOD.MODimmutable, MOD.MODconst | MOD.MODshared):
+	    case X(MOD.MODshared,    MOD.MODconst | MOD.MODshared):
+	    case X(MOD.MODwild | MOD.MODshared,    MOD.MODconst | MOD.MODshared):
+	        return 1;
+
+	    default:
+	        return 0;
+    }
+}
+
+/*********************************
+ * Mangling for mod.
+ */
+void MODtoDecoBuffer(OutBuffer buf, MOD mod)
+{
+    switch (mod)
+    {
+        case MOD.MODundefined:
+	        break;
+	    case MOD.MODconst:
+	        buf.writeByte('x');
+	        break;
+	    case MOD.MODimmutable:
+	        buf.writeByte('y');
+	        break;
+	    case MOD.MODshared:
+	        buf.writeByte('O');
+	        break;
+	    case MOD.MODshared | MOD.MODconst:
+	        buf.writestring("Ox");
+	        break;
+	    case MOD.MODwild:
+	        buf.writestring("Ng");
+	        break;
+	    case MOD.MODshared | MOD.MODwild:
+	        buf.writestring("ONg");
+	        break;
+	    default:
+	        assert(0);
+    }
+}
+
+/*********************************
+ * Name for mod.
+ */
+void MODtoBuffer(OutBuffer buf, MOD mod)
+{
+    switch (mod)
+    {
+    case MOD.MODundefined:
+	    break;
+
+	case MOD.MODimmutable:
+	    buf.writestring(Token.tochars[TOK.TOKimmutable]);
+	    break;
+
+	case MOD.MODshared:
+	    buf.writestring(Token.tochars[TOK.TOKshared]);
+	    break;
+
+	case MOD.MODshared | MOD.MODconst:
+	    buf.writestring(Token.tochars[TOK.TOKshared]);
+	    buf.writeByte(' ');
+	case MOD.MODconst:
+	    buf.writestring(Token.tochars[TOK.TOKconst]);
+	    break;
+
+	case MOD.MODshared | MOD.MODwild:
+	    buf.writestring(Token.tochars[TOK.TOKshared]);
+	    buf.writeByte(' ');
+	case MOD.MODwild:
+	    buf.writestring(Token.tochars[TOKwild]);
+	    break;
+	default:
+	    assert(0);
+    }
+}
+
 class Type
 {
     TY ty;
@@ -143,12 +241,16 @@
      * They should not be referenced by anybody but mtype.c.
      * They can be null if not lazily evaluated yet.
      * Note that there is no "shared immutable", because that is just immutable
+     * Naked == no MOD bits
      */
 
-    Type cto;		// MODconst ? mutable version of this type : const version
-    Type ito;		// MODinvariant ? mutable version of this type : invariant version
-    Type sto;		// MODshared ? mutable version of this type : shared mutable version
-    Type scto;		// MODshared|MODconst ? mutable version of this type : shared const version
+    Type cto;		// MODconst ? naked version of this type : const version
+    Type ito;		// MODimmutable ? naked version of this type : immutable version
+    Type sto;		// MODshared ? naked version of this type : shared mutable version
+    Type scto;		// MODshared|MODconst ? naked version of this type : shared const version
+    Type wto;		// MODwild ? naked version of this type : wild version
+    Type swto;		// MODshared|MODwild ? naked version of this type : shared wild version
+
 
     Type pto;		// merged pointer to this type
     Type rto;		// reference to this type
@@ -173,6 +275,7 @@
     static ClassDeclaration typeinfoconst;
     static ClassDeclaration typeinfoinvariant;
     static ClassDeclaration typeinfoshared;
+    static ClassDeclaration typeinfowild;
 
     static Type basic[TY.TMAX];
     static ubyte mangleChar[TY.TMAX];
@@ -493,7 +596,7 @@
 			 * forward references.
 			 */
 			if ((cast(TypeClass)t1n).sym == (cast(TypeClass)t2n).sym &&
-				t2n.mod == MOD.MODconst)
+				MODimplicitConv(t1n.mod, t2n.mod))
 				goto Lcovariant;
 
 			// If t1n is forward referenced:
@@ -512,6 +615,9 @@
 	Lcovariant:
 		/* Can convert mutable to const
 		 */
+        if (!MODimplicitConv(t2.mod, t1.mod))
+	        goto Lnotcovariant;
+static if(false) {
 		if (t1.mod != t2.mod)
 		{
 			if (!(t1.mod & MOD.MODconst) && (t2.mod & MOD.MODconst))
@@ -519,7 +625,7 @@
 			if (!(t1.mod & MOD.MODshared) && (t2.mod & MOD.MODshared))
 				goto Lnotcovariant;
 		}
-
+}
 		/* Can convert pure to impure, and nothrow to throw
 		 */
 		if (!t1.ispure && t2.ispure)
@@ -628,6 +734,7 @@
 		mangleChar[TY.Twchar] = 'u';
 		mangleChar[TY.Tdchar] = 'w';
 
+        // '@' shouldn't appear anywhere in the deco'd names
 		mangleChar[TY.Tbit] = '@';
 		mangleChar[TY.Tinstance] = '@';
 		mangleChar[TY.Terror] = '@';
@@ -736,16 +843,7 @@
 	{
 		if (flag != mod && flag != 0x100)
 		{
-			if (mod & MOD.MODshared)
-				buf.writeByte('O');
-
-			if (mod & MOD.MODconst)
-				buf.writeByte('x');
-			else if (mod & MOD.MODinvariant)
-				buf.writeByte('y');
-
-			// Cannot be both const and invariant
-			assert((mod & (MOD.MODconst | MOD.MODinvariant)) != (MOD.MODconst | MOD.MODinvariant));
+			MODtoDecoBuffer(buf, mod);
 		}
 		buf.writeByte(mangleChar[ty]);
 	}
@@ -832,40 +930,35 @@
 	{
 		if (mod != this.mod)
 		{
-			string p;
-
 			if (this.mod & MOD.MODshared)
-				buf.writestring("shared(");
+	        {
+	            MODtoBuffer(buf, this.mod & MOD.MODshared);
+	            buf.writeByte('(');
+	        }
 
-			switch (this.mod & (MOD.MODconst | MOD.MODinvariant))
-			{
-				case MOD.MODundefined:
-					toCBuffer2(buf, hgs, this.mod);
-					break;
-				case MOD.MODconst:
-					p = "const(";
-					goto L1;
-				case MOD.MODinvariant:
-					p = "immutable(";
-					L1:	buf.writestring(p);
-					toCBuffer2(buf, hgs, this.mod);
-					buf.writeByte(')');
-					break;
-			}
-
-			if (this.mod & MOD.MODshared)
-				buf.writeByte(')');
+	        if (this.mod & ~MOD.MODshared)
+	        {
+	            MODtoBuffer(buf, this.mod & ~MOD.MODshared);
+	            buf.writeByte('(');
+	            toCBuffer2(buf, hgs, this.mod);
+	            buf.writeByte(')');
+	        }
+	        else
+	            toCBuffer2(buf, hgs, this.mod);
+	        if (this.mod & MOD.MODshared)
+	        {
+	            buf.writeByte(')');
+	        }
 		}
 	}
 
     void modToBuffer(OutBuffer buf)
 	{
-		if (mod & MOD.MODshared)
-			buf.writestring(" shared");
-		if (mod & MOD.MODconst)
-			buf.writestring(" const");
-		if (mod & MOD.MODinvariant)
-			buf.writestring(" immutable");
+        if (mod)
+        {
+    	    buf.writeByte(' ');
+	        MODtoBuffer(buf, mod);
+        }
 	}
 
 version (CPP_MANGLE) {
@@ -948,13 +1041,20 @@
 
     bool isConst()	{ return (mod & MOD.MODconst) != 0; }
 
-	int isInvariant()	{ return mod & MOD.MODinvariant; }
+	int isImmutable()	{ return mod & MOD.MODimmutable; }
 
-	int isMutable()	{ return !(mod & (MOD.MODconst | MOD.MODinvariant)); }
+	int isMutable()	{ return !(mod & (MOD.MODconst | MOD.MODimmutable | MOD.MODwild)); }
 
 	int isShared()	{ return mod & MOD.MODshared; }
 
 	int isSharedConst()	{ return mod == (MOD.MODshared | MOD.MODconst); }
+            
+    int isWild()	{ return mod & MOD.MODwild; }
+
+    int isSharedWild()	{ return mod == (MOD.MODshared | MOD.MODwild); }
+
+    int isNaked()	{ return mod == 0; }
+
 
 	/********************************
 	 * Convert to 'const'.
@@ -982,13 +1082,13 @@
     Type invariantOf()
 	{	
 		//printf("Type.invariantOf() %p %s\n", this, toChars());
-		if (isInvariant())
+		if (isImmutable())
 		{
 			return this;
 		}
 		if (ito)
 		{
-			assert(ito.isInvariant());
+			assert(ito.isImmutable());
 			return ito;
 		}
 		Type t = makeInvariant();
@@ -1007,51 +1107,29 @@
 			if (isShared())
 				t = sto;		// shared const => shared
 			else
-				t = cto;
+				t = cto;		// const => naked
 			assert(!t || t.isMutable());
 		}
-		else if (isInvariant())
+		else if (isImmutable())
 		{	
 			t = ito;
 			assert(!t || (t.isMutable() && !t.isShared()));
 		}
+        else if (isWild())
+        {
+	        if (isShared())
+	            t = sto;		// shared wild => shared
+	        else
+	            t = wto;		// wild => naked
+	        assert(!t || t.isMutable());
+        }
 		if (!t)
 		{
-			uint sz = this.classinfo.init.length;
-			t = cast(Type)GC.malloc(sz);
-			memcpy(cast(void*)t, cast(void*)this, sz);
-			t.mod = mod & MODshared;
-			t.deco = null;
-			t.arrayof = null;
-			t.pto = null;
-			t.rto = null;
-			t.cto = null;
-			t.ito = null;
-			t.sto = null;
-			t.scto = null;
-			t.vtinfo = null;
+            t = makeMutable();
 			t = t.merge();
-
 			t.fixTo(this);
-
-			switch (mod)
-			{
-				case MODconst:
-					t.cto = this;
-					break;
-
-				case MODinvariant:
-					t.ito = this;
-					break;
-
-				case MODshared | MODconst:
-					t.scto = this;
-					break;
-
-				default:
-					assert(0);
-			}
 		}
+            assert(t.isMutable());
 		return t;
 	}
 
@@ -1099,6 +1177,13 @@
 
 	/********************************
 	 * Make type unshared.
+     *	0            => 0
+     *	const        => const
+     *	immutable    => immutable
+     *	shared       => 0
+     *	shared const => const
+     *	wild         => wild
+     *	shared wild  => wild
 	 */
 	Type unSharedOf()
 	{
@@ -1109,6 +1194,8 @@
 		{
 			if (isConst())
 				t = cto;	// shared const => const
+	        else if (isWild())
+	            t = wto;	// shared wild => wild
 			else
 				t = sto;
 			assert(!t || !t.isShared());
@@ -1128,37 +1215,68 @@
 			t.ito = null;
 			t.sto = null;
 			t.scto = null;
+	        t.wto = null;
+	        t.swto = null;
 			t.vtinfo = null;
 			t = t.merge();
 	
 			t.fixTo(this);
-	
-			switch (mod)
-			{
-				case MODshared:
-				t.sto = this;
-				break;
-	
-				case MODshared | MODconst:
-				t.scto = this;
-				break;
-	
-				default:
-				assert(0);
-			}
 		}
 		assert(!t.isShared());
 		return t;
 	}
 
+            
+    /********************************
+     * Convert to 'wild'.
+     */
+
+    Type wildOf()
+    {
+        //printf("Type::wildOf() %p %s\n", this, toChars());
+        if (mod == MOD.MODwild)
+        {
+	        return this;
+        }
+        if (wto)
+        {
+    	    assert(wto.isWild());
+	        return wto;
+        }
+        Type t = makeWild();
+        t = t.merge();
+        t.fixTo(this);
+        //printf("\t%p %s\n", t, t->toChars());
+        return t;
+    }
+
+    Type sharedWildOf()
+    {
+        //printf("Type::sharedWildOf() %p, %s\n", this, toChars());
+        if (mod == (MOD.MODwild))
+        {
+    	    return this;
+        }
+        if (swto)
+        {
+	        assert(swto.mod == (MOD.MODshared | MOD.MODwild));
+	        return swto;
+        }
+        Type t = makeSharedWild();
+        t = t.merge();
+        t.fixTo(this);
+        //printf("\t%p\n", t);
+        return t;
+    }
+
 	static uint X(MOD m, MOD n)
 	{
-		return (((m) << 3) | (n));
+		return (((m) << 4) | (n));
 	}
 
 	/**********************************
 	 * For our new type 'this', which is type-constructed from t,
-	 * fill in the cto, ito, sto, scto shortcuts.
+	 * fill in the cto, ito, sto, scto, wto shortcuts.
 	 */
     void fixTo(Type t)
 	{
@@ -1181,7 +1299,7 @@
 			cto = t;
 			break;
 
-		case X(MOD.MODundefined, MOD.MODinvariant):
+		case X(MOD.MODundefined, MOD.MODimmutable):
 			ito = t;
 			break;
 
@@ -1193,12 +1311,20 @@
 			scto = t;
 			break;
 
+        case X(MOD.MODundefined, MODwild):
+    	    wto = t;
+	        break;
+
+	    case X(MOD.MODundefined, MODshared | MODwild):
+    	    swto = t;
+	        break;
+
 
 		case X(MOD.MODconst, MOD.MODundefined):
 			cto = null;
 			goto L2;
 
-		case X(MOD.MODconst, MOD.MODinvariant):
+		case X(MOD.MODconst, MOD.MODimmutable):
 			ito = t;
 			goto L2;
 
@@ -1208,30 +1334,48 @@
 
 		case X(MOD.MODconst, MOD.MODshared | MOD.MODconst):
 			scto = t;
+	        goto L2;
+
+	    case X(MOD.MODconst, MOD.MODwild):
+	        wto = t;
+	        goto L2;
+
+	    case X(MOD.MODconst, MOD.MODshared | MOD.MODwild):
+	        swto = t;
 		L2:
 			t.cto = this;
 			break;
 
 
-		case X(MOD.MODinvariant, MOD.MODundefined):
+		case X(MOD.MODimmutable, MOD.MODundefined):
 			ito = null;
 			goto L3;
 
-		case X(MOD.MODinvariant, MOD.MODconst):
+		case X(MOD.MODimmutable, MOD.MODconst):
 			cto = t;
 			goto L3;
 
-		case X(MOD.MODinvariant, MOD.MODshared):
+		case X(MOD.MODimmutable, MOD.MODshared):
 			sto = t;
 			goto L3;
 
-		case X(MOD.MODinvariant, MOD.MODshared | MOD.MODconst):
+		case X(MOD.MODimmutable, MOD.MODshared | MOD.MODconst):
 			scto = t;
+	        goto L3;
+
+	    case X(MOD.MODimmutable, MOD.MODwild):
+	        wto = t;
+	        goto L3;
+
+	    case X(MOD.MODimmutable, MOD.MODshared | MOD.MODwild):
+	        swto = t;
 		L3:
 			t.ito = this;
 			if (t.cto) t.cto.ito = this;
 			if (t.sto) t.sto.ito = this;
 			if (t.scto) t.scto.ito = this;
+	        if (t.wto) t.wto.ito = this;
+	        if (t.swto) t.swto.ito = this;
 			break;
 
 
@@ -1243,12 +1387,20 @@
 			cto = t;
 			goto L4;
 
-		case X(MOD.MODshared, MOD.MODinvariant):
+		case X(MOD.MODshared, MOD.MODimmutable):
 			ito = t;
 			goto L4;
 
 		case X(MOD.MODshared, MOD.MODshared | MOD.MODconst):
 			scto = t;
+	        goto L4;
+
+	    case X(MOD.MODshared, MOD.MODwild):
+	        wto = t;
+	        goto L4;
+
+	    case X(MOD.MODshared, MOD.MODshared | MOD.MODwild):
+	        swto = t;
 		L4:
 			t.sto = this;
 			break;
@@ -1256,21 +1408,82 @@
 
 		case X(MOD.MODshared | MOD.MODconst, MOD.MODundefined):
 			scto = null;
-			break;
+			goto L5;
 
 		case X(MOD.MODshared | MOD.MODconst, MOD.MODconst):
 			cto = t;
-			break;
+			goto L5;
 
-		case X(MOD.MODshared | MOD.MODconst, MOD.MODinvariant):
+		case X(MOD.MODshared | MOD.MODconst, MOD.MODimmutable):
 			ito = t;
-			break;
+	        goto L5;
+
+	    case X(MOD.MODshared | MOD.MODconst, MOD.MODwild):
+	        wto = t;
+	        goto L5;
 
 		case X(MOD.MODshared | MOD.MODconst, MOD.MODshared):
 			sto = t;
+	        goto L5;
+
+	    case X(MOD.MODshared | MOD.MODconst, MOD.MODshared | MOD.MODwild):
+	        swto = t;
 		L5:
 			t.scto = this;
 			break;
+            
+	    case X(MOD.MODwild, MOD.MODundefined):
+	        wto = null;
+	        goto L6;
+
+	    case X(MOD.MODwild, MOD.MODconst):
+	        cto = t;
+	        goto L6;
+
+	    case X(MOD.MODwild, MOD.MODimmutable):
+	        ito = t;
+	        goto L6;
+
+	    case X(MOD.MODwild, MOD.MODshared):
+	        sto = t;
+	        goto L6;
+
+	    case X(MOD.MODwild, MOD.MODshared | MOD.MODconst):
+	        scto = t;
+	        goto L6;
+
+	    case X(MOD.MODwild, MOD.MODshared | MOD.MODwild):
+	        swto = t;
+	    L6:
+	        t.wto = this;
+	        break;
+
+
+	    case X(MOD.MODshared | MOD.MODwild, MOD.MODundefined):
+	        swto = null;
+	        goto L7;
+
+	    case X(MOD.MODshared | MOD.MODwild, MOD.MODconst):
+	        cto = t;
+	        goto L7;
+
+	    case X(MOD.MODshared | MOD.MODwild, MOD.MODimmutable):
+	        ito = t;
+	        goto L7;
+
+	    case X(MOD.MODshared | MOD.MODwild, MOD.MODshared):
+	        sto = t;
+	        goto L7;
+
+	    case X(MOD.MODshared | MOD.MODwild, MOD.MODshared | MOD.MODconst):
+	        scto = t;
+	        goto L7;
+
+	    case X(MOD.MODshared | MOD.MODwild, MOD.MODwild):
+	        wto = t;
+	    L7:
+	        t.swto = this;
+	        break;
 		}
 
 		check();
@@ -1287,38 +1500,66 @@
 		{
 		case MOD.MODundefined:
 			if (cto) assert(cto.mod == MOD.MODconst);
-			if (ito) assert(ito.mod == MOD.MODinvariant);
+			if (ito) assert(ito.mod == MOD.MODimmutable);
 			if (sto) assert(sto.mod == MOD.MODshared);
 			if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst));
+	        if (wto) assert(wto.mod == MOD.MODwild);
+	        if (swto) assert(swto.mod == (MOD.MODshared | MOD.MODwild));
 			break;
 
 		case MOD.MODconst:
 			if (cto) assert(cto.mod == MOD.MODundefined);
-			if (ito) assert(ito.mod == MOD.MODinvariant);
+			if (ito) assert(ito.mod == MOD.MODimmutable);
 			if (sto) assert(sto.mod == MOD.MODshared);
 			if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst));
+	        if (wto) assert(wto.mod == MOD.MODwild);
+	        if (swto) assert(swto.mod == (MOD.MODshared | MOD.MODwild));
 			break;
 
-		case MOD.MODinvariant:
+		case MOD.MODimmutable:
 			if (cto) assert(cto.mod == MOD.MODconst);
 			if (ito) assert(ito.mod == MOD.MODundefined);
 			if (sto) assert(sto.mod == MOD.MODshared);
 			if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst));
+	        if (wto) assert(wto.mod == MOD.MODwild);
+	        if (swto) assert(swto.mod == (MOD.MODshared | MOD.MODwild));
 			break;
 
 		case MOD.MODshared:
 			if (cto) assert(cto.mod == MOD.MODconst);
-			if (ito) assert(ito.mod == MOD.MODinvariant);
+			if (ito) assert(ito.mod == MOD.MODimmutable);
 			if (sto) assert(sto.mod == MOD.MODundefined);
 			if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst));
+	        if (wto) assert(wto.mod == MOD.MODwild);
+	        if (swto) assert(swto.mod == (MOD.MODshared | MOD.MODwild));
 			break;
 
 		case MOD.MODshared | MOD.MODconst:
 			if (cto) assert(cto.mod == MOD.MODconst);
-			if (ito) assert(ito.mod == MOD.MODinvariant);
+			if (ito) assert(ito.mod == MOD.MODimmutable);
 			if (sto) assert(sto.mod == MOD.MODshared);
 			if (scto) assert(scto.mod == MOD.MODundefined);
+	        if (wto) assert(wto.mod == MOD.MODwild);
+	        if (swto) assert(swto.mod == (MOD.MODshared | MOD.MODwild));
 			break;
+            
+	    case MOD.MODwild:
+	        if (cto) assert(cto.mod == MOD.MODconst);
+	        if (ito) assert(ito.mod == MOD.MODimmutable);
+	        if (sto) assert(sto.mod == MOD.MODshared);
+	        if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst));
+	        if (wto) assert(wto.mod == MOD.MODundefined);
+	        if (swto) assert(swto.mod == (MOD.MODshared | MOD.MODwild));
+	        break;
+
+	    case MOD.MODshared | MOD.MODwild:
+	        if (cto) assert(cto.mod == MOD.MODconst);
+	        if (ito) assert(ito.mod == MOD.MODimmutable);
+	        if (sto) assert(sto.mod == MOD.MODshared);
+	        if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst));
+	        if (wto) assert(wto.mod == MOD.MODwild);
+	        if (swto) assert(swto.mod == MOD.MODundefined);
+	        break;
 		}
 
 		Type tn = nextOf();
@@ -1331,19 +1572,27 @@
 					break;
 
 				case MOD.MODconst:
-					assert(tn.mod & MOD.MODinvariant || tn.mod & MOD.MODconst);
+					assert(tn.mod & MOD.MODimmutable || tn.mod & MOD.MODconst);
 					break;
 
-				case MOD.MODinvariant:
-					assert(tn.mod == MOD.MODinvariant);
+				case MOD.MODimmutable:
+					assert(tn.mod == MOD.MODimmutable);
 					break;
 
 				case MOD.MODshared:
-					assert(tn.mod & MOD.MODinvariant || tn.mod & MOD.MODshared);
+					assert(tn.mod & MOD.MODimmutable || tn.mod & MOD.MODshared);
 					break;
 
 				case MOD.MODshared | MOD.MODconst:
-					assert(tn.mod & MOD.MODinvariant || tn.mod & (MOD.MODshared | MOD.MODconst));
+					assert(tn.mod & MOD.MODimmutable || tn.mod & (MOD.MODshared | MOD.MODconst));
+    		        break;
+
+	            case MOD.MODwild:
+	    	        assert(tn.mod);
+		            break;
+
+	            case MOD.MODshared | MOD.MODwild:
+		            assert(tn.mod == MOD.MODimmutable || tn.mod == (MOD.MODshared | MOD.MODconst) || tn.mod == (MOD.MODshared | MOD.MODwild));
 					break;
 			}
 			tn.check();
@@ -1360,23 +1609,31 @@
 		switch (mod)
 		{
 		case 0:
-			t = mutableOf();
+			t = unSharedOf().mutableOf();
 			break;
 
 		case MODconst:
-			t = constOf();
+			t = unSharedOf().constOf();
 			break;
 
-		case MODinvariant:
+		case MODimmutable:
 			t = invariantOf();
 			break;
 
 		case MODshared:
-			t = sharedOf();
+			t = mutableOf().sharedOf();
 			break;
 
 		case MODshared | MODconst:
 			t = sharedConstOf();
+	        break;
+
+	    case MODwild:
+	        t = unSharedOf().wildOf();
+	        break;
+
+	    case MODshared | MODwild:
+	        t = sharedWildOf();
 			break;
 
 		default:
@@ -1396,7 +1653,8 @@
 
 		/* Add anything to immutable, and it remains immutable
 		 */
-		if (!t.isInvariant())
+        //printf("addMod(%x) %s\n", mod, toChars());
+		if (!t.isImmutable())
 		{
 			switch (mod)
 			{
@@ -1410,13 +1668,15 @@
 						t = constOf();
 					break;
 
-				case MOD.MODinvariant:
+				case MOD.MODimmutable:
 					t = invariantOf();
 					break;
 
 				case MOD.MODshared:
 					if (isConst())
 						t = sharedConstOf();
+		            else if (isWild())
+		                t = sharedWildOf();
 					else
 						t = sharedOf();
 					break;
@@ -1424,6 +1684,19 @@
 				case MOD.MODshared | MOD.MODconst:
 					t = sharedConstOf();
 					break;
+                
+	            case MOD.MODwild:
+		            if (isConst())
+                    {}
+		            else if (isShared())
+		                t = sharedWildOf();
+		            else
+		                t = wildOf();
+		            break;
+
+	            case MOD.MODshared | MOD.MODwild:
+		            t = sharedWildOf();
+		            break;
 			}
 		}
 		return t;
@@ -1436,13 +1709,15 @@
 		MOD mod = MOD.MODundefined;
 
 		if (stc & STC.STCimmutable)
-			mod = MOD.MODinvariant;
+			mod = MOD.MODimmutable;
 		else
 		{	
 			if (stc & (STC.STCconst | STC.STCin))
 				mod = MOD.MODconst;
 			if (stc & STC.STCshared)
 				mod |= MOD.MODshared;
+	        if (stc & STC.STCwild)
+	            mod |= MOD.MODwild;
 		}
 
 		return addMod(mod);
@@ -1514,6 +1789,8 @@
 		t.ito = null;
 		t.sto = null;
 		t.scto = null;
+        t.wto = null;
+        t.swto = null;
 		t.vtinfo = null;
 		
 		//printf("-Type.makeConst() %p, %s\n", t, toChars());
@@ -1527,7 +1804,7 @@
 		}
 
 		Type t = clone();
-		t.mod = MOD.MODinvariant;
+		t.mod = MOD.MODimmutable;
 
 		t.deco = null;
 		t.arrayof = null;
@@ -1537,6 +1814,8 @@
 		t.ito = null;
 		t.sto = null;
 		t.scto = null;
+        t.wto = null;
+        t.swto = null;
 		t.vtinfo = null;
 
 		return t;
@@ -1558,6 +1837,8 @@
 		t.ito = null;
 		t.sto = null;
 		t.scto = null;
+        t.wto = null;
+        t.swto = null;
 		t.vtinfo = null;
 
 		return t;
@@ -1579,11 +1860,73 @@
 		t.ito = null;
 		t.sto = null;
 		t.scto = null;
+        t.wto = null;
+        t.swto = null;
 		t.vtinfo = null;
 
 		return t;
 	}
 	
+    Type makeWild()
+    {
+        if (wto)
+	        return wto;
+        
+        Type t = clone();
+        t.mod = MOD.MODwild;
+        t.deco = null;
+        t.arrayof = null;
+        t.pto = null;
+        t.rto = null;
+        t.cto = null;
+        t.ito = null;
+        t.sto = null;
+        t.scto = null;
+        t.wto = null;
+        t.swto = null;
+        t.vtinfo = null;
+        return t;
+    }
+
+    Type makeSharedWild()
+    {
+        if (swto)
+	        return swto;
+        
+        Type t = clone();
+        t.mod = MOD.MODshared | MOD.MODwild;
+        t.deco = null;
+        t.arrayof = null;
+        t.pto = null;
+        t.rto = null;
+        t.cto = null;
+        t.ito = null;
+        t.sto = null;
+        t.scto = null;
+        t.wto = null;
+        t.swto = null;
+        t.vtinfo = null;
+        return t;
+    }
+
+    Type makeMutable()
+    {
+        Type t = clone();
+        t.mod =  mod & MOD.MODshared;
+        t.deco = null;
+        t.arrayof = null;
+        t.pto = null;
+        t.rto = null;
+        t.cto = null;
+        t.ito = null;
+        t.sto = null;
+        t.scto = null;
+        t.wto = null;
+        t.swto = null;
+        t.vtinfo = null;
+        return t;
+    }
+    
     Dsymbol toDsymbol(Scope sc)
 	{
 		return null;
@@ -1627,7 +1970,7 @@
 	{
 		if (equals(to))
 			return MATCH.MATCHexact;
-		if (ty == to.ty && to.mod == MOD.MODconst)
+		if (ty == to.ty && MODimplicitConv(mod, to.mod))
 			return MATCH.MATCHconst;
 		return MATCH.MATCHnomatch;
 	}
@@ -1883,6 +2226,18 @@
 		assert(false);
 	}
 	
+    /***************************************
+     * Use when we prefer the default initializer to be a literal,
+     * rather than a global immutable variable.
+     */
+    Expression defaultInitLiteral(Loc loc = Loc(0))
+    {
+version(LOGDEFAULTINIT) {
+        printf("Type::defaultInitLiteral() '%s'\n", toChars());
+}
+        return defaultInit(loc);
+    }
+
     ///bool isZeroInit(Loc loc = Loc(0))		// if initializer is 0
 	bool isZeroInit(Loc loc)		// if initializer is 0
 	{
@@ -1995,20 +2350,24 @@
 			Type at = cast(Type)dedtypes[i];
 
 			// 5*5 == 25 cases
-			static pure int X(int U, int T) { return ((U << 3) | T); }
+			static pure int X(int U, int T) { return ((U << 4) | T); }
 			
 			switch (X(tparam.mod, mod))
 			{
 				case X(0, 0):
 				case X(0, MODconst):
-				case X(0, MODinvariant):
+				case X(0, MODimmutable):
 				case X(0, MODshared):
 				case X(0, MODconst | MODshared):
+	            case X(0, MODwild):
+	            case X(0, MODwild | MODshared):
 				// foo(U:U) T  							=> T
 				// foo(U:U) const(T)					=> const(T)
 				// foo(U:U) immutable(T)				=> immutable(T)
 				// foo(U:U) shared(T)					=> shared(T)
 				// foo(U:U) const(shared(T))			=> const(shared(T))
+		        // foo(U:U) wild(T)                        => wild(T)
+		        // foo(U:U) wild(shared(T))                => wild(shared(T))
 				if (!at)
 				{   dedtypes[i] = tt;
 					goto Lexact;
@@ -2016,13 +2375,20 @@
 				break;
 
 				case X(MODconst, MODconst):
-				case X(MODinvariant, MODinvariant):
+				case X(MODimmutable, MODimmutable):
 				case X(MODshared, MODshared):
 				case X(MODconst | MODshared, MODconst | MODshared):
+	            case X(MODwild, MODwild):
+	            case X(MODwild | MODshared, MODwild | MODshared):
+	            case X(MODconst, MODwild):
+	            case X(MODconst, MODwild | MODshared):
 				// foo(U:const(U))			const(T)		=> T
 				// foo(U:immutable(U))		immutable(T)	=> T
 				// foo(U:shared(U))			shared(T)		=> T
 				// foo(U:const(shared(U))	const(shared(T))=> T
+		        // foo(U:wild(U))         wild(T)          => T
+		        // foo(U:wild(shared(U))  wild(shared(T)) => T
+        		// foo(U:const(U)) wild(shared(T))         => shared(T)
 				tt = mutableOf().unSharedOf();
 				if (!at)
 				{
@@ -2035,10 +2401,12 @@
 				case X(MODconst, MODimmutable):
 				case X(MODconst, MODconst | MODshared):
 				case X(MODconst | MODshared, MODimmutable):
+        	    case X(MODshared, MODwild | MODshared):
 				// foo(U:const(U))			T					=> T
 				// foo(U:const(U))			immutable(T)		=> T
 				// foo(U:const(U))			const(shared(T))	=> shared(T)
 				// foo(U:const(shared(U))	immutable(T)		=> T
+        		// foo(U:shared(U)) wild(shared(T))        => wild(T)
 				tt = mutableOf();
 				if (!at)
 				{   dedtypes[i] = tt;
@@ -2067,6 +2435,23 @@
 				case X(MODshared,			MODimmutable):
 				case X(MODconst | MODshared, 0):
 				case X(MODconst | MODshared, MODconst):
+	            case X(MODimmutable,	 MODwild):
+	            case X(MODshared,		 MODwild):
+	            case X(MODconst | MODshared, MODwild):
+	            case X(MODwild,		 0):
+	            case X(MODwild,		 MODconst):
+	            case X(MODwild,		 MODimmutable):
+	            case X(MODwild,		 MODshared):
+	            case X(MODwild,		 MODconst | MODshared):
+	            case X(MODwild | MODshared,	 0):
+	            case X(MODwild | MODshared,	 MODconst):
+	            case X(MODwild | MODshared,  MODimmutable):
+	            case X(MODwild | MODshared,  MODshared):
+	            case X(MODwild | MODshared,  MODconst | MODshared):
+	            case X(MODwild | MODshared,  MODwild):
+	            case X(MODimmutable,	 MODwild | MODshared):
+	            case X(MODconst | MODshared, MODwild | MODshared):
+	            case X(MODwild,		 MODwild | MODshared):
 				// foo(U:immutable(U)) T				   => nomatch
 				// foo(U:immutable(U)) const(T)			=> nomatch
 				// foo(U:immutable(U)) shared(T)		   => nomatch
@@ -2077,6 +2462,23 @@
 				// foo(U:shared(U)) immutable(T)		   => nomatch
 				// foo(U:const(shared(U)) T				=> nomatch
 				// foo(U:const(shared(U)) const(T)		 => nomatch
+		        // foo(U:immutable(U)) wild(T)             => nomatch
+		        // foo(U:shared(U)) wild(T)                => nomatch
+		        // foo(U:const(shared(U)) wild(T)          => nomatch
+		        // foo(U:wild(U)) T                        => nomatch
+		        // foo(U:wild(U)) const(T)                 => nomatch
+		        // foo(U:wild(U)) immutable(T)             => nomatch
+		        // foo(U:wild(U)) shared(T)                => nomatch
+		        // foo(U:wild(U)) const(shared(T))         => nomatch
+		        // foo(U:wild(shared(U)) T 		   => nomatch
+		        // foo(U:wild(shared(U)) const(T)	   => nomatch
+		        // foo(U:wild(shared(U)) immutable(T)	   => nomatch
+		        // foo(U:wild(shared(U)) shared(T)         => nomatch
+		        // foo(U:wild(shared(U)) const(shared(T))  => nomatch
+		        // foo(U:wild(shared(U)) wild(T)	   => nomatch
+		        // foo(U:immutable(U)) wild(shared(T))     => nomatch
+		        // foo(U:const(shared(U))) wild(shared(T)) => nomatch
+		        // foo(U:wild(U)) wild(shared(T))          => nomatch
 				//if (!at)
 					goto Lnomatch;
 				break;
@@ -2204,8 +2606,11 @@
 				t.vtinfo = new TypeInfoSharedDeclaration(t);
 			else if (t.isConst())
 				t.vtinfo = new TypeInfoConstDeclaration(t);
-			else if (t.isInvariant())
+			else if (t.isImmutable())
 				t.vtinfo = new TypeInfoInvariantDeclaration(t);
+    	    else if (t.isWild())
+	            t.vtinfo = new TypeInfoWildDeclaration(t);
+
 			else
 				t.vtinfo = t.getTypeInfoDeclaration();
 } else {
@@ -2261,6 +2666,24 @@
 		return null;
 	}
 	
+    /***************************************
+     * Return !=0 if the type or any of its subtypes is wild.
+     */
+
+    int hasWild()
+    {
+        return mod & MOD.MODwild;
+    }
+
+    /***************************************
+     * Return MOD bits matching argument type (targ) to wild parameter type (this).
+     */
+
+    uint wildMatch(Type targ)
+    {
+        return 0;
+    }
+    
     Expression toExpression()
 	{
 		assert(false);
@@ -2402,14 +2825,16 @@
 		case MOD.MODundefined:
 			break;
 		case MOD.MODconst:
+	    case MOD.MODwild:
 			t |= mTY.mTYconst;
 			break;
-		case MOD.MODinvariant:
+		case MOD.MODimmutable:
 			t |= mTY.mTYimmutable;
 			break;
 		case MOD.MODshared:
 			t |= mTY.mTYshared;
 			break;
+        case MOD.MODshared | MOD.MODwild:
 		case MOD.MODshared | MOD.MODconst:
 			t |= mTY.mTYshared | mTY.mTYconst;
 			break;