CREATE TABLE t(i int); INSERT INTO t VALUES (1), (1);
WITH RECURSIVE rt(i) AS ( SELECT * FROM t UNION SELECT * FROM rt ) SELECT * FROM rt;
Nice catch. The TupleHashTable's tableslot is created as type TTSOpsMinimalTuple. The RecursiveUnion's non-recursive term generates tuples of type TTSOpsBufferHeapTuple. If the non-recursive term produces duplicate tuples, we'd find non-empty bucket when inserting the same key into the hashtable. In this case we need to check to see if the two tuples match: one is of the hashtable's tableslot (TTSOpsMinimalTuple), and the other comes from the non-recursive term (TTSOpsBufferHeapTuple). And the incompatible slot type would fail CheckOpSlotCompatibility.
I have no idea about how to fix it.
BTW, while reading the codes, I noticed two typos in simplehash.h, one is in the comment of SH_INSERT, the other is in the comment of SH_INSERT_HASH. Attached is a trivial patch for that.