Problem z prostą próbą polega na tym, że masz obsadę wywołującą obsadę, wywołującą obsadę, wywołującą obsadę...
Musisz jakoś uciec od varchar->enum w swojej obsadzie. Najprostszym (najbardziej zrozumiałym) sposobem jest po prostu ręczna konwersja. Zwróć uwagę, że literały ciągu znaków rzutowane w instrukcji case nie są tekstem, lecz są w cudzysłowie typu nieznanego, co omija nieskończoną rekurencję.
BEGIN;
CREATE TYPE t_tl AS ENUM ('red', 'amber', 'green');
CREATE FUNCTION dummy_cast(varchar) RETURNS t_tl AS $$
SELECT CASE $1
WHEN 'red' THEN 'red'::t_tl
WHEN 'amber' THEN 'amber'::t_tl
WHEN 'green' THEN 'green'::t_tl
END;
$$ LANGUAGE SQL;
CREATE CAST (varchar AS t_tl) WITH FUNCTION dummy_cast(varchar) AS ASSIGNMENT;
CREATE TABLE t (x t_tl);
INSERT INTO t VALUES ('red');
INSERT INTO t VALUES ('green'::varchar);
SELECT * FROM t;
ROLLBACK;