Remix.run Logo
queoahfh 3 hours ago

What a peculiar kind of rewrite.

Rust:

https://github.com/malisper/pgrust/blob/3646a73515a5e4ac7d0b...

Original:

https://github.com/postgres/postgres/blob/df293aed46e3133df3...

Usage:

https://github.com/malisper/pgrust/blob/3646a73515a5e4ac7d0b...

The return type in the rewrite is both some sort of Error tagged union that supports the Try machinery in Rust; but, it also contains a boolean that apparently must be checked; or something. It seems labyrinthical and possibly broken and terrible.

khuey 2 hours ago | parent | next [-]

I make no claim as to whether the change makes sense given that I didn't look at the callers of this function, but Result<bool> is an entirely reasonable pattern in Rust. If you want the callers to be able to distinguish between "has the subclass", "doesn't have the subclass", and "something went wrong" this is idiomatic Rust.

queoahfh 5 minutes ago | parent [-]

I wrongly guessed that the boolean in the original C code was for error handling when I skimmed it, but instead it is just a result value, while elog() and related macros/functions are used for general error handling in the C version. I agree that it makes sense in Rust and other languages with tagged unions.

Though often when applicable, a simple tagged union is used instead when that would document the intention better. Like, the Rust version of search_pg_class_full_form::call() returns a Some for cache hit and None for cache miss as far as I can skim, and that group of methods returning that could arguably have returned a basic enum instead with CacheHit(value) and CacheMiss. Though this is a nitpick on my part.

pdevr 3 hours ago | parent | prev [-]

It is a feature in Rust, not a bug :-) (I know you didn't say it is a bug.)

The error-tagged union is PgResult<bool> - which means it contains bool as the result if things go well. (The other part in the union is of course the error.)

In the original function also, it is returning a boolean: "bool has_subclass".

So anyway you have to check for the boolean as part of the logic. That is what it is doing.

queoahfh 3 hours ago | parent [-]

Yes, but the original boolean seems to have been used for error handling, and the tagged union is also used for error handling. Why have both simultaneously in the same function instead of just one of the two?

Edit: Looking at the code again, perhaps I was mistaken, since the boolean might not have been for error handling, just the result of the function, and C's limitations regarding error handling led it to using something like elog(), apparently a macro defined in https://github.com/postgres/postgres/blob/master/src/include... .