Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision f9ad69dc6e86c3c08876734b6909ce8978446504)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision 2f317733f059f66b5e61a69d0dccbb26fd2459fc)
@@ -1241,4 +1241,9 @@
 		Cost minCastCost = Cost::infinity;
 		for ( CandidateRef & cand : finder.candidates ) {
+			ast::ptr< ast::Type > fromType = cand->expr->result;
+			assert( fromType );
+			fromType = resolveTypeof( fromType, context );
+			fromType = adjustExprType( fromType, tenv, symtab );
+
 			ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;
 			ast::OpenVarSet open( cand->open );
@@ -1250,16 +1255,16 @@
 			// subexpression results that are cast directly. The candidate is invalid if it
 			// has fewer results than there are types to cast to.
-			int discardedValues = cand->expr->result->size() - toType->size();
+			int discardedValues = fromType->size() - toType->size();
 			if ( discardedValues < 0 ) continue;
 
 			// unification run for side-effects
-			unify( toType, cand->expr->result, cand->env, need, have, open );
+			unify( toType, fromType, cand->env, need, have, open );
 			Cost thisCost =
 				(castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast)
-					? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env )
-					: castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env );
+					? conversionCost( fromType, toType, cand->expr->get_lvalue(), symtab, cand->env )
+					: castCost( fromType, toType, cand->expr->get_lvalue(), symtab, cand->env );
 			
 			// Redefine enum cast
-			auto argAsEnum = cand->expr->result.as<ast::EnumInstType>();
+			auto argAsEnum = fromType.as<ast::EnumInstType>();
 			auto toAsEnum = toType.as<ast::EnumInstType>();
 			if ( argAsEnum && toAsEnum && argAsEnum->name != toAsEnum->name ) {
@@ -1272,5 +1277,5 @@
 			PRINT(
 				std::cerr << "working on cast with result: " << toType << std::endl;
-				std::cerr << "and expr type: " << cand->expr->result << std::endl;
+				std::cerr << "and expr type: " << fromType << std::endl;
 				std::cerr << "env: " << cand->env << std::endl;
 			)
Index: tests/raii/.expect/typeof-member.txt
===================================================================
--- tests/raii/.expect/typeof-member.txt	(revision 2f317733f059f66b5e61a69d0dccbb26fd2459fc)
+++ tests/raii/.expect/typeof-member.txt	(revision 2f317733f059f66b5e61a69d0dccbb26fd2459fc)
@@ -0,0 +1,3 @@
+custom A ctor called
+5
+custom A dtor called
Index: tests/raii/typeof-member.cfa
===================================================================
--- tests/raii/typeof-member.cfa	(revision 2f317733f059f66b5e61a69d0dccbb26fd2459fc)
+++ tests/raii/typeof-member.cfa	(revision 2f317733f059f66b5e61a69d0dccbb26fd2459fc)
@@ -0,0 +1,38 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2023 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// typeof-member.cfa -- managed type declared as contained member via typeof
+//
+// Author           : Mike Brooks
+// Created On       : Tue Aug 13 12:00:00 2024
+// Last Modified By :
+// Last Modified On :
+// Update Count     :
+//
+
+// Note - array(...) expands as typeof(...).
+// So supporting member as typeof is necessary for having array as member.
+// The array type (arpk) is managed.
+
+struct A {
+    int x;
+};
+
+void  ?{}( A & ) { printf("custom A ctor called\n"); }
+void ^?{}( A & ) { printf("custom A dtor called\n"); }
+
+A foo( void );
+
+struct outer {
+    typeof( foo() ) a;
+};
+
+int main() {
+    outer b;
+    b.a.x = 5;
+    printf( "%d\n", b.a.x );
+    return 0;
+}
