Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 793335167c5347f27e76d8ab9f3434b795a6602d)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision ea83e00ae85e9300955d14033071827d7db730f3)
@@ -608,4 +608,13 @@
 		makeUnifiableVars( funcType, openVars, resultNeed );
 		AltList instantiatedActuals; // filled by instantiate function
+		if ( targetType && ! targetType->isVoid() ) {
+			// attempt to narrow based on expected target type
+			Type * returnType = funcType->get_returnVals().front()->get_type();
+			if ( ! unify( returnType, targetType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
+				// unification failed, don't pursue this alternative
+				return;
+			}
+		}
+
 		if ( instantiateFunction( funcType->get_parameters(), actualAlt, funcType->get_isVarArgs(), openVars, resultEnv, resultNeed, resultHave, instantiatedActuals ) ) {
 			ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
@@ -740,4 +749,17 @@
 
 		findMinCost( candidates.begin(), candidates.end(), std::back_inserter( alternatives ) );
+
+		if ( alternatives.empty() && targetType && ! targetType->isVoid() ) {
+			// xxx - this is a temporary hack. If resolution is unsuccessful with a target type, try again without a
+			// target type, since it will sometimes succeed when it wouldn't easily with target type binding. For example,
+			//   forall( otype T ) lvalue T	?[?]( T *, ptrdiff_t );
+			//   const char * x = "hello world";
+			//   unsigned char ch = x[0];
+			// Fails with simple return type binding. First, T is bound to unsigned char, then (x: const char *) is unified
+			// with unsigned char *, which fails because pointer base types must be unified exactly. The new resolver should
+			// fix this issue in a more robust way.
+			targetType = nullptr;
+			visit( untypedExpr );
+		}
 	}
 
