Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
+++ src/AST/Convert.cpp	(revision fa2c005cdb7210e3aaf9b1170f05fbc75444ece7)
@@ -321,8 +321,4 @@
 			get<Type>().accept1(node->base)
 		);
-		// decl->data_constructors = get<StructDecl>().acceptL( node->data_constructors );
-		// decl->data_union = get<UnionDecl>().accept1( node->data_union );
-		// decl->tag = get<EnumDecl>().accept1( node->tag );
-		// decl->tag_union = get<StructDecl>().accept1( node->tag_union );
 		return aggregatePostamble( decl, node );
 	}
@@ -334,5 +330,4 @@
 			get<Attribute>().acceptL( node->attributes ),
 			LinkageSpec::Spec( node->linkage.val ),
-			get<StructDecl>().acceptL( node->data_constructors ),
 			get<UnionDecl>().accept1( node->data_union ),
 			get<EnumDecl>().accept1( node->tag ),
@@ -1344,4 +1339,8 @@
 	}
 
+	const ast::Type * visit( [[maybe_unused]]const ast::AdtInstType * node ) override final {
+		return nullptr;
+	}
+
 	const ast::Type * visit( const ast::UnionInstType * node ) override final {
 		UnionInstType * ty;
@@ -1824,5 +1823,4 @@
 		decl->uniqueId = old->uniqueId;
 		decl->storage = { old->storageClasses.val };
-		decl->data_constructors = GET_ACCEPT_V( data_constructors, StructDecl );
 		decl->data_union = GET_ACCEPT_1( data_union, UnionDecl );
 		decl->tag = GET_ACCEPT_1( tag, EnumDecl );
@@ -2876,4 +2874,22 @@
 		postvisit( old, ty );
 	}
+	
+	virtual void visit( const AdtInstType * old ) override final {
+		ast::AdtInstType * ty;
+		if ( old->baseAdt ) {
+			ty = new ast::AdtInstType{
+				GET_ACCEPT_1( baseAdt, AdtDecl ),
+				cv( old ),
+				GET_ACCEPT_V( attributes, Attribute )
+			};
+		} else {
+			ty = new ast::AdtInstType{
+				old->name,
+				cv( old ),
+				GET_ACCEPT_V( attributes, Attribute )
+			};
+		}
+		postvisit( old, ty );
+	}
 
 	virtual void visit( const UnionInstType * old ) override final {
Index: src/AST/Decl.hpp
===================================================================
--- src/AST/Decl.hpp	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
+++ src/AST/Decl.hpp	(revision fa2c005cdb7210e3aaf9b1170f05fbc75444ece7)
@@ -248,5 +248,5 @@
 class AggregateDecl : public Decl {
 public:
-	enum Aggregate { Struct, Union, Enum, Exception, Trait, Generator, Coroutine, Monitor, Thread, NoAggregate, Adt };
+	enum Aggregate { Undecided, Struct, Union, Enum, Exception, Trait, Generator, Coroutine, Monitor, Thread, NoAggregate, Adt };
 	static const char * aggrString( Aggregate aggr );
 
@@ -346,5 +346,4 @@
 class AdtDecl final : public AggregateDecl {
 public:
-	std::vector<ptr<StructDecl>> data_constructors; // Todo: members?
 	ptr<UnionDecl> data_union;
 	ptr<EnumDecl> tag;
Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
+++ src/AST/Fwd.hpp	(revision fa2c005cdb7210e3aaf9b1170f05fbc75444ece7)
@@ -123,4 +123,5 @@
 using UnionInstType = SueInstType<UnionDecl>;
 using EnumInstType = SueInstType<EnumDecl>;
+using AdtInstType = SueInstType<AdtDecl>;
 class TraitInstType;
 class TypeInstType;
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
+++ src/AST/Pass.hpp	(revision fa2c005cdb7210e3aaf9b1170f05fbc75444ece7)
@@ -219,4 +219,5 @@
 	const ast::Type *             visit( const ast::FunctionType         * ) override final;
 	const ast::Type *             visit( const ast::StructInstType       * ) override final;
+	const ast::Type *             visit( const ast::AdtInstType          * ) override final; 
 	const ast::Type *             visit( const ast::UnionInstType        * ) override final;
 	const ast::Type *             visit( const ast::EnumInstType         * ) override final;
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
+++ src/AST/Pass.impl.hpp	(revision fa2c005cdb7210e3aaf9b1170f05fbc75444ece7)
@@ -585,4 +585,27 @@
 
 //--------------------------------------------------------------------------
+// AdtDecl
+template< typename core_t >
+const ast::Decl * ast::Pass< core_t >::visit( const ast::AdtDecl * node ) {
+	VISIT_START( node );
+
+	__pass::symtab::addAdtFwd( core, 0, node );
+
+	if ( __visit_children() ) {
+		guard_symtab guard { *this };
+		maybe_accept( node, &AdtDecl::params );
+		maybe_accept( node, &AdtDecl::members );
+		maybe_accept( node, &AdtDecl::attributes );
+
+		maybe_accept( node, &AdtDecl::data_union );
+		maybe_accept( node, &AdtDecl::tag );
+		maybe_accept( node, &AdtDecl::tag_union );
+	}
+
+	__pass::symtab::addAdt( core, 0, node );
+	VISIT_END( Decl, node );
+}
+
+//--------------------------------------------------------------------------
 // UnionDecl
 template< typename core_t >
@@ -620,9 +643,4 @@
 			maybe_accept( node, &EnumDecl::members    );
 			maybe_accept( node, &EnumDecl::attributes );
-
-			// maybe_accept( node, &EnumDecl::data_constructors );
-			// maybe_accept( node, &EnumDecl::data_union );
-			// maybe_accept( node, &EnumDecl::tag );
-			// maybe_accept( node, &EnumDecl::tag_union );
 		} else {
 			maybe_accept( node, &EnumDecl::base );
@@ -630,31 +648,5 @@
 			maybe_accept( node, &EnumDecl::members    );
 			maybe_accept( node, &EnumDecl::attributes );
-
-			// maybe_accept( node, &EnumDecl::data_constructors );
-			// maybe_accept( node, &EnumDecl::data_union );
-			// maybe_accept( node, &EnumDecl::tag );
-			// maybe_accept( node, &EnumDecl::tag_union );
-		}
-	}
-
-	VISIT_END( Decl, node );
-}
-
-template< typename core_t >
-const ast::Decl * ast::Pass< core_t >::visit( const ast::AdtDecl * node ) {
-	VISIT_START( node );
-
-	__pass::symtab::addAdt( core, 0, node );
-
-	if ( __visit_children() ) {
-		guard_symtab guard { *this };
-		maybe_accept( node, &AdtDecl::params );
-		maybe_accept( node, &AdtDecl::members );
-		maybe_accept( node, &AdtDecl::attributes );
-
-		maybe_accept( node, &AdtDecl::data_constructors );
-		maybe_accept( node, &AdtDecl::data_union );
-		maybe_accept( node, &AdtDecl::tag );
-		maybe_accept( node, &AdtDecl::tag_union );
+		}
 	}
 
