Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision 7d651a66289ee32aed2ad5c25b33322822f36702)
+++ src/InitTweak/GenInit.cc	(revision 2c2b60fa2776c3fb2d9d23a8918afd18e2195899)
@@ -26,4 +26,5 @@
 #include "AST/Node.hpp"
 #include "AST/Stmt.hpp"
+#include "CompilationState.h"
 #include "CodeGen/OperatorTable.h"
 #include "Common/PassVisitor.h"        // for PassVisitor, WithGuards, WithShort...
@@ -122,7 +123,10 @@
 
 	void genInit( std::list< Declaration * > & translationUnit ) {
+		HoistArrayDimension::hoistArrayDimension( translationUnit );
 		fixReturnStatements( translationUnit );
-		HoistArrayDimension::hoistArrayDimension( translationUnit );
-		CtorDtor::generateCtorDtor( translationUnit );
+
+		if (!useNewAST) {
+			CtorDtor::generateCtorDtor( translationUnit );
+		}
 	}
 
@@ -192,9 +196,14 @@
 
 			// need to resolve array dimensions in order to accurately determine if constexpr
-			ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer );
-			// array is variable-length when the dimension is not constexpr
-			arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
+			if (!useNewAST) {
+				ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer );
+				// array is variable-length when the dimension is not constexpr
+				arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
+			}
 			// don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects.
-			if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
+			// xxx - hoisting has no side effects anyways, so don't skip since we delay resolve	
+			// only skip in the most trivial case, which does not require resolve
+			if (dynamic_cast<ConstantExpr *>(arrayType->dimension)) return;
+			// if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
 
 			ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
@@ -245,4 +254,5 @@
 	}
 
+	// why is this not just on FunctionDecl?
 	void ManagedTypes::handleDWT( DeclarationWithType * dwt ) {
 		// if this function is a user-defined constructor or destructor, mark down the type as "managed"
@@ -274,4 +284,63 @@
 	void ManagedTypes::beginScope() { managedTypes.beginScope(); }
 	void ManagedTypes::endScope() { managedTypes.endScope(); }
+
+	bool ManagedTypes_new::isManaged( const ast::Type * type ) const {
+		// references are never constructed
+		if ( dynamic_cast< const ast::ReferenceType * >( type ) ) return false;
+		if ( auto tupleType = dynamic_cast< const ast::TupleType * > ( type ) ) {
+			// tuple is also managed if any of its components are managed
+			for (auto & component : tupleType->types) {
+				if (isManaged(component)) return true;
+			}
+		}
+		// need to clear and reset qualifiers when determining if a type is managed
+		// ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() );
+		auto tmp = shallowCopy(type);
+		tmp->qualifiers = {};
+		// delete tmp at return
+		ast::ptr<ast::Type> guard = tmp;
+		// a type is managed if it appears in the map of known managed types, or if it contains any polymorphism (is a type variable or generic type containing a type variable)
+		return managedTypes.find( Mangle::mangle( tmp, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) ) != managedTypes.end() || GenPoly::isPolyType( tmp );
+	}
+
+	bool ManagedTypes_new::isManaged( const ast::ObjectDecl * objDecl ) const {
+		const ast::Type * type = objDecl->type;
+		while ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
+			// must always construct VLAs with an initializer, since this is an error in C
+			if ( at->isVarLen && objDecl->init ) return true;
+			type = at->base;
+		}
+		return isManaged( type );
+	}
+
+	void ManagedTypes_new::handleDWT( const ast::DeclWithType * dwt ) {
+		// if this function is a user-defined constructor or destructor, mark down the type as "managed"
+		if ( ! dwt->linkage.is_overrideable && CodeGen::isCtorDtor( dwt->name ) ) {
+			auto & params = GenPoly::getFunctionType( dwt->get_type())->params;
+			assert( ! params.empty() );
+			// Type * type = InitTweak::getPointerBase( params.front() );
+			// assert( type );
+			managedTypes.insert( Mangle::mangle( params.front(), {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) );
+		}
+	}
+
+	void ManagedTypes_new::handleStruct( const ast::StructDecl * aggregateDecl ) {
+		// don't construct members, but need to take note if there is a managed member,
+		// because that means that this type is also managed
+		for ( auto & member : aggregateDecl->members ) {
+			if ( auto field = member.as<ast::ObjectDecl>() ) {
+				if ( isManaged( field ) ) {
+					// generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that
+					// polymorphic constructors make generic types managed types
+					ast::StructInstType inst( aggregateDecl );
+					managedTypes.insert( Mangle::mangle( &inst, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) );
+					break;
+				}
+			}
+		}
+	}
+
+	void ManagedTypes_new::beginScope() { managedTypes.beginScope(); }
+	void ManagedTypes_new::endScope() { managedTypes.endScope(); }
 
 	ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) {
@@ -370,9 +439,10 @@
 	// constructable object
 	InitExpander_new srcParam{ objDecl->init }, nullParam{ (const ast::Init *)nullptr };
+	ast::ptr< ast::Expr > dstParam = new ast::VariableExpr(loc, objDecl);
 	
 	ast::ptr< ast::Stmt > ctor = SymTab::genImplicitCall( 
-		srcParam, new ast::VariableExpr{ loc, objDecl }, loc, "?{}", objDecl );
+		srcParam, dstParam, loc, "?{}", objDecl );
 	ast::ptr< ast::Stmt > dtor = SymTab::genImplicitCall( 
-		nullParam, new ast::VariableExpr{ loc, objDecl }, loc, "^?{}", objDecl, 
+		nullParam, dstParam, loc, "^?{}", objDecl, 
 		SymTab::LoopBackward );
 	
