Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision d104b0259d2af56d64a4f024802ad2afa0236505)
+++ src/InitTweak/FixInit.cc	(revision 5ccb10d750e81ef921035bdd254327997acd80ae)
@@ -591,23 +591,4 @@
 
 				Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
-				if ( callExpr->get_result()->get_lvalue() ) {
-					// lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning
-					// non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the
-					// type of the return temporary from T to T* to properly capture the return value. Then dereference
-					// the result of the comma expression, since the lvalue returning call was originally wrapped with
-					// an AddressExpr.  Effectively, this turns
-					//   lvalue T f();
-					//   &*f();
-					// into
-					//   T * f();
-					//   T * tmp_cp_retN;
-					//   &*(tmp_cp_retN = &*f(), tmp_cp_retN);		// the first * and second & are generated here
-					// which work out in terms of types, but is pretty messy. It would be nice to find a better way.
-					assign->get_args().back() = new AddressExpr( assign->get_args().back() );
-
-					returnDecl->set_type( new PointerType( Type::Qualifiers(), returnDecl->get_type() ) );
-					retExpr->set_result( new PointerType( Type::Qualifiers(), retExpr->get_result() ) );
-					retExpr = UntypedExpr::createDeref( retExpr );
-				} // if
 				// move env from callExpr to retExpr
 				retExpr->set_env( callExpr->get_env() );
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision d104b0259d2af56d64a4f024802ad2afa0236505)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 5ccb10d750e81ef921035bdd254327997acd80ae)
@@ -845,5 +845,5 @@
 			// then excess components do not come out in the result expression (but UniqueExprs ensure that
 			// side effects will still be done).
-			if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) {
+			if ( Tuples::maybeImpureIgnoreUnique( argExpr ) ) {
 				// expressions which may contain side effects require a single unique instance of the expression.
 				argExpr = new UniqueExpr( argExpr );
Index: src/ResolvExpr/CommonType.cc
===================================================================
--- src/ResolvExpr/CommonType.cc	(revision d104b0259d2af56d64a4f024802ad2afa0236505)
+++ src/ResolvExpr/CommonType.cc	(revision 5ccb10d750e81ef921035bdd254327997acd80ae)
@@ -18,5 +18,5 @@
 #include "Unify.h"
 
-/// #define DEBUG
+// #define DEBUG
 
 namespace ResolvExpr {
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision d104b0259d2af56d64a4f024802ad2afa0236505)
+++ src/ResolvExpr/ConversionCost.cc	(revision 5ccb10d750e81ef921035bdd254327997acd80ae)
@@ -28,4 +28,9 @@
 	const Cost Cost::reference = Cost( 0, 0, 0, 1 );
 
+#if 0
+#define PRINT(x) x
+#else
+#define PRINT(x)
+#endif
 
 	Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
@@ -33,5 +38,5 @@
 			EqvClass eqvClass;
 			NamedTypeDecl *namedType;
-///     std::cout << "type inst " << destAsTypeInst->get_name();
+			PRINT( std::cerr << "type inst " << destAsTypeInst->get_name(); )
 			if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) {
 				if ( eqvClass.type ) {
@@ -41,5 +46,5 @@
 				}
 			} else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) {
-///       std::cout << " found" << std::endl;
+				PRINT( std::cerr << " found" << std::endl; )
 				TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
 				// all typedefs should be gone by this point
@@ -49,19 +54,21 @@
 				} // if
 			} // if
-///     std::cout << " not found" << std::endl;
-		} // if
-///   std::cout << "src is ";
-///   src->print( std::cout );
-///   std::cout << std::endl << "dest is ";
-///   dest->print( std::cout );
-///   std::cout << std::endl << "env is" << std::endl;
-///   env.print( std::cout, 8 );
+			PRINT( std::cerr << " not found" << std::endl; )
+		} // if
+		PRINT(
+			std::cerr << "src is ";
+			src->print( std::cerr );
+			std::cerr << std::endl << "dest is ";
+			dest->print( std::cerr );
+			std::cerr << std::endl << "env is" << std::endl;
+			env.print( std::cerr, 8 );
+		)
 		if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
