Index: src/CodeTools/ResolvProtoDump.cc
===================================================================
--- src/CodeTools/ResolvProtoDump.cc	(revision c715e5ff6f93573553c28ad82808e7e566136c47)
+++ src/CodeTools/ResolvProtoDump.cc	(revision fc134a48a40512fa2957765975077ee1bb642ba2)
@@ -304,5 +304,8 @@
 
 			// replace enums with int
-			void previsit( EnumInstType* ) { ss << (int)BasicType::SignedInt; }
+			void previsit( EnumInstType* ) { 
+				// TODO: add the meaningful representation of typed int
+				ss << (int)BasicType::SignedInt; 
+			}
 
 			void previsit( TypeInstType* vt ) {
Index: src/Common/ResolvProtoDump.cpp
===================================================================
--- src/Common/ResolvProtoDump.cpp	(revision c715e5ff6f93573553c28ad82808e7e566136c47)
+++ src/Common/ResolvProtoDump.cpp	(revision fc134a48a40512fa2957765975077ee1bb642ba2)
@@ -227,5 +227,6 @@
 	}
 
-	void previsit( const ast::EnumInstType * ) {
+	void previsit( const ast::EnumInstType * enumInst) {
+		// TODO: Add the meaningful text representation of typed enum
 		ss << (int)ast::BasicType::SignedInt;
 	}
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision c715e5ff6f93573553c28ad82808e7e566136c47)
+++ src/InitTweak/GenInit.cc	(revision fc134a48a40512fa2957765975077ee1bb642ba2)
@@ -368,5 +368,5 @@
 
 	struct ReturnFixer_New final :
-			public ast::WithStmtsToAdd<>, ast::WithGuards {
+			public ast::WithStmtsToAdd<>, ast::WithGuards, ast::WithShortCircuiting {
 		void previsit( const ast::FunctionDecl * decl );
 		const ast::ReturnStmt * previsit( const ast::ReturnStmt * stmt );
@@ -376,4 +376,5 @@
 
 	void ReturnFixer_New::previsit( const ast::FunctionDecl * decl ) {
+		if (decl->linkage == ast::Linkage::Intrinsic) visit_children = false;
 		GuardValue( funcDecl ) = decl;
 	}
Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision c715e5ff6f93573553c28ad82808e7e566136c47)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision fc134a48a40512fa2957765975077ee1bb642ba2)
@@ -899,4 +899,14 @@
 
 						if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer);
+						else if (const ast::EnumInstType * enumInst = argType.as<ast::EnumInstType>()) {
+							const ast::EnumDecl * enumDecl = enumInst->base;
+							if ( const ast::Type* enumType = enumDecl->base ) {
+								// instance of enum (T) is a instance of type (T) 
+								funcFinder.otypeKeys.insert(Mangle::mangle(enumType, Mangle::NoGenericParams | Mangle::Type));
+							} else {
+								// instance of an untyped enum is techically int
+								funcFinder.otypeKeys.insert(Mangle::mangle(enumDecl, Mangle::NoGenericParams | Mangle::Type));
+							}
+						} 
 						else funcFinder.otypeKeys.insert(Mangle::mangle(argType, Mangle::NoGenericParams | Mangle::Type));
 					}
@@ -918,5 +928,5 @@
 
 			// find function operators
-			ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" };
+			ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" }; // ??? why not ?{}
 			CandidateFinder opFinder( context, tenv );
 			// okay if there aren't any function operations
Index: src/ResolvExpr/CommonType.cc
===================================================================
--- src/ResolvExpr/CommonType.cc	(revision c715e5ff6f93573553c28ad82808e7e566136c47)
+++ src/ResolvExpr/CommonType.cc	(revision fc134a48a40512fa2957765975077ee1bb642ba2)
@@ -497,5 +497,5 @@
 				result = new BasicType( basicType->tq | otherBasic->tq, newType );
 			} // if
-		} else if ( dynamic_cast< EnumInstType * > ( type2 ) || dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) {
+		} else if (  dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) {
 			// use signed int in lieu of the enum/zero/one type
 			BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ BasicType::SignedInt ];
@@ -503,5 +503,15 @@
 				result = new BasicType( basicType->tq | type2->tq, newType );
 			} // if
-		} // if
+		} else if ( const EnumInstType * enumInst = dynamic_cast< const EnumInstType * > ( type2 ) ) {
+			const EnumDecl* enumDecl = enumInst->baseEnum;
+			if ( const Type* baseType = enumDecl->base ) {
+				result = baseType->clone();
+			} else {
+				BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ BasicType::SignedInt ];
+				if ( ( ( newType == basicType->get_kind() && basicType->tq >= type2->tq ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->tq <= type2->tq ) || widenSecond ) ) {
+					result = new BasicType( basicType->tq | type2->tq, newType );
+				} // if
+			}
+		}
 	}
 