Index: src/InitTweak/GenInit.h
===================================================================
--- src/InitTweak/GenInit.h	(revision 7d651a66289ee32aed2ad5c25b33322822f36702)
+++ src/InitTweak/GenInit.h	(revision 2c2b60fa2776c3fb2d9d23a8918afd18e2195899)
@@ -52,4 +52,18 @@
 		GenPoly::ScopedSet< std::string > managedTypes;
 	};
+
+	class ManagedTypes_new {
+	public:
+		bool isManaged( const ast::ObjectDecl * objDecl ) const ; // determine if object is managed
+		bool isManaged( const ast::Type * type ) const; // determine if type is managed
+
+		void handleDWT( const ast::DeclWithType * dwt ); // add type to managed if ctor/dtor
+		void handleStruct( const ast::StructDecl * aggregateDecl ); // add type to managed if child is managed
+
+		void beginScope();
+		void endScope();
+	private:
+		GenPoly::ScopedSet< std::string > managedTypes;
+	};
 } // namespace
 
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 7d651a66289ee32aed2ad5c25b33322822f36702)
+++ src/InitTweak/InitTweak.cc	(revision 2c2b60fa2776c3fb2d9d23a8918afd18e2195899)
@@ -87,4 +87,41 @@
 		};
 
+		struct HasDesignations_new : public ast::WithShortCircuiting {
+			bool result = false;
+
+			void previsit( const ast::Node * ) {
+				// short circuit if we already know there are designations
+				if ( result ) visit_children = false;
+			}
+
+			void previsit( const ast::Designation * des ) {
+				// short circuit if we already know there are designations
+				if ( result ) visit_children = false;
+				else if ( ! des->designators.empty() ) {
+					result = true;
+					visit_children = false;
+				}
+			}
+		};
+
+		struct InitDepthChecker_new : public ast::WithGuards {
+			bool result = true;
+			const ast::Type * type;
+			int curDepth = 0, maxDepth = 0;
+			InitDepthChecker_new( const ast::Type * type ) : type( type ) {
+				const ast::Type * t = type;
+				while ( auto at = dynamic_cast< const ast::ArrayType * >( t ) ) {
+					maxDepth++;
+					t = at->base;
+				}
+				maxDepth++;
+			}
+			void previsit( ListInit * ) {
+				curDepth++;
+				GuardAction( [this]() { curDepth--; } );
+				if ( curDepth > maxDepth ) result = false;
+			}
+		};
+
 		struct InitFlattener_old : public WithShortCircuiting {
 			void previsit( SingleInit * singleInit ) {
@@ -122,4 +159,16 @@
 		maybeAccept( objDecl->init, checker );
 		return checker.pass.depthOkay;
+	}
+
+	bool isDesignated( const ast::Init * init ) {
+		ast::Pass<HasDesignations_new> finder;
+		maybe_accept( init, finder );
+		return finder.core.result;
+	}
+
+	bool checkInitDepth( const ast::ObjectDecl * objDecl ) {
+		ast::Pass<InitDepthChecker_new> checker( objDecl->type );
+		maybe_accept( objDecl->init.get(), checker );
+		return checker.core.result;
 	}
 
@@ -358,8 +407,8 @@
 			if ( auto listInit = dynamic_cast< const ast::ListInit * >( init ) ) {
 				for ( const ast::Init * init : *listInit ) {
-					buildCallExpr( callExpr, index, dimension, init, out );
+					buildCallExpr( shallowCopy(callExpr), index, dimension, init, out );
 				}
 			} else {
-				buildCallExpr( callExpr, index, dimension, init, out );
+				buildCallExpr( shallowCopy(callExpr), index, dimension, init, out );
 			}
 		} else {
@@ -1027,4 +1076,47 @@
 	};
 