-///     std::cout << "compatible!" << std::endl;
+			PRINT( std::cerr << "compatible!" << std::endl; )
 			return Cost::zero;
 		} else if ( dynamic_cast< VoidType* >( dest ) ) {
 			return Cost::safe;
 		} else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
-			// std::cerr << "conversionCost: dest is reference" << std::endl;
+			PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
 			return convertToReferenceCost( src, refType, indexer, env );
 		} else {
@@ -77,5 +84,5 @@
 
 	Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
-		// std::cerr << "convert to reference cost..." << std::endl;
+		PRINT( std::cerr << "convert to reference cost..." << std::endl; )
 		if ( diff > 0 ) {
 			// TODO: document this
@@ -92,9 +99,10 @@
 			ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
 			if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
-				// std::cerr << "converting between references" << std::endl;
+				PRINT( std::cerr << "converting between references" << std::endl; )
 				if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) {
 					return Cost::safe;
 				} else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
 					int assignResult = ptrsAssignable( srcAsRef->get_base(), destAsRef->get_base(), env );
+					PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
 					if ( assignResult < 0 ) {
 						return Cost::safe;
@@ -104,5 +112,5 @@
 				} // if
 			} else {
-				// std::cerr << "reference to rvalue conversion" << std::endl;
+				PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
 				ConversionCost converter( dest, indexer, env );
 				src->accept( converter );
@@ -113,7 +121,10 @@
 			assert( diff == -1 && destAsRef );
 			if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) {
-				// std::cerr << "converting compatible base type" << std::endl;
+				PRINT( std::cerr << "converting compatible base type" << std::endl; )
 				if ( src->get_lvalue() ) {
-					// std::cerr << "lvalue to reference conversion" << std::endl;
+					PRINT(
+						std::cerr << "lvalue to reference conversion" << std::endl;
+						std::cerr << src << " => " << destAsRef << std::endl;
+					)
 					// lvalue-to-reference conversion:  cv lvalue T => cv T &
 					if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) {
@@ -125,14 +136,14 @@
 					} // if
 				} else if ( destAsRef->get_base()->get_const() ) {
-					// std::cerr << "rvalue to const ref conversion" << std::endl;
+					PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; )
 					// rvalue-to-const-reference conversion: T => const T &
 					return Cost::safe;
 				} else {
-					// std::cerr << "rvalue to non-const reference conversion" << std::endl;
+					PRINT( std::cerr << "rvalue to non-const reference conversion" << std::endl; )
 					// rvalue-to-reference conversion: T => T &
 					return Cost::unsafe;
 				} // if
 			} // if
-			// std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl;
+			PRINT( std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; )
 		}
 		return Cost::infinity;
@@ -248,5 +259,5 @@
 	void ConversionCost::visit(PointerType *pointerType) {
 		if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
-			// std::cerr << pointerType << " ===> " << destAsPtr;
+			PRINT( std::cerr << pointerType << " ===> " << destAsPtr; )
 			Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers();
 			Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers();
@@ -257,10 +268,10 @@
 				} else {
 					// types are the same, except otherPointer has more qualifiers
-					// std::cerr << " :: compatible and good qualifiers" << std::endl;
+					PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
 					cost = Cost::safe;
 				}
 			} else {  // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
 				int assignResult = ptrsAssignable( pointerType->get_base(), destAsPtr->get_base(), env );
-				// std::cerr << " :: " << assignResult << std::endl;
+				PRINT( std::cerr << " :: " << assignResult << std::endl; )
 				if ( assignResult < 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) {
 					cost = Cost::safe;
@@ -291,5 +302,5 @@
 			cost.incUnsafe(); // lose qualifiers as last resort
 		}
-		// std::cerr << refType << " ==> " << dest << " " << cost << std::endl;
+		PRINT( std::cerr << refType << " ==> " << dest << " " << cost << std::endl; )
 	}
 
Index: src/ResolvExpr/PtrsAssignable.cc
===================================================================
--- src/ResolvExpr/PtrsAssignable.cc	(revision d104b0259d2af56d64a4f024802ad2afa0236505)
+++ src/ResolvExpr/PtrsAssignable.cc	(revision 5ccb10d750e81ef921035bdd254327997acd80ae)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// PtrsAssignable.cc -- 
+// PtrsAssignable.cc --
 //
 // Author           : Richard C. Bilson
