Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 6fc5c14c6f831f36aaf4f6736da31f67985da917)
+++ src/InitTweak/FixInit.cc	(revision ae1b9eaca1bda2fba72d857681b6459557fd6784)
@@ -93,5 +93,5 @@
 			/// true if type does not need to be copy constructed to ensure correctness
 			bool skipCopyConstruct( Type * type );
-			void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr );
+			void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal );
 			void destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr );
 
@@ -260,4 +260,5 @@
 
 		GenStructMemberCalls::generate( translationUnit );
+
 		// xxx - ctor expansion currently has to be after FixCopyCtors, because there is currently a
 		// hack in the way untyped assignments are generated, where the first argument cannot have
@@ -384,15 +385,16 @@
 		}
 
-		void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ) {
+		void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal ) {
 			static UniqueName tempNamer("_tmp_cp");
 			assert( env );
 			CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *env << std::endl; )
 			assert( arg->result );
-			Type * result = arg->get_result();
+			Type * result = arg->result;
 			if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types
 
-			// type may involve type variables, so apply type substitution to get temporary variable's actual type
+			// type may involve type variables, so apply type substitution to get temporary variable's actual type.
+			// Use applyFree so that types bound in function pointers are not substituted, e.g. in forall(dtype T) void (*)(T).
 			result = result->clone();
-			env->apply( result );
+			env->applyFree( result );
 			ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr );
 			tmp->get_type()->set_const( false );
@@ -405,7 +407,10 @@
 				// if the chosen constructor is intrinsic, the copy is unnecessary, so
 				// don't create the temporary and don't call the copy constructor
-				VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
-				assert( function );
-				if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return;
+				VariableExpr * function = strict_dynamic_cast< VariableExpr * >( appExpr->function );
+				if ( function->var->linkage == LinkageSpec::Intrinsic ) {
+					// arguments that need to be boxed need a temporary regardless of whether the copy constructor is intrinsic,
+					// so that the object isn't changed inside of the polymorphic function
+					if ( ! GenPoly::needsBoxing( formal, result, impCpCtorExpr->callExpr, env ) ) return;
+				}
 			}
 
@@ -415,6 +420,6 @@
 			// replace argument to function call with temporary
 			arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
-			impCpCtorExpr->get_tempDecls().push_back( tmp );
-			impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
+			impCpCtorExpr->tempDecls.push_back( tmp );
+			impCpCtorExpr->dtors.push_front( makeCtorDtor( "^?{}", tmp ) );
 		}
 
@@ -426,9 +431,19 @@
 			CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
 
-			ApplicationExpr * appExpr = impCpCtorExpr->get_callExpr();
+			ApplicationExpr * appExpr = impCpCtorExpr->callExpr;
 
 			// take each argument and attempt to copy construct it.
-			for ( Expression * & arg : appExpr->get_args() ) {
-				copyConstructArg( arg, impCpCtorExpr );
+			FunctionType * ftype = GenPoly::getFunctionType( appExpr->function->result );
+			assert( ftype );
+			auto & params = ftype->parameters;
+			auto iter = params.begin();
+			for ( Expression * & arg : appExpr->args ) {
+				Type * formal = nullptr;
+				if ( iter != params.end() ) {
+					DeclarationWithType * param = *iter++;
+					formal = param->get_type();
+				}
+
+				copyConstructArg( arg, impCpCtorExpr, formal );
 			} // for
 
@@ -436,5 +451,5 @@
 			// initialized with the return value and is destructed later
 			// xxx - handle named return values?
-			Type * result = appExpr->get_result();
+			Type * result = appExpr->result;
 			if ( ! result->isVoid() ) {
 				static UniqueName retNamer("_tmp_cp_ret");
@@ -442,6 +457,6 @@
 				env->apply( result );
 				ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
-				ret->get_type()->set_const( false );
-				impCpCtorExpr->get_returnDecls().push_back( ret );
+				ret->type->set_const( false );
+				impCpCtorExpr->returnDecls.push_back( ret );
 				CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
 				if ( ! dynamic_cast< ReferenceType * >( result ) ) {
