parse_coerce.c's resolve_generic_type() is written on the assumption that it might be asked to infer any polymorphic type's concrete type given any other polymorphic type's concrete type. This is overkill, because the only call sites look like
anyelement_type = resolve_generic_type(ANYELEMENTOID, anyarray_type, ANYARRAYOID); subtype = resolve_generic_type(ANYELEMENTOID, anyrange_type, ANYRANGEOID); anyarray_type = resolve_generic_type(ANYARRAYOID, anyelement_type, ANYELEMENTOID); (There are two occurrences of each of these in funcapi.c, and nothing anywhere else.) But that's a good thing, because resolve_generic_type() gets some of the un-exercised cases wrong. Notably, it appears to believe that anyrange is the same type variable as anyelement: if asked to resolve anyarray from anyrange, it will produce the array over the concrete range type, where it should produce the array over the range's subtype. Rather than fix this up, I'm inclined to just nuke resolve_generic_type() altogether, and replace the call sites with direct uses of the underlying lookups such as get_array_type(). I think this is simpler to understand as well as being significantly less code. I also noticed that there's an asymmetry in funcapi.c's usage pattern: it can resolve anyelement from either anyarray or anyrange, but it can only resolve anyarray from anyelement not anyrange. This results in warts like so: regression=# create function foo(x anyrange) returns anyarray language sql as 'select array[lower(x),upper(x)]'; CREATE FUNCTION regression=# select foo(int4range(6,9)); foo ------- {6,9} (1 row) -- so far so good, but let's try it with OUT parameters: regression=# create function foo2(x anyrange, out lu anyarray, out ul anyarray) language sql as 'select array[lower(x),upper(x)], array[upper(x),lower(x)]'; CREATE FUNCTION regression=# select * from foo2(int4range(6,9)); ERROR: cache lookup failed for type 0 So that's a bug that needs fixing in any case. regards, tom lane