Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 361bf012e550db91b38f772bfbc7cb7ed2e49033)
+++ src/AST/Convert.cpp	(revision c8025a2106ce52966312a91c95b8d09da7b91b8b)
@@ -205,5 +205,10 @@
 		ftype->parameters = get<DeclarationWithType>().acceptL(node->params);
 
-		ftype->forall = get<TypeDecl>().acceptL( node->type->forall );
+		ftype->forall = get<TypeDecl>().acceptL( node->type_params );
+		if (!node->assertions.empty()) {
+			assert(!ftype->forall.empty());
+			// find somewhere to place assertions back, for convenience it is the last slot
+			ftype->forall.back()->assertions = get<DeclarationWithType>().acceptL(node->assertions);
+		}
 
 		visitType(node->type, ftype);
@@ -602,11 +607,6 @@
 
 		for (decltype(src->begin()) src_i = src->begin(); src_i != src->end(); src_i++) {
-			rslt->add( src_i->first,
+			rslt->add( src_i->first.typeString(),
 			           get<Type>().accept1(src_i->second) );
-		}
-
-		for (decltype(src->beginVar()) src_i = src->beginVar(); src_i != src->endVar(); src_i++) {
-			rslt->addVar( src_i->first,
-			              get<Expression>().accept1(src_i->second) );
 		}
 
@@ -1212,5 +1212,25 @@
 		// ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
 		// ty->parameters = get<DeclarationWithType>().acceptL( node->params );
-		ty->forall = get<TypeDecl>().acceptL( node->forall );
+
+		auto types = get<TypeInstType>().acceptL( node->forall );
+		for (auto t : types) {
+			auto newT = new TypeDecl(*t->baseType);
+			newT->name = t->name; // converted by typeString()
+			for (auto asst : newT->assertions) delete asst;
+			newT->assertions.clear();
+			ty->forall.push_back(newT);
+		}
+		auto assts = get<VariableExpr>().acceptL( node->assertions );
+		if (!assts.empty()) {
+			assert(!types.empty());
+			for (auto asst : assts) {
+				auto newDecl = new ObjectDecl(*strict_dynamic_cast<ObjectDecl*>(asst->var));
+				delete newDecl->type;
+				newDecl->type = asst->result->clone();
+				newDecl->storageClasses.is_extern = true; // hack
+				ty->forall.back()->assertions.push_back(newDecl);
+			}
+		}
+
 		return visitType( node, ty );
 	}
@@ -1299,5 +1319,5 @@
 			ty = new TypeInstType{
 				cv( node ),
-				node->name,
+				node->typeString(),
 				get<TypeDecl>().accept1( node->base ),
 				get<Attribute>().acceptL( node->attributes )
@@ -1306,5 +1326,5 @@
 			ty = new TypeInstType{
 				cv( node ),
-				node->name,
+				node->typeString(),
 				node->kind == ast::TypeDecl::Ftype,
 				get<Attribute>().acceptL( node->attributes )
@@ -1431,5 +1451,5 @@
 	/// at conversion stage, all created nodes are guaranteed to be unique, therefore
 	/// const_casting out of smart pointers is permitted.
-	std::unordered_map< const BaseSyntaxNode *, ast::ptr<ast::Node> > cache = {};
+	std::unordered_map< const BaseSyntaxNode *, ast::readonly<ast::Node> > cache = {};
 
 	// Local Utilities:
@@ -1565,4 +1585,16 @@
 		// can function type have attributes? seems not to be the case.
 		// visitType(old->type, ftype);
+
+		// collect assertions and put directly in FunctionDecl
+		std::vector<ast::ptr<ast::DeclWithType>> assertions;
+		for (auto & param: forall) {
+			for (auto & asst: param->assertions) {
+				assertf(asst->unique(), "newly converted decl must be unique");
+				assertions.emplace_back(asst);
+			}
+			auto mut = param.get_and_mutate();
+			assertf(mut == param, "newly converted decl must be unique");
+			mut->assertions.clear();
+		}
 
 		auto decl = new ast::FunctionDecl{
@@ -1584,4 +1616,5 @@
 		cache.emplace( old, decl );
 
+		decl->assertions = std::move(assertions);
 		decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
 		decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
@@ -2066,8 +2099,12 @@
 	}
 
+	// TypeSubstitution shouldn't exist yet in old.
 	ast::TypeSubstitution * convertTypeSubstitution(const TypeSubstitution * old) {
-
+		
 		if (!old) return nullptr;
-
+		if (old->empty()) return nullptr;
+		assert(false);
+
+		/*
 		ast::TypeSubstitution *rslt = new ast::TypeSubstitution();
 
@@ -2077,10 +2114,6 @@
 		}
 
-		for (decltype(old->beginVar()) old_i = old->beginVar(); old_i != old->endVar(); old_i++) {
-			rslt->addVar( old_i->first,
-			              getAccept1<ast::Expr>(old_i->second) );
-		}
-
 		return rslt;
+		*/
 	}
 
@@ -2610,5 +2643,14 @@
 			ty->params.emplace_back(v->get_type());
 		}
-		ty->forall = GET_ACCEPT_V( forall, TypeDecl );
+		// xxx - when will this be non-null?
+		// will have to create dangling (no-owner) decls to be pointed to
+		auto foralls = GET_ACCEPT_V( forall, TypeDecl );
+
+		for (auto & param : foralls) {
+			ty->forall.emplace_back(new ast::TypeInstType(param->name, param));
+			for (auto asst : param->assertions) {
+				ty->assertions.emplace_back(new ast::VariableExpr({}, asst));
+			}
+		}
 		visitType( old, ty );
 	}