@@ -691,6 +701,5 @@
 				}
 			} else if (
-				dynamic_cast< const ast::EnumInstType * >( type2 )
-				|| dynamic_cast< const ast::ZeroType * >( type2 )
+				dynamic_cast< const ast::ZeroType * >( type2 )
 				|| dynamic_cast< const ast::OneType * >( type2 )
 			) {
@@ -705,4 +714,20 @@
 					result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers };
 				}
+			} else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) {
+				#warning remove casts when `commonTypes` moved to new AST
+				const ast::EnumDecl* enumDecl = enumInst->base;
+				if ( enumDecl->base ) {
+					result = enumDecl->base.get();
+				} else {
+					ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)ast::BasicType::SignedInt ];
+					if (
+						( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers )
+							|| widen.first )
+						&& ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers )
+							|| widen.second )
+					) {
+						result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers };
+					}
+				}
 			}
 		}
@@ -723,4 +748,18 @@
 			result = voidPtr;
 			add_qualifiers( result, oPtr->qualifiers );
+		}
+
+		// For a typed enum, we want to unify type1 with the base type of the enum
+		bool tryResolveWithTypedEnum( const ast::Type * type1 ) {
+			if (auto enumInst = dynamic_cast<const ast::EnumInstType *> (type2) ) {
+				ast::AssertionSet have, need; // unused
+				ast::OpenVarSet newOpen{ open };
+				if (enumInst->base->base 
+				&& unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen, symtab)) {
+					result = type1;
+					return true;
+				}
+			}
+			return false;
 		}
 
@@ -768,8 +807,13 @@
 				result = pointer;
 				add_qualifiers( result, type2->qualifiers );
-			}
-		}
-
-		void postvisit( const ast::ArrayType * ) {}
+			} else {
+				tryResolveWithTypedEnum( pointer );
+			}
+		}
+
+		void postvisit( const ast::ArrayType * arr ) {
+			// xxx - does it make sense? 
+			tryResolveWithTypedEnum( arr );
+		}
 
 		void postvisit( const ast::ReferenceType * ref ) {
@@ -810,22 +854,28 @@
 				result = ref;
 				add_qualifiers( result, type2->qualifiers );
-			}
-		}
-
-		void postvisit( const ast::FunctionType * ) {}
-
-		void postvisit( const ast::StructInstType * ) {}
-
-		void postvisit( const ast::UnionInstType * ) {}
+			} else {
+				// xxx - does unifying a ref with typed enumInst makes sense?
+				if (!dynamic_cast<const ast::EnumInstType *>(type2))
+					result = commonType( type2, ref, widen, symtab, tenv, open );
+			}
+		}
+
+		void postvisit( const ast::FunctionType * func) {
+			tryResolveWithTypedEnum( func ); 
+		}
+
+		void postvisit( const ast::StructInstType * inst ) {
+			tryResolveWithTypedEnum( inst );
+		}
+
+		void postvisit( const ast::UnionInstType * inst ) {
+			tryResolveWithTypedEnum( inst );
+		}
 
 		void postvisit( const ast::EnumInstType * enumInst ) {
-			if (
-				dynamic_cast< const ast::BasicType * >( type2 )
-				|| dynamic_cast< const ast::ZeroType * >( type2 )
-				|| dynamic_cast< const ast::OneType * >( type2 )
-			) {
-				// reuse BasicType/EnumInstType common type by swapping
+			// reuse BasicType/EnumInstType common type by swapping
+			// xxx - is this already handled by unify?
+			if (!dynamic_cast<const ast::EnumInstType *>(type2))
 				result = commonType( type2, enumInst, widen, symtab, tenv, open );
-			}
 		}
 
@@ -850,4 +900,6 @@
 						result = type2;
 						reset_qualifiers( result, q1 | q2 );
+					} else {
+						tryResolveWithTypedEnum( t1 );
 					}
 				}
@@ -855,5 +907,7 @@
 		}
 
-		void postvisit( const ast::TupleType * ) {}
+		void postvisit( const ast::TupleType * tuple) {
+			tryResolveWithTypedEnum( tuple );
+		}
 
 		void postvisit( const ast::VarArgsType * ) {}
