Index: doc/theses/jiada_liang_MMath/CFAenum.tex
===================================================================
--- doc/theses/jiada_liang_MMath/CFAenum.tex	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ doc/theses/jiada_liang_MMath/CFAenum.tex	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -70,18 +70,119 @@
 As in Section~\ref{s:EnumeratorUnscoping}, opening multiple scoped enumerations in a @with@ can result in duplicate enumeration names, but \CFA implicit type resolution and explicit qualification/casting handles ambiguities.
 
-
-\section{Enumeration Pseudo-functions}
-
-Pseudo-functions are function-like operators that do not result in any run-time computations, \ie like @sizeof@, @alignof@, @typeof@.
-A pseudo-function call is often substituted with information extracted from the compilation symbol-table, like storage size or alignment associated with the underlying architecture.
-
-The attributes of an enumerator are accessed by pseudo-functions @posE@, @valueE@, and @labelE@.
-\begin{cfa}
-int jane_pos = @posE@( Names.Jane );   $\C{// 2}$
-char * jane_value = @valueE@( Names.Jane ); $\C{// "JANE"}$
-char * jane_label = @labelE@( Names.Jane ); $\C{// "Jane"}$
-sout | posE( Names.Jane) | labelE( Names.Jane ) | valueE( Names.Jane );
-\end{cfa}
-Note the ability to print all of an enumerator's properties.
+\section{Enumeration Trait}
+
+The header file \lstinline[deletekeywords=enum]{<enum.hfa>} defines the set of traits containing operators and helper functions for @enum@.
+A \CFA enumeration satisfies all of these traits allowing it to interact with runtime features in \CFA.
+Each trait is discussed in detail.
+
+The trait @Bounded@:
+\begin{cfa}
+forall( E ) trait Bounded {
+	E first();
+	E last();
+};
+\end{cfa}
+defines the bounds of the enumeration, where @first()@ returns the first enumerator and @last()@ returns the last, \eg:
+\begin{cfa}
+Workday day = first();					$\C{// Mon}$
+Planet outermost = last();				$\C{// NEPTUNE}$
+\end{cfa}
+@first()@ and @last()@ are overloaded with return types only, so in the example, the enumeration type is found on the left-hand side of the assignment.
+Calling either functions without a context results in a type ambiguity, except in the rare case where the type environment has only one enumeration.
+\begin{cfa}
+@first();@								$\C{// ambiguous Workday and Planet implement Bounded}$
+sout | @last()@;
+Workday day = first();					$\C{// day provides type Workday}$
+void foo( Planet p );
+foo( last() );							$\C{// parameter provides type Planet}$
+\end{cfa}
+
+The trait @Serial@:
+\begin{cfa}
+forall( E | Bounded( E ) ) trait Serial {
+	unsigned fromInstance( E e );
+	E fromInt( unsigned int posn );
+	E succ( E e );
+	E pred( E e );
+};
+\end{cfa}
+is a @Bounded@ trait, where elements can be mapped to an integer sequence.
+A type @T@ matching @Serial@ can project to an unsigned @int@ type, \ie an instance of type T has a corresponding integer value.
+%However, the inverse may not be possible, and possible requires a bound check.
+The mapping from a serial type to integer is defined by @fromInstance@, which returns the enumerator's position.
+The inverse operation is @fromInt@, which performs a bound check using @first()@ and @last()@ before casting the integer into an enumerator.
+Specifically, for enumerator @E@ declaring $N$ enumerators, @fromInt( i )@ returns the $i-1_{th}$ enumerator, if $0 \leq i < N$, or raises the exception @enumBound@.
+
+The @Serial@ trait also requires interface functions @succ( E e )@ and @pred( E e )@ be implemented for a serial type, which imply the enumeration positions are consecutive and ordinal. 
+Specifically, if @e@ is the $i_{th}$ enumerator, @succ( e )@ returns the $i+1_{th}$ enumerator when $e \ne last()$, and @pred( e )@ returns the $i-1_{th}$ enumerator when $e \ne first()$. 
+The exception @enumRange@ is raised if the result of either operation is outside the range of type @E@.
+
+The trait @TypedEnum@:
+\begin{cfa}
+forall( E, T ) trait TypedEnum {
+	T valueE( E e );
+	char * labelE( E e );
+	unsigned int posE( E e );
+};
+\end{cfa}
+captures three basic attributes of an enumeration type: value, label, and position. 
+@TypedEnum@ asserts two types @E@ and @T@, with @T@ being the base type of the enumeration @E@, \eg @enum( T ) E { ... };@.
+Implementing general functions across all enumeration types is possible by asserting @TypeEnum( E, T )@, \eg:
+\begin{cfa}
+forall( E, T | TypeEnum( E, T ) )
+void printEnum( E e ) {
+	sout | "Enum "| labelE( e );
+}
+printEunm( MARS );
+\end{cfa}
+
+Finally, there is an associated trait defining comparison operators among enumerators. 
+\begin{cfa}
+forall( E, T | TypedEnum( E, T ) ) {
+	// comparison
+	int ?==?( E l, E r ); 		$\C{// true if l and r are same enumerators}$
+	int ?!=?( E l, E r ); 		$\C{// true if l and r are different enumerators}$
+	int ?!=?( E l, zero_t ); 	$\C{// true if l is not the first enumerator}$
+	int ?<?( E l, E r ); 		$\C{// true if l is an enumerator before r}$
+	int ?<=?( E l, E r ); 		$\C{// true if l before or the same as r}$
+	int ?>?( E l, E r ); 		$\C{// true if l is an enumerator after r}$
+	int ?>=?( E l, E r ); 		$\C{// true if l after or the same as r}$         
+}
+\end{cfa}
+Note, the overloaded operators are defined only when the header @<enum.hfa>@ is included.
+If not, the compiler converts an enumerator to its value, and applies the operators defined for the value type @E@, \eg:
+\begin{cfa}
+// if not include <enum.hfa>
+enum( int ) Fruits { APPLE = 2, BANANA = 10, CHERRY = 2 };
+APPLE == CHERRY; // true because valueE( APPLE ) == valueE( CHERRY )
+
+#include <enum.hfa>
+APPLE == CHERRY; // false because posE( APPLE ) != posE( CHERRY )
+\end{cfa}
+An enumerator returns its @position@ by default.
+In particular, @printf( ... )@ from @<stdio.h>@ functions provides no context to its parameter type, so it prints @position@. 
+On the other hand, the pipeline operator @?|?( ostream os, E enumType )@ provides type context for type @E@, and \CFA has overwritten this operator to print the enumeration @value@ over @position@.
+\begin{cfa}
+printf( "Position of BANANA is \%d", BANANA ); // Position of BANANA is 1
+sout | "Value of BANANA is " | BANANA; // Value of BANANA is 10
+\end{cfa}
+Programmers can overwrite this behaviour by overloading the pipeline operator themselves.
+\PAB{This needs discussing because including \lstinline{<enum.hfa>} can change the entire meaning of a program.}
+
+
+% \section{Enumeration Pseudo-functions}
+
+% Pseudo-functions are function-like operators that do not result in any run-time computations, \ie like @sizeof@, @alignof@, @typeof@.
+% A pseudo-function call is often substituted with information extracted from the compilation symbol-table, like storage size or alignment associated with the underlying architecture.
+
+% The attributes of an enumerator are accessed by pseudo-functions @posE@, @valueE@, and @labelE@.
+% \begin{cfa}
+% int jane_pos = @posE@( Names.Jane );   $\C{// 2}$
+% char * jane_value = @valueE@( Names.Jane ); $\C{// "JANE"}$
+% char * jane_label = @labelE@( Names.Jane ); $\C{// "Jane"}$
+% sout | posE( Names.Jane) | labelE( Names.Jane ) | valueE( Names.Jane );
+% \end{cfa}
+% Note the ability to print all of an enumerator's properties.
+
 
 
@@ -270,104 +371,15 @@
 
 
-\section{Enumeration Trait}
-
-The header file \lstinline[deletekeywords=enum]{<enum.hfa>} defines the set of traits containing operators and helper functions for @enum@.
-A \CFA enumeration satisfies all of these traits allowing it to interact with runtime features in \CFA.
-Each trait is discussed in detail.
-
-The trait @Bounded@:
-\begin{cfa}
-forall( E ) trait Bounded {
-	E first();
-	E last();
-};
-\end{cfa}
-defines the bounds of the enumeration, where @first()@ returns the first enumerator and @last()@ returns the last, \eg:
-\begin{cfa}
-Workday day = first();					$\C{// Mon}$
-Planet outermost = last();				$\C{// NEPTUNE}$
-\end{cfa}
-@first()@ and @last()@ are overloaded with return types only, so in the example, the enumeration type is found on the left-hand side of the assignment.
-Calling either functions without a context results in a type ambiguity, except in the rare case where the type environment has only one enumeration.
-\begin{cfa}
-@first();@								$\C{// ambiguous Workday and Planet implement Bounded}$
-sout | @last()@;
-Workday day = first();					$\C{// day provides type Workday}$
-void foo( Planet p );
-foo( last() );							$\C{// parameter provides type Planet}$
-\end{cfa}
-
-The trait @Serial@:
-\begin{cfa}
-forall( E | Bounded( E ) ) trait Serial {
-	unsigned fromInstance( E e );
-	E fromInt( unsigned int posn );
-	E succ( E e );
-	E pred( E e );
-};
-\end{cfa}
-is a @Bounded@ trait, where elements can be mapped to an integer sequence.
-A type @T@ matching @Serial@ can project to an unsigned @int@ type, \ie an instance of type T has a corresponding integer value.
-%However, the inverse may not be possible, and possible requires a bound check.
-The mapping from a serial type to integer is defined by @fromInstance@, which returns the enumerator's position.
-The inverse operation is @fromInt@, which performs a bound check using @first()@ and @last()@ before casting the integer into an enumerator.
-Specifically, for enumerator @E@ declaring $N$ enumerators, @fromInt( i )@ returns the $i-1_{th}$ enumerator, if $0 \leq i < N$, or raises the exception @enumBound@.
-
-The @Serial@ trait also requires interface functions @succ( E e )@ and @pred( E e )@ be implemented for a serial type, which imply the enumeration positions are consecutive and ordinal. 
-Specifically, if @e@ is the $i_{th}$ enumerator, @succ( e )@ returns the $i+1_{th}$ enumerator when $e \ne last()$, and @pred( e )@ returns the $i-1_{th}$ enumerator when $e \ne first()$. 
-The exception @enumRange@ is raised if the result of either operation is outside the range of type @E@.
-
-The trait @TypedEnum@:
-\begin{cfa}
-forall( E, T ) trait TypedEnum {
-	T valueE( E e );
-	char * labelE( E e );
-	unsigned int posE( E e );
-};
-\end{cfa}
-captures three basic attributes of an enumeration type: value, label, and position. 
-@TypedEnum@ asserts two types @E@ and @T@, with @T@ being the base type of the enumeration @E@, \eg @enum( T ) E { ... };@.
-Implementing general functions across all enumeration types is possible by asserting @TypeEnum( E, T )@, \eg:
-\begin{cfa}
-forall( E, T | TypeEnum( E, T ) )
-void printEnum( E e ) {
-	sout | "Enum "| labelE( e );
-}
-printEunm( MARS );
-\end{cfa}
-
-Finally, there is an associated trait defining comparison operators among enumerators. 
-\begin{cfa}
-forall( E, T | TypedEnum( E, T ) ) {
-	// comparison
-	int ?==?( E l, E r ); 		$\C{// true if l and r are same enumerators}$
-	int ?!=?( E l, E r ); 		$\C{// true if l and r are different enumerators}$
-	int ?!=?( E l, zero_t ); 	$\C{// true if l is not the first enumerator}$
-	int ?<?( E l, E r ); 		$\C{// true if l is an enumerator before r}$
-	int ?<=?( E l, E r ); 		$\C{// true if l before or the same as r}$
-	int ?>?( E l, E r ); 		$\C{// true if l is an enumerator after r}$
-	int ?>=?( E l, E r ); 		$\C{// true if l after or the same as r}$         
-}
-\end{cfa}
-Note, the overloaded operators are defined only when the header @<enum.hfa>@ is included.
-If not, the compiler converts an enumerator to its value, and applies the operators defined for the value type @E@, \eg:
-\begin{cfa}
-// if not include <enum.hfa>
-enum( int ) Fruits { APPLE = 2, BANANA = 10, CHERRY = 2 };
-APPLE == CHERRY; // true because valueE( APPLE ) == valueE( CHERRY )
-
-#include <enum.hfa>
-APPLE == CHERRY; // false because posE( APPLE ) != posE( CHERRY )
-\end{cfa}
-An enumerator returns its @position@ by default.
-In particular, @printf( ... )@ from @<stdio.h>@ functions provides no context to its parameter type, so it prints @position@. 
-On the other hand, the pipeline operator @?|?( ostream os, E enumType )@ provides type context for type @E@, and \CFA has overwritten this operator to print the enumeration @value@ over @position@.
-\begin{cfa}
-printf( "Position of BANANA is \%d", BANANA ); // Position of BANANA is 1
-sout | "Value of BANANA is " | BANANA; // Value of BANANA is 10
-\end{cfa}
-Programmers can overwrite this behaviour by overloading the pipeline operator themselves.
-\PAB{This needs discussing because including \lstinline{<enum.hfa>} can change the entire meaning of a program.}
-
+
+\section{Enumerated Arrays}
+Enumerated array use an \CFA array as their index.
+\begin{cfa}
+enum() Colour {
+	Red, Orange, Yellow, Green, Blue, Indigo, Violet
+};
+
+string colourCode[Colour] = { "#e81416", "#ffa500", "#ffa500", "#ffa500", "#487de7", "#4b369d", "#70369d" };
+sout | "Colour Code of Orange is " | colourCode[Orange];
+\end{cfa}
 
 \section{Planet Example}
Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ src/AST/Fwd.hpp	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -133,5 +133,4 @@
 class OneType;
 class GlobalScopeType;
-class EnumAttrType;
 
 class Designation;
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ src/AST/Pass.hpp	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -207,5 +207,4 @@
 	const ast::Type *             visit( const ast::UnionInstType        * ) override final;
 	const ast::Type *             visit( const ast::EnumInstType         * ) override final;
-	const ast::Type *             visit( const ast::EnumAttrType         * ) override final;
 	const ast::Type *             visit( const ast::TraitInstType        * ) override final;
 	const ast::Type *             visit( const ast::TypeInstType         * ) override final;
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ src/AST/Pass.impl.hpp	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -1940,12 +1940,4 @@
 
 //--------------------------------------------------------------------------
-// EnumAttrType
-template< typename core_t >
-const ast::Type * ast::Pass< core_t >::visit( const ast::EnumAttrType * node ) {
-	VISIT_START( node );
-	VISIT_END( Type, node );
-}
-
-//--------------------------------------------------------------------------
 // TraitInstType
 template< typename core_t >
Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ src/AST/Print.cpp	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -1576,18 +1576,4 @@
 	}
 
-	virtual const ast::Type * visit( const ast::EnumAttrType * node ) override final {
-		preprint( node );
-		os << "enum attr ";
-		if ( node->attr == ast::EnumAttribute::Label ) {
-			os << "Label ";
-		} else if ( node->attr == ast::EnumAttribute::Value ) {
-			os << "Value ";
-		} else {
-			os << "Posn ";
-		}
-		(*(node->instance)).accept( *this );
-		return node;
-	}
-
 	virtual const ast::Type * visit( const ast::TraitInstType * node ) override final {
 		preprint( node );
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ src/AST/Type.hpp	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -319,20 +319,4 @@
 using EnumInstType = SueInstType<EnumDecl>;
 
-class EnumAttrType final : public Type {
-public:
-	readonly<EnumInstType> instance;
-	EnumAttribute attr;
-	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
-	EnumAttrType( const EnumInstType * instance, EnumAttribute attr = EnumAttribute::Posn )
-		: instance(instance), attr(attr) {}
-
-	bool match( const ast::EnumAttrType * other) const {
-		return instance->base->name == other->instance->base->name && attr == other->attr;
-	}
-private:
-	EnumAttrType * clone() const override { return new EnumAttrType{ *this }; }
-	MUTATE_FRIEND
-};
-
 /// An instance of a trait type.
 class TraitInstType final : public BaseInstType {
Index: src/AST/Visitor.hpp
===================================================================
--- src/AST/Visitor.hpp	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ src/AST/Visitor.hpp	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -119,5 +119,4 @@
     virtual const ast::Type *             visit( const ast::OneType              * ) = 0;
     virtual const ast::Type *             visit( const ast::GlobalScopeType      * ) = 0;
-    virtual const ast::Type *             visit( const ast::EnumAttrType         * ) = 0;
     virtual const ast::Designation *      visit( const ast::Designation          * ) = 0;
     virtual const ast::Init *             visit( const ast::SingleInit           * ) = 0;
Index: src/CodeGen/GenType.cc
===================================================================
--- src/CodeGen/GenType.cc	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ src/CodeGen/GenType.cc	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -46,5 +46,4 @@
 	void postvisit( ast::UnionInstType const * type );
 	void postvisit( ast::EnumInstType const * type );
-	void postvisit( ast::EnumAttrType const * type );
 	void postvisit( ast::TypeInstType const * type );
 	void postvisit( ast::TupleType const * type );
@@ -240,8 +239,4 @@
 }
 
-void GenType::postvisit( ast::EnumAttrType const * type ) {
-	postvisit( type->instance );
-}
-
 void GenType::postvisit( ast::TypeInstType const * type ) {
 	assertf( !options.genC, "TypeInstType should not reach code generation." );
Index: src/Common/CodeLocationTools.cpp
===================================================================
--- src/Common/CodeLocationTools.cpp	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ src/Common/CodeLocationTools.cpp	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -188,5 +188,4 @@
     macro(UnionInstType, Type) \
     macro(EnumInstType, Type) \
-    macro(EnumAttrType, Type) \
     macro(TraitInstType, Type) \
     macro(TypeInstType, Type) \
Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -906,5 +906,5 @@
 				}
 				CandidateRef & choice = winners.front();
-				choice->cost.incSafe();
+				choice->cost = Cost::unsafe;
 				candidates.emplace_back( std::move(choice) );
 			}
@@ -955,5 +955,7 @@
 
 		CandidateFinder funcFinder( context, tenv );
+		std::string funcName;
 		if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) {
+			funcName = nameExpr->name;
 			auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);
 			if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) {
@@ -1019,4 +1021,5 @@
 		CandidateList found;
 		SemanticErrorException errors;
+		
 		for ( CandidateRef & func : funcFinder ) {
 			try {
@@ -1093,4 +1096,5 @@
 			Cost cvtCost = computeApplicationConversionCost( withFunc, symtab );
 
+			if (funcName == "?|?") {
 			PRINT(
 				auto appExpr = withFunc->expr.strict_as< ast::ApplicationExpr >();
@@ -1108,5 +1112,5 @@
 				std::cerr << "cost of conversion is:" << cvtCost << std::endl;
 			)
-
+			}
 			if ( cvtCost != Cost::infinity ) {
 				withFunc->cvtCost = cvtCost;
@@ -1774,39 +1778,14 @@
 						matches.clear();
 					}
-					// ambiguous case, still output candidates to print in error message
-					if ( cand->cost == minExprCost && thisCost == minCastCost ) {
-						auto commonAsEnumAttr = common.as<ast::EnumAttrType>();
-						if ( commonAsEnumAttr && commonAsEnumAttr->attr == ast::EnumAttribute::Value ) {
-							auto callExpr = new ast::UntypedExpr(
-								cand->expr->location, new ast::NameExpr( cand->expr->location, "valueE"), {cand->expr} );
-							CandidateFinder finder( context, env );
-							finder.find( callExpr );
-							CandidateList winners = findMinCost( finder.candidates );
-							if (winners.size() != 1) {
-								SemanticError( callExpr, "Ambiguous expression in valueE..." );
-							}
-							CandidateRef & choice = winners.front();
-							// assert( valueCall->result );
-							CandidateRef newCand = std::make_shared<Candidate>(
-								new ast::InitExpr{
-									initExpr->location,
-									// restructureCast( cand->expr, toType ),
-									choice->expr,
-									initAlt.designation },
-								std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost );
-								inferParameters( newCand, matches );
-						} else {
-							CandidateRef newCand = std::make_shared<Candidate>(
-								new ast::InitExpr{
-									initExpr->location,
-									restructureCast( cand->expr, toType ),
-									initAlt.designation },
-								std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost );
-							// currently assertions are always resolved immediately so this should have no effect.
-							// if this somehow changes in the future (e.g. delayed by indeterminate return type)
-							// we may need to revisit the logic.
-							inferParameters( newCand, matches );
-						}
-					}
+					CandidateRef newCand = std::make_shared<Candidate>(
+						new ast::InitExpr{
+							initExpr->location,
+							restructureCast( cand->expr, toType ),
+							initAlt.designation },
+						std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost );
+					// currently assertions are always resolved immediately so this should have no effect.
+					// if this somehow changes in the future (e.g. delayed by indeterminate return type)
+					// we may need to revisit the logic.
+					inferParameters( newCand, matches );
 				}
 			}
Index: src/ResolvExpr/CommonType.cc
===================================================================
--- src/ResolvExpr/CommonType.cc	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ src/ResolvExpr/CommonType.cc	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -388,16 +388,4 @@
 			const ast::EnumDecl* enumDecl = enumInst->base;
 			if ( !enumDecl->base ) {
-				ast::BasicKind kind = commonTypes[ basic->kind ][ ast::BasicKind::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 };
-				}
-			}
-		} else if ( auto type2AsAttr = dynamic_cast< const ast::EnumAttrType * >( type2 ) ) {
-			if ( type2AsAttr->attr == ast::EnumAttribute::Posn ) {
 				ast::BasicKind kind = commonTypes[ basic->kind ][ ast::BasicKind::SignedInt ];
 				if (
@@ -656,6 +644,4 @@
 	}
 
-	void postvisit( const ast::EnumAttrType * ) {}
-
 	void postvisit( const ast::TraitInstType * ) {}
 
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ src/ResolvExpr/ConversionCost.cc	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -279,8 +279,5 @@
 	if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
 		conversionCostFromBasicToBasic( basicType, dstAsBasic );
-	} else if ( dynamic_cast< const ast::EnumAttrType *>(dst) ) {
-		static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicKind::SignedInt ) };
-		cost = costCalc( basicType, integer, srcIsLvalue, symtab, env );
-	} else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
+	}	else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
 		if ( dstAsEnumInst->base && !dstAsEnumInst->base->isTyped ) {
 			cost = Cost::unsafe;
@@ -373,34 +370,11 @@
 	static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicKind::SignedInt ) };
 	cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
-	if ( cost < Cost::unsafe ) {
-		cost.incSafe();
-	}
-}
-
-void ConversionCost::postvisit( const ast::EnumAttrType * src ) {
-	auto dstAsEnumAttrType = dynamic_cast<const ast::EnumAttrType *>(dst);
-	assert( src->attr != ast::EnumAttribute::Label );
-	if ( src->attr == ast::EnumAttribute::Value ) {
-		if ( dstAsEnumAttrType && dstAsEnumAttrType->attr == ast::EnumAttribute::Value) {
-			cost = costCalc( src->instance, dstAsEnumAttrType->instance, srcIsLvalue, symtab, env );
-		} else {
-			auto baseType = src->instance->base->base;
-			cost = costCalc( baseType, dst, srcIsLvalue, symtab, env );
-			if ( cost < Cost::infinity ) {
-				cost.incUnsafe();
-			}
-		}
-	} else { // ast::EnumAttribute::Posn
-		if ( auto dstBase = dynamic_cast<const ast::EnumInstType *>( dst ) ) {
-			cost = costCalc( src->instance, dstBase, srcIsLvalue, symtab, env );
-			if ( cost < Cost::unsafe ) cost.incSafe();
-		} else {
-			static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicKind::SignedInt ) };
-			cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
-			if ( cost < Cost::unsafe ) {
-				cost.incSafe();
-			}
-		}
-	}
+	if ( !inst->base->isTyped ) {
+		if ( cost < Cost::unsafe ) {
+			cost.incSafe();
+		}
+		return;
+	}
+	cost.incUnsafe();
 }
 
Index: src/ResolvExpr/ConversionCost.h
===================================================================
--- src/ResolvExpr/ConversionCost.h	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ src/ResolvExpr/ConversionCost.h	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -72,5 +72,4 @@
 	void postvisit( const ast::ZeroType * zeroType );
 	void postvisit( const ast::OneType * oneType );
-	void postvisit( const ast::EnumAttrType * posType );
 private:
 	// refactor for code resue
Index: src/ResolvExpr/Unify.cc
===================================================================
--- src/ResolvExpr/Unify.cc	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ src/ResolvExpr/Unify.cc	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -275,6 +275,6 @@
 
 	void postvisit( const ast::VoidType * vt) {
-		result = dynamic_cast< const ast::VoidType * >( type2 )
-			|| tryToUnifyWithEnumValue(vt, type2, tenv, need, have, open, noWiden());
+		result = dynamic_cast< const ast::VoidType * >( type2 ); 
+			// || tryToUnifyWithEnumValue(vt, type2, tenv, need, have, open, noWiden());
 		;
 	}
@@ -284,5 +284,5 @@
 			result = basic->kind == basic2->kind;
 		}
-		result = result || tryToUnifyWithEnumValue(basic, type2, tenv, need, have, open, noWiden());
+		// result = result || tryToUnifyWithEnumValue(basic, type2, tenv, need, have, open, noWiden());
 	}
 
@@ -293,5 +293,5 @@
 				noWiden());
 		}
-		result = result || tryToUnifyWithEnumValue(pointer, type2, tenv, need, have, open, noWiden());
+		// result = result || tryToUnifyWithEnumValue(pointer, type2, tenv, need, have, open, noWiden());
 	}
 
@@ -311,6 +311,6 @@
 
 		result = unifyExact(
-			array->base, array2->base, tenv, need, have, open, noWiden())
-			|| tryToUnifyWithEnumValue(array, type2, tenv, need, have, open, noWiden());
+			array->base, array2->base, tenv, need, have, open, noWiden());
+			// || tryToUnifyWithEnumValue(array, type2, tenv, need, have, open, noWiden());
 	}
 
@@ -404,18 +404,4 @@
 	}
 
-	bool tryToUnifyWithEnumValue( const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
-		ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
-		WidenMode widen) {
-		if ( auto attrType2 = dynamic_cast<const ast::EnumAttrType *>(type2)) {
-			if (attrType2->attr == ast::EnumAttribute::Value) {
-				return unifyExact( type1, attrType2->instance->base->base, env, need, have, open,
-					widen);
-			} else if (attrType2->attr == ast::EnumAttribute::Posn) {
-				return unifyExact( type1, attrType2->instance, env, need, have, open, widen );
-			}
-		}
-		return false;
-	}
-
 public:
 	void postvisit( const ast::FunctionType * func ) {
@@ -527,29 +513,16 @@
 	void postvisit( const ast::StructInstType * aggrType ) {
 		handleGenericRefType( aggrType, type2 );
-		result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
 	}
 
 	void postvisit( const ast::UnionInstType * aggrType ) {
 		handleGenericRefType( aggrType, type2 );
-		result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
 	}
 
 	void postvisit( const ast::EnumInstType * aggrType ) {
 		handleRefType( aggrType, type2 );
-		result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
-	}
-
-	void postvisit( const ast::EnumAttrType * enumAttr ) {
-		// Lazy approach for now
-		if ( auto otherPos = dynamic_cast< const ast::EnumAttrType *>( type2 ) ) {
-			if ( enumAttr->match(otherPos) ) {
-				result = otherPos;
-			}
-		}
 	}
 
 	void postvisit( const ast::TraitInstType * aggrType ) {
 		handleRefType( aggrType, type2 );
-		result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
 	}
 
@@ -560,5 +533,4 @@
 			this->result = otherInst;
 		}
-		result = result || tryToUnifyWithEnumValue(typeInst, type2, tenv, need, have, open, noWiden());
 	}
 
@@ -634,21 +606,21 @@
 		auto types2 = flatten( flat2 );
 
-		result = unifyList( types, types2, tenv, need, have, open )
-			|| tryToUnifyWithEnumValue(tuple, type2, tenv, need, have, open, noWiden());
+		result = unifyList( types, types2, tenv, need, have, open );
+			// || tryToUnifyWithEnumValue(tuple, type2, tenv, need, have, open, noWiden());
 	}
 
 	void postvisit( const ast::VarArgsType * vat) {
-		result = dynamic_cast< const ast::VarArgsType * >( type2 )
-			|| tryToUnifyWithEnumValue(vat, type2, tenv, need, have, open, noWiden());
+		result = dynamic_cast< const ast::VarArgsType * >( type2 );
+			// || tryToUnifyWithEnumValue(vat, type2, tenv, need, have, open, noWiden());
 	}
 
 	void postvisit( const ast::ZeroType * zt) {
-		result = dynamic_cast< const ast::ZeroType * >( type2 )
-			|| tryToUnifyWithEnumValue(zt, type2, tenv, need, have, open, noWiden());
+		result = dynamic_cast< const ast::ZeroType * >( type2 );
+			// || tryToUnifyWithEnumValue(zt, type2, tenv, need, have, open, noWiden());
 	}
 
 	void postvisit( const ast::OneType * ot) {
-		result = dynamic_cast< const ast::OneType * >( type2 )
-			|| tryToUnifyWithEnumValue(ot, type2, tenv, need, have, open, noWiden());
+		result = dynamic_cast< const ast::OneType * >( type2 );
+			// || tryToUnifyWithEnumValue(ot, type2, tenv, need, have, open, noWiden());
 	}
 };
Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ src/SymTab/Mangler.cc	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -58,5 +58,4 @@
 	void postvisit( const ast::OneType * oneType );
 	void postvisit( const ast::QualifiedType * qualType );
-	void postvisit( const ast::EnumAttrType * posType );
 
 	/// The result is the current constructed mangled name.
@@ -278,22 +277,4 @@
 	assertf( decl->kind < ast::TypeDecl::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
 	mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name;
-}
-
-void Mangler::postvisit( const ast::EnumAttrType * enumAttr ) {
-	postvisit( enumAttr->instance );
-	// mangleName += "_pos";
-	switch ( enumAttr->attr )
-	{
-		case ast::EnumAttribute::Label:
-			mangleName += "_label_";
-			break;
-		case ast::EnumAttribute::Posn:
-			mangleName += "_posn_";
-			break;
-		case ast::EnumAttribute::Value:
-			mangleName += "_value_";
-			break;
-	}
-
 }
 
Index: src/Validate/ImplementEnumFunc.cpp
===================================================================
--- src/Validate/ImplementEnumFunc.cpp	(revision 41c83121f5e4650dd259fae0fa0d8ceb346ed008)
+++ src/Validate/ImplementEnumFunc.cpp	(revision acb33f15d3e545defb3cca21e653745f42fa6553)
@@ -72,16 +72,4 @@
 		ast::DeclWithType* decl = declPtr.get_and_mutate();
 		decl->attributes.push_back(new ast::Attribute("unused"));
-	}
-
-	ast::ObjectDecl* dstParam() const {
-		return new ast::ObjectDecl(getLocation(), "_dst",
-		                           new ast::ReferenceType(new ast::EnumAttrType(
-		                               ast::deepCopy(instType))));
-	}
-
-	ast::ObjectDecl* srcParam() const {
-		return new ast::ObjectDecl(
-			getLocation(), "_src",
-			new ast::EnumAttrType(ast::deepCopy(instType)));
 	}
 
@@ -329,8 +317,4 @@
 }
 
-inline ast::EnumAttrType * getPosnType( const ast::EnumDecl * decl ) {
-	return new ast::EnumAttrType(new ast::EnumInstType(decl), ast::EnumAttribute::Posn);
-}
-
 ast::ObjectDecl* EnumAttrFuncGenerator::genAttrArrayProto(
 	const ast::EnumAttribute attr, const CodeLocation& location,
@@ -360,6 +344,7 @@
 			func->location,
 			new ast::VariableExpr( func->location, func->params.front() ),
-			new ast::EnumAttrType( new ast::EnumInstType(decl),
-				ast::EnumAttribute::Posn))});
+			new ast::BasicType( ast::BasicKind::UnsignedInt ),
+			ast::GeneratedFlag::ExplicitCast
+		)});
 	func->stmts = new ast::CompoundStmt(
 		func->location, {new ast::ReturnStmt(func->location, untyped)});
@@ -370,6 +355,6 @@
 		func->location,
 		new ast::VariableExpr(func->location, func->params.front()),
-		new ast::EnumAttrType(new ast::EnumInstType(decl),
-							  ast::EnumAttribute::Posn));
+		new ast::BasicType( ast::BasicKind::UnsignedInt ),
+			ast::GeneratedFlag::ExplicitCast);
 	func->stmts = new ast::CompoundStmt(
 		func->location, {new ast::ReturnStmt(func->location, castExpr)});
