Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision d56c05d0943d88c5d163c26b5c1c91bfb8f39345)
+++ src/GenPoly/Box.cc	(revision c2ad3c956349ba6452ba15e9d447ad02aa3f922b)
@@ -197,5 +197,5 @@
 			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 findTypeOps( const std::list< TypeDecl *> &forall );
 			void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars );
 			FunctionDecl *makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars );
@@ -205,6 +205,12 @@
 			ObjectDecl *makeTemporary( Type *type );
 
-			ScopedMap< std::string, DeclarationWithType *> assignOps;    ///< Currently known type variable assignment operators
+			ScopedMap< std::string, DeclarationWithType* > assignOps;    ///< Currently known type variable assignment operators
+			ScopedMap< std::string, DeclarationWithType* > ctorOps;      ///< Currently known type variable constructors
+			ScopedMap< std::string, DeclarationWithType* > copyOps;      ///< Currently known type variable copy constructors
+			ScopedMap< std::string, DeclarationWithType* > dtorOps;      ///< Currently known type variable destructors
 			ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps;  ///< Currently known assignment operators
+			ResolvExpr::TypeMap< DeclarationWithType > scopedCtorOps;    ///< Currently known assignment operators
+			ResolvExpr::TypeMap< DeclarationWithType > scopedCopyOps;    ///< Currently known assignment operators
+			ResolvExpr::TypeMap< DeclarationWithType > scopedDtorOps;    ///< Currently known assignment operators
 			ScopedMap< std::string, DeclarationWithType* > adapters;     ///< Set of adapter functions in the current scope
 
@@ -600,15 +606,27 @@
 		Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) {}
 
