Index: src/GenPoly/InstantiateGeneric.cc
===================================================================
--- src/GenPoly/InstantiateGeneric.cc	(revision 875a72fc63ec1c00f94434e8e20f18e17cd51d0c)
+++ src/GenPoly/InstantiateGeneric.cc	(revision 35bae5268c7dcbf1d3b046f227bc3ea92f379aef)
@@ -21,4 +21,5 @@
 #include <vector>                      // for vector
 
+#include "CodeGen/OperatorTable.h"
 #include "Common/PassVisitor.h"        // for PassVisitor, WithDeclsToAdd
 #include "Common/ScopedMap.h"          // for ScopedMap
@@ -27,4 +28,5 @@
 #include "Common/utility.h"            // for deleteAll, cloneAll
 #include "GenPoly.h"                   // for isPolyType, typesPolyCompatible
+#include "InitTweak/InitTweak.h"
 #include "ResolvExpr/typeops.h"
 #include "ScopedSet.h"                 // for ScopedSet, ScopedSet<>::iterator
@@ -154,9 +156,14 @@
 
 	/// Add cast to dtype-static member expressions so that type information is not lost in GenericInstantiator
-	struct FixDtypeStatic final {
+	struct FixDtypeStatic final : public WithGuards, public WithVisitorRef<FixDtypeStatic>, public WithShortCircuiting, public WithStmtsToAdd {
 		Expression * postmutate( MemberExpr * memberExpr );
+
+		void premutate( ApplicationExpr * appExpr );
+		void premutate( AddressExpr * addrExpr );
 
 		template<typename AggrInst>
 		Expression * fixMemberExpr( AggrInst * inst, MemberExpr * memberExpr );
+
+		bool isLvalueArg = false;
 	};
 
@@ -210,5 +217,5 @@
 		PassVisitor<GenericInstantiator> instantiator;
 
-		// mutateAll( translationUnit, fixer );
+		mutateAll( translationUnit, fixer );
 		mutateAll( translationUnit, instantiator );
 	}
@@ -501,6 +508,28 @@
 		if ( isDtypeStatic( baseParams ) ) {
 			if ( ! ResolvExpr::typesCompatible( memberExpr->result, memberExpr->member->get_type(), SymTab::Indexer() ) ) {
-				// type of member and type of expression differ, so add cast to actual type
-				return new CastExpr( memberExpr, memberExpr->result->clone() );
+				// type of member and type of expression differ
+				Type * concType = memberExpr->result->clone();
+				if ( isLvalueArg ) {
+					// result must be C lvalue, so make a new reference variable with the correct actual type to replace the member expression
+					//   forall(dtype T)
+					//   struct Ptr {
+					//     T * x
+					//   };
+					//   Ptr(int) p;
+					//   int i;
+					//   p.x = &i;
+					// becomes
+					//   int *& _dtype_static_member_0 = (int **)&p.x;
+					//   _dtype_static_member_0 = &i;
+					// Note: this currently creates more temporaries than is strictly necessary, since it does not check for duplicate uses of the same member expression.
+					static UniqueName tmpNamer( "_dtype_static_member_" );
+					Expression * init = new CastExpr( new AddressExpr( memberExpr ), new PointerType( Type::Qualifiers(), concType->clone() ) );
+					ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), new ReferenceType( Type::Qualifiers(), concType ), new SingleInit( init ) );
+					stmtsToAddBefore.push_back( new DeclStmt( noLabels, tmp ) );
+					return new VariableExpr( tmp );
+				} else {
+					// can simply add a cast to actual type
+					return new CastExpr( memberExpr, concType );
+				}
 			}
 		}
@@ -520,4 +549,27 @@
 	}
 
+	void FixDtypeStatic::premutate( ApplicationExpr * appExpr ) {
+		GuardValue( isLvalueArg );
+		isLvalueArg = false;
+		DeclarationWithType * function = InitTweak::getFunction( appExpr );
+		if ( function->linkage == LinkageSpec::Intrinsic && CodeGen::isAssignment( function->name ) ) {
+			// explicitly visit children because only the first argument must be a C lvalue.
+			visit_children = false;
+			appExpr->env = maybeMutate( appExpr->env, *visitor );
+			appExpr->result = maybeMutate( appExpr->result, *visitor );
+			appExpr->function = maybeMutate( appExpr->function, *visitor );
+			isLvalueArg = true;
+			for ( Expression * arg : appExpr->args ) {
+				arg = maybeMutate( arg, *visitor );
+				isLvalueArg = false;
+			}
+		}
+	}
+
+	void FixDtypeStatic::premutate( AddressExpr * ) {
+		// argument of & must be C lvalue
+		GuardValue( isLvalueArg );
+		isLvalueArg = true;
+	}
 } // namespace GenPoly
 
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 875a72fc63ec1c00f94434e8e20f18e17cd51d0c)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 35bae5268c7dcbf1d3b046f227bc3ea92f379aef)
@@ -897,5 +897,5 @@
 		// sum cost and accumulate actuals
 		std::list<Expression*>& args = appExpr->get_args();
-		Cost cost = Cost::zero;
+		Cost cost = func.cost;
 		const ArgPack* pack = &result;
 		while ( pack->expr ) {
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision 875a72fc63ec1c00f94434e8e20f18e17cd51d0c)
+++ src/SynTree/Expression.cc	(revision 35bae5268c7dcbf1d3b046f227bc3ea92f379aef)
@@ -356,6 +356,7 @@
 	Type * res = member->get_type()->clone();
 	sub.apply( res );
-	set_result( res );
-	get_result()->set_lvalue( true );
+	result = res;
+	result->set_lvalue( true );
+	result->get_qualifiers() |= aggregate->result->get_qualifiers();
 }
 
