Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision c957e7f46a4ebf150c4cb6778b8d0053595805bb)
+++ src/AST/Print.cpp	(revision b0ec9711a35db17d11fd4733884f1d7ba52d3b68)
@@ -96,4 +96,44 @@
 	}
 
+	void print( const ast::ParameterizedType::ForallList & forall ) {
+		if ( forall.empty() ) return;	
+		os << "forall" << std::endl;
+		++indent;
+		printAll( forall );
+		os << indent;
+		--indent;
+	}
+
+	void print( const std::vector<ptr<Attribute>> & attrs ) {
+		if ( attrs.empty() ) return;
+		os << "with attributes" << std::endl;
+		++indent;
+		printAll( attrs );
+		--indent;
+	}
+
+	void print( const std::vector<ptr<Expr>> & params ) {
+		if ( params.empty() ) return;
+		os << std::endl << indent << "... with parameters" << std::endl;
+		++indent;
+		printAll( params );
+		--indent;
+	}
+
+	void preprint( const ast::Type * node ) {
+		print( node->qualifiers );
+	}
+
+	void preprint( const ast::ParameterizedType * node ) {
+		print( node->forall );
+		print( node->qualifiers );
+	}
+
+	void preprint( const ast::ReferenceToType * node ) {
+		print( node->forall );
+		print( node->attributes );
+		print( node->qualifiers );
+	}
+
 public:
 	virtual const ast::DeclWithType *     visit( const ast::ObjectDecl           * node ) {
@@ -404,72 +444,227 @@
 
 	virtual const ast::Type *             visit( const ast::VoidType             * node ) {
+		preprint( node );
+		os << "void";
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::BasicType            * node ) {
+		preprint( node );
+		os << ast::BasicType::typeNames[ node->kind ];
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::PointerType          * node ) {
+		preprint( node );
+		if ( ! node->isArray() ) {
+			os << "pointer to ";
+		} else {
+			os << "decayed ";
+			if ( node->isStatic ) {
+				os << "static ";
+			}
+
+			if ( node->isVarLen ) {
+				os << "variable length array of ";
+			} else if ( node->dimension ) {
+				os << "array of ";
+				node->dimension->accept( *this );
+				os << " ";
+			}
+		}
+
+		if ( node->base ) {
+			node->base->accept( *this );
+		} else {
+			os << "UNDEFINED";
+		}
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::ArrayType            * node ) {
+		preprint( node );
+		if ( node->isStatic ) {
+			os << "static ";
+		}
+
+		if ( node->isVarLen ) {
+			os << "variable length array of ";
+		} else if ( node->dimension ) {
+			os << "array of ";
+		} else {
+			os << "open array of ";
+		}
+
+		if ( node->base ) {
+			node->base->accept( *this );
+		} else {
+			os << "UNDEFINED";
+		}
+
+		if ( node->dimension ) {
+			os << " with dimension of ";
+			node->dimension->accept( *this );
+		}
+
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::ReferenceType        * node ) {
+		preprint( node );
+
+		os << "reference to ";
+		if ( node->base ) {
+			node->base->accept( *this );
+		} else {
+			os << "UNDEFINED";
+		}
+
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::QualifiedType        * node ) {
+		preprint( node );
+
+		++indent;
+		os << "Qualified Type:" << std::endl << indent;
+		node->parent->accept( *this );
+		os << std::endl << indent;
+		node->child->accept( *this );
+		os << std::endl;
+		--indent;
+
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::FunctionType         * node ) {
+		preprint( node );
+
+		os << "function" << std::endl;
+		if ( ! node->params.empty() ) {
+			os << indent << "... with parameters" << std::endl;
+			++indent;
+			printAll( node->params );
+			if ( node->isVarArgs ) {
+				os << indent << "and a variable number of other arguments" << std::endl;
+			}
+			--indent;
+		} else if ( node->isVarArgs ) {
+			os << indent+1 << "accepting unspecified arguments" << std::endl;
+		}
+
+		os << indent << "... returning";
+		if ( node->returns.empty() ) {
+			os << " nothing" << std::endl;
+		} else {
+			os << std::endl;
+			++indent;
+			printAll( node->returns );
+			--indent;
+		}
+
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::StructInstType       * node ) {
+		preprint( node );
+
+		os << "instance of struct " << node->name;
+		if ( node->base ) {
+			os << " " << ( node->base->body ? "with" : "without" ) << " body";
+		}
+		print( node->params );
+
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::UnionInstType        * node ) {
+		preprint( node );
+
+		os << "instance of union " << node->name;
+		if ( node->base ) {
+			os << " " << ( node->base->body ? "with" : "without" ) << " body";
+		}
+		print( node->params );
+
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::EnumInstType         * node ) {
+		preprint( node );
+
+		os << "instance of enum " << node->name;
+		if ( node->base ) {
+			os << " " << ( node->base->body ? "with" : "without" ) << " body";
+		}
+		print( node->params );
+
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::TraitInstType        * node ) {
+		preprint( node );
+
+		os << "instance of trait " << node->name;
+		print( node->params );
+
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::TypeInstType         * node ) {
+		preprint( node );
+
+		os << "instance of type " << node->name 
+		   << " (" << (node->kind == ast::TypeVar::Ftype ? "" : "not ") << "function type)";
+		print( node->params );
+
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::TupleType            * node ) {
+		preprint( node );
+
+		os << "tuple of types" << std::endl;
+		++indent;
+		printAll( node->types );
+		--indent;
+
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::TypeofType           * node ) {
+		preprint( node );
+
+		if ( node->kind == ast::TypeofType::Basetypeof ) { os << "base-"; }
+		os << "type-of expression ";
+		if ( node->expr ) {
+			node->expr->accept( *this );
+		} else {
+			os << "UNDEFINED";
+		}
+
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::VarArgsType          * node ) {
+		preprint( node );
+		os << "builtin var args pack";
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::ZeroType             * node ) {
+		preprint( node );
+		os << "zero_t";
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::OneType              * node ) {
+		preprint( node );
+		os << "one_t";
 		return node;
 	}
 
 	virtual const ast::Type *             visit( const ast::GlobalScopeType      * node ) {
+		preprint( node );
+		os << "Global Scope Type";
 		return node;
 	}
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision c957e7f46a4ebf150c4cb6778b8d0053595805bb)
+++ src/AST/Type.hpp	(revision b0ec9711a35db17d11fd4733884f1d7ba52d3b68)
@@ -308,8 +308,4 @@
 	virtual ReferenceToType * clone() const override = 0;
 	MUTATE_FRIEND
-
-protected:
-	/// Name for the kind of type this is
-	virtual std::string typeString() const = 0;
 };
 
@@ -333,6 +329,4 @@
 	StructInstType * clone() const override { return new StructInstType{ *this }; }
 	MUTATE_FRIEND
-
-	std::string typeString() const override { return "struct"; }
 };
 
@@ -356,6 +350,4 @@
 	UnionInstType * clone() const override { return new UnionInstType{ *this }; }
 	MUTATE_FRIEND
-
-	std::string typeString() const override { return "union"; }
 };
 
@@ -379,6 +371,4 @@
 	EnumInstType * clone() const override { return new EnumInstType{ *this }; }
 	MUTATE_FRIEND
-
-	std::string typeString() const override { return "enum"; }
 };
 
@@ -403,6 +393,4 @@
 	TraitInstType * clone() const override { return new TraitInstType{ *this }; }
 	MUTATE_FRIEND
-
-	std::string typeString() const override { return "trait"; }
 };
 
@@ -432,6 +420,4 @@
 	TypeInstType * clone() const override { return new TypeInstType{ *this }; }
 	MUTATE_FRIEND
-
-	std::string typeString() const override { return "type"; }
 };
 