+	struct ConstExprChecker_new : public ast::WithShortCircuiting {
+		// most expressions are not const expr
+		void previsit( const ast::Expr * ) { result = false; visit_children = false; }
+
+		void previsit( const ast::AddressExpr *addressExpr ) {
+			visit_children = false;
+			const ast::Expr * arg = addressExpr->arg;
+
+			// address of a variable or member expression is constexpr
+			if ( ! dynamic_cast< const ast::NameExpr * >( arg ) 
+			&& ! dynamic_cast< const ast::VariableExpr * >( arg ) 
+			&& ! dynamic_cast< const ast::MemberExpr * >( arg ) 
+			&& ! dynamic_cast< const ast::UntypedMemberExpr * >( arg ) ) result = false;
+		}
+
+		// these expressions may be const expr, depending on their children
+		void previsit( const ast::SizeofExpr * ) {}
+		void previsit( const ast::AlignofExpr * ) {}
+		void previsit( const ast::UntypedOffsetofExpr * ) {}
+		void previsit( const ast::OffsetofExpr * ) {}
+		void previsit( const ast::OffsetPackExpr * ) {}
+		void previsit( const ast::CommaExpr * ) {}
+		void previsit( const ast::LogicalExpr * ) {}
+		void previsit( const ast::ConditionalExpr * ) {}
+		void previsit( const ast::CastExpr * ) {}
+		void previsit( const ast::ConstantExpr * ) {}
+
+		void previsit( const ast::VariableExpr * varExpr ) {
+			visit_children = false;
+
+			if ( auto inst = varExpr->result.as<ast::EnumInstType>() ) {
+				long long int value;
+				if ( inst->base->valueOf( varExpr->var, value ) ) {
+					// enumerators are const expr
+					return;
+				}
+			}
+			result = false;
+		}
+
+		bool result = true;
+	};
+
 	bool isConstExpr( Expression * expr ) {
 		if ( expr ) {
@@ -1046,4 +1138,23 @@
 	}
 
+	bool isConstExpr( const ast::Expr * expr ) {
+		if ( expr ) {
+			ast::Pass<ConstExprChecker_new> checker;
+			expr->accept( checker );
+			return checker.core.result;
+		}
+		return true;
+	}
+
+	bool isConstExpr( const ast::Init * init ) {
+		if ( init ) {
+			ast::Pass<ConstExprChecker_new> checker;
+			init->accept( checker );
+			return checker.core.result;
+		} // if
+		// for all intents and purposes, no initializer means const expr
+		return true;
+	}
+
 	bool isConstructor( const std::string & str ) { return str == "?{}"; }
 	bool isDestructor( const std::string & str ) { return str == "^?{}"; }
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision 7d651a66289ee32aed2ad5c25b33322822f36702)
+++ src/InitTweak/InitTweak.h	(revision 2c2b60fa2776c3fb2d9d23a8918afd18e2195899)
@@ -59,8 +59,10 @@
 	/// True if the Initializer contains designations
 	bool isDesignated( Initializer * init );
+	bool isDesignated( const ast::Init * init );
 
 	/// True if the ObjectDecl's Initializer nesting level is not deeper than the depth of its
 	/// type, where the depth of its type is the number of nested ArrayTypes + 1
 	bool checkInitDepth( ObjectDecl * objDecl );
+	bool checkInitDepth( const ast::ObjectDecl * objDecl );
 
 	/// returns the declaration of the function called by the expr (must be ApplicationExpr or UntypedExpr)
@@ -107,4 +109,7 @@
 	bool isConstExpr( Expression * expr );
 	bool isConstExpr( Initializer * init );
+
+	bool isConstExpr( const ast::Expr * expr );
+	bool isConstExpr( const ast::Init * init );
 
 	/// Modifies objDecl to have:
