changeset 137:09c858522d55

merge
author Trass3r
date Mon, 13 Sep 2010 23:29:00 +0200
parents 9d194c848e3a (current diff) af1bebfd96a4 (diff)
children 90821c10b6a7
files dmd/Optimize.d dmd/Util.d
diffstat 78 files changed, 1847 insertions(+), 555 deletions(-) [+]
line wrap: on
line diff
--- a/commands.linux.txt	Mon Sep 13 23:27:38 2010 +0200
+++ b/commands.linux.txt	Mon Sep 13 23:29:00 2010 +0200
@@ -78,6 +78,7 @@
 dmd/ArrayLengthExp.d
 dmd/TypeInfoConstDeclaration.d
 dmd/TypeInfoInvariantDeclaration.d
+dmd/TypeInfoWildDeclaration.d
 dmd/TypeInfoSharedDeclaration.d
 dmd/TypeInfoStructDeclaration.d
 dmd/TypeInfoInterfaceDeclaration.d
@@ -272,6 +273,7 @@
 dmd/Parser.d
 dmd/PostBlitDeclaration.d
 dmd/PowExp.d
+dmd/PowAssignExp.d
 dmd/PragmaDeclaration.d
 dmd/PragmaStatement.d
 dmd/ProtDeclaration.d
--- a/commands.txt	Mon Sep 13 23:27:38 2010 +0200
+++ b/commands.txt	Mon Sep 13 23:29:00 2010 +0200
@@ -73,6 +73,7 @@
 dmd\ArrayLengthExp.d
 dmd\TypeInfoConstDeclaration.d
 dmd\TypeInfoInvariantDeclaration.d
+dmd\TypeInfoWildDeclaration.d
 dmd\TypeInfoSharedDeclaration.d
 dmd\TypeInfoStructDeclaration.d
 dmd\TypeInfoInterfaceDeclaration.d
@@ -267,6 +268,7 @@
 dmd\Parser.d
 dmd\PostBlitDeclaration.d
 dmd\PowExp.d
+dmd\PowAssignExp.d
 dmd\PragmaDeclaration.d
 dmd\PragmaStatement.d
 dmd\ProtDeclaration.d
--- a/ddmd.visualdproj	Mon Sep 13 23:27:38 2010 +0200
+++ b/ddmd.visualdproj	Mon Sep 13 23:29:00 2010 +0200
@@ -608,6 +608,8 @@
    <File path="dmd\Parameter.d" />
    <File path="dmd\TRUST.d" />
    <File path="dmd\PowExp.d" />
+   <File path="dmd\TypeInfoWildDeclaration.d" />
+   <File path="dmd\PowAssignExp.d" />
   </Folder>
   <File path="bridge.obj" />
   <File path="ddmd.def" />
--- a/dmd/AddrExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/AddrExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -126,6 +126,11 @@
 		return this;
 	}
 
+    override void checkEscape()
+    {
+        e1.checkEscapeRef();
+    }
+    
 	override elem* toElem(IRState* irs)
 	{
 		elem* e;
--- a/dmd/AliasDeclaration.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/AliasDeclaration.d	Mon Sep 13 23:29:00 2010 +0200
@@ -100,9 +100,10 @@
 		}
 		this.inSemantic = 1;
 
+version(DMDV1) {   // don't really know why this is here
 		if (storage_class & STC.STCconst)
 			error("cannot be const");
-
+}
 		storage_class |= sc.stc & STC.STCdeprecated;
 
 		// Given:
@@ -128,11 +129,12 @@
 			goto L2;			// it's a symbolic alias
 
 ///version (DMDV2) {
+        type = type.addStorageClass(storage_class);
 		if (storage_class & (STC.STCref | STCnothrow | STCpure))
 		{	// For 'ref' to be attached to function types, and picked
 			// up by Type.resolve(), it has to go into sc.
 			sc = sc.push();
-			sc.stc |= storage_class & (STCref | STCnothrow | STCpure);
+		    sc.stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared);
 			type.resolve(loc, sc, &e, &t, &s);
 			sc = sc.pop();
 		}
--- a/dmd/ArrayLiteralExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/ArrayLiteralExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -213,10 +213,7 @@
 
 				ex = e.interpret(istate);
 				if (ex is EXP_CANT_INTERPRET)
-				{   
-					delete expsx;
-					return EXP_CANT_INTERPRET;
-				}
+				    goto Lerror;
 
 				/* If any changes, do Copy On Write
 				 */
@@ -239,10 +236,7 @@
 		{
 			expandTuples(expsx);
 			if (expsx.dim != elements.dim)
-			{   
-				delete expsx;
-				return EXP_CANT_INTERPRET;
-			}
+			    goto Lerror;
 			
 			ArrayLiteralExp ae = new ArrayLiteralExp(loc, expsx);
 			ae.type = type;
@@ -250,6 +244,12 @@
 			return ae;
 		}
 		return this;
+
+    Lerror:
+        if (expsx)
+	        delete expsx;
+        error("cannot interpret array literal");
+        return EXP_CANT_INTERPRET;
 	}
 
 	override MATCH implicitConvTo(Type t)
--- a/dmd/BinExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/BinExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -552,6 +552,7 @@
 			case TOK.TOKandass:
 			case TOK.TOKorass:
 			case TOK.TOKxorass:
+            case TOK.TOKpowass:
 			case TOK.TOKin:
 			case TOK.TOKremove:
 				return true;
@@ -803,7 +804,7 @@
 			}
 			else if (v && v.value && (v.value.op==TOKindex || v.value.op == TOKdotvar))
 			{
-				// It is no longer be a TOKvar, eg when a[4] is passed by ref.
+				// It is no longer a TOKvar, eg when a[4] is passed by ref.
 				e1 = v.value;	    
 			}
 		}
@@ -826,13 +827,13 @@
 			VarExp ve = cast(VarExp)e1;
 			VarDeclaration v = ve.var.isVarDeclaration();
 			assert(v);
-			if (v && v.isDataseg())
+			if (v && !v.isCTFE())
 			{   
 				// Can't modify global or static data
 				error("%s cannot be modified at compile time", v.toChars());
 				return EXP_CANT_INTERPRET;
 			}
-			if (v && !v.isDataseg())
+			if (v && v.isCTFE())
 			{
 				Expression ev = v.value;
 				if (fp && !ev)
@@ -848,7 +849,7 @@
 					 */
 					if (v.type.toBasetype().ty == Tstruct && e2.op == TOKint64)
 					{
-						e2 = v.type.defaultInit(Loc(0));
+						e2 = v.type.defaultInitLiteral(Loc(0));
 					}
 					e2 = Cast(v.type, v.type, e2);
 				}
