Index: src/Validate/Autogen.cpp
===================================================================
--- src/Validate/Autogen.cpp	(revision fb4dc2836f4baf232dfe867576343c1133659525)
+++ src/Validate/Autogen.cpp	(revision 28f8f154b94c0b9fd3ef74a8d0de01187a5522c6)
@@ -125,4 +125,6 @@
 	// Built-ins do not use autogeneration.
 	bool shouldAutogen() const final { return !decl->linkage.is_builtin && !structHasFlexibleArray(decl); }
+	void genADTFuncs();
+	void getADTFuncBody(const ast::ObjectDecl * lhs, ast::FunctionDecl * func);
 private:
 	void genFuncBody( ast::FunctionDecl * decl ) final;
@@ -193,5 +195,5 @@
 	}
 
-	bool shouldAutogen() const final { return true; }
+	bool shouldAutogen() const final { return !(decl->isData); }
 private:
 	void genFuncBody( ast::FunctionDecl * decl ) final;
@@ -238,11 +240,4 @@
 	if ( !enumDecl->body ) return;
 
-	// if ( auto enumBaseType = enumDecl->base ) {
-	// 	if ( auto enumBaseTypeAsStructInst = dynamic_cast<const ast::StructInstType *>(enumBaseType.get()) ) {
-	// 		const ast::StructDecl * structDecl = enumBaseTypeAsStructInst->base.get();
-	// 		this->previsit( structDecl );
-	// 	}
-	// }
-
 	ast::EnumInstType enumInst( enumDecl->name );
 	enumInst.base = enumDecl;
@@ -264,4 +259,6 @@
 	}
 	StructFuncGenerator gen( structDecl, &structInst, functionNesting );
+
+	gen.genADTFuncs();
 	gen.generateAndAppendFunctions( declsToAddAfter );
 }
@@ -475,4 +472,92 @@
 		}
 		produceDecl( decl );
+	}
+}
+
+void StructFuncGenerator::getADTFuncBody(
+		const ast::ObjectDecl * lhs,
+	 	ast::FunctionDecl * func
+	) {
+	const CodeLocation& location = func->location;
+	assert( decl->members.size() == 2 );
+	auto first = (decl->members[0]).as<ast::ObjectDecl>();
+	assert(first != nullptr);
+	auto firstType = first->type;
+	auto unionInstDecl = firstType.as<ast::UnionInstType>();
+	assert(unionInstDecl != nullptr);
+
+	auto unionDecl = unionInstDecl->base;
+	
+	const ast::ObjectDecl * dstParam =
+			func->params.front().strict_as<ast::ObjectDecl>();
+	const ast::ObjectDecl * srcParam = 
+			func->params.back().strict_as<ast::ObjectDecl>();
+	
+	ast::Expr * srcSelect = new ast::VariableExpr( location, srcParam );
+
+	ast::CompoundStmt * stmts = new ast::CompoundStmt( location );
+
+	InitTweak::InitExpander_new srcParamTweak( srcSelect );
+	ast::Expr * dstSelect = 
+	new ast::MemberExpr(
+		location,
+		lhs,
+		new ast::MemberExpr(
+			location,
+			first,
+			new ast::CastExpr(
+				location,
+				new ast::VariableExpr( location, dstParam ),
+				dstParam->type.strict_as<ast::ReferenceType>()->base
+			)
+		)
+	);
+	auto stmt = genImplicitCall(
+		srcParamTweak, dstSelect, location, func->name,
+		first, SymTab::LoopForward
+	);
+	stmts->push_back( stmt );
+	func->stmts = stmts;
+} 
+
+void StructFuncGenerator::genADTFuncs() {
+	if ( decl->kind != ast::AggregateDecl::ADT ) return;
+	assert( decl->members.size() == 2 );
+	auto first = (decl->members[0]).as<ast::ObjectDecl>();
+	assert(first != nullptr);
+	auto firstType = first->type;
+	auto unionInstDecl = firstType.as<ast::UnionInstType>();
+	assert(unionInstDecl != nullptr);
+	auto unionDecl = unionInstDecl->base;
+
+	// for (auto mem: unionDecl->members) {
+	for ( std::size_t i = 0; i < unionDecl->members.size(); ++i ) {
+		auto mem = unionDecl->members[i];
+		const ast::ObjectDecl * mem_as_obj = mem.as<ast::ObjectDecl>();
+		assert( mem_as_obj );
+		auto mem_type = mem_as_obj->type.as<ast::StructInstType>();
+		assert( mem_type );
+		auto location = getLocation();
+		ast::FunctionDecl * func = new ast::FunctionDecl(
+			getLocation(),
+			"?{}", // name
+			{}, //forall
+			{ dstParam(), new ast::ObjectDecl( getLocation(), "_src", ast::deepCopy( mem_type ) ) }, // params
+			{}, // returns
+			{}, // statements
+			// Use static storage if we are at the top level.
+			(0 < functionNesting) ? ast::Storage::Classes() : ast::Storage::Static,
+			proto_linkage,
+			std::vector<ast::ptr<ast::Attribute>>(),
+			// Auto-generated routines are inline to avoid conflicts.
+			ast::Function::Specs( ast::Function::Inline )
+		);
+		getADTFuncBody(mem_as_obj, func);
+		func->fixUniqueId();
+		produceForwardDecl(func);
+		if ( CodeGen::isAssignment( func->name ) ) {
+			appendReturnThis( func );
+		}
+		produceDecl( func );
 	}
 }
