Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision 2a4b0884c14643e09650daaeb3a6667b5bff6b48)
+++ src/GenPoly/Box.cc	(revision b10c9959109272e0304123be8aaefa37571499cf)
@@ -989,4 +989,13 @@
 		}
 
+		/// Wraps a function declaration in a new pointer-to-function variable expression
+		VariableExpr *wrapFunctionDecl( DeclarationWithType *functionDecl ) {
+			// line below cloned from FixFunction.cc
+			ObjectDecl *functionObj = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0,
+			                                          new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );
+			functionObj->set_mangleName( functionDecl->get_mangleName() );
+			return new VariableExpr( functionObj );
+		}
+		
 		Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
 			if ( retval && returnStmt->get_expr() ) {
@@ -1004,26 +1013,66 @@
 
 				// find assignment operator for (polymorphic) return type
-				DeclarationWithType *assignDecl = 0;
+				ApplicationExpr *assignExpr = 0;
 				if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) {
+					// find assignment operator for type variable
 					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;
+					assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) );
 				} else if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( retval->get_type() ) ) {
+					// find assignment operator for generic 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() );
 					}
+
+					// wrap it up in an application expression
 					DeclarationWithType *functionDecl = assignIter->second;
-					// line below cloned from FixFunction.cc
-					assignDecl = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0,
-					                             new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );
-					assignDecl->set_mangleName( functionDecl->get_mangleName() );
+					assignExpr = new ApplicationExpr( wrapFunctionDecl( functionDecl ) );
+					assignExpr->set_env( env->clone() );
+
+					// find each of its needed secondary assignment operators
+					std::list< Expression* > &tyParams = refType->get_parameters();
+					std::list< TypeDecl* > &forallParams = functionDecl->get_type()->get_forall();
+					std::list< Expression* >::const_iterator tyIt = tyParams.begin();
+					std::list< TypeDecl* >::const_iterator forallIt = forallParams.begin();
+					for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) {
+						if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue; // skip types with no assign op (ftype/dtype)
+
+						std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions();
+						assert( ! asserts.empty() && "Type param needs assignment operator assertion" );
+						DeclarationWithType *actualDecl = asserts.front();
+						ReferenceToType *actualType = isAssignment( actualDecl );
+						assert( actualType && "First assertion of type with assertions should be assignment operator" );
+						TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt );
+						assert( formalTypeExpr && "type parameters must be type expressions" );
+						Type *formalType = formalTypeExpr->get_type();
+						assignExpr->get_env()->add( actualType->get_name(), formalType );
+						
+						DeclarationWithType *assertAssign = 0;
+						if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) {
+							std::map< std::string, DeclarationWithType *>::const_iterator assertAssignIt = assignOps.find( formalTypeInstType->get_name() );
+							if ( assertAssignIt == assignOps.end() ) {
+								throw SemanticError( "No assignment operation found for ", formalTypeInstType );
+							}
+							assertAssign = assertAssignIt->second;
+							//assignExpr->get_env()->add( formalTypeInstType->get_name(), actualType );
+						} else if ( ReferenceToType *formalReferenceType = dynamic_cast< ReferenceToType* >( formalType ) )  {
+							ScopedMap< std::string, DeclarationWithType *>::const_iterator assertAssignIt = scopedAssignOps.find( formalReferenceType->get_name() );
+							if ( assertAssignIt == scopedAssignOps.end() ) {
+								throw SemanticError( "No assignment operation found for ", formalReferenceType );
+							}
+							assertAssign = assertAssignIt->second;
+						} else assert( false && "returning polymorphic types with non struct/polymorphic parameters not yet supported" );
+						
+
+						assignExpr->get_inferParams()[ actualDecl->get_uniqueId() ]
+							= ParamEntry( assertAssign->get_uniqueId(), assertAssign->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertAssign ) );
+					}
 				}
-				assert( assignDecl );
+				assert( assignExpr );
 
 				// 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() ) );