@@ -861,9 +915,6 @@
 		void postvisit( const ast::ZeroType * zero ) {
 			if ( ! widen.first ) return;
-			if (
-				dynamic_cast< const ast::BasicType * >( type2 )
-				|| dynamic_cast< const ast::PointerType * >( type2 )
-				|| dynamic_cast< const ast::EnumInstType * >( type2 )
-			) {
+			if ( dynamic_cast< const ast::BasicType * >( type2 )
+				|| dynamic_cast< const ast::PointerType * >( type2 ) ) {
 				if ( widen.second || zero->qualifiers <= type2->qualifiers ) {
 					result = type2;
@@ -873,4 +924,15 @@
 				result = new ast::BasicType{
 					ast::BasicType::SignedInt, zero->qualifiers | type2->qualifiers };
+			} else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) {
+				const ast::EnumDecl * enumDecl = enumInst->base;
+				if ( enumDecl->base ) {
+					if ( tryResolveWithTypedEnum( zero ) ) 
+						add_qualifiers( result, zero->qualifiers );
+				} else {
+					if ( widen.second || zero->qualifiers <= type2->qualifiers ) {
+						result = type2;
+						add_qualifiers( result, zero->qualifiers );
+					}
+				}
 			}
 		}
@@ -878,8 +940,5 @@
 		void postvisit( const ast::OneType * one ) {
 			if ( ! widen.first ) return;
-			if (
-				dynamic_cast< const ast::BasicType * >( type2 )
-				|| dynamic_cast< const ast::EnumInstType * >( type2 )
-			) {
+			if ( dynamic_cast< const ast::BasicType * >( type2 ) ) {
 				if ( widen.second || one->qualifiers <= type2->qualifiers ) {
 					result = type2;
@@ -889,4 +948,15 @@
 				result = new ast::BasicType{
 					ast::BasicType::SignedInt, one->qualifiers | type2->qualifiers };
+			} else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) {
+				const ast::EnumDecl * enumBase = enumInst->base;
+				if ( enumBase->base ) {
+					if ( tryResolveWithTypedEnum( one ))
+						add_qualifiers( result, one->qualifiers );
+				} else {
+					if ( widen.second || one->qualifiers <= type2->qualifiers ) {
+						result = type2;
+						add_qualifiers( result, one->qualifiers );
+					}
+				}
 			}
 		}
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision c715e5ff6f93573553c28ad82808e7e566136c47)
+++ src/ResolvExpr/ConversionCost.cc	(revision fc134a48a40512fa2957765975077ee1bb642ba2)
@@ -321,20 +321,27 @@
 	}
 