@@ -872,7 +873,7 @@
 		{	
 			VarDeclaration v = (cast(VarExp)aggregate).var.isVarDeclaration();
 
-			if (v.isDataseg())
+			if (!v.isCTFE())
 			{   
 				// Can't modify global or static data
 				error("%s cannot be modified at compile time", v.toChars());
@@ -949,7 +950,7 @@
 			SymOffExp soe = cast(SymOffExp)(cast(PtrExp)e1).e1;
 			VarDeclaration v = soe.var.isVarDeclaration();
 
-			if (v.isDataseg())
+			if (!v.isCTFE())
 			{
 				error("%s cannot be modified at compile time", v.toChars());
 				return EXP_CANT_INTERPRET;
@@ -997,7 +998,7 @@
 			IndexExp ie = cast(IndexExp)e1;
 			VarExp ve = cast(VarExp)ie.e1;
 			VarDeclaration v = ve.var.isVarDeclaration();
-			if (!v || v.isDataseg())
+			if (!v || !v.isCTFE())
 			{
 				error("%s cannot be modified at compile time", v ? v.toChars(): "void");
 				return EXP_CANT_INTERPRET;
@@ -1165,7 +1166,7 @@
 			IndexExp ie = cast(IndexExp)aggregate;
 			VarExp ve = cast(VarExp)(ie.e1);
 			VarDeclaration v = ve.var.isVarDeclaration();
-			if (!v || v.isDataseg())
+			if (!v || !v.isCTFE())
 			{
 				error("%s cannot be modified at compile time", v ? v.toChars(): "void");
 				return EXP_CANT_INTERPRET;
@@ -1188,8 +1189,7 @@
 				if (telem.ty != Tstruct) { return EXP_CANT_INTERPRET; }
 
 				// Create a default struct literal...
-				StructDeclaration sym = (cast(TypeStruct)telem).sym;
-				StructLiteralExp structinit = createDefaultInitStructLiteral(v.loc, sym);
+				Expression structinit = telem.defaultInitLiteral(v.loc);
 
 				// ... and use to create a blank array literal
 				size_t dim = cast(size_t)(cast(TypeSArray)t2).dim.toInteger();
@@ -1257,7 +1257,7 @@
 			SliceExp sexp = cast(SliceExp)e1;
 			VarExp ve = cast(VarExp)(sexp.e1);
 			VarDeclaration v = ve.var.isVarDeclaration();
-			if (!v || v.isDataseg())
+			if (!v || !v.isCTFE())
 			{
 				error("%s cannot be modified at compile time", v.toChars());
 				return EXP_CANT_INTERPRET;
--- a/dmd/CallExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/CallExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -279,7 +279,6 @@
 		istemp = 0;
 	Lagain:
 		//printf("Lagain: %s\n", toChars());
-		//printf("test1 %s\n", toChars());
 		f = null;
 		if (e1.op == TOK.TOKthis || e1.op == TOK.TOKsuper)
 		{
@@ -509,7 +508,7 @@
 				printf("e1 = %s\n", e1.toChars());
 				printf("e1.type = %s\n", e1.type.toChars());
 }
-				// Const member function can take const/immutable/mutable this
+				// Const member function can take const/immutable/mutable/inout this
 				if (!(f.type.isConst()))
 				{
 					// Check for const/immutable compatibility
@@ -518,14 +517,14 @@
 						tthis = tthis.nextOf().toBasetype();
 
 	static if (false) {	// this checking should have been already done
-					if (f.type.isInvariant())
+					if (f.type.isImmutable())
 					{
-						if (tthis.mod != MOD.MODinvariant)
+						if (tthis.mod != MOD.MODimmutable)
 							error("%s can only be called with an immutable object", e1.toChars());
 					}
 					else if (f.type.isShared())
 					{
-						if (tthis.mod != MOD.MODinvariant && tthis.mod != MOD.MODshared && tthis.mod != (MOD.MODshared | MOD.MODconst))
+						if (tthis.mod != MOD.MODimmutable && tthis.mod != MOD.MODshared && tthis.mod != (MOD.MODshared | MOD.MODconst))
 							error("shared %s can only be called with a shared or immutable object", e1.toChars());
 					}
 					else
@@ -795,12 +794,11 @@
 
 	Lcheckargs:
 		assert(tf.ty == TY.Tfunction);
-		type = tf.next;
 
 		if (!arguments)
 			arguments = new Expressions();
 
-		functionParameters(loc, sc, tf, arguments);
+		type = functionParameters(loc, sc, tf, arguments);
 
 		if (!type)
 		{
--- a/dmd/Cast.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Cast.d	Mon Sep 13 23:29:00 2010 +0200
@@ -61,6 +61,9 @@
 		}
     }
 
+    if (e1.op == TOK.TOKarrayliteral && typeb == tb)
+        return e1;
+
     if (e1.isConst() != 1)
 		return EXP_CANT_INTERPRET;
 
--- a/dmd/CastExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/CastExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -183,6 +183,10 @@
 					// Cast away pointer to shared
 					goto Lunsafe;
 
+        	    if (t1bn.isWild() && !tobn.isConst() && !tobn.isWild())
+            		// Cast wild to anything but const | wild
+		            goto Lunsafe;
+
 				if (tobn.isTypeBasic() && tobn.size() < t1bn.size()) {
 					// Allow things like casting a long* to an int*
 					;
@@ -425,27 +429,7 @@
 			to.toCBuffer(buf, null, hgs);
 		else
 		{
-			switch (mod)
-			{   
-				case MODundefined:
-					break;
-				case MODconst:
-					buf.writestring(Token.tochars[TOKconst]);
-					break;
-				case MODinvariant:
-					buf.writestring(Token.tochars[TOKimmutable]);
-					break;
-				case MODshared:
-					buf.writestring(Token.tochars[TOKshared]);
-					break;
-				case MODshared | MODconst:
-					buf.writestring(Token.tochars[TOKshared]);
-					buf.writeByte(' ');
-					buf.writestring(Token.tochars[TOKconst]);
-					break;
-				default:
-					assert(0);
-			}
+			MODtoBuffer(buf, mod);
 		}
 	}
 		buf.writeByte(')');
--- a/dmd/CatExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/CatExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -67,6 +67,7 @@
 				e2.implicitConvTo(tb1next) >= MATCHconvert)
 			{
 				e2 = e2.implicitCastTo(sc, tb1next);
+                type = tb1next.arrayOf();
 				if (tb2.ty == Tarray)
 				{	
 					// Make e2 into [e2]
@@ -79,6 +80,7 @@
 				e1.implicitConvTo(tb2next) >= MATCHconvert)
 			{
 				e1 = e1.implicitCastTo(sc, tb2next);
+                type = tb2next.arrayOf();
 				if (tb1.ty == Tarray)
 				{	
 					// Make e1 into [e1]
--- a/dmd/ClassDeclaration.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/ClassDeclaration.d	Mon Sep 13 23:29:00 2010 +0200
@@ -258,6 +258,13 @@
 						Type.typeinfoshared.error("%s", msg);
 					Type.typeinfoshared = this;
 				}
+
+	            if (id == Id.TypeInfo_Wild)
+	            {
+                    if (Type.typeinfowild)
+		                Type.typeinfowild.error("%s", msg);
+		            Type.typeinfowild = this;
+	            }
 	}
 			}
 
@@ -699,6 +706,22 @@
 		structsize = sc.offset;
 		Scope scsave = sc.clone();
 		sizeok = 0;
+
+        /* Set scope so if there are forward references, we still might be able to
+         * resolve individual members like enums.
+         */
+        foreach (s; members)
+        {
+	        /* There are problems doing this in the general case because
+	         * Scope keeps track of things like 'offset'
+	         */
+	        if (s.isEnumDeclaration() || (s.isAggregateDeclaration() && s.ident))
+	        {
+	            //printf("setScope %s %s\n", s->kind(), s->toChars());
+	            s.setScope(sc);
+	        }
+        }
+            
 		foreach (Dsymbol s; members) {
 			s.semantic(sc);
 		}
--- a/dmd/CommaExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/CommaExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -38,6 +38,11 @@
 		e2.checkEscape();
 	}
 	
+    override void checkEscapeRef()
+    {
+        e2.checkEscapeRef();
+    }
+    
     override IntRange getIntRange()
 	{
 		assert(false);
--- a/dmd/CondExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/CondExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -184,6 +184,12 @@
 		e2.checkEscape();
 	}
 
+    override void checkEscapeRef()
+    {
+        e1.checkEscapeRef();
+        e2.checkEscapeRef();
+    }
+    
     override int isLvalue()
 	{
 		return e1.isLvalue() && e2.isLvalue();
--- a/dmd/Declaration.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Declaration.d	Mon Sep 13 23:29:00 2010 +0200
@@ -158,7 +158,7 @@
 				string p = null;
 				if (isConst())
 					p = "const";
-				else if (isInvariant())
+				else if (isImmutable())
 					p = "immutable";
 				else if (storage_class & STC.STCmanifest)
 					p = "enum";
@@ -311,7 +311,7 @@
     
 	bool isConst()        { return (storage_class & STC.STCconst) != 0; }
     
-	int isInvariant()    { return storage_class & STC.STCinvariant; }
+	int isImmutable()    { return storage_class & STC.STCimmutable; }
     
 	int isAuto()         { return storage_class & STC.STCauto; }
     
--- a/dmd/DeclarationExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/DeclarationExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -148,7 +148,7 @@
 					e = null;
 			}
 ///version (DMDV2) {
-			else if (s == v && (v.isConst() || v.isInvariant()) && v.init)
+			else if (s == v && (v.isConst() || v.isImmutable()) && v.init)
 ///} else {
 ///			else if (s == v && v.isConst() && v.init)
 ///}
--- a/dmd/DotVarExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/DotVarExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -187,7 +187,7 @@
 			if (!t1.isMutable() || (t1.ty == TY.Tpointer && !t1.nextOf().isMutable()) ||
 				!var.type.isMutable() || !var.type.isAssignable() || var.storage_class & STC.STCmanifest)
 			{
-				error("cannot modify const/immutable expression %s", toChars());
+				error("cannot modify const/immutable/inout expression %s", toChars());
 			}
 }
 		}
@@ -242,10 +242,15 @@
 				{	
 					e = se.getField(type, v.offset);
 					if (!e)
+		            {
+		                error("couldn't find field %s in %s", v.toChars(), type.toChars());
 						e = EXP_CANT_INTERPRET;
+                    }
 					return e;
 				}
-			} else {
+			}
+            else
+            {
 				error("%s.%s is not yet implemented at compile time", ex.toChars(), var.toChars());
 			}
 		}
--- a/dmd/Expression.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Expression.d	Mon Sep 13 23:29:00 2010 +0200
@@ -657,6 +657,10 @@
 	{
 	}
     
+    void checkEscapeRef()
+    {
+    }
+    
     void checkScalar()
 	{
 		if (!type.isscalar())
--- a/dmd/ForeachStatement.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/ForeachStatement.d	Mon Sep 13 23:29:00 2010 +0200
@@ -115,6 +115,7 @@
 		Statement s = this;
 		size_t dim = arguments.dim;
 		TypeAArray taa = null;
+        Dsymbol sapply = null;
 
 		Type tn = null;
 		Type tnv = null;
@@ -255,6 +256,9 @@
 		sc.noctor++;
 
 	Lagain:
+        Identifier idapply = (op == TOK.TOKforeach_reverse)
+		        ? Id.applyReverse : Id.apply;
+        sapply = null;
 		switch (tab.ty)
 		{
 			case TY.Tarray:
@@ -445,6 +449,15 @@
 			case TY.Tclass:
 			case TY.Tstruct:
 version (DMDV2) {
+	            /* Prefer using opApply, if it exists
+	             */
+	            if (dim != 1)	// only one argument allowed with ranges
+		        goto Lapply;
+
+	            sapply = search_function(cast(AggregateDeclaration)tab.toDsymbol(sc), idapply);
+	            if (sapply)
+		        goto Lapply;
+
 			{   /* Look for range iteration, i.e. the properties
 				 * .empty, .next, .retreat, .head and .rear
 				 *    foreach (e; aggr) { ... }
@@ -454,9 +467,6 @@
 				 *        ...
 				 *    }
 				 */
-				if (dim != 1)	// only one argument allowed with ranges
-				goto Lapply;
-
 				AggregateDeclaration ad = (tab.ty == TY.Tclass)
 					? cast(AggregateDeclaration)(cast(TypeClass)tab).sym
 					: cast(AggregateDeclaration)(cast(TypeStruct)tab).sym;
@@ -531,16 +541,9 @@
 			case TY.Tdelegate:
 			Lapply:
 			{   
-				FuncDeclaration fdapply;
-				Parameters args;
 				Expression ec;
 				Expression e;
-				FuncLiteralDeclaration fld;
 				Parameter a;
-				Type t;
-				Expression flde;
-				Identifier id;
-				Type tret;
 
 				if (!checkForArgTypes())
 				{	
@@ -548,7 +551,7 @@
 					return this;
 				}
 
-				tret = func.type.nextOf();
+				Type tret = func.type.nextOf();
 
 				// Need a variable to hold value from any return statements in body.
 				if (!sc.func.vresult && tret && tret != Type.tvoid)
@@ -566,10 +569,11 @@
 				/* Turn body into the function literal:
 				 *	int delegate(ref T arg) { body }
 				 */
-				args = new Parameters();
+				auto args = new Parameters();
 				for (size_t i = 0; i < dim; i++)
 				{
 					auto arg = arguments[i];
+                    Identifier id;
 
 					arg.type = arg.type.semantic(loc, sc);
 					if (arg.storageClass & STC.STCref)
@@ -577,28 +581,25 @@
 					else
 					{   // Make a copy of the ref argument so it isn't
 						// a reference.
-						VarDeclaration v;
-						Initializer ie;
-
 						id = Lexer.uniqueId("__applyArg", i);
 
-						ie = new ExpInitializer(Loc(0), new IdentifierExp(Loc(0), id));
-						v = new VarDeclaration(Loc(0), arg.type, arg.ident, ie);
+						Initializer ie = new ExpInitializer(Loc(0), new IdentifierExp(Loc(0), id));
+						auto v = new VarDeclaration(Loc(0), arg.type, arg.ident, ie);
 						s = new DeclarationStatement(Loc(0), v);
 						body_ = new CompoundStatement(loc, s, body_);
 					}
 					a = new Parameter(STC.STCref, arg.type, id, null);
 					args.push(a);
 				}
-				t = new TypeFunction(args, Type.tint32, 0, LINK.LINKd);
-				fld = new FuncLiteralDeclaration(loc, Loc(0), t, TOK.TOKdelegate, this);
+				Type t = new TypeFunction(args, Type.tint32, 0, LINK.LINKd);
+				FuncLiteralDeclaration fld = new FuncLiteralDeclaration(loc, Loc(0), t, TOK.TOKdelegate, this);
 				fld.fbody = body_;
-				flde = new FuncExp(loc, fld);
+				Expression flde = new FuncExp(loc, fld);
 				flde = flde.semantic(sc);
 				fld.tookAddressOf = 0;
 
 				// Resolve any forward referenced goto's
-				for (int i = 0; i < gotos.dim; i++)
+				for (size_t i = 0; i < gotos.dim; i++)
 				{	
 					auto cs = cast(CompoundStatement)gotos.data[i];
 					auto gs = cast(GotoStatement)cs.statements[0];
@@ -631,6 +632,7 @@
 					/* Call:
 					 *	_aaApply(aggr, keysize, flde)
 					 */
+		            FuncDeclaration fdapply;
 					if (dim == 2)
 						fdapply = FuncDeclaration.genCfunc(Type.tindex, "_aaApply2");
 					else
@@ -674,7 +676,7 @@
 					string r = (op == TOK.TOKforeach_reverse) ? "R" : "";
 					int j = sprintf(fdname.ptr, "_aApply%.*s%.*s%zd".ptr, r, 2, fntab[flag].ptr, dim);
 					assert(j < fdname.sizeof);
-					fdapply = FuncDeclaration.genCfunc(Type.tindex, fdname[0..j].idup);
+					FuncDeclaration fdapply = FuncDeclaration.genCfunc(Type.tindex, fdname[0..j].idup);
 
 					ec = new VarExp(Loc(0), fdapply);
 					auto exps = new Expressions();
@@ -700,10 +702,9 @@
 				else
 				{
 					assert(tab.ty == TY.Tstruct || tab.ty == TY.Tclass);
-					Identifier idapply = (op == TOK.TOKforeach_reverse)
-							? Id.applyReverse : Id.apply;
-					Dsymbol sapply = search_function(cast(AggregateDeclaration)tab.toDsymbol(sc), idapply);
-					Expressions exps = new Expressions();
+					auto exps = new Expressions();
+		            if (!sapply)
+		                sapply = search_function(cast(AggregateDeclaration)tab.toDsymbol(sc), idapply);
 static if (false) {
 					TemplateDeclaration td;
 					if (sapply && (td = sapply.isTemplateDeclaration()) !is null)
--- a/dmd/FuncDeclaration.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/FuncDeclaration.d	Mon Sep 13 23:29:00 2010 +0200
@@ -309,37 +309,59 @@
 			originalType = type;
 		if (!type.deco)
 		{
+    	    sc = sc.push();
+	        sc.stc |= storage_class & STC.STCref;	// forward refness to function type
+	        type = type.semantic(loc, sc);
+	        sc = sc.pop();
+            
 			/* Apply const, immutable and shared storage class
 			 * to the function type
 			 */
-			type = type.semantic(loc, sc);
 			StorageClass stc = storage_class;
-			if (type.isInvariant())
+			if (type.isImmutable())
 				stc |= STC.STCimmutable;
 			if (type.isConst())
 				stc |= STC.STCconst;
 			if (type.isShared() || storage_class & STC.STCsynchronized)
 				stc |= STC.STCshared;
+	        if (type.isWild())
+	            stc |= STC.STCwild;
 			switch (stc & STC.STC_TYPECTOR)
 			{
 				case STC.STCimmutable:
 				case STC.STCimmutable | STC.STCconst:
 				case STC.STCimmutable | STC.STCconst | STC.STCshared:
 				case STC.STCimmutable | STC.STCshared:
+                case STC.STCimmutable | STC.STCwild:
+	            case STC.STCimmutable | STC.STCconst | STC.STCwild:
+	            case STC.STCimmutable | STC.STCconst | STC.STCshared | STC.STCwild:
+	            case STC.STCimmutable | STC.STCshared | STC.STCwild:
 				// Don't use toInvariant(), as that will do a merge()
 				type = type.makeInvariant();
 				goto Lmerge;
 	
 				case STC.STCconst:
+	            case STC.STCconst | STC.STCwild:
 				type = type.makeConst();
 				goto Lmerge;
 	
 				case STC.STCshared | STC.STCconst:
+	            case STC.STCshared | STC.STCconst | STC.STCwild:
 				type = type.makeSharedConst();
 				goto Lmerge;
 	
 				case STC.STCshared:
 				type = type.makeShared();
+		        goto Lmerge;
+
+	            case STC.STCwild:
+		        type = type.makeWild();
+		        goto Lmerge;
+
+	            case STC.STCshared | STC.STCwild:
+		        type = type.makeSharedWild();
+		        goto Lmerge;
+
 				Lmerge:
 					if (!(type.ty == Tfunction && !type.nextOf()))
 						/* Can't do merge if return type is not known yet
@@ -354,7 +376,7 @@
 				assert(0);
 			}
 		}
-		//type.print();
+        storage_class &= ~STC.STCref;
 		if (type.ty != TY.Tfunction)
 		{
 		error("%s must be a function", toChars());
@@ -378,7 +400,7 @@
 		if (isAbstract() && !isVirtual())
 		error("non-virtual functions cannot be abstract");
 
-		if ((f.isConst() || f.isInvariant()) && !isThis())
+		if ((f.isConst() || f.isImmutable()) && !isThis())
 		error("without 'this' cannot be const/immutable");
 
 		if (isAbstract() && isFinal())
@@ -965,7 +987,7 @@
 				thandle = thandle.nextOf().constOf().pointerTo();
 				}
 			}
-			else if (storage_class & STC.STCimmutable || type.isInvariant())
+			else if (storage_class & STC.STCimmutable || type.isImmutable())
 			{
 				if (thandle.ty == TY.Tclass)
 				thandle = thandle.invariantOf();
@@ -1054,7 +1076,7 @@
 			}
 }
 		}
-
+static if(false) {
 		// Propagate storage class from tuple parameters to their element-parameters.
 		if (f.parameters)
 		{
@@ -1072,7 +1094,7 @@
 			}
 			}
 		}
-
+}
 		/* Declare all the function parameters as variables
 		 * and install them in parameters[]
 		 */
@@ -2399,10 +2421,10 @@
 		assert(tb.ty == Tfunction);
 		TypeFunction tf = cast(TypeFunction)tb;
 		Type tret = tf.next.toBasetype();
-		if (tf.varargs)
+		if (tf.varargs && arguments && parameters && arguments.dim != parameters.dim)
 		{	
 			cantInterpret = 1;
-			error("Variadic functions are not yet implemented in CTFE");
+			error("C-style variadic functions are not yet implemented in CTFE");
 			return null;
 		}
 		
@@ -2547,7 +2569,7 @@
 			}
 		}
 		// Don't restore the value of 'this' upon function return
-		if (needThis() && thisarg.op==TOKvar) {
+		if (needThis() && thisarg.op == TOKvar && istate) {
 			VarDeclaration thisvar = (cast(VarExp)thisarg).var.isVarDeclaration();
  			foreach (size_t i, Dsymbol s; istate.vars)
 			{   
@@ -2562,7 +2584,7 @@
 
 		/* Save the values of the local variables used
 		 */
-		scope Expressions valueSaves = new Expressions();
+		scope valueSaves = new Expressions();
 		if (istate && !isNested())
 		{
 			//printf("saving local variables...\n");
@@ -3835,6 +3857,35 @@
 		}
 	}
 
+    /*********************************************
+     * Return the function's parameter list, and whether
+     * it is variadic or not.
+     */
+
+    Parameters getParameters(int *pvarargs)
+    {
+        Parameters fparameters;
+        int fvarargs;
+
+        if (type)
+        {
+	        assert(type.ty == Tfunction);
+	        auto fdtype = cast(TypeFunction)type;
+	        fparameters = fdtype.parameters;
+	        fvarargs = fdtype.varargs;
+        }
+        else // Constructors don't have type's
+        {
+            CtorDeclaration fctor = isCtorDeclaration();
+	        assert(fctor);
+	        fparameters = fctor.arguments;
+	        fvarargs = fctor.varargs;
+        }
+        if (pvarargs)
+	    *pvarargs = fvarargs;
+        return fparameters;
+    }
+
     override FuncDeclaration isFuncDeclaration() { return this; }
 }
 
--- a/dmd/Global.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Global.d	Mon Sep 13 23:29:00 2010 +0200
@@ -39,7 +39,7 @@
     string[] path;	// Array of char*'s which form the import lookup path
     string[] filePath;	// Array of char*'s which form the file import lookup path
     int structalign = 8;
-    string version_ = "v2.037";
+    string version_ = "v2.038";
 
     Param params;
     uint errors;	// number of errors reported so far
--- a/dmd/Id.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Id.d	Mon Sep 13 23:29:00 2010 +0200
@@ -96,6 +96,8 @@
 		ID( "TypeInfo_Const" ),
 		ID( "TypeInfo_Invariant" ),
 		ID( "TypeInfo_Shared" ),
+        ID( "TypeInfo_Wild", "TypeInfo_Inout" ),
+            
 		ID( "elements" ),
 		ID( "_arguments_typeinfo" ),
 		ID( "_arguments" ),
@@ -217,7 +219,7 @@
 		ID( "opImplicitCast" ),
         ID( "pow", "opPow" ),
         ID( "pow_r", "opPow_r" ),
-        //ID( "powass", "opPowAssign" ),
+        ID( "powass", "opPowAssign" ),
     
 		ID( "classNew", "new" ),
 		ID( "classDelete", "delete" ),
@@ -294,6 +296,9 @@
 		ID( "isVirtualFunction" ),
 		ID( "isAbstractFunction" ),
 		ID( "isFinalFunction" ),
+        ID( "isRef" ),
+        ID( "isOut" ),
+        ID( "isLazy" ),
 		ID( "hasMember" ),
 		ID( "getMember" ),
 		ID( "getVirtualFunctions" ),
--- a/dmd/IdentityExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/IdentityExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -53,12 +53,10 @@
 
 	override Expression optimize(int result)
 	{
-		Expression e;
-
 		//printf("IdentityExp.optimize(result = %d) %s\n", result, toChars());
 		e1 = e1.optimize(WANT.WANTvalue | (result & WANT.WANTinterpret));
 		e2 = e2.optimize(WANT.WANTvalue | (result & WANT.WANTinterpret));
-		e = this;
+		Expression e = this;
 
 		if ((this.e1.isConst() && this.e2.isConst()) || (this.e1.op == TOK.TOKnull && this.e2.op == TOK.TOKnull))
 		{
--- a/dmd/IntegerExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/IntegerExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -209,7 +209,8 @@
 
 	override bool isBool(bool result)
 	{
-		return result ? value != 0 : value == 0;
+        int r = toInteger() != 0;
+        return cast(bool)(result ? r : !r);
 	}
 
 	override MATCH implicitConvTo(Type t)
--- a/dmd/IsExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/IsExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -146,13 +146,19 @@
 
 				case TOKinvariant:
 				case TOKimmutable:
-					if (!targ.isInvariant())
+					if (!targ.isImmutable())
 						goto Lno;
 					tded = targ;
 					break;
 
 				case TOKshared:
 					if (!targ.isShared())
+            		    goto Lno;
+            		tded = targ;
+		            break;
+
+        	    case TOKwild:
+		            if (!targ.isWild())
 						goto Lno;
 					tded = targ;
 					break;
--- a/dmd/Lexer.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Lexer.d	Mon Sep 13 23:29:00 2010 +0200
@@ -498,7 +498,7 @@
 		Token.tochars[TOK.TOKidentifier]	= "identifier";
 		Token.tochars[TOK.TOKat]		= "@";
         Token.tochars[TOK.TOKpow]		= "^^";
-        //Token.tochars[TOK.TOKpowass]		= "^^=";
+        Token.tochars[TOK.TOKpowass]		= "^^=";
         
 		 // For debugging
 		Token.tochars[TOKerror]		= "error";
@@ -750,16 +750,29 @@
 				case 'Z':
 				case '_':
 				case_ident:
-				{   ubyte c;
-				StringValue *sv;
-				Identifier id;
+				{
+                ubyte c;
 
-				do
-				{
-					c = *++p;
-				} while (isidchar(c) || (c & 0x80 && isUniAlpha(decodeUTF())));
-				sv = stringtable.update((cast(immutable(char)*)t.ptr)[0.. p - t.ptr]);	///
-				id = cast(Identifier) sv.ptrvalue;
+		        while (1)
+		        {
+		            c = *++p;
+		            if (isidchar(c))
+			            continue;
+		            else if (c & 0x80)
+		            {
+                        ubyte *s = p;
+			            uint u = decodeUTF();
+			            if (isUniAlpha(u))
+    			            continue;
+			            error("char 0x%04x not allowed in identifier", u);
+			            p = s;
+		            }
+		            break;
+		        }
+
+		        StringValue *sv = stringtable.update((cast(immutable(char)*)t.ptr)[0.. p - t.ptr]);
+		        Identifier id = cast(Identifier) sv.ptrvalue;
+                    
 				if (id is null)
 				{   id = new Identifier(sv.lstring.string_, TOK.TOKidentifier);
 					sv.ptrvalue = cast(void*)id;
@@ -1266,13 +1279,11 @@
 		p++;
 		if (*p == '^')
 		{   p++;
-//static if (false) {
-//		    if (*p == '=')
-//		    {   p++;
-//			t.value = TOKpowass;  // ^^=
-//		    }
-//		    else
-//}
+		    if (*p == '=')
+		    {   p++;
+			t.value = TOKpowass;  // ^^=
+		    }
+		    else
 			t.value = TOKpow;     // ^^
 		}
 		else if (*p == '=')
@@ -1370,23 +1381,23 @@
 				continue;
 
 				default:
-				{	ubyte c = *p;
+				{	uint c = *p;
 
 				if (c & 0x80)
-				{   uint u = decodeUTF();
+				{   c = decodeUTF();
 
 					// Check for start of unicode identifier
-					if (isUniAlpha(u))
+					if (isUniAlpha(c))
 					goto case_ident;
 
-					if (u == PS || u == LS)
+					if (c == PS || c == LS)
 					{
 					loc.linnum++;
 					p++;
 					continue;
 					}
 				}
-				if (isprint(c))
+				if (c < 0x80 && isprint(c))
 					error("unsupported char '%c'", c);
 				else
 					error("unsupported char 0x%02x", c);
@@ -1719,7 +1730,7 @@
 					if (u == PS || u == LS)
 					loc.linnum++;
 					else
-					error("non-hex character \\u%x", u);
+					error("non-hex character \\u%04x", u);
 				}
 				else
 					error("non-hex character '%c'", c);
--- a/dmd/MOD.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/MOD.d	Mon Sep 13 23:29:00 2010 +0200
@@ -5,8 +5,9 @@
 	MODundefined = 0,
 	MODconst = 1,	// type is const
 	MODshared = 2,	// type is shared
-	MODinvariant = 4,	// type is immutable
 	MODimmutable = 4,	// type is immutable
+	MODwild	= 8,	// type is wild
+	MODmutable = 0x10,	// type is mutable (only used in wildcard matching)
 }
 
 import dmd.EnumUtils;
--- a/dmd/NullExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/NullExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -21,9 +21,10 @@
 {
 	ubyte committed;
 
-	this(Loc loc)
+	this(Loc loc, Type type = null)
 	{
 		super(loc, TOK.TOKnull, NullExp.sizeof);
+        this.type = type;
 	}
 
 	override Expression semantic(Scope sc)
--- a/dmd/Optimize.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Optimize.d	Mon Sep 13 23:29:00 2010 +0200
@@ -24,7 +24,7 @@
     if (!v)
     	return e;
 
-    if (v.isConst() || v.isInvariant() || v.storage_class & STC.STCmanifest)
+    if (v.isConst() || v.isImmutable() || v.storage_class & STC.STCmanifest)
     {
 	if (!v.type)
 	{
--- a/dmd/PREC.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/PREC.d	Mon Sep 13 23:29:00 2010 +0200
@@ -25,6 +25,7 @@
     PREC_shift,
     PREC_add,
     PREC_mul,
+    PREC_pow,
     PREC_unary,
     PREC_primary,
 }
--- a/dmd/Parameter.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Parameter.d	Mon Sep 13 23:29:00 2010 +0200
@@ -177,6 +177,9 @@
 					buf.writestring(", ");
 				auto arg = arguments[i];
 
+	            if (arg.storageClass & STCauto)
+		            buf.writestring("auto ");
+
 				if (arg.storageClass & STCout)
 					buf.writestring("out ");
 				else if (arg.storageClass & STCref)
@@ -187,8 +190,6 @@
 					buf.writestring("lazy ");
 				else if (arg.storageClass & STCalias)
 					buf.writestring("alias ");
-				else if (arg.storageClass & STCauto)
-					buf.writestring("auto ");
 
 				StorageClass stc = arg.storageClass;
 				if (arg.type && arg.type.mod & MODshared)
--- a/dmd/Parser.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Parser.d	Mon Sep 13 23:29:00 2010 +0200
@@ -79,6 +79,7 @@
 import dmd.DivAssignExp;
 import dmd.AndAssignExp;
 import dmd.AddAssignExp;
+import dmd.PowAssignExp;
 import dmd.ModuleDeclaration;
 import dmd.CaseRangeStatement;
 import dmd.CommaExp;
@@ -496,6 +497,12 @@
 			stc = STC.STCshared;
 			goto Lstc;
 
+	        case TOKwild:
+		    if (peek(&token).value == TOK.TOKlparen)
+		        goto Ldeclaration;
+		    stc = STCwild;
+		    goto Lstc;
+
 			case TOK.TOKfinal:	  stc = STC.STCfinal;	 goto Lstc;
 			case TOK.TOKauto:	  stc = STC.STCauto;	 goto Lstc;
 			case TOK.TOKscope:	  stc = STC.STCscope;	 goto Lstc;
@@ -527,6 +534,7 @@
 				case TOK.TOKinvariant:
 				case TOK.TOKimmutable:
 				case TOK.TOKshared:
+		        case TOKwild:
 				// If followed by a (, it is not a storage class
 				if (peek(&token).value == TOK.TOKlparen)
 					break;
@@ -534,6 +542,8 @@
 					stc = STC.STCconst;
 				else if (token.value == TOK.TOKshared)
 					stc = STC.STCshared;
+			    else if (token.value == TOKwild)
+			        stc = STC.STCwild;
 				else
 					stc = STC.STCimmutable;
 				goto Lstc;
@@ -1840,14 +1850,23 @@
 				goto Ldefault;
 				stc = STC.STCshared;
 				goto L2;
+                
+		    case TOKwild:
+		        if (peek(&token).value == TOK.TOKlparen)
+			    goto Ldefault;
+		        stc = STCwild;
+		        goto L2;
 
 			case TOK.TOKin:	   stc = STC.STCin;		goto L2;
 			case TOK.TOKout:	   stc = STC.STCout;	goto L2;
+version(D1INOUT) {
 			case TOK.TOKinout:
+}
 			case TOK.TOKref:	   stc = STC.STCref;	goto L2;
 			case TOK.TOKlazy:	   stc = STC.STClazy;	goto L2;
 			case TOK.TOKscope:	   stc = STC.STCscope;	goto L2;
 			case TOK.TOKfinal:	   stc = STC.STCfinal;	goto L2;
+		    case TOK.TOKauto:	   stc = STCauto;	    goto L2;
 			L2:
 				if (storageClass & stc ||
 				(storageClass & STC.STCin && stc & (STC.STCconst | STC.STCscope)) ||
@@ -2316,6 +2335,17 @@
 			t = t.makeSharedConst();
 			return t;
 		}
+        else if (token.value == TOKwild && peekNext() == TOKshared && peekNext2() != TOKlparen ||
+	             token.value == TOKshared && peekNext() == TOKwild && peekNext2() != TOKlparen)
+        {
+	        nextToken();
+	        nextToken();
+	        /* shared wild type
+	         */
+	        t = parseType(pident, tpl);
+	        t = t.makeSharedWild();
+	        return t;
+        }
 		else if (token.value == TOK.TOKconst && peekNext() != TOK.TOKlparen)
 		{
 			nextToken();
@@ -2344,6 +2374,15 @@
 			t = t.makeShared();
 			return t;
 		}
+        else if (token.value == TOKwild && peekNext() != TOKlparen)
+        {
+	        nextToken();
+	        /* wild type
+	         */
+	        t = parseType(pident, tpl);
+	        t = t.makeWild();
+	        return t;
+        }
 		else
 			t = parseBasicType();	
 		t = parseDeclarator(t, pident, tpl);
@@ -2471,10 +2510,24 @@
 			check(TOK.TOKrparen);
 			if (t.isConst())
 			t = t.makeSharedConst();
+	        else if (t.isWild())
+		    t = t.makeSharedWild();
 			else
 			t = t.makeShared();
 			break;
 
+	    case TOKwild:
+	        // wild(type)
+	        nextToken();
+	        check(TOK.TOKlparen);
+	        t = parseType();
+	        check(TOK.TOKrparen);
+	        if (t.isShared())
+		    t = t.makeSharedWild();
+	        else
+		    t = t.makeWild();
+	        break;
+            
 		default:
 			error("basic type expected, not %s", token.toChars());
 			t = Type.tint32;
@@ -2742,6 +2795,14 @@
 						nextToken();
 						continue;
 
+                    case TOKwild:
+			            if (tf.isShared())
+				        tf = tf.makeSharedWild();
+			            else
+				        tf = tf.makeWild();
+			            nextToken();
+			            continue;
+
 					case TOK.TOKnothrow:
 						(cast(TypeFunction)tf).isnothrow = 1;
 						nextToken();
@@ -2874,6 +2935,12 @@
 			if (peek(&token).value == TOK.TOKlparen)
 				break;
 			stc = STC.STCshared;
+		    goto L1;
+
+	        case TOKwild:
+		    if (peek(&token).value == TOK.TOKlparen)
+		        break;
+		    stc = STC.STCwild;
 			goto L1;
 
 			case TOK.TOKstatic:	stc = STC.STCstatic;	 goto L1;
@@ -3334,6 +3401,7 @@
 version (DMDV2) {
 		case TOK.TOKimmutable:
 		case TOK.TOKshared:
+        case TOKwild:
 		case TOK.TOKnothrow:
 		case TOK.TOKpure:
 		case TOK.TOKtls:
@@ -3526,7 +3594,11 @@
 			Type at;
 			StorageClass storageClass = STC.STCundefined;
 
-			if (token.value == TOK.TOKinout || token.value == TOK.TOKref)
+		if (token.value == TOKref
+//#if D1INOUT
+//			|| token.value == TOKinout
+//#endif
+		   )
 			{   storageClass = STC.STCref;
 				nextToken();
 			}
@@ -4374,12 +4446,14 @@
 		if ((t.value == TOK.TOKconst ||
 			t.value == TOK.TOKinvariant ||
 			t.value == TOK.TOKimmutable ||
+	        t.value == TOKwild ||
 			t.value == TOK.TOKshared) &&
 			peek(t).value != TOK.TOKlparen)
 		{
 			/* const type
 			* immutable type
 			* shared type
+	        * wild type
 			*/
 			t = peek(t);
 		}
@@ -4538,7 +4612,8 @@
 		case TOK.TOKinvariant:
 		case TOK.TOKimmutable:
 		case TOK.TOKshared:
-			// const(type)  or  immutable(type)  or  shared(type)
+    	case TOKwild:
+			// const(type)  or  immutable(type)  or  shared(type)  or  wild(type)
 			t = peek(t);
 			if (t.value != TOK.TOKlparen)
 			goto Lfalse;
@@ -4703,6 +4778,7 @@
 							case TOK.TOKinvariant:
 							case TOK.TOKimmutable:
 							case TOK.TOKshared:
+                            case TOKwild:
 							case TOK.TOKpure:
 							case TOK.TOKnothrow:
 								t = peek(t);
@@ -4763,18 +4839,22 @@
 					t = peek(t);
 					break;
 
+version(D1INOUT) {
+	            case TOKinout:
+}
 				case TOKin:
 				case TOKout:
-				case TOKinout:
 				case TOKref:
 				case TOKlazy:
 				case TOKfinal:
+	            case TOKauto:
 					continue;
 
 				case TOKconst:
 				case TOKinvariant:
 				case TOKimmutable:
 				case TOKshared:
+	            case TOKwild:
 					t = peek(t);
 					if (t.value == TOKlparen)
 					{
@@ -5287,6 +5367,7 @@
 					 token.value == TOK.TOKinvariant && peek(&token).value == TOK.TOKrparen ||
 					 token.value == TOK.TOKimmutable && peek(&token).value == TOK.TOKrparen ||
 					 token.value == TOK.TOKshared && peek(&token).value == TOK.TOKrparen ||
+                     token.value == TOKwild && peek(&token).value == TOKrparen ||
 	///}
 					 token.value == TOK.TOKfunction ||
 					 token.value == TOK.TOKdelegate ||
@@ -5581,7 +5662,7 @@
 			nextToken();
 			check(TOK.TOKlparen);
 			/* Look for cast(), cast(const), cast(immutable),
-			 * cast(shared), cast(shared const)
+			 * cast(shared), cast(shared const), cast(wild), cast(shared wild)
 			 */
 			MOD m;
 			if (token.value == TOK.TOKrparen)
@@ -5596,7 +5677,7 @@
 			}
 			else if ((token.value == TOK.TOKimmutable || token.value == TOK.TOKinvariant) && peekNext() == TOK.TOKrparen)
 			{
-			m = MOD.MODinvariant;
+			m = MOD.MODimmutable;
 			goto Lmod2;
 			}
 			else if (token.value == TOK.TOKshared && peekNext() == TOK.TOKrparen)
@@ -5604,10 +5685,22 @@
 			m = MOD.MODshared;
 			goto Lmod2;
 			}
+	        else if (token.value == TOKwild && peekNext() == TOK.TOKrparen)
+	        {
+		    m = MODwild;
+		    goto Lmod2;
+	        }
+	        else if (token.value == TOKwild && peekNext() == TOK.TOKshared && peekNext2() == TOK.TOKrparen ||
+		         token.value == TOK.TOKshared && peekNext() == TOKwild && peekNext2() == TOK.TOKrparen)
+	        {
+		    m = MOD.MODshared | MOD.MODwild;
+		    goto Lmod3;
+	        }
 			else if (token.value == TOK.TOKconst && peekNext() == TOK.TOKshared && peekNext2() == TOK.TOKrparen ||
 				 token.value == TOK.TOKshared && peekNext() == TOK.TOKconst && peekNext2() == TOK.TOKrparen)
 			{
 			m = MOD.MODshared | MOD.MODconst;
+	          Lmod3:
 			nextToken();
 			  Lmod2:
 			nextToken();
@@ -5734,6 +5827,15 @@
 			break;
 		}
 		assert(e);
+
+        // ^^ is right associative and has higher precedence than the unary operators
+        while (token.value == TOK.TOKpow)
+        {
+	        nextToken();
+	        Expression e2 = parseUnaryExp();
+	        e = new PowExp(loc, e, e2);
+        }
+
 		return e;
 	}
 	
@@ -5862,7 +5964,6 @@
 				case TOK.TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue;
 	            case TOK.TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue;
 	            case TOK.TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue;
-	            case TOK.TOKpow: nextToken(); e2 = parseUnaryExp(); e = new PowExp(loc,e,e2); continue;
 
 				default:
 				break;
@@ -6129,7 +6230,7 @@
 				case TOK.TOKmulass:  nextToken(); e2 = parseAssignExp(); e = new MulAssignExp(loc,e,e2); continue;
 				case TOK.TOKdivass:  nextToken(); e2 = parseAssignExp(); e = new DivAssignExp(loc,e,e2); continue;
 				case TOK.TOKmodass:  nextToken(); e2 = parseAssignExp(); e = new ModAssignExp(loc,e,e2); continue;
-//				case TOK.TOKpowass:  nextToken(); e2 = parseAssignExp(); e = new PowAssignExp(loc,e,e2); continue;
+				case TOK.TOKpowass:  nextToken(); e2 = parseAssignExp(); e = new PowAssignExp(loc,e,e2); continue;
 				case TOK.TOKandass:  nextToken(); e2 = parseAssignExp(); e = new AndAssignExp(loc,e,e2); continue;
 				case TOK.TOKorass:   nextToken(); e2 = parseAssignExp(); e = new OrAssignExp(loc,e,e2); continue;
 				case TOK.TOKxorass:  nextToken(); e2 = parseAssignExp(); e = new XorAssignExp(loc,e,e2); continue;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/PowAssignExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -0,0 +1,77 @@
+module dmd.PowAssignExp;
+
+import dmd.BinExp;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Expression;
+import dmd.TOK;
+import dmd.STC;
+import dmd.PowExp;
+import dmd.AssignExp;
+import dmd.Lexer;
+import dmd.VarDeclaration;
+import dmd.ExpInitializer;
+import dmd.DeclarationExp;
+import dmd.VarExp;
+import dmd.CommaExp;
+import dmd.ErrorExp;
+import dmd.Id;
+
+// Only a reduced subset of operations for now.
+class PowAssignExp : BinExp
+{
+    this(Loc loc, Expression e1, Expression e2)
+    {
+        super(loc, TOK.TOKpowass, PowAssignExp.sizeof, e1, e2);
+    }
+    
+    override Expression semantic(Scope sc)
+    {
+        Expression e;
+
+        if (type)
+	    return this;
+
+        BinExp.semantic(sc);
+        e2 = resolveProperties(sc, e2);
+
+        e = op_overload(sc);
+        if (e)
+	        return e;
+
+        e1 = e1.modifiableLvalue(sc, e1);
+        assert(e1.type && e2.type);
+
+        if ( (e1.type.isintegral() || e1.type.isfloating()) &&
+	     (e2.type.isintegral() || e2.type.isfloating()))
+        {
+	        if (e1.op == TOKvar)
+	        {   // Rewrite: e1 = e1 ^^ e2
+	            e = new PowExp(loc, e1.syntaxCopy(), e2);
+	            e = new AssignExp(loc, e1, e);
+	        }
+	        else
+	        {   // Rewrite: ref tmp = e1; tmp = tmp ^^ e2
+	            Identifier id = Lexer.uniqueId("__powtmp");
+	            auto v = new VarDeclaration(e1.loc, e1.type, id, new ExpInitializer(loc, e1));
+	            v.storage_class |= STC.STCref | STC.STCforeach;
+	            Expression de = new DeclarationExp(e1.loc, v);
+	            VarExp ve = new VarExp(e1.loc, v);
+	            e = new PowExp(loc, ve, e2);
+	            e = new AssignExp(loc, new VarExp(e1.loc, v), e);
+	            e = new CommaExp(loc, de, e);
+	        }
+	        e = e.semantic(sc);
+	        return e;
+        }
+        error("%s ^^= %s is not supported", e1.type.toChars(), e2.type.toChars() );
+        return new ErrorExp();
+    }
+    
+    // For operator overloading
+    Identifier opId()
+    {
+        return Id.powass;
+    }
+};
\ No newline at end of file
--- a/dmd/PowExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/PowExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -12,6 +12,18 @@
 import dmd.DotIdExp;
 import dmd.CallExp;
 import dmd.ErrorExp;
+import dmd.CommaExp;
+import dmd.AndExp;
+import dmd.CondExp;
+import dmd.IntegerExp;
+import dmd.Type;
+import dmd.Lexer;
+import dmd.VarDeclaration;
+import dmd.ExpInitializer;
+import dmd.VarExp;
+import dmd.DeclarationExp;
+import dmd.MulExp;
+import dmd.WANT;
 
 version(DMDV2) {
 
@@ -22,65 +34,121 @@
         super(loc, TOK.TOKpow, PowExp.sizeof, e1, e2);
     }
         
-    Expression semantic(Scope sc)
+    override Expression semantic(Scope sc)
     {
         Expression e;
 
         if (type)
 	        return this;
 
+        //printf("PowExp::semantic() %s\n", toChars());
         BinExp.semanticp(sc);
         e = op_overload(sc);
         if (e)
 	        return e;
 
-        static int importMathChecked = 0;
-        if (!importMathChecked)
-        {
-	        importMathChecked = 1;
-	        for (int i = 0; i < Module.amodules.dim; i++)
-	        {
-                auto mi = cast(Module)Module.amodules.data[i];
-	            //printf("\t[%d] %s\n", i, mi->toChars());
-	            if (mi.ident == Id.math &&
-		        mi.parent.ident == Id.std &&
-		        !mi.parent.parent)
-		        goto L1;
-	        }
-	        error("must import std.math to use ^^ operator");
-
-            L1: ;
-        }
-
         assert(e1.type && e2.type);
         if ( (e1.type.isintegral() || e1.type.isfloating()) &&
 	     (e2.type.isintegral() || e2.type.isfloating()))
         {
-	        // For built-in numeric types, there are three cases:
-	        // x ^^ 1   ----> x
-	        // x ^^ 0.5 ----> sqrt(x)
-	        // x ^^ y   ----> pow(x, y)
+	        // For built-in numeric types, there are several cases.
 	        // TODO: backend support, especially for  e1 ^^ 2.
+            
 	        bool wantSqrt = false;	
+        	e1 = e1.optimize(0);
 	        e2 = e2.optimize(0);
-	        if ((e2.op == TOK.TOKfloat64 && e2.toReal() == 1.0) ||
-	            (e2.op == TOK.TOKint64 && e2.toInteger() == 1))
+	        	
+	        // Replace 1 ^^ x or 1.0^^x by (x, 1)
+	        if ((e1.op == TOK.TOKint64 && e1.toInteger() == 1) ||
+		        (e1.op == TOK.TOKfloat64 && e1.toReal() == 1.0))
+	        {
+	            typeCombine(sc);
+	            e = new CommaExp(loc, e2, e1);
+	            e = e.semantic(sc);
+	            return e;
+ 	        }
+	        // Replace -1 ^^ x by (x&1) ? -1 : 1, where x is integral
+	        if (e2.type.isintegral() && e1.op == TOKint64 && cast(long)e1.toInteger() == -1)
+	        {
+	            typeCombine(sc);
+	            Type resultType = type;
+	            e = new AndExp(loc, e2, new IntegerExp(loc, 1, e2.type));
+	            e = new CondExp(loc, e, new IntegerExp(loc, -1, resultType), new IntegerExp(loc, 1, resultType));
+	            e = e.semantic(sc);
+	            return e;
+	        }
+	        // All other negative integral powers are illegal
+	        if ((e1.type.isintegral()) && (e2.op == TOK.TOKint64) && cast(long)e2.toInteger() < 0)
 	        {
-	            return e1;  // Replace x ^^ 1 with x.
+	            error("cannot raise %s to a negative integer power. Did you mean (cast(real)%s)^^%s ?",
+		        e1.type.toBasetype().toChars(), e1.toChars(), e2.toChars());
+	            return new ErrorExp();
+	        }
+	
+	        // Deal with x^^2, x^^3 immediately, since they are of practical importance.
+	        // Don't bother if x is a literal, since it will be constant-folded anyway.
+	        if ( (  (e2.op == TOK.TOKint64 && (e2.toInteger() == 2 || e2.toInteger() == 3)) 
+	             ||	(e2.op == TOK.TOKfloat64 && (e2.toReal() == 2.0 || e2.toReal() == 3.0))
+	             ) && (e1.op == TOK.TOKint64 || e1.op == TOK.TOKfloat64)
+	           )
+	        {
+	            typeCombine(sc);
+	            // Replace x^^2 with (tmp = x, tmp*tmp)
+	            // Replace x^^3 with (tmp = x, tmp*tmp*tmp) 
+	            Identifier idtmp = Lexer.uniqueId("__tmp");
+	            VarDeclaration tmp = new VarDeclaration(loc, e1.type.toBasetype(), idtmp, new ExpInitializer(Loc(0), e1));
+	            VarExp ve = new VarExp(loc, tmp);
+	            Expression ae = new DeclarationExp(loc, tmp);
+	            Expression me = new MulExp(loc, ve, ve);
+	            if ( (e2.op == TOK.TOKint64 && e2.toInteger() == 3) 
+	              || (e2.op == TOK.TOKfloat64 && e2.toReal() == 3.0))
+		        me = new MulExp(loc, me, ve);
+	            e = new CommaExp(loc, ae, me);
+	            e = e.semantic(sc);
+	            return e;
 	        }
 
-	        e = new IdentifierExp(loc, Id.empty);
-	        e = new DotIdExp(loc, e, Id.std);
-	        e = new DotIdExp(loc, e, Id.math);
-	        if (e2.op == TOKfloat64 && e2.toReal() == 0.5)
-	        {   // Replace e1 ^^ 0.5 with .std.math.sqrt(x)
-	            e = new CallExp(loc, new DotIdExp(loc, e, Id._sqrt), e1);
+	        static int importMathChecked = 0;
+	        if (!importMathChecked)
+	        {
+	            importMathChecked = 1;
+	            for (int i = 0; i < Module.amodules.dim; i++)
+	            {
+                    auto mi = cast(Module)Module.amodules.data[i];
+		            //printf("\t[%d] %s\n", i, mi->toChars());
+		            if (mi.ident == Id.math &&
+		                mi.parent.ident == Id.std &&
+		                !mi.parent.parent)
+		                goto L1;
+	            }
+	            error("must import std.math to use ^^ operator");
+
+	         L1: ;
 	        }
-	        else 
-	        {   // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
- 	            e = new CallExp(loc, new DotIdExp(loc, e, Id._pow), e1, e2);	
-	        }	
-	        e = e.semantic(sc);
+ 
+ 	        e = new IdentifierExp(loc, Id.empty);
+ 	        e = new DotIdExp(loc, e, Id.std);
+ 	        e = new DotIdExp(loc, e, Id.math);
+ 	        if (e2.op == TOK.TOKfloat64 && e2.toReal() == 0.5)
+ 	        {   // Replace e1 ^^ 0.5 with .std.math.sqrt(x)
+	            typeCombine(sc);
+ 	            e = new CallExp(loc, new DotIdExp(loc, e, Id._sqrt), e1);
+ 	        }
+ 	        else 
+	        {
+	            // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
+	            // We don't combine the types if raising to an integer power (because
+	            // integer powers are treated specially by std.math.pow).
+	            if (!e2.type.isintegral())
+		            typeCombine(sc);
+	            e = new CallExp(loc, new DotIdExp(loc, e, Id._pow), e1, e2);	
+ 	        }	
+ 	        e = e.semantic(sc);
+	        // Always constant fold integer powers of literals. This will run the interpreter
+	        // on .std.math.pow
+	        if ((e1.op == TOK.TOKfloat64 || e1.op == TOK.TOKint64) && (e2.op == TOK.TOKint64))
+	            e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+
 	        return e;
         }
         error("%s ^^ %s is not supported", e1.type.toChars(), e2.type.toChars() );
@@ -89,12 +157,12 @@
    
 
     // For operator overloading
-    Identifier opId()
+    override Identifier opId()
     {
         return Id.pow;
     }
     
-    Identifier opId_r()
+    override Identifier opId_r()
     {
         return Id.pow_r;
     }
--- a/dmd/PtrExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/PtrExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -85,7 +85,12 @@
 	{
 		return 1;
 	}
-
+    
+    override void checkEscapeRef()
+    {
+        e1.checkEscape();
+    }
+    
 	override Expression toLvalue(Scope sc, Expression e)
 	{
 static if (false) {
--- a/dmd/ReturnStatement.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/ReturnStatement.d	Mon Sep 13 23:29:00 2010 +0200
@@ -35,6 +35,7 @@
 import dmd.VarDeclaration;
 import dmd.GlobalExpressions;
 import dmd.BE;
+import dmd.Global;
 
 import dmd.codegen.Util;
 
@@ -173,14 +174,46 @@
 			if (fd.returnLabel && tbret.ty != TY.Tvoid) {
 				;
 			} else if (fd.inferRetType) {
-				if (fd.type.nextOf()) {
-					if (!exp.type.equals(fd.type.nextOf()))
-						error("mismatched function return type inference of %s and %s", exp.type.toChars(), fd.type.nextOf().toChars());
+				auto tf = cast(TypeFunction)fd.type;
+	            assert(tf.ty == TY.Tfunction);
+	            Type tfret = tf.nextOf();
+	            if (tfret)
+                {
+   					if (!exp.type.equals(tfret))
+						error("mismatched function return type inference of %s and %s", exp.type.toChars(), tfret.toChars());
+		            /* The "refness" is determined by the first return statement,
+		             * not all of them. This means:
+		             *    return 3; return x;  // ok, x can be a value
+		             *    return x; return 3;  // error, 3 is not an lvalue
+		             */
 				}
 				else
 				{
-					(cast(TypeFunction)fd.type).next = exp.type;
-					fd.type = fd.type.semantic(loc, sc);
+		            if (tf.isref)
+		            {   /* Determine "refness" of function return:
+		                 * if it's an lvalue, return by ref, else return by value
+		                 */
+		                if (exp.isLvalue())
+		                {
+			                /* Return by ref
+			                 * (but first ensure it doesn't fail the "check for
+			                 * escaping reference" test)
+			                 */
+			                uint errors = global.errors;
+			                global.gag++;
+			                exp.checkEscapeRef();
+			                global.gag--;
+			                if (errors != global.errors)
+			                {   tf.isref = false;	// return by value
+			                    global.errors = errors;
+			                }
+		                }
+		                else
+			                tf.isref = false;	// return by value
+		            }
+		            tf.next = exp.type;
+		            fd.type = tf.semantic(loc, sc);
+
 					if (!fd.tintro)
 					{   
 						tret = fd.type.nextOf();
@@ -290,19 +323,14 @@
 				else
 					exp = exp.toLvalue(sc, exp);
 
-				if (exp.op == TOK.TOKvar)
-				{	
-					VarExp ve = cast(VarExp)exp;
-					VarDeclaration v = ve.var.isVarDeclaration();
-					if (v && !v.isDataseg() && !(v.storage_class & (STC.STCref | STC.STCout))) {
-						error("escaping reference to local variable %s", v.toChars());
-					}
-				}
+				exp.checkEscapeRef();
 			}
-
-			//exp.dump(0);
-			//exp.print();
-			exp.checkEscape();
+            else
+            {
+			    //exp.dump(0);
+			    //exp.print();
+			    exp.checkEscape();
+            }
 		}
 
 		/* BUG: need to issue an error on:
--- a/dmd/STC.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/STC.d	Mon Sep 13 23:29:00 2010 +0200
@@ -23,7 +23,6 @@
     STCctorinit     = 0x20000,		// can only be set inside constructor
     STCtemplateparameter = 0x40000,	// template parameter
     STCscope	    = 0x80000,		// template parameter
-    STCinvariant    = 0x100000,
     STCimmutable    = 0x100000,
     STCref	    = 0x200000,
     STCinit	    = 0x400000,		// has explicit initializer
@@ -36,7 +35,8 @@
     STCshared       = 0x20000000,	// accessible from multiple threads
     STCgshared      = 0x40000000,	// accessible from multiple threads
 					// but not typed as "shared"
-    STC_TYPECTOR    = (STCconst | STCimmutable | STCshared),
+    STCwild         = 0x80000000,	// for "wild" type constructor
+    STC_TYPECTOR    = (STCconst | STCimmutable | STCshared | STCwild),
 }
 
 import dmd.EnumUtils;
@@ -46,5 +46,6 @@
 enum STCsafe		= 0x200000000;
 enum STCtrusted		= 0x400000000;
 enum STCsystem		= 0x800000000;
+enum STCctfe		= 0x1000000000;	// can be used in CTFE, even if it is static
 
 alias ulong StorageClass;
\ No newline at end of file
--- a/dmd/Scope.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Scope.d	Mon Sep 13 23:29:00 2010 +0200
@@ -137,6 +137,7 @@
 		this.sd = null;
 		this.sw = enclosing.sw;
 		this.tf = enclosing.tf;
+        this.tinst = enclosing.tinst;
 		this.tinst = enclosing.tinst;
 		this.sbreak = enclosing.sbreak;
 		this.scontinue = enclosing.scontinue;
--- a/dmd/SliceExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/SliceExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -265,6 +265,11 @@
 	{
 		e1.checkEscape();
 	}
+    
+    override void checkEscapeRef()
+    {
+        e1.checkEscapeRef();
+    }
 
 version (DMDV2) {
 	override int isLvalue()
--- a/dmd/StaticAssert.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/StaticAssert.d	Mon Sep 13 23:29:00 2010 +0200
@@ -68,12 +68,11 @@
 			else
 				error("(%s) is false", exp.toChars());
 
-			if(sc.tinst)
+			if (sc.tinst)
 				sc.tinst.printInstantiationTrace();
 
-			if (!global.gag) {
+			if (!global.gag)
 				fatal();
-			}
 		}
 		else if (!e.isBool(true))
 		{
--- a/dmd/StructDeclaration.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/StructDeclaration.d	Mon Sep 13 23:29:00 2010 +0200
@@ -207,7 +207,22 @@
 		sc2.protection = PROT.PROTpublic;
 		sc2.explicitProtection = 0;
 
-		int members_dim = members.dim;
+
+        /* Set scope so if there are forward references, we still might be able to
+         * resolve individual members like enums.
+         */
+        foreach (s; members)
+        {
+	        /* There are problems doing this in the general case because
+	         * Scope keeps track of things like 'offset'
+	         */
+	        if (s.isEnumDeclaration() || (s.isAggregateDeclaration() && s.ident))
+	        {
+	            //printf("setScope %s %s\n", s->kind(), s->toChars());
+	            s.setScope(sc2);
+	        }
+        }
+
 		foreach(Dsymbol s; members)
 		{
 			s.semantic(sc2);
@@ -412,6 +427,22 @@
 		}
 	}
 	
+    Dsymbol search(Loc loc, Identifier ident, int flags)
+    {
+        //printf("%s.StructDeclaration::search('%s')\n", toChars(), ident->toChars());
+
+        if (scope_)
+    	    semantic(scope_);
+
+        if (!members || !symtab)
+        {
+    	    error("is forward referenced when looking for '%s'", ident.toChars());
+	        return null;
+        }
+
+        return ScopeDsymbol.search(loc, ident, flags);
+    }
+
     override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
 	{
 		assert(false);
--- a/dmd/StructInitializer.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/StructInitializer.d	Mon Sep 13 23:29:00 2010 +0200
@@ -78,7 +78,6 @@
 	
     override Initializer semantic(Scope sc, Type t)
 	{
-		TypeStruct ts;
 		int errors = 0;
 
 		//printf("StructInitializer.semantic(t = %s) %s\n", t.toChars(), toChars());
@@ -86,12 +85,14 @@
 		t = t.toBasetype();
 		if (t.ty == Tstruct)
 		{	
-			uint i;
 			uint fieldi = 0;
 
-			ts = cast(TypeStruct)t;
+			auto ts = cast(TypeStruct)t;
 			ad = ts.sym;
-			for (i = 0; i < field.dim; i++)
+	        if (ad.ctor)
+	            error("%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead",
+		        ad.kind(), ad.toChars(), ad.toChars());
+			for (size_t i = 0; i < field.dim; i++)
 			{
 				Identifier id = field[i];
 				Initializer val = value[i];
--- a/dmd/StructLiteralExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/StructLiteralExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -157,8 +157,7 @@
 				}
 				else
 				{	
-					e = v.type.defaultInit(Loc(0));
-					e.loc = loc;
+					e = v.type.defaultInitLiteral(loc);
 				}
 				offset = v.offset + cast(uint)v.type.size();
 			}
@@ -660,7 +659,7 @@
 					te = te.mutableOf();
 				else
 				{	
-					assert(t.mod == MODinvariant);
+					assert(t.mod == MODimmutable);
 					te = te.invariantOf();
 				}
 				MATCH m2 = e.implicitConvTo(te);
--- a/dmd/SwitchStatement.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/SwitchStatement.d	Mon Sep 13 23:29:00 2010 +0200
@@ -412,7 +412,7 @@
 		block_appendexp(mystate.switchBlock, econd);
 		block_next(blx,BCswitch,null);
 
-		/// 
+        // Corresponding free is in block_free
 		targ_llong* pu = cast(targ_llong*) malloc(targ_llong.sizeof * (numcases + 1));
 		mystate.switchBlock.Bswitch = pu;
 		/* First pair is the number of cases, and the default block
--- a/dmd/SymOffExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/SymOffExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -20,6 +20,7 @@
 import dmd.ErrorExp;
 import dmd.TY;
 import dmd.TOK;
+import dmd.STC;
 
 import dmd.backend.Symbol;
 import dmd.backend.Util;
@@ -58,14 +59,14 @@
 		VarDeclaration v = var.isVarDeclaration();
 		if (v)
 		{
-			if (!v.isDataseg())
+			if (!v.isDataseg() && !(v.storage_class & (STC.STCref | STC.STCout)))
 			{   /* BUG: This should be allowed:
 				 *   void foo()
 				 *   { int a;
 				 *     int* bar() { return &a; }
 				 *   }
 				 */
-				error("escaping reference to local variable %s", v.toChars());
+				error("escaping reference to local %s", v.toChars());
 			}
 		}
 	}
--- a/dmd/TOK.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TOK.d	Mon Sep 13 23:29:00 2010 +0200
@@ -127,7 +127,7 @@
 		TOKshared,
 		TOKat,
 	    TOKpow,
-	    //TOKpowass,
+	    TOKpowass,
 
 		TOKMAX
 	}
@@ -251,5 +251,7 @@
 	}
 }
 
+alias TOK.TOKinout TOKwild;
+
 import dmd.EnumUtils;
 mixin(BringToCurrentScope!(TOK));
\ No newline at end of file
--- a/dmd/TemplateDeclaration.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TemplateDeclaration.d	Mon Sep 13 23:29:00 2010 +0200
@@ -797,21 +797,7 @@
 		}
 	}
 
-		if (fd.type)
-		{
-			assert(fd.type.ty == Tfunction);
-			TypeFunction fdtype = cast(TypeFunction)fd.type;
-			fparameters = fdtype.parameters;
-			fvarargs = fdtype.varargs;
-		}
-		else
-		{	
-			CtorDeclaration fctor = fd.isCtorDeclaration();
-			assert(fctor);
-			fparameters = fctor.arguments;
-			fvarargs = fctor.varargs;
-		}
-
+		fparameters = fd.getParameters(&fvarargs);
 		nfparams = Parameter.dim(fparameters);	// number of function parameters
 		nfargs = fargs ? fargs.dim : 0;		// number of function arguments
 
@@ -1258,7 +1244,7 @@
 		 */
 		assert(cast(size_t)cast(void*)td_best.scope_ > 0x10000);
 		ti = new TemplateInstance(loc, td_best, tdargs);
-		ti.semantic(sc);
+		ti.semantic(sc, fargs);
 		fd = ti.toAlias().isFuncDeclaration();
 		if (!fd)
 		goto Lerror;
@@ -1390,21 +1376,8 @@
         if (fd)
         {
 	        paramscope.parent = fd;
-	        Parameters fparameters;		// function parameter list
 	        int fvarargs;				// function varargs
-	        if (fd.type)
-	        {
-	            assert(fd.type.ty == Tfunction);
-	            TypeFunction fdtype = cast(TypeFunction )fd.type;
-	            fparameters = fdtype.parameters;
-	            fvarargs = fdtype.varargs;
-	        }
-	        else // Constructors don't have type's
-	        {   CtorDeclaration fctor = fd.isCtorDeclaration();
-	            assert(fctor);
-	            fparameters = fctor.arguments;
-	            fvarargs = fctor.varargs;
-	        }
+            Parameters fparameters = fd.getParameters(&fvarargs);
 	        size_t nfparams = Parameter.dim(fparameters); // Num function parameters
 	        for (int i = 0; i < nfparams; i++)
 	        {
--- a/dmd/TemplateInstance.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TemplateInstance.d	Mon Sep 13 23:29:00 2010 +0200
@@ -40,6 +40,7 @@
 import dmd.TypeFunction;
 import dmd.TemplateTupleParameter;
 import dmd.FuncDeclaration;
+import dmd.OverloadSet;
 import dmd.templates.Util;
 
 import dmd.backend.glue;
@@ -263,6 +264,11 @@
 
     override void semantic(Scope sc)
 	{
+        semantic(sc, null);
+    }
+
+    void semantic(Scope sc, Expressions fargs)
+    {
 	    if (global.errors)
 		{
 			if (!global.gag)
@@ -364,6 +370,34 @@
 				if (!match(o1, o2, tempdecl, sc))
 				{
 					goto L1;
+	            }
+	        }
+
+	        /* Template functions may have different instantiations based on
+	         * "auto ref" parameters.
+	         */
+	        if (fargs)
+	        {
+	            FuncDeclaration fd = ti.toAlias().isFuncDeclaration();
+	            if (fd)
+	            {
+		            auto fparameters = fd.getParameters(null);
+		            size_t nfparams = Parameter.dim(fparameters); // Num function parameters
+		            for (int i = 0; i < nfparams && i < fargs.dim; i++)
+		            {   auto fparam = Parameter.getNth(fparameters, i);
+		                auto farg = fargs[i];
+		                if (fparam.storageClass & STCauto)		// if "auto ref"
+		                {
+			                if (farg.isLvalue())
+			                {   if (!(fparam.storageClass & STC.STCref))
+				                goto L1;			// auto ref's don't match
+			                }
+			                else
+			                {   if (fparam.storageClass & STC.STCref)
+				                goto L1;			// auto ref's don't match
+			                }
+		                }
+		            }
 				}
 			}
 
@@ -514,6 +548,22 @@
 				}
 			}
 		}
+        
+        /* If function template declaration
+         */
+        if (fargs && aliasdecl)
+        {
+	        FuncDeclaration fd = aliasdecl.toAlias().isFuncDeclaration();
+	        if (fd)
+	        {
+	            /* Transmit fargs to type so that TypeFunction::semantic() can
+	             * resolve any "auto ref" storage classes.
+	             */
+	            auto tf = cast(TypeFunction)fd.type;
+	            if (tf && tf.ty == TY.Tfunction)
+		        tf.fargs = fargs;
+	        }
+        }
 
 		// Do semantic() analysis on template instance members
 	version (LOG) {
@@ -610,10 +660,9 @@
 		if (global.errors != errorsave)
 		{
 			error("error instantiating");
-			if (tinst && !global.gag)
+			if (tinst)
 			{   
 				tinst.printInstantiationTrace();
-				fatal();
 			}
 			errors = 1;
 			if (global.gag)
@@ -832,10 +881,82 @@
 	    return id;
 	}
 	
+    /**************************************
+     * Given an error instantiating the TemplateInstance,
+     * give the nested TemplateInstance instantiations that got
+     * us here. Those are a list threaded into the nested scopes.
+     */
     void printInstantiationTrace()
 	{
 	    if (global.gag)
-		return;
+		    return;
+/+
+        const int max_shown = 6;
+        const string format = "%s:        instantiated from here: %s\n";
+
+        // determine instantiation depth and number of recursive instantiations
+        int n_instantiations = 1;
+        int n_totalrecursions = 0;
+        for (TemplateInstance cur = this; cur; cur = cur.tinst)
+        {
+	        ++n_instantiations;
+	        // If two instantiations use the same declaration, they are recursive.
+	        // (this works even if they are instantiated from different places in the
+	        // same template).
+	        // In principle, we could also check for multiple-template recursion, but it's
+	        // probably not worthwhile.
+	        if (cur.tinst && cur.tempdecl && cur.tinst.tempdecl
+	            && cur.tempdecl.loc.equals(cur.tinst.tempdecl.loc))
+	            ++n_totalrecursions;
+        }
+
+        // show full trace only if it's short or verbose is on
+        if (n_instantiations <= max_shown || global.params.verbose)
+        {
+	        for (TemplateInstance cur = this; cur; cur = cur.tinst)
+	        {
+	            fprintf(stdmsg, format, cur.loc.toChars(), cur.toChars());
+	        }
+        }
+        else if (n_instantiations - n_totalrecursions <= max_shown)
+        {
+	        // By collapsing recursive instantiations into a single line,
+	        // we can stay under the limit.
+	        int recursionDepth=0;
+	        for (TemplateInstance cur = this; cur; cur = cur.tinst)
+	        {
+	            if (cur.tinst && cur.tempdecl && cur.tinst.tempdecl
+		            && cur.tempdecl.loc.equals(cur.tinst.tempdecl.loc))
+	            {
+    		        ++recursionDepth;
+	            }
+	            else
+	            {
+		            if (recursionDepth)
+		                fprintf(stdmsg, "%s:        %d recursive instantiations from here: %s\n", cur.loc.toChars(), recursionDepth+2, cur.toChars());
+		            else 
+		                fprintf(stdmsg,format, cur.loc.toChars(), cur.toChars());
+		            recursionDepth = 0;
+	            }
+	        }
+        }
+        else
+        {
+	        // Even after collapsing the recursions, the depth is too deep.
+	        // Just display the first few and last few instantiations.
+	        size_t i = 0;
+	        for (TemplateInstance cur = this; cur; cur = cur.tinst)
+	        {
+	            if (i == max_shown / 2)
+		        fprintf(stdmsg,"    ... (%d instantiations, -v to show) ...\n", n_instantiations - max_shown);
+
+	            if (i < max_shown / 2 ||
+		        i >= n_instantiations - max_shown + max_shown / 2)
+		        fprintf(stdmsg, format, cur.loc.toChars(), cur.toChars());
+	            ++i;
+	        }
+        }
++/
 	}
 
     override void toObjFile(int multiobj)			// compile to .obj file
@@ -1024,9 +1145,32 @@
 			s = sc.search(loc, id, &scopesym);
 			if (!s)
 			{   
-				error("identifier '%s' is not defined", id.toChars());
+				error("template '%s' is not defined", id.toChars());
 				return null;
 			}
+
+	        /* If an OverloadSet, look for a unique member that is a template declaration
+	         */
+	        OverloadSet os = s.isOverloadSet();
+	        if (os)
+	        {
+                s = null;
+	            foreach (s2; os.a)
+	            {
+		            if (s2.isTemplateDeclaration())
+		            {
+		                if (s)
+			                error("ambiguous template declaration %s and %s", s.toPrettyChars(), s2.toPrettyChars());
+		                s = s2;
+		            }
+	            }
+	            if (!s)
+	            {
+                    error("template '%s' is not defined", id.toChars());
+		            return null;
+	            }
+	        }
+
 		version (LOG) {
 			printf("It's an instance of '%s' kind '%s'\n", s.toChars(), s.kind());
 			if (s.parent)
--- a/dmd/TraitsExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TraitsExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -31,6 +31,7 @@
 import dmd.TemplateDeclaration;
 import dmd.TemplateInstance;
 import dmd.TypeClass;
+import dmd.Declaration;
 import dmd.Util;
 import dmd.expression.Util;
 
@@ -92,6 +93,7 @@
 			TemplateInstance.semanticTiargs(loc, sc, args, 1);
 		size_t dim = args ? args.dim : 0;
 		Object o;
+        Declaration d;
 		FuncDeclaration f;
 
 		string ISTYPE(string cond)
@@ -172,6 +174,20 @@
 		{
 			mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isFinal()}));
 		}
+//version(DMDV2) {
+        else if (ident == Id.isRef)
+        {
+	        mixin(ISDSYMBOL(q{(d = s.isDeclaration()) !is null && d.isRef()}));
+        }
+        else if (ident == Id.isOut)
+        {
+            mixin(ISDSYMBOL(q{(d = s.isDeclaration()) !is null && d.isOut()}));
+        }
+        else if (ident == Id.isLazy)
+        {
+	        mixin(ISDSYMBOL(q{(d = s.isDeclaration()) !is null && d.storage_class & STClazy}));
+        }
+//}
 		else if (ident == Id.hasMember ||
 				ident == Id.getMember ||
 				ident == Id.getVirtualFunctions)
--- a/dmd/Type.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Type.d	Mon Sep 13 23:29:00 2010 +0200
@@ -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;
--- a/dmd/TypeAArray.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeAArray.d	Mon Sep 13 23:29:00 2010 +0200
@@ -116,7 +116,7 @@
 		else
 			index = index.semantic(loc,sc);
 
-		if (index.nextOf() && !index.nextOf().isInvariant())
+		if (index.nextOf() && !index.nextOf().isImmutable())
 		{
 			index = index.constOf().mutableOf();
 static if (false)
@@ -330,9 +330,7 @@
 	version (LOGDEFAULTINIT) {
 		printf("TypeAArray.defaultInit() '%s'\n", toChars());
 	}
-		Expression e = new NullExp(loc);
-		e.type = this;
-		return e;
+		return new NullExp(loc, this);
 	}
 	
     override MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
@@ -385,10 +383,10 @@
 		{	
 			TypeAArray ta = cast(TypeAArray)to;
 
-			if (!(next.mod == ta.next.mod || ta.next.mod == MODconst))
+			if (!MODimplicitConv(next.mod, ta.next.mod))
 				return MATCHnomatch;	// not const-compatible
 
-			if (!(index.mod == ta.index.mod || ta.index.mod == MODconst))
+			if (!MODimplicitConv(index.mod, ta.index.mod))
 				return MATCHnomatch;	// not const-compatible
 
 			MATCH m = next.constConv(ta.next);
--- a/dmd/TypeBasic.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeBasic.d	Mon Sep 13 23:29:00 2010 +0200
@@ -308,6 +308,7 @@
 				case TY.Tcomplex80:
 				case TY.Timaginary80:
 				case TY.Tfloat80:	fvalue = real.min;		goto Lfvalue;
+                default:
 			}
 		}
 		else if (ident is Id.nan)
--- a/dmd/TypeClass.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeClass.d	Mon Sep 13 23:29:00 2010 +0200
@@ -486,9 +486,7 @@
 version (LOGDEFAULTINIT) {
 		printf("TypeClass::defaultInit() '%s'\n", toChars());
 }
-		Expression e = new NullExp(loc);
-		e.type = this;
-		return e;
+		return new NullExp(loc, this);
 	}
 	
     override bool isZeroInit(Loc loc)
--- a/dmd/TypeDArray.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeDArray.d	Mon Sep 13 23:29:00 2010 +0200
@@ -195,7 +195,7 @@
 			/* Allow conversion to void*
 			 */
 			if (tp.next.ty == Tvoid &&
-				(next.mod == tp.next.mod || tp.next.mod == MODconst))
+				MODimplicitConv(next.mod, tp.next.mod))
 			{
 				return MATCHconvert;
 			}
@@ -208,7 +208,7 @@
 			int offset = 0;
 			TypeDArray ta = cast(TypeDArray)to;
 
-			if (!(next.mod == ta.next.mod || ta.next.mod == MODconst))
+			if (!MODimplicitConv(next.mod, ta.next.mod))
 				return MATCHnomatch;	// not const-compatible
 
 			/* Allow conversion to void[]
@@ -226,6 +226,7 @@
 				return m;
 			}
 
+static if(false) {
 			/* Allow conversions of T[][] to const(T)[][]
 			 */
 			if (mod == ta.mod && next.ty == Tarray && ta.next.ty == Tarray)
@@ -234,7 +235,7 @@
 				if (m == MATCHconst)
 				return m;
 			}
-
+}
 			/* Conversion of array of derived to array of base
 			 */
 			if (ta.next.isBaseOf(next, &offset) && offset == 0)
@@ -248,9 +249,7 @@
 	version (LOGDEFAULTINIT) {
 		printf("TypeDArray.defaultInit() '%s'\n", toChars());
 	}
-		Expression e = new NullExp(loc);
-		e.type = this;
-		return e;
+		return new NullExp(loc, this);
 	}
 	
     override bool builtinTypeInfo()
@@ -258,7 +257,7 @@
 	version (DMDV2) {
 		return !mod && (next.isTypeBasic() !is null && !next.mod ||
 			// strings are so common, make them builtin
-			next.ty == Tchar && next.mod == MODinvariant);
+			next.ty == Tchar && next.mod == MODimmutable);
 	} else {
 		return next.isTypeBasic() !is null;
 	}
--- a/dmd/TypeDelegate.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeDelegate.d	Mon Sep 13 23:29:00 2010 +0200
@@ -113,10 +113,7 @@
 	version (LOGDEFAULTINIT) {
 		printf("TypeDelegate.defaultInit() '%s'\n", toChars());
 	}
-		Expression e;
-		e = new NullExp(loc);
-		e.type = this;
-		return e;
+		return new NullExp(loc, this);
 	}
 	
     override bool isZeroInit(Loc loc)
--- a/dmd/TypeEnum.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeEnum.d	Mon Sep 13 23:29:00 2010 +0200
@@ -189,11 +189,20 @@
 	
     override MATCH constConv(Type to)
 	{
-		assert(false);
+        if (equals(to))
+	        return MATCHexact;
+        if (ty == to.ty && sym == (cast(TypeEnum)to).sym &&
+	        MODimplicitConv(mod, to.mod))
+	        return MATCHconst;
+        return MATCHnomatch;
 	}
 	
     override Type toBasetype()
 	{
+        if (sym.scope_)
+        {
+    	    sym.semantic(null);	// attempt to resolve forward reference
+        }
 		if (!sym.memtype)
 		{
 			debug writef("2: ");
--- a/dmd/TypeFunction.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeFunction.d	Mon Sep 13 23:29:00 2010 +0200
@@ -34,6 +34,7 @@
 import dmd.Util;
 import dmd.FuncDeclaration;
 import dmd.Dsymbol;
+import dmd.TypeTuple;
 import dmd.TemplateInstance : isTuple;
 
 import dmd.backend.TYPE;
@@ -61,6 +62,7 @@
     bool isref;		// true: returns a reference
     LINK linkage;	// calling convention
     TRUST trust;	// level of trust
+    Expressions fargs;	// function arguments
 
     int inuse;
 
@@ -88,6 +90,7 @@
 		t.isproperty = isproperty;
 		t.isref = isref;
         t.trust = trust;
+        t.fargs = fargs;
 
 		return t;
 	}
@@ -136,7 +139,7 @@
 			return this;
 		}
 		//printf("TypeFunction.semantic() this = %p\n", this);
-		//printf("TypeFunction.semantic() %s, sc.stc = %x\n", toChars(), sc.stc);
+		//printf("TypeFunction::semantic() %s, sc->stc = %llx, fargs = %p\n", toChars(), sc->stc, fargs);
 
 		/* Copy in order to not mess up original.
 		 * This can produce redundant copies if inferring return type,
@@ -174,6 +177,7 @@
 	            }
 	        }
 
+        bool wildreturn = false;
 		if (tf.next)
 		{
 			tf.next = tf.next.semantic(loc,sc);
@@ -197,8 +201,14 @@
 			}
 			if (tf.next.isauto() && !(sc.flags & SCOPE.SCOPEctor))
 				error(loc, "functions cannot return scope %s", tf.next.toChars());
-		}
+	        if (tf.next.toBasetype().ty == TY.Tvoid)
+	            tf.isref = false;			// rewrite "ref void" as just "void"
+	        if (tf.next.isWild())
+	            wildreturn = true;
+        }
 
+        bool wildparams = false;
+        bool wildsubparams = false;
 		if (tf.parameters)
 		{	
 			/* Create a scope for evaluating the default arguments for the parameters
@@ -210,49 +220,97 @@
 			size_t dim = Parameter.dim(tf.parameters);
 
 			for (size_t i = 0; i < dim; i++)
-			{   auto arg = Parameter.getNth(tf.parameters, i);
+			{   auto fparam = Parameter.getNth(tf.parameters, i);
 
 				tf.inuse++;
-				arg.type = arg.type.semantic(loc, argsc);
+				fparam.type = fparam.type.semantic(loc, argsc);
 				if (tf.inuse == 1) tf.inuse--;
 
-				arg.type = arg.type.addStorageClass(arg.storageClass);
+				fparam.type = fparam.type.addStorageClass(fparam.storageClass);
 
-				if (arg.storageClass & (STC.STCauto | STC.STCalias | STC.STCstatic))
+				if (fparam.storageClass & (STC.STCauto | STC.STCalias | STC.STCstatic))
 				{
-					if (!arg.type)
+					if (!fparam.type)
 					continue;
 				}
 
-				Type t = arg.type.toBasetype();
+				Type t = fparam.type.toBasetype();
 
-				if (arg.storageClass & (STC.STCout | STC.STCref | STC.STClazy))
+				if (fparam.storageClass & (STC.STCout | STC.STCref | STC.STClazy))
 				{
 					//if (t.ty == TY.Tsarray)
 						//error(loc, "cannot have out or ref parameter of type %s", t.toChars());
-					if (arg.storageClass & STC.STCout && arg.type.mod & (STCconst | STCimmutable))
+					if (fparam.storageClass & STC.STCout && fparam.type.mod & (STCconst | STCimmutable))
 						error(loc, "cannot have const or immutabl out parameter of type %s", t.toChars());
 				}
-				if (!(arg.storageClass & STC.STClazy) && t.ty == TY.Tvoid)
-					error(loc, "cannot have parameter of type %s", arg.type.toChars());
+				if (!(fparam.storageClass & STC.STClazy) && t.ty == TY.Tvoid)
+					error(loc, "cannot have parameter of type %s", fparam.type.toChars());
 
-				if (arg.defaultArg)
-				{
-					arg.defaultArg = arg.defaultArg.semantic(argsc);
-					arg.defaultArg = resolveProperties(argsc, arg.defaultArg);
-					arg.defaultArg = arg.defaultArg.implicitCastTo(argsc, arg.type);
-				}
+	            if (t.isWild())
+	            {
+		            wildparams = true;
+		            if (tf.next && !wildreturn)
+		                error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with 'ref')");
+	            }
+	            else if (!wildsubparams && t.hasWild())
+		            wildsubparams = true;
 
-				/* If arg turns out to be a tuple, the number of parameters may
+	            if (fparam.defaultArg)
+	            {
+		            fparam.defaultArg = fparam.defaultArg.semantic(argsc);
+		            fparam.defaultArg = resolveProperties(argsc, fparam.defaultArg);
+		            fparam.defaultArg = fparam.defaultArg.implicitCastTo(argsc, fparam.type);
+	            }
+
+				/* If fparam turns out to be a tuple, the number of parameters may
 				 * change.
 				 */
 				if (t.ty == TY.Ttuple)
-				{	dim = Parameter.dim(tf.parameters);
+	            {
+		        // Propagate storage class from tuple parameters to their element-parameters.
+		            auto tt = cast(TypeTuple)t;
+		            if (tt.arguments)
+		            {
+		                auto tdim = tt.arguments.dim;
+		                foreach (narg; tt.arguments)
+		                {
+			                narg.storageClass = fparam.storageClass;
+		                }
+		            }
+
+		            /* Reset number of parameters, and back up one to do this fparam again,
+		             * now that it is the first element of a tuple
+		             */
+		            dim = Parameter.dim(tf.parameters);
 					i--;
+                    continue;
 				}
+
+	            /* Resolve "auto ref" storage class to be either ref or value,
+	             * based on the argument matching the parameter
+	             */
+	            if (fparam.storageClass & STC.STCauto)
+	            {
+		            if (fargs && i < fargs.dim)
+		            {
+                        auto farg = fargs[i];
+		                if (farg.isLvalue())
+                            {}				// ref parameter
+		                else
+			                fparam.storageClass &= ~STC.STCref;	// value parameter
+		            }
+		            else
+		                error(loc, "auto can only be used for template function parameters");
+	            }
 			}
 			argsc.pop();
 		}
+
+        if (wildreturn && !wildparams)
+	    error(loc, "inout on return means inout must be on a parameter as well for %s", toChars());
+        if (wildsubparams && wildparams)
+	    error(loc, "inout must be all or none on top level for %s", toChars());
+
 		if (tf.next)
 		tf.deco = tf.merge().deco;
 
@@ -287,14 +345,7 @@
 			return;
 		}
 		inuse++;
-static if (true) {
-		if (mod & MOD.MODshared)
-			buf.writeByte('O');
-		if (mod & MOD.MODconst)
-			buf.writeByte('x');
-		else if (mod & MOD.MODinvariant)
-			buf.writeByte('y');
-}
+        MODtoDecoBuffer(buf, mod);
 		switch (linkage)
 		{
 			case LINK.LINKd:		mc = 'F';	break;
@@ -320,7 +371,7 @@
 		            buf.writestring("Ne");
 		            break;
 	            case TRUST.TRUSTsafe:
-		            buf.writestring("Nd");
+		            buf.writestring("Nf");
 		            break;
                 default:
 	        }
@@ -348,12 +399,11 @@
 
 		/* Use 'storage class' style for attributes
 		 */
-		if (mod & MODconst)
-			buf.writestring("const ");
-		if (mod & MODinvariant)
-			buf.writestring("immutable ");
-		if (mod & MODshared)
-			buf.writestring("shared ");
+	    if (mod)
+        {
+	        MODtoBuffer(buf, mod);
+	        buf.writeByte(' ');
+        }
 
 		if (ispure)
 			buf.writestring("pure ");
@@ -569,16 +619,15 @@
 	
     override Type reliesOnTident()
 	{
-		if (parameters)
-		{
-			foreach (arg; parameters)
-			{   
-				Type t = arg.type.reliesOnTident();
-				if (t)
-					return t;
-			}
-		}
-		return next.reliesOnTident();
+        size_t dim = Parameter.dim(parameters);
+        for (size_t i = 0; i < dim; i++)
+        {
+            auto fparam = Parameter.getNth(parameters, i);
+	        Type t = fparam.type.reliesOnTident();
+	        if (t)
+	            return t;
+        }
+        return next ? next.reliesOnTident() : null;
 	}
 
 version (CPP_MANGLE) {
@@ -631,6 +680,8 @@
 	{
 		//printf("TypeFunction.callMatch() %s\n", toChars());
 		MATCH match = MATCH.MATCHexact;		// assume exact match
+        bool exactwildmatch = false;
+        bool wildmatch = false;
 
 		if (ethis)
 		{
@@ -640,7 +691,7 @@
 
 			if (t.mod != mod)
 			{
-				if (mod == MOD.MODconst)
+				if (MODimplicitConv(t.mod, mod))
 					match = MATCH.MATCHconst;
 				else
 					return MATCH.MATCHnomatch;
@@ -690,7 +741,7 @@
 			
 			if (p.storageClass & STCref)
 			{
-				/* Don't allow static arrays to be passed to mutable refereces
+				/* Don't allow static arrays to be passed to mutable references
 				 * to static arrays if the argument cannot be modified.
 				 */
 				Type targb = arg.type.toBasetype();
@@ -698,15 +749,36 @@
 				//writef("%s\n", targb.toChars());
 				//writef("%s\n", tparb.toChars());
 				if (targb.nextOf() && tparb.ty == Tsarray &&
-				    targb.nextOf().mod != tparb.nextOf().mod &&
-				    !tparb.nextOf().isConst())
+				   !MODimplicitConv(targb.nextOf().mod, tparb.nextOf().mod))
 					goto Nomatch;
 			}
 
 			if (p.storageClass & STC.STClazy && p.type.ty == TY.Tvoid && arg.type.ty != TY.Tvoid)
 				m = MATCH.MATCHconvert;
 			else
+            {
 				m = arg.implicitConvTo(p.type);
+	            if (p.type.isWild())
+	            {
+		            if (m == MATCHnomatch)
+		            {
+		                m = arg.implicitConvTo(p.type.constOf());
+		                if (m == MATCHnomatch)
+			            m = arg.implicitConvTo(p.type.sharedConstOf());
+		                if (m != MATCHnomatch)
+			            wildmatch = true;	// mod matched to wild
+		            }
+		            else
+		                exactwildmatch = true;	// wild matched to wild
+
+		            /* If both are allowed, then there could be more than one
+		             * binding of mod to wild, leaving a gaping type hole.
+		             */
+		            if (wildmatch && exactwildmatch)
+		                m = MATCHnomatch;
+	            }
+	        }
+
 			//printf("\tm = %d\n", m);
 			if (m == MATCH.MATCHnomatch)			// if no match
 			{
--- a/dmd/TypeInfoStructDeclaration.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeInfoStructDeclaration.d	Mon Sep 13 23:29:00 2010 +0200
@@ -99,7 +99,7 @@
 		TypeFunction tfeqptr;
 		{	
 			// bool opEqual(const T*) const;
-			scope Scope sc = new Scope();
+			scope sc = new Scope();
 			auto arguments = new Parameters;
 		version (STRUCTTHISREF) {
 			// arg type is ref const T
@@ -116,7 +116,7 @@
         }
 
         {
-	        Scope sc;
+	        scope sc = new Scope;
 	        auto arguments = new Parameters;
 version(STRUCTTHISREF) {
 	        // arg type is ref const T
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInfoWildDeclaration.d	Mon Sep 13 23:29:00 2010 +0200
@@ -0,0 +1,29 @@
+module dmd.TypeInfoWildDeclaration;
+
+import dmd.TY;
+import dmd.Type;
+import dmd.TypeInfoDeclaration;
+
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+
+class TypeInfoWildDeclaration : TypeInfoDeclaration
+{
+    this(Type tinfo)
+    {
+        super(tinfo, 0);
+        type = Type.typeinfowild.type;
+    }
+
+    override void toDt(dt_t **pdt)
+    {
+        //printf("TypeInfoWildDeclaration::toDt() %s\n", toChars());
+        dtxoff(pdt, Type.typeinfowild.toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Wild
+        dtdword(pdt, 0);			    // monitor
+        Type tm = tinfo.mutableOf();
+        tm = tm.merge();
+        tm.getTypeInfo(null);
+        dtxoff(pdt, tm.vtinfo.toSymbol(), 0, TYnptr);
+    }
+};
--- a/dmd/TypeNext.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeNext.d	Mon Sep 13 23:29:00 2010 +0200
@@ -53,6 +53,35 @@
 		return next.reliesOnTident();
 	}
 	
+    override int hasWild()
+    {
+        return mod == MOD.MODwild || next.hasWild();
+    }
+
+    /***************************************
+     * Return MOD bits matching argument type (targ) to wild parameter type (this).
+     */
+
+    override uint wildMatch(Type targ)
+    {
+        uint mod;
+
+        Type tb = targ.nextOf();
+        if (!tb)
+	        return 0;
+        tb = tb.toBasetype();
+        if (tb.isMutable())
+	        mod = MOD.MODmutable;
+        else if (tb.isConst() || tb.isWild())
+	        return MOD.MODconst;
+        else if (tb.isImmutable())
+	        mod = MOD.MODimmutable;
+        else
+	        assert(0);
+        mod |= next.wildMatch(tb);
+        return mod;
+    }
+    
     override Type nextOf()
 	{
 		return next;
@@ -70,7 +99,7 @@
 		TypeNext t = cast(TypeNext)super.makeConst();
 		if (ty != TY.Tfunction && ty != TY.Tdelegate &&
 			(next.deco || next.ty == TY.Tfunction) &&
-			!next.isInvariant() && !next.isConst())
+			!next.isImmutable() && !next.isConst())
 		{
 			if (next.isShared())
 				t.next = next.sharedConstOf();
@@ -90,11 +119,11 @@
 		//printf("TypeNext::makeInvariant() %s\n", toChars());
 		if (ito)
 		{	
-			assert(ito.isInvariant());
+			assert(ito.isImmutable());
 			return ito;
 		}
 		TypeNext t = cast(TypeNext)Type.makeInvariant();
-		if (ty != TY.Tfunction && ty != TY.Tdelegate && (next.deco || next.ty == TY.Tfunction) && !next.isInvariant())
+		if (ty != TY.Tfunction && ty != TY.Tdelegate && (next.deco || next.ty == TY.Tfunction) && !next.isImmutable())
 		{	
 			t.next = next.invariantOf();
 		}
@@ -116,9 +145,9 @@
 		TypeNext t = cast(TypeNext)Type.makeShared();
 		if (ty != Tfunction && ty != Tdelegate &&
 			(next.deco || next.ty == Tfunction) &&
-			!next.isInvariant() && !next.isShared())
+			!next.isImmutable() && !next.isShared())
 		{
-			if (next.isConst())
+			if (next.isConst() || next.isWild())
 				t.next = next.sharedConstOf();
 			else
 				t.next = next.sharedOf();
@@ -142,7 +171,7 @@
 		TypeNext t = cast(TypeNext) Type.makeSharedConst();
 		if (ty != Tfunction && ty != Tdelegate &&
 		    (next.deco || next.ty == Tfunction) &&
-			!next.isInvariant() && !next.isSharedConst())
+			!next.isImmutable() && !next.isSharedConst())
 		{
 			t.next = next.sharedConstOf();
 		}
@@ -154,6 +183,73 @@
 		return t;
 	}
 	
+    override Type makeWild()
+    {
+        //printf("TypeNext::makeWild() %s\n", toChars());
+        if (wto)
+        {
+            assert(wto.mod == MODwild);
+	        return wto;
+        }    
+        auto t = cast(TypeNext)Type.makeWild();
+        if (ty != TY.Tfunction && ty != TY.Tdelegate &&
+	    (next.deco || next.ty == TY.Tfunction) &&
+            !next.isImmutable() && !next.isConst() && !next.isWild())
+        {
+	        if (next.isShared())
+	            t.next = next.sharedWildOf();
+	        else
+	            t.next = next.wildOf();
+        }
+        if (ty == TY.Taarray)
+        {
+    	    (cast(TypeAArray)t).impl = null;		// lazily recompute it
+        }
+        //printf("TypeNext::makeWild() returns %p, %s\n", t, t->toChars());
+        return t;
+    }
+
+    Type makeSharedWild()
+    {
+        //printf("TypeNext::makeSharedWild() %s\n", toChars());
+        if (swto)
+        {
+            assert(swto.isSharedWild());
+	        return swto;
+        }    
+        auto t = cast(TypeNext)Type.makeSharedWild();
+        if (ty != TY.Tfunction && ty != TY.Tdelegate &&
+	    (next.deco || next.ty == TY.Tfunction) &&
+            !next.isImmutable() && !next.isSharedConst())
+        {
+	        t.next = next.sharedWildOf();
+        }
+        if (ty == Taarray)
+        {
+	        (cast(TypeAArray)t).impl = null;		// lazily recompute it
+        }
+        //printf("TypeNext::makeSharedWild() returns %p, %s\n", t, t->toChars());
+        return t;
+    }
+
+    Type makeMutable()
+    {
+        //printf("TypeNext::makeMutable() %p, %s\n", this, toChars());
+        auto t = cast(TypeNext)Type.makeMutable();
+        if (ty != TY.Tfunction && ty != TY.Tdelegate &&
+	    (next.deco || next.ty == TY.Tfunction) &&
+            next.isWild())
+        {
+	        t.next = next.mutableOf();
+        }
+        if (ty == Taarray)
+        {
+	        (cast(TypeAArray)t).impl = null;		// lazily recompute it
+        }
+        //printf("TypeNext::makeMutable() returns %p, %s\n", t, t->toChars());
+        return t;
+    }
+    
 	override MATCH constConv(Type to)
 	{
 		MATCH m = Type.constConv(to);
--- a/dmd/TypePointer.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypePointer.d	Mon Sep 13 23:29:00 2010 +0200
@@ -108,7 +108,7 @@
 			TypePointer tp = cast(TypePointer)to;
 			assert(tp.next);
 
-			if (!(next.mod == tp.next.mod || tp.next.mod == MOD.MODconst))
+			if (!MODimplicitConv(next.mod, tp.next.mod))
 				return MATCH.MATCHnomatch;        // not const-compatible
 
 			/* Alloc conversion to void[]
@@ -145,9 +145,7 @@
 	version (LOGDEFAULTINIT) {
 		printf("TypePointer::defaultInit() '%s'\n", toChars());
 	}
-		Expression e = new NullExp(loc);
-		e.type = this;
-		return e;
+		return new NullExp(loc, this);
 	}
 	
     override bool isZeroInit(Loc loc)
--- a/dmd/TypeQualified.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeQualified.d	Mon Sep 13 23:29:00 2010 +0200
@@ -22,6 +22,7 @@
 import dmd.Dsymbol;
 import dmd.DYNCAST;
 import dmd.Expression;
+import dmd.FuncDeclaration;
 import dmd.Util;
 
 class TypeQualified : Type
@@ -100,6 +101,7 @@
     void resolveHelper(Loc loc, Scope sc, Dsymbol s, Dsymbol scopesym, Expression* pe, Type* pt, Dsymbol* ps)
 	{
 		VarDeclaration v;
+        FuncDeclaration fd;
 		EnumMember em;
 		TupleDeclaration td;
 		Expression e;
@@ -174,7 +176,7 @@
 						{
 							id = cast(Identifier)idents.data[i];
 							//printf("e: '%s', id: '%s', type = %p\n", e.toChars(), id.toChars(), e.type);
-							if (id == Id.offsetof)
+							if (id == Id.offsetof || !e.type)
 							{   e = new DotIdExp(e.loc, e, id);
 								e = e.semantic(sc);
 							}
@@ -195,32 +197,17 @@
 			v = s.isVarDeclaration();
 			if (v)
 			{
-///static if (false) {
-///				// It's not a type, it's an expression
-///				Expression *e = v.getConstInitializer();
-///				if (e)
-///				{
-///					*pe = e.copy();	// make copy so we can change loc
-///					(*pe).loc = loc;
-///				}
-///				else
-///}
-				{
-///static if (false) {
-///					WithScopeSymbol withsym;
-///					if (scopesym && (withsym = scopesym.isWithScopeSymbol()) !is null)
-///					{
-///						// Same as wthis.ident
-///						e = new VarExp(loc, withsym.withstate.wthis);
-///						e = new DotIdExp(loc, e, ident);
-///						//assert(0);	// BUG: should handle this
-///					}
-///					else
-///}
-						*pe = new VarExp(loc, v);
-				}
+				*pe = new VarExp(loc, v);
 				return;
 			}
+//#if 0
+//	fd = s->isFuncDeclaration();
+//	if (fd)
+//	{
+//	    *pe = new DsymbolExp(loc, fd, 1);
+//	    return;
+//	}
+//#endif
 			em = s.isEnumMember();
 			if (em)
 			{
--- a/dmd/TypeReference.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeReference.d	Mon Sep 13 23:29:00 2010 +0200
@@ -10,6 +10,7 @@
 import dmd.HdrGenState;
 import dmd.Expression;
 import dmd.Identifier;
+import dmd.NullExp;
 import dmd.CppMangleState;
 import dmd.TY;
 
@@ -56,7 +57,10 @@
 	
     override Expression defaultInit(Loc loc)
 	{
-		assert(false);
+version(LOGDEFAULTINIT) {
+    printf("TypeReference::defaultInit() '%s'\n", toChars());
+}
+		return new NullExp(loc, this);
 	}
 	
     override bool isZeroInit(Loc loc)
--- a/dmd/TypeSArray.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeSArray.d	Mon Sep 13 23:29:00 2010 +0200
@@ -367,7 +367,7 @@
 		{
 			TypePointer tp = cast(TypePointer)to;
 
-			if (next.mod != tp.next.mod && tp.next.mod != MODconst)
+			if (!MODimplicitConv(next.mod, tp.next.mod))
 				return MATCHnomatch;
 
 			if (tp.next.ty == Tvoid || next.constConv(tp.next) != MATCHnomatch)
@@ -381,11 +381,12 @@
 			int offset = 0;
 			TypeDArray ta = cast(TypeDArray)to;
 
-			if (next.mod != ta.next.mod && ta.next.mod != MODconst)
+			if (!MODimplicitConv(next.mod, ta.next.mod))
 				return MATCHnomatch;
 
 			if (next.equals(ta.next) ||
-				next.implicitConvTo(ta.next) >= MATCHconst ||
+//				next.implicitConvTo(ta.next) >= MATCHconst ||
+                next.constConv(ta.next) != MATCHnomatch ||
 				(ta.next.isBaseOf(next, &offset) && offset == 0) ||
 				ta.next.ty == Tvoid
 			)
--- a/dmd/TypeStruct.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeStruct.d	Mon Sep 13 23:29:00 2010 +0200
@@ -37,6 +37,7 @@
 import dmd.VarExp;
 import dmd.CommaExp;
 import dmd.ThisExp;
+import dmd.StructLiteralExp;
 import dmd.SymbolDeclaration;
 import dmd.TypeInfoDeclaration;
 import dmd.TypeInfoStructDeclaration;
@@ -377,18 +378,44 @@
 	
     override Expression defaultInit(Loc loc)
 	{
-		Symbol* s;
-		Declaration d;
-
 	version (LOGDEFAULTINIT) {
 		printf("TypeStruct::defaultInit() '%s'\n", toChars());
 	}
-		s = sym.toInitializer();
-		d = new SymbolDeclaration(sym.loc, s, sym);
+		Symbol *s = sym.toInitializer();
+		Declaration d = new SymbolDeclaration(sym.loc, s, sym);
 		assert(d);
 		d.type = this;
 		return new VarExp(sym.loc, d);
 	}
+    
+    /***************************************
+     * Use when we prefer the default initializer to be a literal,
+     * rather than a global immutable variable.
+     */
+    Expression defaultInitLiteral(Loc loc)
+    {
+	version (LOGDEFAULTINIT) {
+        printf("TypeStruct::defaultInitLiteral() '%s'\n", toChars());
+    }
+        auto structelems = new Expressions();
+        structelems.setDim(sym.fields.dim);
+        for (size_t j = 0; j < structelems.dim; j++)
+        {
+	        auto vd = cast(VarDeclaration)(sym.fields[j]);
+	        Expression e;
+	        if (vd.init)
+	            e = vd.init.toExpression();
+	        else
+	            e = vd.type.defaultInitLiteral();
+	        structelems[j] = e;
+        }
+        auto structinit = new StructLiteralExp(loc, cast(StructDeclaration)sym, structelems);
+        // Why doesn't the StructLiteralExp constructor do this, when
+        // sym->type != NULL ?
+        structinit.type = sym.type;
+        return structinit;
+    }
+
 	
     override bool isZeroInit(Loc loc)
 	{
@@ -403,7 +430,7 @@
 		for (size_t i = 0; i < sym.fields.dim; i++)
 		{   
 			VarDeclaration v = cast(VarDeclaration)sym.fields[i];
-			if (v.isConst() || v.isInvariant())
+			if (v.isConst() || v.isImmutable())
 				return false;
 		}
 		return true;
@@ -480,6 +507,7 @@
 	
     override bool hasPointers()
 	{
+        // Probably should cache this information in sym rather than recompute
 		StructDeclaration s = sym;
 
 		sym.size(Loc(0));		// give error for forward references
@@ -503,7 +531,7 @@
 			m = MATCHexact;		// exact match
 			if (mod != to.mod)
 			{
-				if (to.mod == MODconst)
+				if (MODimplicitConv(mod, to.mod))
 					m = MATCHconst;
 				else
 				{	/* Check all the fields. If they can all be converted,
@@ -547,7 +575,8 @@
 	{
 		if (equals(to))
 			return MATCHexact;
-		if (ty == to.ty && sym == (cast(TypeStruct)to).sym && to.mod == MODconst)
+		if (ty == to.ty && sym == (cast(TypeStruct)to).sym &&
+            MODimplicitConv(mod, to.mod))
 			return MATCHconst;
 		return MATCHnomatch;
 	}
--- a/dmd/TypeTuple.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeTuple.d	Mon Sep 13 23:29:00 2010 +0200
@@ -28,7 +28,7 @@
 		super(TY.Ttuple);
 		//printf("TypeTuple(this = %p)\n", this);
 		this.arguments = arguments;
-		//printf("TypeTuple() %s\n", toChars());
+		//printf("TypeTuple() %p, %s\n", this, toChars());
 		debug {
 			if (arguments)
 			{
@@ -68,6 +68,7 @@
 			}
 		}
 		this.arguments = arguments;
+        //printf("TypeTuple() %p, %s\n", this, toChars());
 	}
 
 	override Type syntaxCopy()
--- a/dmd/TypeTypedef.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeTypedef.d	Mon Sep 13 23:29:00 2010 +0200
@@ -213,9 +213,6 @@
 	
     override Expression defaultInit(Loc loc)
 	{
-		Expression e;
-		Type bt;
-
 	version (LOGDEFAULTINIT) {
 		printf("TypeTypedef::defaultInit() '%s'\n", toChars());
 	}
@@ -224,8 +221,8 @@
 			//sym->init->toExpression()->print();
 			return sym.init.toExpression();
 		}
-		bt = sym.basetype;
-		e = bt.defaultInit(loc);
+		Type bt = sym.basetype;
+		Expression e = bt.defaultInit(loc);
 		e.type = this;
 		while (bt.ty == Tsarray)
 		{	
@@ -299,6 +296,11 @@
 		return toBasetype().hasPointers();
 	}
 	
+    override int hasWild()
+    {
+        return mod & MOD.MODwild || toBasetype().hasWild();
+    }
+    
     override Type toHeadMutable()
 	{
 		assert(false);
--- a/dmd/TypedefDeclaration.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypedefDeclaration.d	Mon Sep 13 23:29:00 2010 +0200
@@ -71,6 +71,9 @@
 			sem = 1;
 			basetype = basetype.semantic(loc, sc);
 			sem = 2;
+version(DMDV2) {
+    	    type = type.addStorageClass(storage_class);
+}
 			type = type.semantic(loc, sc);
 			if (sc.parent.isFuncDeclaration() && init)
 				semantic2(sc);
--- a/dmd/TypeidExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeidExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -43,16 +43,19 @@
 		Expression e;
 
 	version (LOGSEMANTIC) {
-		printf("TypeidExp.semantic()\n");
+		printf("TypeidExp.semantic() %s\n", toChars());
 	}
 		Type ta = isType(obj);
 		Expression ea = isExpression(obj);
 		Dsymbol sa = isDsymbol(obj);
 
+        //printf("ta %p ea %p sa %p\n", ta, ea, sa);
+
 		if (ta)
 		{
 			ta.resolve(loc, sc, &ea, &ta, &sa);
 		}
+        
 		if (ea)
 		{
 			ea = ea.semantic(sc);
@@ -63,7 +66,9 @@
 		}
 
 		if (!ta)
-		{	error("no type for typeid(%s)", ea ? ea.toChars() : (sa ? sa.toChars() : ""));
+		{	
+        	//printf("ta %p ea %p sa %p\n", ta, ea, sa);
+            error("no type for typeid(%s)", ea ? ea.toChars() : (sa ? sa.toChars() : ""));
 			return new ErrorExp();
 		}
 
--- a/dmd/UshrExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/UshrExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -75,6 +75,12 @@
 
 	override elem* toElem(IRState* irs)
 	{
-		return toElemBin(irs, OPER.OPshr);
+		//return toElemBin(irs, OPER.OPshr);
+        elem *eleft = e1.toElem(irs);
+        eleft.Ety = touns(eleft.Ety);
+        elem *eright = e2.toElem(irs);
+        elem *e = el_bin(OPER.OPshr, type.totym(), eleft, eright);
+        el_setLoc(e, loc);
+        return e;
 	}
 }
\ No newline at end of file
--- a/dmd/Util.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Util.d	Mon Sep 13 23:29:00 2010 +0200
@@ -635,6 +635,8 @@
     precedence[TOK.TOKnew] = PREC.PREC_unary;
     precedence[TOK.TOKcast] = PREC.PREC_unary;
 
+    precedence[TOK.TOKpow] = PREC.PREC_pow;
+
     precedence[TOK.TOKmul] = PREC.PREC_mul;
     precedence[TOK.TOKdiv] = PREC.PREC_mul;
     precedence[TOK.TOKmod] = PREC.PREC_mul;
@@ -698,7 +700,7 @@
     precedence[TOK.TOKmulass] = PREC.PREC_assign;
     precedence[TOK.TOKdivass] = PREC.PREC_assign;
     precedence[TOK.TOKmodass] = PREC.PREC_assign;
-    //precedence[TOKpowass]   = PREC.PREC_assign;
+    precedence[TOK.TOKpowass]   = PREC.PREC_assign;
     precedence[TOK.TOKshlass] = PREC.PREC_assign;
     precedence[TOK.TOKshrass] = PREC.PREC_assign;
     precedence[TOK.TOKushrass] = PREC.PREC_assign;
--- a/dmd/VarDeclaration.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/VarDeclaration.d	Mon Sep 13 23:29:00 2010 +0200
@@ -343,10 +343,12 @@
 		if (type.isShared())
 			storage_class |= STC.STCshared;
 		}
-		else if (type.isInvariant())
+		else if (type.isImmutable())
 		storage_class |= STC.STCimmutable;
 		else if (type.isShared())
 		storage_class |= STC.STCshared;
+        else if (type.isWild())
+	    storage_class |= STC.STCwild;
 
 		if (isSynchronized())
 		{
@@ -422,6 +424,13 @@
 		{
 			error("only parameters or foreach declarations can be ref");
 		}
+
+        if ((storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest) ||
+	        isDataseg()) &&
+	        type.hasWild())
+        {
+	        error("only fields, parameters or stack based variables can be inout");
+        }
 }
 
 		if (type.isauto() && !noauto)
@@ -438,7 +447,7 @@
 			}
 		}
 
-		if ((isConst() || isInvariant()) && !init && !fd)
+		if ((isConst() || isImmutable()) && !init && !fd)
 		{
 			// Initialize by constructor only
 			storage_class |= STC.STCctorinit;
@@ -652,7 +661,7 @@
 			}
 		}
 		else if (storage_class & (STC.STCconst | STC.STCimmutable | STC.STCmanifest) ||
-			type.isConst() || type.isInvariant() ||
+			type.isConst() || type.isImmutable() ||
 			parent.isAggregateDeclaration())
 		{
 			/* Because we may need the results of a const declaration in a
@@ -795,7 +804,7 @@
 	{
 static if (false) {
 		printf("VarDeclaration.isDataseg(%p, '%s')\n", this, toChars());
-		printf("%x, %p, %p\n", storage_class & (STC.STCstatic | STC.STCconst), parent.isModule(), parent.isTemplateInstance());
+		printf("%llx, isModule: %p, isTemplateInstance: %p\n", storage_class & (STC.STCstatic | STC.STCconst), parent.isModule(), parent.isTemplateInstance());
 		printf("parent = '%s'\n", parent.toChars());
 }
 		if (storage_class & STC.STCmanifest)
@@ -830,6 +839,15 @@
 }
 	}
 	
+    /********************************************
+     * Can variable be read and written by CTFE?
+     */
+
+    int isCTFE()
+    {
+        return (storage_class & STCctfe) || !isDataseg();
+    }
+
     override bool hasPointers()
 	{
 		//printf("VarDeclaration.hasPointers() %s, ty = %d\n", toChars(), type.ty);
@@ -844,7 +862,7 @@
 		 *	const int x = 3;
 		 * are not stored and hence cannot have their address taken.
 		 */
-		if ((isConst() || isInvariant()) && (storage_class & STC.STCinit) && (!(storage_class & (STC.STCstatic | STC.STCextern)) || (storage_class & STC.STCfield)) &&
+		if ((isConst() || isImmutable()) && (storage_class & STC.STCinit) && (!(storage_class & (STC.STCstatic | STC.STCextern)) || (storage_class & STC.STCfield)) &&
 			(!parent || toParent().isModule() || toParent().isTemplateInstance()) && type.toBasetype().isTypeBasic())
 		{
 			return false;
@@ -992,7 +1010,7 @@
 	 */
     Expression getConstInitializer()
 	{
-		if ((isConst() || isInvariant() || storage_class & STC.STCmanifest) && storage_class & STC.STCinit)
+		if ((isConst() || isImmutable() || storage_class & STC.STCmanifest) && storage_class & STC.STCinit)
 		{
 			ExpInitializer ei = getExpInitializer();
 			if (ei)
--- a/dmd/VarExp.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/VarExp.d	Mon Sep 13 23:29:00 2010 +0200
@@ -70,7 +70,7 @@
 		if (v)
 		{
 static if (false) {
-			if ((v.isConst() || v.isInvariant()) && type.toBasetype().ty != TY.Tsarray && v.init)
+			if ((v.isConst() || v.isImmutable()) && type.toBasetype().ty != TY.Tsarray && v.init)
 			{
 				ExpInitializer ei = v.init.isExpInitializer();
 				if (ei)
@@ -121,12 +121,12 @@
 				 * If it is pure, it cannot access any mutable variables other
 				 * than those inside itself
 				 */
-				if (hasPureParent && v.isDataseg() && !v.isInvariant())
+				if (hasPureParent && v.isDataseg() && !v.isImmutable())
 				{
 					error("pure function '%s' cannot access mutable static data '%s'",
 						sc.func.toChars(), v.toChars());
 				}
-				else if (sc.func.isPure() && sc.parent != v.parent && !v.isInvariant() && !(v.storage_class & STC.STCmanifest))
+				else if (sc.func.isPure() && sc.parent != v.parent && !v.isImmutable() && !(v.storage_class & STC.STCmanifest))
 				{
 					error("pure nested function '%s' cannot access mutable data '%s'", sc.func.toChars(), v.toChars());
 					if (v.isEnumDeclaration())
@@ -142,7 +142,7 @@
 	} else {
 			if (sc.func && sc.func.isPure() && !sc.intypeof)
 			{
-				if (v.isDataseg() && !v.isInvariant())
+				if (v.isDataseg() && !v.isImmutable())
 					error("pure function '%s' cannot access mutable static data '%s'", sc.func.toChars(), v.toChars());
 			}
 	}
@@ -207,6 +207,16 @@
 			}
 		}
 	}
+    
+    override void checkEscapeRef()
+    {
+        VarDeclaration v = var.isVarDeclaration();
+        if (v)
+        {
+	    if (!v.isDataseg() && !(v.storage_class & (STCref | STCout)))
+	        error("escaping reference to local variable %s", v.toChars());
+        }
+    }
 
 version (DMDV2)
 {
--- a/dmd/WhileStatement.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/WhileStatement.d	Mon Sep 13 23:29:00 2010 +0200
@@ -68,7 +68,11 @@
 	
     override Expression interpret(InterState istate)
 	{
-		assert(false);
+version(LOG) {
+       printf("WhileStatement::interpret()\n");
+}
+        assert(false);			// rewritten to ForStatement
+        return null;
 	}
 	
     override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
--- a/dmd/backend/iasm.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/backend/iasm.d	Mon Sep 13 23:29:00 2010 +0200
@@ -4340,7 +4340,7 @@
 		}
 		if ((v.isConst()
 ///version (DMDV2) {
-			|| v.isInvariant() || v.storage_class & STCmanifest
+			|| v.isImmutable() || v.storage_class & STCmanifest
 ///}
 			) && !v.type.isfloating() && v.init)
 		{   
--- a/dmd/codegen/Util.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/codegen/Util.d	Mon Sep 13 23:29:00 2010 +0200
@@ -297,9 +297,15 @@
 			e = el_una(op,tyret,ep);
     }
     else if (ep)
-		e = el_bin((tf.ispure && tf.isnothrow) ? OPER.OPcallns : OPER.OPcall, tyret, ec, ep);
+	    /* Do not do "no side effect" calls if a hidden parameter is passed,
+	     * as the return value is stored through the hidden parameter, which
+	     * is a side effect.
+	     */
+		e = el_bin((tf.ispure && tf.isnothrow && (retmethod != RET.RETstack)) ?
+		            OPcallns : OPcall, tyret, ec, ep);
     else
-		e = el_una((tf.ispure && tf.isnothrow) ? OPER.OPucallns : OPER.OPucall, tyret, ec);
+		e = el_una((tf.ispure && tf.isnothrow && (retmethod != RET.RETstack)) ?
+		            OPucallns : OPucall, tyret, ec);
 
     if (retmethod == RET.RETstack)
     {
--- a/dmd/expression/Util.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/expression/Util.d	Mon Sep 13 23:29:00 2010 +0200
@@ -594,12 +594,12 @@
  *	3. do default promotions on arguments corresponding to ...
  *	4. add hidden _arguments[] argument
  *	5. call copy constructor for struct value arguments
+ * Returns:
+ *	return type from function
  */
 
-void functionParameters(Loc loc, Scope sc, TypeFunction tf, Expressions arguments)
+Type functionParameters(Loc loc, Scope sc, TypeFunction tf, Expressions arguments)
 {
-	uint n;
-
     //printf("functionParameters()\n");
     assert(arguments);
     size_t nargs = arguments ? arguments.dim : 0;
@@ -608,8 +608,10 @@
     if (nargs > nparams && tf.varargs == 0)
 	error(loc, "expected %zu arguments, not %zu for non-variadic function type %s", nparams, nargs, tf.toChars());
 
-    n = (nargs > nparams) ? nargs : nparams;	// n = max(nargs, nparams)
+    uint n = (nargs > nparams) ? nargs : nparams;	// n = max(nargs, nparams)
 
+    uint wildmatch = 0;
+    
     int done = 0;
     for (size_t i = 0; i < n; i++)
     {
@@ -634,7 +636,7 @@
 						goto L2;
 
 					error(loc, "expected %d function arguments, not %d", nparams, nargs);
-					return;
+					return tf.next;
 				}
 				arg = p.defaultArg;
 				arg = arg.copy();
@@ -654,7 +656,7 @@
 					if (nargs != nparams)
 					{
 						error(loc, "expected %zu function arguments, not %zu", nparams, nargs);
-						return;
+						return tf.next;
 					}
 					goto L1;
 				}
@@ -680,6 +682,7 @@
 						Type t = new TypeSArray((cast(TypeArray)tb).next, new IntegerExp(nargs - i));
 						t = t.semantic(loc, sc);
 						VarDeclaration v = new VarDeclaration(loc, t, id, new VoidInitializer(loc));
+			            v.storage_class |= STCctfe;
 						v.semantic(sc);
 						v.parent = sc.parent;
 						//sc.insert(v);
@@ -729,7 +732,7 @@
 						if (!arg)
 						{   
 							error(loc, "not enough arguments");
-							return;
+							return tf.next;
 						}
 						break;
 				}
@@ -748,7 +751,25 @@
 					//printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars());
 					if (arg.op == TOKtype)
 						arg.error("cannot pass type %s as function argument", arg.toChars());
-					arg = arg.implicitCastTo(sc, p.type);
+		            if (p.type.isWild() && tf.next.isWild())
+		            {	
+                        Type t = p.type;
+			            MATCH m = arg.implicitConvTo(t);
+			            if (m == MATCH.MATCHnomatch)
+			            {
+                            t = t.constOf();
+			                m = arg.implicitConvTo(t);
+			                if (m == MATCHnomatch)
+			                {
+                                t = t.sharedConstOf();
+				                m = arg.implicitConvTo(t);
+			                }
+			                wildmatch |= p.type.wildMatch(arg.type);
+			            }
+			            arg = arg.implicitCastTo(sc, t);
+		            }
+		            else
+    					arg = arg.implicitCastTo(sc, p.type);
 					arg = arg.optimize(WANT.WANTvalue);
 				}
 			}
@@ -848,14 +869,9 @@
 				TypeSArray ts = cast(TypeSArray)tb;
 				Type ta = ts.next.arrayOf();
 				if (ts.size(arg.loc) == 0)
-				{   
-					arg = new NullExp(arg.loc);
-					arg.type = ta;
-				}
+					arg = new NullExp(arg.loc, ta);
 				else
-				{
 					arg = arg.castTo(sc, ta);
-				}
 			}
 version (DMDV2) {
 			if (tb.ty == Tstruct)
@@ -893,6 +909,24 @@
 		auto e = createTypeInfoArray(sc, &arguments[nparams], arguments.dim - nparams);
 		arguments.insert(0, e);
     }
+    
+    Type tret = tf.next;
+    if (wildmatch)
+    {	/* Adjust function return type based on wildmatch
+	 */
+	    //printf("wildmatch = x%x\n", wildmatch);
+	    assert(tret.isWild());
+	    if (wildmatch & MOD.MODconst || wildmatch & (wildmatch - 1))
+	        tret = tret.constOf();
+	    else if (wildmatch & MOD.MODimmutable)
+	        tret = tret.invariantOf();
+	    else
+	    {
+            assert(wildmatch & MOD.MODmutable);
+	        tret = tret.mutableOf();
+	    }
+    }
+    return tret;
 }
 
 /******************************
@@ -1256,7 +1290,7 @@
     if (!v)
 		return e;
 
-    if (v.isConst() || v.isInvariant() || v.storage_class & STC.STCmanifest)
+    if (v.isConst() || v.isImmutable() || v.storage_class & STC.STCmanifest)
     {
 		if (!v.type)
 		{
@@ -1403,6 +1437,7 @@
 			break;
     }
 
+    Dsymbol s;
     AggregateDeclaration ad;
 
     auto arg = arguments[0];
@@ -1449,6 +1484,10 @@
 			goto Laggr;
 
 		Laggr:
+	        s = search_function(ad, (op == TOKforeach_reverse) ? Id.applyReverse : Id.apply);
+	        if (s)
+		        goto Lapply;			// prefer opApply
+
 			if (arguments.dim == 1)
 			{
 				if (!arg.type)
@@ -1456,11 +1495,11 @@
 					/* Look for a head() or rear() overload
 					 */
 					Identifier id = (op == TOK.TOKforeach) ? Id.Fhead : Id.Ftoe;
-					Dsymbol s = search_function(ad, id);
-					FuncDeclaration fd = s ? s.isFuncDeclaration() : null;
+					Dsymbol s1 = search_function(ad, id);
+					FuncDeclaration fd = s1 ? s1.isFuncDeclaration() : null;
 					if (!fd)
 					{	
-						if (s && s.isTemplateDeclaration())
+						if (s1 && s1.isTemplateDeclaration())
 							break;
 						goto Lapply;
 					}
@@ -1474,7 +1513,6 @@
 			 *	int opApply(int delegate(ref Type [, ...]) dg);
 			 * overload
 			 */
-			Dsymbol s = search_function(ad, (op == TOK.TOKforeach_reverse) ? Id.applyReverse : Id.apply);
 			if (s)
 			{
 				FuncDeclaration fd = s.isFuncDeclaration();
--- a/dmd/interpret/Util.d	Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/interpret/Util.d	Mon Sep 13 23:29:00 2010 +0200
@@ -140,7 +140,7 @@
 	if (v)
 	{
 ///version (DMDV2) {
-		if ((v.isConst() || v.isInvariant() || v.storage_class & STCmanifest) && v.init && !v.value)
+		if ((v.isConst() || v.isImmutable() || v.storage_class & STCmanifest) && v.init && !v.value)
 ///} else {
 ///	if (v.isConst() && v.init)
 ///}
@@ -152,7 +152,7 @@
 		else
 		{   
 			e = v.value;
-			if (v.isDataseg())
+			if (v.isCTFE())
 			{	
 				error(loc, "static variable %s cannot be read at compile time", v.toChars());
 				e = EXP_CANT_INTERPRET;
@@ -232,24 +232,6 @@
 
 
 /********************************
- * Necessary because defaultInit() for a struct is a VarExp, not a StructLiteralExp.
- */
-StructLiteralExp createDefaultInitStructLiteral(Loc loc, StructDeclaration sym)
-{
-	Expressions structelems = new Expressions();
-	structelems.setDim(sym.fields.dim);
-	for (size_t j = 0; j < structelems.dim; j++)
-	{
-		structelems[j] = sym.fields[j].type.defaultInit(Loc(0));
-	}
-	StructLiteralExp structinit = new StructLiteralExp(loc, sym, structelems);
-	// Why doesn't the StructLiteralExp constructor do this, when
-	// sym.type != null ?
-	structinit.type = sym.type;
-	return structinit;
-}
-
-/********************************
  *  Add v to the istate list, unless it already exists there.
  */
 void addVarToInterstate(InterState istate, VarDeclaration v)