Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision 933667da0b0b2c10e059816d1a2fa308a10dcc14)
+++ src/GenPoly/Box.cc	(revision 11947341ab0cf19717b538b36ae3ec940382743f)
@@ -24,4 +24,5 @@
 #include "PolyMutator.h"
 #include "FindFunction.h"
+#include "ScopedMap.h"
 #include "ScrubTyVars.h"
 
@@ -83,4 +84,5 @@
 			void boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
 			void addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars );
+			/// Stores assignment operators from assertion list in local map of assignment operations
 			void findAssignOps( const std::list< TypeDecl *> &forall );
 			void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars );
@@ -91,4 +93,5 @@
 			typedef std::map< std::string, DeclarationWithType *> AdapterMap;
 			std::map< std::string, DeclarationWithType *> assignOps;
+			ScopedMap< std::string, DeclarationWithType *> scopedAssignOps;
 			std::stack< AdapterMap > adapters;
 			DeclarationWithType *retval;
@@ -192,17 +195,14 @@
 		}
 
-		// returns true if the given declaration is: (*?=?)(T *, T) for some T (return not checked, but maybe should be)
-		bool checkAssignment( DeclarationWithType *decl, std::string &name ) {
+		/// returns T if the given declaration is: (*?=?)(T *, T) for some T (return not checked, but maybe should be), NULL otherwise
+		ReferenceToType *isAssignment( DeclarationWithType *decl ) {
 			if ( decl->get_name() == "?=?" ) {
-				if ( PointerType *ptrType = dynamic_cast< PointerType *>( decl->get_type() ) ) {
-					if ( FunctionType *funType = dynamic_cast< FunctionType *>( ptrType->get_base() ) ) {
-						if ( funType->get_parameters().size() == 2 ) {
-							if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {
-								if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {
-									if ( TypeInstType *typeInst2 = dynamic_cast< TypeInstType *>( funType->get_parameters().back()->get_type() ) ) {
-										if ( typeInst->get_name() == typeInst2->get_name() ) {
-											name = typeInst->get_name();
-											return true;
-										} // if
+				if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
+					if ( funType->get_parameters().size() == 2 ) {
+						if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {
+							if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( pointer->get_base() ) ) {
+								if ( ReferenceToType *refType2 = dynamic_cast< ReferenceToType *>( funType->get_parameters().back()->get_type() ) ) {
+									if ( refType->get_name() == refType2->get_name() ) {
+										return refType;
 									} // if
 								} // if
@@ -212,5 +212,5 @@
 				} // if
 			} // if
-			return false;
+			return 0;
 		}
 
@@ -221,6 +221,6 @@
 				for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
 					std::string typeName;
-					if ( checkAssignment( *assert, typeName ) ) {
-						assignOps[ typeName ] = *assert;
+					if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( isAssignment( *assert ) ) ) {
+						assignOps[ typeInst->get_name() ] = *assert;
 					} // if
 				} // for
@@ -229,4 +229,11 @@
 
 		DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
+			// if this is a polymorphic assignment function, put it in the map for this scope
+			if ( ReferenceToType *refType = isAssignment( functionDecl ) ) {
+				if ( ! dynamic_cast< TypeInstType* >( refType ) ) {
+					scopedAssignOps.insert( refType->get_name(), functionDecl );
+				}
+			}
+			
 			if ( functionDecl->get_statements() ) {		// empty routine body ?
 				doBeginScope();
@@ -908,11 +915,25 @@
 					delete castExpr;
 				} //while
-				TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() );
-				assert( typeInst );
-				std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
-				if ( assignIter == assignOps.end() ) {
-					throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
-				} // if
-				ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) );
+
+				// find assignment operator for (polymorphic) return type
+				DeclarationWithType *assignDecl = 0;
+				if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) {
+					std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
+					if ( assignIter == assignOps.end() ) {
+						throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
+					} // if
+					assignDecl = assignIter->second;
+				} else if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( retval->get_type() ) ) {
+					ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = scopedAssignOps.find( refType->get_name() );
+					if ( assignIter == scopedAssignOps.end() ) {
+						throw SemanticError( "Attempt to return dtype or ftype generic object in ", returnStmt->get_expr() );
+					}
+					assignDecl = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0,
+												 new PointerType( Type::Qualifiers(), assignIter->second->get_type()->clone() ), 0 );
+				}
+				assert( assignDecl );
+
+				// replace return statement with appropriate assignment to out parameter
+				ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignDecl ) );
 				Expression *retParm = new NameExpr( retval->get_name() );
 				retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) );
@@ -955,8 +976,10 @@
 			// push a copy of the current map
 			adapters.push(adapters.top());
+			scopedAssignOps.beginScope();
 		}
 
 		void Pass1::doEndScope() {
 			adapters.pop();
+			scopedAssignOps.endScope();
 		}
 
