Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision 5339a87ca7689b734a2eb1d355830ea9713784a1)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision 4ef08f76a55ae935c3aff3e628469cb6618b8ca8)
@@ -1089,4 +1089,59 @@
 		}
 
+		void postvisit( const ast::KeywordCastExpr * castExpr ) {
+			const auto & loc = castExpr->location;
+			assertf( castExpr->result, "Cast target should have been set in Validate." );
+			auto ref = castExpr->result.strict_as<ast::ReferenceType>();
+			auto inst = ref->base.strict_as<ast::StructInstType>();
+			auto target = inst->base.get();
+
+			CandidateFinder finder{ symtab, tenv };
+
+			auto pick_alternatives = [target, this](CandidateList & found, bool expect_ref) {
+				for(auto & cand : found) {
+					const ast::Type * expr = cand->expr->result.get();
+					if(expect_ref) {
+						auto res = dynamic_cast<const ast::ReferenceType*>(expr);
+						if(!res) { continue; }
+						expr = res->base.get();
+					}
+
+					if(auto insttype = dynamic_cast<const ast::TypeInstType*>(expr)) {
+						auto td = cand->env.lookup(insttype->name);
+						if(!td) { continue; }
+						expr = td->bound.get();
+					}
+
+					if(auto base = dynamic_cast<const ast::StructInstType*>(expr)) {
+						if(base->base == target) {
+							candidates.push_back( std::move(cand) );
+							reason.code = NoReason;
+						}
+					}
+				}
+			};
+
+			try {
+				// Attempt 1 : turn (thread&)X into ($thread&)X.__thrd
+				// Clone is purely for memory management
+				std::unique_ptr<const ast::Expr> tech1 { new ast::UntypedMemberExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.field), castExpr->arg) };
+
+				// don't prune here, since it's guaranteed all alternatives will have the same type
+				finder.find( tech1.get(), ResolvMode::withoutPrune() );
+				pick_alternatives(finder.candidates, false);
+
+				return;
+			} catch(SemanticErrorException & ) {}
+
+			// Fallback : turn (thread&)X into ($thread&)get_thread(X)
+			std::unique_ptr<const ast::Expr> fallback { ast::UntypedExpr::createDeref(loc,  new ast::UntypedExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.getter), { castExpr->arg })) };
+			// don't prune here, since it's guaranteed all alternatives will have the same type
+			finder.find( fallback.get(), ResolvMode::withoutPrune() );
+
+			pick_alternatives(finder.candidates, true);
+
+			// Whatever happens here, we have no more fallbacks
+		}
+
 		void postvisit( const ast::UntypedMemberExpr * memberExpr ) {
 			CandidateFinder aggFinder{ symtab, tenv };
