Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 7528ba10cd66aa6353fc8a1b816f5aca7fdde207)
+++ src/SymTab/Validate.cc	(revision a172972bc130b439dace7f7225567fd6f27cab02)
@@ -396,5 +396,5 @@
 		// it's not a semantic error if the struct is not found, just an implicit forward declaration
 		if ( st ) {
-			assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() );
+			//assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() );
 			structInst->set_baseStruct( st );
 		} // if
@@ -673,4 +673,25 @@
 	}
 
+	/// Creates a new type decl that's the same as src, but renamed and with only the ?=? assertion (for complete types only)
+	TypeDecl *cloneAndRename( TypeDecl *src, const std::string &name ) {
+		TypeDecl *dst = new TypeDecl( name, src->get_storageClass(), 0, src->get_kind() );
+
+		if ( src->get_kind() == TypeDecl::Any ) {
+			// just include assignment operator assertion
+			TypeInstType *assignParamType = new TypeInstType( Type::Qualifiers(), name, dst );
+			FunctionType *assignFunctionType = new FunctionType( Type::Qualifiers(), false );
+			assignFunctionType->get_returnVals().push_back(
+				new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType->clone(), 0 ) );
+			assignFunctionType->get_parameters().push_back(
+				new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), assignParamType->clone() ), 0 ) );
+			assignFunctionType->get_parameters().push_back(
+				new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType, 0 ) );
+			FunctionDecl *assignAssert = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, assignFunctionType, 0, false, false );
+			dst->get_assertions().push_back( assignAssert );
+		}
+
+		return dst;
+	}
+
 	Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) {
 		FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
@@ -680,9 +701,12 @@
 		std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
 		std::list< Expression* > structParams;  // List of matching parameters to put on types
+		TypeSubstitution genericSubs; // Substitutions to make to member types of struct
 		for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
 			isGeneric = true;
-			TypeDecl *typeParam = (*param)->clone();
+			TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
 			assignType->get_forall().push_back( typeParam );
-			structParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
+			TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam );
+			genericSubs.add( (*param)->get_name(), newParamType );
+			structParams.push_back( new TypeExpr( newParamType ) );
 		}
 
@@ -715,10 +739,24 @@
 				}
 
-				if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
-					makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
-					if ( isGeneric ) makeArrayAssignment( srcParam, returnVal, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
+				if ( isGeneric ) {
+					// rewrite member type in terms of the type variables on this operator
+					DeclarationWithType *fixedMember = dwt->clone();
+					genericSubs.apply( fixedMember );
+
+					// assign to both destination and return value
+					if ( ArrayType *array = dynamic_cast< ArrayType * >( fixedMember->get_type() ) ) {
+						makeArrayAssignment( srcParam, dstParam, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
+						makeArrayAssignment( srcParam, returnVal, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
+					} else {
+						makeScalarAssignment( srcParam, dstParam, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
+						makeScalarAssignment( srcParam, returnVal, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
+					} // if
 				} else {
-					makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
-					if ( isGeneric ) makeScalarAssignment( srcParam, returnVal, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
+					// assign to destination
+					if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
+						makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
+					} else {
+						makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
+					} // if
 				} // if
 			} // if
@@ -799,5 +837,5 @@
 		for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
 			isGeneric = true;
-			TypeDecl *typeParam = (*param)->clone();
+			TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
 			assignType->get_forall().push_back( typeParam );
 			unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