-		/// Returns T if the given declaration is (*?=?)(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
-		TypeInstType *isTypeInstAssignment( DeclarationWithType *decl ) {
-			if ( decl->get_name() == "?=?" ) {
-				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 ( TypeInstType *refType = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {
-								if ( TypeInstType *refType2 = dynamic_cast< TypeInstType *>( funType->get_parameters().back()->get_type() ) ) {
-									if ( refType->get_name() == refType2->get_name() ) {
-										return refType;
-									} // if
+		/// Returns T if the given declaration is a function with parameter (T*) for some TypeInstType T, NULL otherwise
+		TypeInstType *isTypeInstPtrFn( DeclarationWithType *decl ) {
+			if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
+				if ( funType->get_parameters().size() == 1 ) {
+					if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {
+						if ( TypeInstType *refType = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {
+							return refType;
+						} // if
+					} // if
+				} // if
+			} // if
+			return 0;
+		}
+		
+		/// Returns T if the given declaration is a function with parameters (T*, T) for some TypeInstType T, NULL otherwise
+		TypeInstType *isTypeInstPtrValFn( DeclarationWithType *decl ) {
+			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 ( TypeInstType *refType = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {
+							if ( TypeInstType *refType2 = dynamic_cast< TypeInstType *>( funType->get_parameters().back()->get_type() ) ) {
+								if ( refType->get_name() == refType2->get_name() ) {
+									return refType;
 								} // if
 							} // if
@@ -619,24 +637,38 @@
 			return 0;
 		}
-
-		/// returns T if the given declaration is: (*?=?)(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise
-		/// Only picks assignments where neither parameter is cv-qualified
-		Type *isAssignment( DeclarationWithType *decl ) {
-			if ( decl->get_name() == "?=?" ) {
-				if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
-					if ( funType->get_parameters().size() == 2 ) {
-						Type::Qualifiers defaultQualifiers;
-						Type *paramType1 = funType->get_parameters().front()->get_type();
-						if ( paramType1->get_qualifiers() != defaultQualifiers ) return 0;
-						Type *paramType2 = funType->get_parameters().back()->get_type();
-						if ( paramType2->get_qualifiers() != defaultQualifiers ) return 0;
-
-						if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType1 ) ) {
-							Type *baseType1 = pointerType->get_base();
-							if ( baseType1->get_qualifiers() != defaultQualifiers ) return 0;
-							SymTab::Indexer dummy;
-							if ( ResolvExpr::typesCompatible( baseType1, paramType2, dummy ) ) {
-								return baseType1;
-							} // if
+		
+		/// Returns T if the given declaration is (*?=?)(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
+		TypeInstType *isTypeInstAssignment( DeclarationWithType *decl ) {
+			return decl->get_name() == "?=?" ? isTypeInstPtrValFn( decl ) : 0;
+		}
+
+		/// Returns T if the given declaration is (*?{})(T *) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
+		TypeInstType *isTypeInstCtor( DeclarationWithType *decl ) {
+			return decl->get_name() == "?{}" ? isTypeInstPtrFn( decl ) : 0;
+		}
+
+		/// Returns T if the given declaration is (*?{})(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
+		TypeInstType *isTypeInstCopy( DeclarationWithType *decl ) {
+			return decl->get_name() == "?{}" ? isTypeInstPtrValFn( decl ) : 0;
+		}
+
+		/// Returns T if the given declaration is (*^?{})(T *) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
+		TypeInstType *isTypeInstDtor( DeclarationWithType *decl ) {
+			return decl->get_name() == "^?{}" ? isTypeInstPtrFn( decl ) : 0;
+		}
+
+		/// Returns T if the given declaration is a function with parameters (T*, T) for some type T, where neither parameter is cv-qualified,
+		/// NULL otherwise
+		Type *isNoCvPtrFn( DeclarationWithType *decl ) {
+			if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
+				if ( funType->get_parameters().size() == 1 ) {
+					Type::Qualifiers defaultQualifiers;
+					Type *paramType = funType->get_parameters().front()->get_type();
+					if ( paramType->get_qualifiers() != defaultQualifiers ) return 0;
+
+					if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType ) ) {
+						Type *baseType = pointerType->get_base();
+						if ( baseType->get_qualifiers() == defaultQualifiers ) {
+							return baseType;
 						} // if
 					} // if
@@ -645,6 +677,54 @@
 			return 0;
 		}
-
-		void Pass1::findAssignOps( const std::list< TypeDecl *> &forall ) {
+		
+		/// Returns T if the given declaration is a function with parameters (T*, T) for some type T, where neither parameter is cv-qualified,
+		/// NULL otherwise
+		Type *isNoCvPtrValFn( DeclarationWithType *decl ) {
+			if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
+				if ( funType->get_parameters().size() == 2 ) {
+					Type::Qualifiers defaultQualifiers;
+					Type *paramType1 = funType->get_parameters().front()->get_type();
+					if ( paramType1->get_qualifiers() != defaultQualifiers ) return 0;
+					Type *paramType2 = funType->get_parameters().back()->get_type();
+					if ( paramType2->get_qualifiers() != defaultQualifiers ) return 0;
+
+					if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType1 ) ) {
+						Type *baseType1 = pointerType->get_base();
+						if ( baseType1->get_qualifiers() != defaultQualifiers ) return 0;
+						SymTab::Indexer dummy;
+						if ( ResolvExpr::typesCompatible( baseType1, paramType2, dummy ) ) {
+							return baseType1;
+						} // if
+					} // if
+				} // if
+			} // if
+			return 0;
+		}
+
+		/// returns T if the given declaration is: (*?=?)(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise
+		/// Only picks assignments where neither parameter is cv-qualified
+		Type *isAssignment( DeclarationWithType *decl ) {
+			return decl->get_name() == "?=?" ? isNoCvPtrValFn( decl ) : 0;
+		}
+
+		/// returns T if the given declaration is: (*?{})(T *) for some type T, NULL otherwise
+		/// Only picks ctors where the parameter is not cv-qualified
+		Type *isCtor( DeclarationWithType *decl ) {
+			return decl->get_name() == "?{}" ? isNoCvPtrFn( decl ) : 0;
+		}
+
+		/// returns T if the given declaration is: (*?{})(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise
+		/// Only picks copy constructors where neither parameter is cv-qualified
+		Type *isCopy( DeclarationWithType *decl ) {
+			return decl->get_name() == "?{}" ? isNoCvPtrValFn( decl ) : 0;
+		}
+
+		/// returns T if the given declaration is: (*?{})(T *) for some type T, NULL otherwise
+		/// Only picks ctors where the parameter is not cv-qualified
+		Type *isDtor( DeclarationWithType *decl ) {
+			return decl->get_name() == "^?{}" ? isNoCvPtrFn( decl ) : 0;
+		}
+
+		void Pass1::findTypeOps( const std::list< TypeDecl *> &forall ) {
 			// what if a nested function uses an assignment operator?
 			// assignOps.clear();
@@ -654,4 +734,10 @@
 					if ( TypeInstType *typeInst = isTypeInstAssignment( *assert ) ) {
 						assignOps[ typeInst->get_name() ] = *assert;
+					} else if ( TypeInstType *typeInst = isTypeInstCtor( *assert ) ) {
+						ctorOps[ typeInst->get_name() ] = *assert;
+					} else if ( TypeInstType *typeInst = isTypeInstCopy( *assert ) ) {
+						copyOps[ typeInst->get_name() ] = *assert;
+					} else if ( TypeInstType *typeInst = isTypeInstDtor( *assert ) ) {
+						dtorOps[ typeInst->get_name() ] = *assert;
 					} // if
 				} // for
@@ -661,7 +747,19 @@
 		DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
 			// if this is a assignment function, put it in the map for this scope
-			if ( Type *assignedType = isAssignment( functionDecl ) ) {
-				if ( ! dynamic_cast< TypeInstType* >( assignedType ) ) {
-					scopedAssignOps.insert( assignedType, functionDecl );
+			if ( Type *paramType = isAssignment( functionDecl ) ) {
+				if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {
+					scopedAssignOps.insert( paramType, functionDecl );
+				}
+			} else if ( Type *paramType = isCtor( functionDecl ) ) {
+				if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {
+					scopedCtorOps.insert( paramType, functionDecl );
+				}
+			} else if ( Type *paramType = isCopy( functionDecl ) ) {
+				if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {
+					scopedCopyOps.insert( paramType, functionDecl );
+				}
+			} else if ( Type *paramType = isDtor( functionDecl ) ) {
+				if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {
+					scopedDtorOps.insert( paramType, functionDecl );
 				}
 			}
@@ -671,4 +769,8 @@
 				scopeTyVars.beginScope();
 				assignOps.beginScope();
+				ctorOps.beginScope();
+				copyOps.beginScope();
+				dtorOps.beginScope();
+				
 				DeclarationWithType *oldRetval = retval;
 				bool oldUseRetval = useRetval;
@@ -688,5 +790,5 @@
 				FunctionType *functionType = functionDecl->get_functionType();
 				makeTyVarMap( functionDecl->get_functionType(), scopeTyVars );
-				findAssignOps( functionDecl->get_functionType()->get_forall() );
+				findTypeOps( functionDecl->get_functionType()->get_forall() );
 
 				std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
@@ -713,4 +815,7 @@
 				scopeTyVars.endScope();
 				assignOps.endScope();
+				ctorOps.endScope();
+				copyOps.endScope();
+				dtorOps.endScope();
 				retval = oldRetval;
 				useRetval = oldUseRetval;
@@ -1372,4 +1477,20 @@
 		}
 
+		/// Finds the operation declaration for a given type in one of the two maps
+		DeclarationWithType* findOpForType( Type *formalType, const ScopedMap< std::string, DeclarationWithType* >& ops, ResolvExpr::TypeMap< DeclarationWithType >& scopedOps ) {
+			if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) {
+				ScopedMap< std::string, DeclarationWithType *>::const_iterator opIt = ops.find( formalTypeInstType->get_name() );
+				return opIt == ops.end() ? 0 : opIt->second;
+			} else {
+				return scopedOps.find( formalType );
+			}
+		}
+
+		/// Adds an assertion parameter to the application expression for the actual assertion declaration valued with the assert op
+		void addAssertionFor( ApplicationExpr *appExpr, DeclarationWithType *actualDecl, DeclarationWithType *assertOp ) {
+			appExpr->get_inferParams()[ actualDecl->get_uniqueId() ]
+					= ParamEntry( assertOp->get_uniqueId(), assertOp->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertOp ) );
+		}
+		
 		Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
 			if ( retval && returnStmt->get_expr() ) {
@@ -1418,28 +1539,37 @@
 						assignExpr->get_env()->add( (*forallIt)->get_name(), formalType );
 
-						// skip types with no assign op (ftype/dtype)
+						// skip non-otype parameters (ftype/dtype)
 						if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue;
 
-						// find assignment operator for formal type
-						DeclarationWithType *assertAssign = 0;
-						if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) {
-							ScopedMap< 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;
-						} else {
-							assertAssign = scopedAssignOps.find( formalType );
-							if ( ! assertAssign ) {
-								throw SemanticError( "No assignment operation found for ", formalType );
-							}
-						}
-
-						// add inferred parameter for field assignment operator to assignment expression
+						// find otype operators for formal type
+						DeclarationWithType *assertAssign = findOpForType( formalType, assignOps, scopedAssignOps );
+						if ( ! assertAssign ) throw SemanticError( "No assignment operation found for ", formalType );
+
+						DeclarationWithType *assertCtor = findOpForType( formalType, ctorOps, scopedCtorOps );
+						if ( ! assertCtor ) throw SemanticError( "No default constructor found for ", formalType );
+
+						DeclarationWithType *assertCopy = findOpForType( formalType, copyOps, scopedCopyOps );
+						if ( ! assertCopy ) throw SemanticError( "No copy constructor found for ", formalType );
+
+						DeclarationWithType *assertDtor = findOpForType( formalType, dtorOps, scopedDtorOps );
+						if ( ! assertDtor ) throw SemanticError( "No destructor found for ", formalType );
+						
+						// add inferred parameters for otype operators to assignment expression
+						// NOTE: Code here assumes that first four assertions are assign op, ctor, copy ctor, dtor, in that order
 						std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions();
-						assert( ! asserts.empty() && "Type param needs assignment operator assertion" );
-						DeclarationWithType *actualDecl = asserts.front();
-						assignExpr->get_inferParams()[ actualDecl->get_uniqueId() ]
-							= ParamEntry( assertAssign->get_uniqueId(), assertAssign->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertAssign ) );
+						assert( asserts.size() >= 4 && "Type param needs otype operator assertions" );
+
+						std::list< DeclarationWithType* >::iterator actualIt = asserts.begin();
+						addAssertionFor( assignExpr, *actualIt, assertAssign );
+						++actualIt;
+						addAssertionFor( assignExpr, *actualIt, assertCtor );
+						++actualIt;
+						addAssertionFor( assignExpr, *actualIt, assertCopy );
+						++actualIt;
+						addAssertionFor( assignExpr, *actualIt, assertDtor );
+						
+						//DeclarationWithType *actualDecl = asserts.front();
+						//assignExpr->get_inferParams()[ actualDecl->get_uniqueId() ]
+						//	= ParamEntry( assertAssign->get_uniqueId(), assertAssign->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertAssign ) );
 					}
 				}
@@ -1487,4 +1617,7 @@
 			adapters.beginScope();
 			scopedAssignOps.beginScope();
+			scopedCtorOps.beginScope();
+			scopedCopyOps.beginScope();
+			scopedDtorOps.beginScope();
 		}
 
@@ -1492,4 +1625,7 @@
 			adapters.endScope();
 			scopedAssignOps.endScope();
+			scopedCtorOps.endScope();
+			scopedCopyOps.endScope();
+			scopedDtorOps.endScope();
 		}
 