@@ -1967,4 +1959,20 @@
 
 //--------------------------------------------------------------------------
+// AdtInstType
+template< typename core_t >
+const ast::Type * ast::Pass< core_t >::visit( const ast::AdtInstType * node ) {
+	VISIT_START( node );
+
+	__pass::symtab::addAdt( core, 0, node->name );
+
+	if ( __visit_children() ) {
+		guard_symtab guard { *this };
+		maybe_accept( node, &AdtInstType::params );
+	}
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
 // UnionInstType
 template< typename core_t >
Index: src/AST/Pass.proto.hpp
===================================================================
--- src/AST/Pass.proto.hpp	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
+++ src/AST/Pass.proto.hpp	(revision fa2c005cdb7210e3aaf9b1170f05fbc75444ece7)
@@ -477,4 +477,16 @@
 
 	template<typename core_t>
+	static inline auto addAdtFwd( core_t & core, int, const ast::AdtDecl * decl ) -> decltype( core.symtab.addAdt( decl ), void() ) {
+		ast::AdtDecl * fwd = new ast::AdtDecl( decl->location, decl->name );
+		for ( const auto & param : decl->params ) {
+			fwd->params.push_back( deepCopy( param.get() ) );
+		}
+		core.symtab.addAdt( fwd );
+	}
+
+	template<typename core_t>
+	static inline auto addAdtFwd( core_t &, long, const ast::AdtDecl * ) {}
+
+	template<typename core_t>
 	static inline auto addUnionFwd( core_t & core, int, const ast::UnionDecl * decl ) -> decltype( core.symtab.addUnion( decl ), void() ) {
 		ast::UnionDecl * fwd = new ast::UnionDecl( decl->location, decl->name );
@@ -489,20 +501,4 @@
 
 	template<typename core_t>
-	static inline auto addAdtFwd( core_t & core, int, const ast::AdtDecl * decl ) -> decltype( core.symtab.addAdt( decl ), void() ) {
-		ast::AdtDecl * fwd = new ast::AdtDecl( decl->location, decl->name );
-		for ( const auto & param : decl->params ) {
-			fwd->params.push_back( deepCopy( param.get() ) );
-		}
-		// Experimental
-		for ( const auto & ctor : decl->data_constructors ) {
-			addStructFwd( core, 0, ctor  );
-		} 
-		core.symtab.addAdt( fwd );
-	}
-
-	template<typename core_t>
-	static inline auto addAdtFwd( core_t &, long, const ast::AdtDecl) {}
-
-	template<typename core_t>
 	static inline auto addStruct( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addStruct( str ), void() ) {
 		if ( ! core.symtab.lookupStruct( str ) ) {
@@ -513,4 +509,14 @@
 	template<typename core_t>
 	static inline void addStruct( core_t &, long, const std::string & ) {}
+
+		template<typename core_t>
+	static inline auto addAdt( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addAdt( str ), void() ) {
+		if ( ! core.symtab.lookupAdt( str ) ) {
+			core.symtab.addAdt( str );
+		}
+	}
+
+	template<typename core_t>
+	static inline void addAdt( core_t &, long, const std::string & ) {}
 
 	template<typename core_t>
Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
+++ src/AST/Print.cpp	(revision fa2c005cdb7210e3aaf9b1170f05fbc75444ece7)
@@ -1501,4 +1501,11 @@
 	}
 
+	virtual const ast::Type * visit( const ast::AdtInstType * node ) override final {
+		preprint( node );
+		os << "instance of Adt " << node->name;
+		print( node->params );
+		return node;
+	}
+
 	virtual const ast::Type * visit( const ast::UnionInstType * node ) override final {
 		preprint( node );
Index: src/AST/SymbolTable.cpp
===================================================================
--- src/AST/SymbolTable.cpp	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
+++ src/AST/SymbolTable.cpp	(revision fa2c005cdb7210e3aaf9b1170f05fbc75444ece7)
@@ -218,4 +218,11 @@
 }
 
+const AdtDecl * SymbolTable::lookupAdt( const std::string &id ) const {
+	++*stats().lookup_calls;
+	if ( ! adtTable ) return nullptr;
+	auto it = adtTable->find( id );
+	return it == adtTable->end() ? nullptr : it->second.decl;
+}
+
 const EnumDecl * SymbolTable::lookupEnum( const std::string &id ) const {
 	++*stats().lookup_calls;
@@ -339,21 +346,6 @@
 }
 
-void SymbolTable::addEnum( const EnumDecl *decl ) {
-	++*stats().add_calls;
-	const std::string &id = decl->name;
-
-	if ( ! enumTable ) {
-		enumTable = EnumTable::new_ptr();
-	} else {
-		++*stats().map_lookups;
-		auto existing = enumTable->find( id );
-		if ( existing != enumTable->end()
-			&& existing->second.scope == scope
-			&& addedDeclConflicts( existing->second.decl, decl ) ) return;
-	}
-
-	lazyInitScope();
-	++*stats().map_mutations;
-	enumTable = enumTable->set( id, scoped<EnumDecl>{ decl, scope } );
+void SymbolTable::addAdt( const std::string &id ) {
+	addAdt( new AdtDecl( CodeLocation(), id ) );
 }
 
@@ -377,4 +369,24 @@
 	adtTable = adtTable->set( id, scoped<AdtDecl>{ decl, scope });
 }
+
+void SymbolTable::addEnum( const EnumDecl *decl ) {
+	++*stats().add_calls;
+	const std::string &id = decl->name;
+
+	if ( ! enumTable ) {
+		enumTable = EnumTable::new_ptr();
+	} else {
+		++*stats().map_lookups;
+		auto existing = enumTable->find( id );
+		if ( existing != enumTable->end()
+			&& existing->second.scope == scope
+			&& addedDeclConflicts( existing->second.decl, decl ) ) return;
+	}
+
+	lazyInitScope();
+	++*stats().map_mutations;
+	enumTable = enumTable->set( id, scoped<EnumDecl>{ decl, scope } );
+}
+
 
 void SymbolTable::addUnion( const std::string &id ) {
Index: src/AST/SymbolTable.hpp
===================================================================
--- src/AST/SymbolTable.hpp	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
+++ src/AST/SymbolTable.hpp	(revision fa2c005cdb7210e3aaf9b1170f05fbc75444ece7)
@@ -111,4 +111,6 @@
 	/// Gets the top-most struct declaration with the given ID
 	const StructDecl * lookupStruct( const std::string &id ) const;
+
+	const AdtDecl * lookupAdt( const std::string &id ) const;
 	/// Gets the top-most enum declaration with the given ID
 	const EnumDecl * lookupEnum( const std::string &id ) const;
@@ -141,4 +143,5 @@
 	void addEnum( const EnumDecl * decl );
 	/// Adds an adt declaration to the symbol table
+	void addAdt( const std::string & id );
 	void addAdt( const AdtDecl * decl );
 	/// Adds a union declaration to the symbol table by name
Index: src/AST/Type.cpp
===================================================================
--- src/AST/Type.cpp	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
+++ src/AST/Type.cpp	(revision fa2c005cdb7210e3aaf9b1170f05fbc75444ece7)
@@ -138,4 +138,5 @@
 template class SueInstType<UnionDecl>;
 template class SueInstType<EnumDecl>;
+template class SueInstType<AdtDecl>;
 
 // --- TraitInstType
Index: src/AST/Visitor.hpp
===================================================================
--- src/AST/Visitor.hpp	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
+++ src/AST/Visitor.hpp	(revision fa2c005cdb7210e3aaf9b1170f05fbc75444ece7)
@@ -111,4 +111,5 @@
     virtual const ast::Type *             visit( const ast::TraitInstType        * ) = 0;
     virtual const ast::Type *             visit( const ast::TypeInstType         * ) = 0;
+    virtual const ast::Type *             visit( const ast::AdtInstType          * ) = 0;
     virtual const ast::Type *             visit( const ast::TupleType            * ) = 0;
     virtual const ast::Type *             visit( const ast::TypeofType           * ) = 0;
