Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision 1dafdfc356ef109039c90bff9ffe0abe74b74097)
+++ src/GenPoly/Box.cc	(revision b3212de9003ac5b898990244b2bfcbc3acb1b6e1)
@@ -676,6 +676,40 @@
 		}
 
+		// find instances of polymorphic type parameters
+		struct PolyFinder {
+			const TyVarMap * tyVars = nullptr;
+			bool found = false;
+
+			void previsit( TypeInstType * t ) {
+				if ( isPolyType( t, *tyVars ) ) {
+					found = true;
+				}
+			}
+		};
+
+		// true if there is an instance of a polymorphic type parameter in t
+		bool hasPolymorphism( Type * t, const TyVarMap &tyVars ) {
+			PassVisitor<PolyFinder> finder;
+			finder.pass.tyVars = &tyVars;
+			maybeAccept( t, finder );
+			return finder.pass.found;
+		}
+
+		/// cast parameters to polymorphic functions so that types are replaced with
+		/// void * if they are type parameters in the formal type.
+		/// this gets rid of warnings from gcc.
+		void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) {
+			// type contains polymorphism, but isn't exactly a polytype, in which case it
+			// has some real actual type (e.g. unsigned int) and casting to void * is wrong
+			if ( hasPolymorphism( formal, tyVars ) && ! isPolyType( formal, tyVars ) ) {
+				Type * newType = formal->clone();
+				newType = ScrubTyVars::scrub( newType, tyVars );
+				actual = new CastExpr( actual, newType );
+			} // if
+		}
+
 		void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) {
 			assertf( arg->result, "arg does not have result: %s", toString( arg ).c_str() );
+			addCast( arg, param, exprTyVars );
 			if ( ! needsBoxing( param, arg->result, exprTyVars, env ) ) return;
 
@@ -708,41 +742,7 @@
 		}
 
-		// find instances of polymorphic type parameters
-		struct PolyFinder {
-			const TyVarMap * tyVars = nullptr;
-			bool found = false;
-
-			void previsit( TypeInstType * t ) {
-				if ( isPolyType( t, *tyVars ) ) {
-					found = true;
-				}
-			}
-		};
-
-		// true if there is an instance of a polymorphic type parameter in t
-		bool hasPolymorphism( Type * t, const TyVarMap &tyVars ) {
-			PassVisitor<PolyFinder> finder;
-			finder.pass.tyVars = &tyVars;
-			maybeAccept( t, finder );
-			return finder.pass.found;
-		}
-
-		/// cast parameters to polymorphic functions so that types are replaced with
-		/// void * if they are type parameters in the formal type.
-		/// this gets rid of warnings from gcc.
-		void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) {
-			// type contains polymorphism, but isn't exactly a polytype, in which case it
-			// has some real actual type (e.g. unsigned int) and casting to void * is wrong
-			if ( hasPolymorphism( formal, tyVars ) && ! isPolyType( formal, tyVars ) ) {
-				Type * newType = formal->clone();
-				newType = ScrubTyVars::scrub( newType, tyVars );
-				actual = new CastExpr( actual, newType );
-			} // if
-		}
-
 		void Pass1::boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
 			for ( DeclarationWithType * param : function->parameters ) {
 				assertf( arg != appExpr->args.end(), "boxParams: missing argument for param %s to %s in %s", toString( param ).c_str(), toString( function ).c_str(), toString( appExpr ).c_str() );
-				addCast( *arg, param->get_type(), exprTyVars );
 				boxParam( param->get_type(), *arg, exprTyVars );
 				++arg;
@@ -757,5 +757,4 @@
 					assertf( inferParam != appExpr->inferParams.end(), "addInferredParams missing inferred parameter: %s in: %s", toString( assert ).c_str(), toString( appExpr ).c_str() );
 					Expression *newExpr = inferParam->second.expr->clone();
-					addCast( newExpr, assert->get_type(), tyVars );
 					boxParam( assert->get_type(), newExpr, tyVars );
 					appExpr->get_args().insert( cur, newExpr );
@@ -788,11 +787,10 @@
 			assert( param );
 			assert( arg );
-			if ( isPolyType( realParam->get_type(), tyVars ) ) {
-				if ( ! isPolyType( arg->get_type() ) ) {
-					UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
-					deref->args.push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
-					deref->result = arg->get_type()->clone();
-					return deref;
-				} // if
+			if ( isPolyType( realParam->get_type(), tyVars )
+					&& ! isPolyType( arg->get_type() ) ) {
+				UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
+				deref->args.push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
+				deref->result = arg->get_type()->clone();
+				return deref;
 			} // if
 			return new VariableExpr( param );
@@ -1130,15 +1128,22 @@
 		}
 
-		Expression * Pass1::postmutate( UntypedExpr *expr ) {
+		bool isPolyDeref( UntypedExpr * expr, TyVarMap const & scopeTyVars, TypeSubstitution const * env ) {
 			if ( expr->result && isPolyType( expr->result, scopeTyVars, env ) ) {
 				if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->function ) ) {
 					if ( name->name == "*?" ) {
-						Expression *ret = expr->args.front();
-						expr->args.clear();
-						delete expr;
-						return ret;
+						return true;
 					} // if
 				} // if
 			} // if
+			return false;
+		}
+
+		Expression * Pass1::postmutate( UntypedExpr *expr ) {
+			if ( isPolyDeref( expr, scopeTyVars, env ) ) {
+				Expression *ret = expr->args.front();
+				expr->args.clear();
+				delete expr;
+				return ret;
+			}
 			return expr;
 		}
@@ -1150,14 +1155,10 @@
 			bool needs = false;
 			if ( UntypedExpr *expr = dynamic_cast< UntypedExpr *>( addrExpr->arg ) ) {
-				if ( expr->result && isPolyType( expr->result, scopeTyVars, env ) ) {
-					if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->function ) ) {
-						if ( name->name == "*?" ) {
-							if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->args.front() ) ) {
-								assert( appExpr->function->result );
-								FunctionType *function = getFunctionType( appExpr->function->result );
-								assert( function );
-								needs = needsAdapter( function, scopeTyVars );
-							} // if
-						} // if
+				if ( isPolyDeref( expr, scopeTyVars, env ) ) {
+					if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->args.front() ) ) {
+						assert( appExpr->function->result );
+						FunctionType *function = getFunctionType( appExpr->function->result );
+						assert( function );
+						needs = needsAdapter( function, scopeTyVars );
 					} // if
 				} // if
@@ -1432,12 +1433,7 @@
 
 			if(!expect_func_type) {
-				GuardAction( [this]() {
-					knownLayouts.endScope();
-					knownOffsets.endScope();
-				});
 				// If this is the first function type we see
 				// Then it's the type of the declaration and we care about it
-				knownLayouts.beginScope();
-				knownOffsets.beginScope();
+				GuardScope( *this );
 			}
 