@@ -83,8 +83,8 @@
 	void PtrsAssignable::visit(  __attribute__((unused)) UnionInstType *inst ) {}
 
-	void PtrsAssignable::visit( EnumInstType *inst ) {
-		if ( dynamic_cast< EnumInstType* >( inst ) ) {
+	void PtrsAssignable::visit( EnumInstType * ) {
+		if ( dynamic_cast< EnumInstType* >( dest ) ) {
 			result = 1;
-		} else if ( BasicType *bt = dynamic_cast< BasicType* >( inst ) ) {
+		} else if ( BasicType *bt = dynamic_cast< BasicType* >( dest ) ) {
 			result = bt->get_kind() == BasicType::SignedInt;
 		}
@@ -105,5 +105,5 @@
 	void PtrsAssignable::visit(  __attribute__((unused)) ZeroType *zeroType ) {}
 	void PtrsAssignable::visit(  __attribute__((unused)) OneType *oneType ) {}
-	
+
 } // namespace ResolvExpr
 
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision d104b0259d2af56d64a4f024802ad2afa0236505)
+++ src/SynTree/Expression.cc	(revision 5ccb10d750e81ef921035bdd254327997acd80ae)
@@ -611,4 +611,5 @@
 CompoundLiteralExpr::CompoundLiteralExpr( Type * type, Initializer * initializer ) : initializer( initializer ) {
 	assert( type && initializer );
+	type->set_lvalue( true );
 	set_result( type );
 }
Index: src/SynTree/TupleExpr.cc
===================================================================
--- src/SynTree/TupleExpr.cc	(revision d104b0259d2af56d64a4f024802ad2afa0236505)
+++ src/SynTree/TupleExpr.cc	(revision 5ccb10d750e81ef921035bdd254327997acd80ae)
@@ -60,5 +60,6 @@
 	assertf( type->size() > index, "TupleIndexExpr index out of bounds: tuple size %d, requested index %d in expr %s", type->size(), index, toString( tuple ).c_str() );
 	set_result( (*std::next( type->get_types().begin(), index ))->clone() );
-	get_result()->set_lvalue( type->get_lvalue() );
+	// like MemberExpr, TupleIndexExpr is always an lvalue
+	get_result()->set_lvalue( true );
 }
 
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision d104b0259d2af56d64a4f024802ad2afa0236505)
+++ src/SynTree/Type.h	(revision 5ccb10d750e81ef921035bdd254327997acd80ae)
@@ -311,4 +311,9 @@
 	virtual int referenceDepth() const;
 
+	// Since reference types act like value types, their size is the size of the base.
+	// This makes it simple to cast the empty tuple to a reference type, since casts that increase
+	// the number of values are disallowed.
+	virtual unsigned size() const { return base->size(); }
+
 	virtual ReferenceType *clone() const { return new ReferenceType( *this ); }
 	virtual void accept( Visitor & v ) { v.visit( this ); }
Index: src/prelude/prelude.cf
===================================================================
--- src/prelude/prelude.cf	(revision d104b0259d2af56d64a4f024802ad2afa0236505)
+++ src/prelude/prelude.cf	(revision 5ccb10d750e81ef921035bdd254327997acd80ae)
@@ -456,6 +456,6 @@
 forall( dtype DT ) const volatile DT *	?=?( const volatile DT * volatile &, zero_t );
 
-forall( ftype FT ) FT *			?=?( FT *	   &, forall( ftype FT2 ) FT2 * );
-forall( ftype FT ) FT *			?=?( FT * volatile &, forall( ftype FT2 ) FT2 * );
+forall( ftype FT ) FT *			?=?( FT *	   &, zero_t );
+forall( ftype FT ) FT *			?=?( FT * volatile &, zero_t );
 
 forall( dtype T | sized(T) ) T *			?+=?(		     T *	  &, ptrdiff_t );
@@ -806,5 +806,5 @@
 forall( dtype DT ) void ?{}( const volatile DT *	  &, zero_t );
 
-forall( ftype FT ) void	?{}( FT *	   &, forall( ftype FT2 ) FT2 * );
+forall( ftype FT ) void	?{}( FT *	   &, zero_t );
 
 // default ctors