@@ -2044,11 +2180,7 @@
 
 		bool PolyGenericCalculator::findGeneric( Type *ty ) {
+			ty = replaceTypeInst( ty, env );
+			
 			if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
-				// duplicate logic from isPolyType()
-				if ( env ) {
-					if ( Type *newType = env->lookup( typeInst->get_name() ) ) {
-						return findGeneric( newType );
-					} // if
-				} // if
 				if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) {
 					// NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
Index: src/GenPoly/GenPoly.cc
===================================================================
--- src/GenPoly/GenPoly.cc	(revision d56c05d0943d88c5d163c26b5c1c91bfb8f39345)
+++ src/GenPoly/GenPoly.cc	(revision c2ad3c956349ba6452ba15e9d447ad02aa3f922b)
@@ -64,14 +64,13 @@
 			return false;
 		}
-
-		/// Replaces a TypeInstType by its referrent in the environment, if applicable
-		Type* replaceTypeInst( Type* type, const TypeSubstitution* env ) {
-			if ( ! env ) return type;
-			if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
-				Type *newType = env->lookup( typeInst->get_name() );
-				if ( newType ) return newType;
-			}
-			return type;
-		}
+	}
+
+	Type* replaceTypeInst( Type* type, const TypeSubstitution* env ) {
+		if ( ! env ) return type;
+		if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
+			Type *newType = env->lookup( typeInst->get_name() );
+			if ( newType ) return newType;
+		}
+		return type;
 	}
 
Index: src/GenPoly/GenPoly.h
===================================================================
--- src/GenPoly/GenPoly.h	(revision d56c05d0943d88c5d163c26b5c1c91bfb8f39345)
+++ src/GenPoly/GenPoly.h	(revision c2ad3c956349ba6452ba15e9d447ad02aa3f922b)
@@ -39,4 +39,7 @@
 	ReferenceToType *isPolyRet( FunctionType *function );
 
+	/// Replaces a TypeInstType by its referrent in the environment, if applicable
+	Type* replaceTypeInst( Type* type, const TypeSubstitution* env );
+	
 	/// returns polymorphic type if is polymorphic type, NULL otherwise; will look up substitution in env if provided
 	Type *isPolyType( Type *type, const TypeSubstitution *env = 0 );