+	// refactor for code resue
+	void ConversionCost::conversionCostFromBasicToBasic(const BasicType * src, const BasicType * dest) {
+		int tableResult = costMatrix[ src->kind ][ dest->kind ];
+		if ( tableResult == -1 ) {
+			cost = Cost::unsafe;
+		} else {
+			cost = Cost::zero;
+			cost.incSafe( tableResult );
+			cost.incSign( signMatrix[ src->kind ][ dest->kind ] );
+		} // if
+	} // ConversionCost::conversionCostFromBasicToBasic
+
 	void ConversionCost::postvisit(const BasicType * basicType) {
 		if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
-			int tableResult = costMatrix[ basicType->kind ][ destAsBasic->kind ];
-			if ( tableResult == -1 ) {
-				cost = Cost::unsafe;
-			} else {
-				cost = Cost::zero;
-				cost.incSafe( tableResult );
-				cost.incSign( signMatrix[ basicType->kind ][ destAsBasic->kind ] );
-			} // if
-		} else if ( dynamic_cast< const EnumInstType * >( dest ) ) {
-			// xxx - not positive this is correct, but appears to allow casting int => enum
-			// TODO
-			EnumDecl * decl = dynamic_cast< const EnumInstType * >( dest )->baseEnum;
-			if ( decl->base ) {
-				cost = Cost::infinity;
+			conversionCostFromBasicToBasic(basicType, destAsBasic);
+		} else if ( const EnumInstType * enumInst = dynamic_cast< const EnumInstType * >( dest ) ) {
+			const EnumDecl * base_enum = enumInst->baseEnum;
+			if ( const Type * base = base_enum->base ) { // if the base enum has a base (if it is typed)
+				if ( const BasicType * enumBaseAstBasic = dynamic_cast< const BasicType *> (base) ) {
+					conversionCostFromBasicToBasic(basicType, enumBaseAstBasic);
+				} else {
+					cost = Cost::infinity;
+				} // if
 			} else {
 				cost = Cost::unsafe;
@@ -398,10 +405,15 @@
 	void ConversionCost::postvisit( const FunctionType * ) {}
 
-	void ConversionCost::postvisit( const EnumInstType * ) {
-		static Type::Qualifiers q;
-		static BasicType integer( q, BasicType::SignedInt );
-		cost = costFunc( &integer, dest, srcIsLvalue, indexer, env );  // safe if dest >= int
+	void ConversionCost::postvisit( const EnumInstType * enumInst) {
+		const EnumDecl * enumDecl = enumInst -> baseEnum;
+		if ( const Type * enumType = enumDecl -> base ) { // if it is a typed enum
+			cost = costFunc( enumType, dest, srcIsLvalue, indexer, env );
+		} else {
+			static Type::Qualifiers q;
+			static BasicType integer( q, BasicType::SignedInt );
+			cost = costFunc( &integer, dest, srcIsLvalue, indexer, env );  // safe if dest >= int
+		} // if
 		if ( cost < Cost::unsafe ) {
-			cost.incSafe();
+				cost.incSafe();
 		} // if
 	}
@@ -604,22 +616,29 @@
 }
 
+void ConversionCost_new::conversionCostFromBasicToBasic( const ast::BasicType * src, const ast::BasicType* dest ) {
+	int tableResult = costMatrix[ src->kind ][ dest->kind ];
+	if ( tableResult == -1 ) {
+		cost = Cost::unsafe;
+	} else {
+		cost = Cost::zero;
+		cost.incSafe( tableResult );
+		cost.incSign( signMatrix[ src->kind ][ dest->kind ] );
+	}
+}
+
 void ConversionCost_new::postvisit( const ast::BasicType * basicType ) {
 	if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
-		int tableResult = costMatrix[ basicType->kind ][ dstAsBasic->kind ];
-		if ( tableResult == -1 ) {
-			cost = Cost::unsafe;
-		} else {
-			cost = Cost::zero;
-			cost.incSafe( tableResult );
-			cost.incSign( signMatrix[ basicType->kind ][ dstAsBasic->kind ] );
-		}
-	} else if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) {
-		// xxx - not positive this is correct, but appears to allow casting int => enum
-		const ast::EnumDecl * decl = (dynamic_cast< const ast::EnumInstType * >( dst ))->base.get();
-		if ( decl->base ) {
-			cost = Cost::infinity;
-		} else {
-			cost = Cost::unsafe;
-		} // if
+		conversionCostFromBasicToBasic( basicType, dstAsBasic );
+	} else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
+		const ast::EnumDecl * enumDecl = enumInst->base.get();
+		if ( const ast::Type * enumType = enumDecl->base.get() ) {
+			if ( const ast::BasicType * enumTypeAsBasic = dynamic_cast<const ast::BasicType *>(enumType) ) {
+				conversionCostFromBasicToBasic( basicType, enumTypeAsBasic );
+			} else {
+				cost = Cost::infinity;
+			}
+		} else {
+            cost = Cost::unsafe;
+		}
 	}
 }
@@ -673,7 +692,12 @@
 
 void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
-	(void)enumInstType;
-	static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
-	cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
+	const ast::EnumDecl * baseEnum = enumInstType->base;
+	if ( const ast::Type * baseType = baseEnum->base ) {
+		cost = costCalc( baseType, dst, srcIsLvalue, symtab, env );
+	} else {
+		(void)enumInstType;
+		static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
+		cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
+	}
 	if ( cost < Cost::unsafe ) {
 		cost.incSafe();
Index: src/ResolvExpr/ConversionCost.h
===================================================================
--- src/ResolvExpr/ConversionCost.h	(revision c715e5ff6f93573553c28ad82808e7e566136c47)
+++ src/ResolvExpr/ConversionCost.h	(revision fc134a48a40512fa2957765975077ee1bb642ba2)
@@ -65,4 +65,7 @@
 		const TypeEnvironment &env;
 		CostFunction costFunc;
+	  private:
+	  	// refactor for code resue
+	  	void conversionCostFromBasicToBasic( const BasicType * src, const BasicType* dest );
 	};
 
@@ -111,4 +114,7 @@
 	void postvisit( const ast::ZeroType * zeroType );
 	void postvisit( const ast::OneType * oneType );
+private:
+	// refactor for code resue
+	void conversionCostFromBasicToBasic( const ast::BasicType * src, const ast::BasicType* dest );
 };
 
Index: src/Validate/Autogen.cpp
===================================================================
--- src/Validate/Autogen.cpp	(revision c715e5ff6f93573553c28ad82808e7e566136c47)
+++ src/Validate/Autogen.cpp	(revision fc134a48a40512fa2957765975077ee1bb642ba2)
@@ -402,4 +402,8 @@
 	auto retval = srcParam();
 	retval->name = "_ret";
+	// xxx - Adding this unused attribute can slience unused variable warning
+	// However, some code might not be compiled as expected
+	// Temporarily disabled
+	// retval->attributes.push_back(new ast::Attribute("unused"));
 	return genProto( "?=?", { dstParam(), srcParam() }, { retval } );
 }
