Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/InitTweak/InitTweak.cc	(revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -9,7 +9,7 @@
 // Author           : Rob Schluntz
 // Created On       : Fri May 13 11:26:36 2016
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Mon Jun 10 13:30:00 2019
-// Update Count     : 5
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Jun 19 14:34:00 2019
+// Update Count     : 6
 //
 
@@ -633,13 +633,21 @@
 			return nullptr;
 		}
+
+		DeclarationWithType * getFunctionCore( const Expression * expr ) {
+			if ( const auto * appExpr = dynamic_cast< const ApplicationExpr * >( expr ) ) {
+				return getCalledFunction( appExpr->function );
+			} else if ( const auto * untyped = dynamic_cast< const UntypedExpr * >( expr ) ) {
+				return getCalledFunction( untyped->function );
+			}
+			assertf( false, "getFunction with unknown expression: %s", toString( expr ).c_str() );
+		}
 	}
 
 	DeclarationWithType * getFunction( Expression * expr ) {
-		if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ) ) {
-			return getCalledFunction( appExpr->get_function() );
-		} else if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * > ( expr ) ) {
-			return getCalledFunction( untyped->get_function() );
-		}
-		assertf( false, "getFunction received unknown expression: %s", toString( expr ).c_str() );
+		return getFunctionCore( expr );
+	}
+
+	const DeclarationWithType * getFunction( const Expression * expr ) {
+		return getFunctionCore( expr );
 	}
 
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/InitTweak/InitTweak.h	(revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -9,7 +9,7 @@
 // Author           : Rob Schluntz
 // Created On       : Fri May 13 11:26:36 2016
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Mon Jun 10 13:30:00 2019
-// Update Count     : 5
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Jul 19 14:18:00 2019
+// Update Count     : 6
 //
 
@@ -61,4 +61,5 @@
 	/// returns the declaration of the function called by the expr (must be ApplicationExpr or UntypedExpr)
 	DeclarationWithType * getFunction( Expression * expr );
+	const DeclarationWithType * getFunction( const Expression * expr );
 	const ast::DeclWithType * getFunction( const ast::Expr * expr );
 
Index: src/ResolvExpr/Alternative.h
===================================================================
--- src/ResolvExpr/Alternative.h	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/ResolvExpr/Alternative.h	(revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -29,9 +29,9 @@
 	/// One assertion to resolve
 	struct AssertionItem {
-		DeclarationWithType* decl;
+		const DeclarationWithType* decl;
 		AssertionSetValue info;
-		
+
 		AssertionItem() = default;
-		AssertionItem( DeclarationWithType* decl, const AssertionSetValue& info ) 
+		AssertionItem( const DeclarationWithType* decl, const AssertionSetValue& info )
 		: decl(decl), info(info) {}
 		AssertionItem( const AssertionSet::value_type& e ) : decl(e.first), info(e.second) {}
Index: src/ResolvExpr/FindOpenVars.cc
===================================================================
--- src/ResolvExpr/FindOpenVars.cc	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/ResolvExpr/FindOpenVars.cc	(revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 09:42:48 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sun May 17 09:45:25 2015
-// Update Count     : 3
+// Last Modified By : Andrew
+// Last Modified On : Fri Jul 12 14:18:00 2019
+// Update Count     : 4
 //
 
@@ -29,10 +29,10 @@
 		FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
 
-		void previsit( PointerType * pointerType );
-		void previsit( ArrayType * arrayType );
-		void previsit( FunctionType * functionType );
-		void previsit( TupleType * tupleType );
+		void previsit( const PointerType * pointerType );
+		void previsit( const ArrayType * arrayType );
+		void previsit( const FunctionType * functionType );
+		void previsit( const TupleType * tupleType );
 
-		void common_action( Type *type );
+		void common_action( const Type *type );
 
 		OpenVarSet &openVars, &closedVars;
@@ -41,5 +41,5 @@
 	};
 
-	void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) {
+	void findOpenVars( const Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) {
 		PassVisitor<FindOpenVars_old> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );
 		type->accept( finder );
@@ -50,7 +50,7 @@
 	}
 
-	void FindOpenVars_old::common_action( Type *type ) {
+	void FindOpenVars_old::common_action( const Type * type ) {
 		if ( nextIsOpen ) {
-			for ( Type::ForallList::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
+			for ( Type::ForallList::const_iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
 				openVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) };
 				for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
@@ -61,5 +61,5 @@
 			}
 		} else {
-			for ( Type::ForallList::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
+			for ( Type::ForallList::const_iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
 				closedVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) };
 				for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
@@ -78,13 +78,13 @@
 	}
 
-	void FindOpenVars_old::previsit(PointerType *pointerType) {
+	void FindOpenVars_old::previsit(const PointerType * pointerType) {
 		common_action( pointerType );
 	}
 
-	void FindOpenVars_old::previsit(ArrayType *arrayType) {
+	void FindOpenVars_old::previsit(const ArrayType * arrayType) {
 		common_action( arrayType );
 	}
 
-	void FindOpenVars_old::previsit(FunctionType *functionType) {
+	void FindOpenVars_old::previsit(const FunctionType * functionType) {
 		common_action( functionType );
 		nextIsOpen = ! nextIsOpen;
@@ -92,5 +92,5 @@
 	}
 
-	void FindOpenVars_old::previsit(TupleType *tupleType) {
+	void FindOpenVars_old::previsit(const TupleType * tupleType) {
 		common_action( tupleType );
 	}
@@ -104,6 +104,6 @@
 			bool nextIsOpen;
 
-			FindOpenVars_new( 
-				ast::OpenVarSet & o, ast::OpenVarSet & c, ast::AssertionSet & n, 
+			FindOpenVars_new(
+				ast::OpenVarSet & o, ast::OpenVarSet & c, ast::AssertionSet & n,
 				ast::AssertionSet & h, FirstMode firstIsOpen )
 			: open( o ), closed( c ), need( n ), have( h ), nextIsOpen( firstIsOpen ) {}
@@ -135,6 +135,6 @@
 	}
 
-	void findOpenVars( 
-			const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed, 
+	void findOpenVars(
+			const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed,
 			ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen ) {
 		ast::Pass< FindOpenVars_new > finder{ open, closed, need, have, firstIsOpen };
Index: src/ResolvExpr/FindOpenVars.h
===================================================================
--- src/ResolvExpr/FindOpenVars.h	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/ResolvExpr/FindOpenVars.h	(revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -26,5 +26,5 @@
 namespace ResolvExpr {
 	// Updates open and closed variables and their associated assertions
-	void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
+	void findOpenVars( const Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
 
 	enum FirstMode { FirstClosed, FirstOpen };
Index: src/ResolvExpr/Occurs.cc
===================================================================
--- src/ResolvExpr/Occurs.cc	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/ResolvExpr/Occurs.cc	(revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -24,5 +24,5 @@
 	struct Occurs : public WithVisitorRef<Occurs> {
 		Occurs( std::string varName, const TypeEnvironment &env );
-		void previsit( TypeInstType * typeInst );
+		void previsit( const TypeInstType * typeInst );
 
 		bool result;
@@ -31,5 +31,5 @@
 	};
 
-	bool occurs( Type *type, std::string varName, const TypeEnvironment &env ) {
+	bool occurs( const Type *type, const std::string & varName, const TypeEnvironment &env ) {
 		PassVisitor<Occurs> occur( varName, env );
 		type->accept( occur );
@@ -45,5 +45,5 @@
 	}
 
-	void Occurs::previsit( TypeInstType * typeInst ) {
+	void Occurs::previsit( const TypeInstType * typeInst ) {
 		///   std::cerr << "searching for vars: ";
 ///   std::copy( eqvVars.begin(), eqvVars.end(), std::ostream_iterator< std::string >( std::cerr, " " ) );
Index: src/ResolvExpr/ResolveAssertions.cc
===================================================================
--- src/ResolvExpr/ResolveAssertions.cc	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/ResolvExpr/ResolveAssertions.cc	(revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -73,5 +73,5 @@
 		CandidateList matches;
 
-		DeferItem( DeclarationWithType* decl, const AssertionSetValue& info, CandidateList&& matches )
+		DeferItem( const DeclarationWithType* decl, const AssertionSetValue& info, CandidateList&& matches )
 		: decl(decl), info(info), matches(std::move(matches)) {}
 
Index: src/ResolvExpr/TypeEnvironment.cc
===================================================================
--- src/ResolvExpr/TypeEnvironment.cc	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/ResolvExpr/TypeEnvironment.cc	(revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 12:19:47 2015
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Mon Jun 18 11:58:00 2018
-// Update Count     : 4
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Jun 18 14:27:00 2019
+// Update Count     : 5
 //
 
@@ -315,8 +315,8 @@
 	}
 
-	bool isFtype( Type *type ) {
-		if ( dynamic_cast< FunctionType* >( type ) ) {
+	bool isFtype( const Type * type ) {
+		if ( dynamic_cast< const FunctionType * >( type ) ) {
 			return true;
-		} else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
+		} else if ( const TypeInstType *typeInst = dynamic_cast< const TypeInstType * >( type ) ) {
 			return typeInst->get_isFtype();
 		} // if
@@ -324,5 +324,5 @@
 	}
 
-	bool tyVarCompatible( const TypeDecl::Data & data, Type *type ) {
+	bool tyVarCompatible( const TypeDecl::Data & data, const Type * type ) {
 		switch ( data.kind ) {
 		  case TypeDecl::Dtype:
@@ -336,5 +336,5 @@
 		  case TypeDecl::Ttype:
 			// ttype unifies with any tuple type
-			return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type );
+			return dynamic_cast< const TupleType * >( type ) || Tuples::isTtype( type );
 		  default:
 			assertf(false, "Unhandled tyvar kind: %d", data.kind);
@@ -343,5 +343,5 @@
 	}
 
-	bool TypeEnvironment::bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
+	bool TypeEnvironment::bindVar( const TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
 
 		// remove references from other, so that type variables can only bind to value types
@@ -361,5 +361,5 @@
 				// attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to
 				std::unique_ptr< Type > newType( curClass->type->clone() );
-				newType->get_qualifiers() = typeInst->get_qualifiers();
+				newType->tq = typeInst->tq;
 				if ( unifyInexact( newType.get(), bindTo, *this, need, have, openVars, widen & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
 					if ( common ) {
@@ -386,6 +386,6 @@
 	}
 
-	bool TypeEnvironment::bindVarToVar( TypeInstType *var1, TypeInstType *var2, 
-			TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, 
+	bool TypeEnvironment::bindVarToVar( const TypeInstType * var1, const TypeInstType * var2,
+			TypeDecl::Data && data, AssertionSet &need, AssertionSet &have,
 			const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
 
Index: src/ResolvExpr/TypeEnvironment.h
===================================================================
--- src/ResolvExpr/TypeEnvironment.h	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/ResolvExpr/TypeEnvironment.h	(revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 12:24:58 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Apr 30 23:04:10 2019
-// Update Count     : 9
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Jul 19 17:00:10 2019
+// Update Count     : 10
 //
 
@@ -40,5 +40,5 @@
 	// declarations.
 	//
-	// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this 
+	// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this
 	// comparator.
 	//
@@ -46,12 +46,12 @@
 	// memory layout can alter compilation time in unpredictable ways. For example, the placement
 	// of a line directive can reorder type pointers with respect to each other so that assertions
-	// are seen in different orders, causing a potentially different number of unification calls 
-	// when resolving assertions. I've seen a TU go from 36 seconds to 27 seconds by reordering 
-	// line directives alone, so it would be nice to fix this comparison so that assertions compare 
-	// more consistently. I've tried to modify this to compare on mangle name instead of type as 
-	// the second comparator, but this causes some assertions to never be recorded. More 
+	// are seen in different orders, causing a potentially different number of unification calls
+	// when resolving assertions. I've seen a TU go from 36 seconds to 27 seconds by reordering
+	// line directives alone, so it would be nice to fix this comparison so that assertions compare
+	// more consistently. I've tried to modify this to compare on mangle name instead of type as
+	// the second comparator, but this causes some assertions to never be recorded. More
 	// investigation is needed.
 	struct AssertCompare {
-		bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const {
+		bool operator()( const DeclarationWithType * d1, const DeclarationWithType * d2 ) const {
 			int cmp = d1->get_name().compare( d2->get_name() );
 			return cmp < 0 ||
@@ -65,5 +65,5 @@
 		AssertionSetValue() : isUsed(false), resnSlot(0) {}
 	};
-	typedef std::map< DeclarationWithType *, AssertionSetValue, AssertCompare > AssertionSet;
+	typedef std::map< const DeclarationWithType *, AssertionSetValue, AssertCompare > AssertionSet;
 	typedef std::unordered_map< std::string, TypeDecl::Data > OpenVarSet;
 
@@ -78,5 +78,5 @@
 	struct EqvClass {
 		std::set< std::string > vars;
-		Type *type;
+		Type * type;
 		bool allowWidening;
 		TypeDecl::Data data;
@@ -111,5 +111,5 @@
 		bool isEmpty() const { return env.empty(); }
 		void print( std::ostream &os, Indenter indent = {} ) const;
-		
+
 		/// Simply concatenate the second environment onto this one; no safety checks performed
 		void simpleCombine( const TypeEnvironment &second );
@@ -126,5 +126,5 @@
 		/// Returns false if fails, but does NOT roll back partial changes.
 		bool combine( const TypeEnvironment& second, OpenVarSet& openVars, const SymTab::Indexer& indexer );
-		
+
 		void extractOpenVars( OpenVarSet &openVars ) const;
 		TypeEnvironment *clone() const { return new TypeEnvironment( *this ); }
@@ -134,11 +134,11 @@
 		void addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars );
 
-		/// Binds the type class represented by `typeInst` to the type `bindTo`; will add 
+		/// Binds the type class represented by `typeInst` to the type `bindTo`; will add
 		/// the class if needed. Returns false on failure.
-		bool bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
-		
-		/// Binds the type classes represented by `var1` and `var2` together; will add 
+		bool bindVar( const TypeInstType * typeInst, Type * bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
+
+		/// Binds the type classes represented by `var1` and `var2` together; will add
 		/// one or both classes if needed. Returns false on failure.
-		bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
+		bool bindVarToVar( const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
 
 		/// Disallows widening for all bindings in the environment
@@ -151,5 +151,5 @@
 	  private:
 		ClassList env;
-		
+
 		ClassList::iterator internal_lookup( const std::string &var );
 	};
Index: src/ResolvExpr/typeops.h
===================================================================
--- src/ResolvExpr/typeops.h	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/ResolvExpr/typeops.h	(revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -149,5 +149,5 @@
 
 	// in Occurs.cc
-	bool occurs( Type * type, std::string varName, const TypeEnvironment & env );
+	bool occurs( const Type * type, const std::string & varName, const TypeEnvironment & env );
 	// new AST version in TypeEnvironment.cpp (only place it was used in old AST)
 
@@ -200,5 +200,5 @@
 
 	// in TypeEnvironment.cc
-	bool isFtype( Type * type );
+	bool isFtype( const Type * type );
 } // namespace ResolvExpr
 
Index: src/SynTree/Type.cc
===================================================================
--- src/SynTree/Type.cc	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/SynTree/Type.cc	(revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Jan 31 21:54:16 2019
-// Update Count     : 43
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Jul 12 15:48:00 2019
+// Update Count     : 44
 //
 #include "Type.h"
@@ -141,4 +141,11 @@
 }
 
+const Type * Type::stripReferences() const {
+	const Type * type;
+	const ReferenceType * ref;
+	for ( type = this; (ref = dynamic_cast<const ReferenceType *>( type )); type = ref->base );
+	return type;
+}
+
 int Type::referenceDepth() const { return 0; }
 
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/SynTree/Type.h	(revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -172,4 +172,5 @@
 	/// return type without outer references
 	Type * stripReferences();
+	const Type * stripReferences() const;
 
 	/// return the number of references occuring consecutively on the outermost layer of this type (i.e. do not count references nested within other types)
@@ -256,5 +257,5 @@
 	BasicType( const Type::Qualifiers & tq, Kind bt, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
 
-	Kind get_kind() { return kind; }
+	Kind get_kind() const { return kind; }
 	void set_kind( Kind newValue ) { kind = newValue; }
 
Index: src/SynTree/module.mk
===================================================================
--- src/SynTree/module.mk	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/SynTree/module.mk	(revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
Index: src/Tuples/TupleExpansion.cc
===================================================================
--- src/Tuples/TupleExpansion.cc	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/Tuples/TupleExpansion.cc	(revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -9,7 +9,7 @@
 // Author           : Rodolfo G. Esteves
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb 13 18:14:12 2019
-// Update Count     : 21
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Jul 19 14:39:00 2019
+// Update Count     : 22
 //
 
@@ -350,4 +350,13 @@
 	}
 
+	const TypeInstType * isTtype( const Type * type ) {
+		if ( const TypeInstType * inst = dynamic_cast< const TypeInstType * >( type ) ) {
+			if ( inst->baseType && inst->baseType->kind == TypeDecl::Ttype ) {
+				return inst;
+			}
+		}
+		return nullptr;
+	}
+
 	const ast::TypeInstType * isTtype( const ast::Type * type ) {
 		if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
@@ -364,9 +373,9 @@
 			ImpurityDetector( bool ignoreUnique ) : ignoreUnique( ignoreUnique ) {}
 
-			void previsit( ApplicationExpr * appExpr ) {
+			void previsit( const ApplicationExpr * appExpr ) {
 				visit_children = false;
-				if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
-					if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
-						if ( function->get_name() == "*?" || function->get_name() == "?[?]" ) {
+				if ( const DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
+					if ( function->linkage == LinkageSpec::Intrinsic ) {
+						if ( function->name == "*?" || function->name == "?[?]" ) {
 							// intrinsic dereference, subscript are pure, but need to recursively look for impurity
 							visit_children = true;
@@ -377,6 +386,6 @@
 				maybeImpure = true;
 			}
-			void previsit( UntypedExpr * ) { maybeImpure = true; visit_children = false; }
-			void previsit( UniqueExpr * ) {
+			void previsit( const UntypedExpr * ) { maybeImpure = true; visit_children = false; }
+			void previsit( const UniqueExpr * ) {
 				if ( ignoreUnique ) {
 					// bottom out at unique expression.
@@ -393,5 +402,5 @@
 	} // namespace
 
-	bool maybeImpure( Expression * expr ) {
+	bool maybeImpure( const Expression * expr ) {
 		PassVisitor<ImpurityDetector> detector( false );
 		expr->accept( detector );
@@ -399,5 +408,5 @@
 	}
 
-	bool maybeImpureIgnoreUnique( Expression * expr ) {
+	bool maybeImpureIgnoreUnique( const Expression * expr ) {
 		PassVisitor<ImpurityDetector> detector( true );
 		expr->accept( detector );
Index: src/Tuples/Tuples.h
===================================================================
--- src/Tuples/Tuples.h	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/Tuples/Tuples.h	(revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -52,13 +52,14 @@
 	/// returns a TypeInstType if `type` is a ttype, nullptr otherwise
 	TypeInstType * isTtype( Type * type );
+	const TypeInstType * isTtype( const Type * type );
 	const ast::TypeInstType * isTtype( const ast::Type * type );
 
 	/// returns true if the expression may contain side-effects.
-	bool maybeImpure( Expression * expr );
+	bool maybeImpure( const Expression * expr );
 	bool maybeImpure( const ast::Expr * expr );
 
 	/// Returns true if the expression may contain side-effect,
 	/// ignoring the presence of unique expressions.
-	bool maybeImpureIgnoreUnique( Expression * expr );
+	bool maybeImpureIgnoreUnique( const Expression * expr );
 	bool maybeImpureIgnoreUnique( const ast::Expr * expr );
 } // namespace Tuples
