From: phillip.wood123@gmail.com
To: Emily Shaffer <nasamuffin@google.com>, phillip.wood@dunelm.org.uk
Cc: "brian m. carlson" <sandals@crustytoothpaste.net>,
git@vger.kernel.org, Junio C Hamano <gitster@pobox.com>,
Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Subject: Re: [RFC PATCH 1/1] Add a type for errors
Date: Fri, 4 Oct 2024 10:00:24 +0100 [thread overview]
Message-ID: <9731c23c-4383-42c4-83f6-1cf6b25f89d8@gmail.com> (raw)
In-Reply-To: <CAJoAoZnhY0Z7XdNqt8A598jptiNVDJC=4kT5n_n1FCGN5GkXRg@mail.gmail.com>
Hi Emily
On 03/10/2024 17:17, Emily Shaffer wrote:
> On Wed, Oct 2, 2024 at 2:54 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>>
>> Part of the reason it works well in rust is that it supports
>> discriminated unions with pattern matching and has the "?" macro for
>> early returns. In C the code ends up being quite verbose compared to
>> taking a pointer to error struct as a function parameter and returning a
>> boolean success/fail flag.
>>
>> struct git_error e;
>> struct object_id oid;
>>
>> e = repo_get_oid(r, "HEAD", &oid);
>> if (!GIT_ERROR_SUCCESS(e))
>> return e;
>>
>> With a boolean return we can have
>>
>> struct object_id oid;
>>
>> if (repo_get_oid(r, "HEAD", &oid, e))
>> return -1;
>>
>> where "e" is a "struct git_error*" passed into the function.
>
> I actually don't find this complaint all that compelling; it's not
> hard to write a shorter macro that can be used inline, so we can do
> things like:
>
> ERR_VAR(e);
> if(ERR(e, repo_get_oid(...))
> return e;
Right, but what's the advantage over passing the error struct as a
function parameter? It feels like we're adding extra complexity and
hiding the assignment to "e" to work around the inconvenience of
returning a struct rather than a flag. Is there some other advantage to
returning a struct that makes this worthwhile?
Best Wishes
Phillip
> or even a macro to do the return if desired:
>
> ERR_VAR(e); // or, i guess we can be not SO lazy and just write
> struct git_error e here, whatever :) )
> RETURN_IF_ERR(e, repo_get_oid(...));
>
> For better or worse, you can do a lot of things in a macro, so I don't
> see verboseness as much of an issue because I think we can hide a lot
> of it this way.
>
>>
>>> Provide the ability to specify either an errno value or a git error code
>>> as the code. This allows us to use this type generically when handling
>>> errno values such as processing files, as well as express a rich set of
>>> possible error codes specific to Git. We pick an unsigned 32-bit code
>>> because Windows can use the full set of 32 bits in its error values,
>>> even though most Unix systems use only a small set of codes which
>>> traditionally start at 1. 32 bits for Git errors also allows us plenty
>>> of space to expand as we see fit.
>>
>> I think the design of the struct is fine. It does mean we need a global
>> list of error values. GError [1] avoids this by having a "domain" field
>> that is an interned string so that error codes only need to be unique
>> within a given domain. I think that for a self-contained project like
>> git a global list is probably fine - svn does this for example [2].
>>
>> [1] https://docs.gtk.org/glib/error-reporting.html
>> [2]
>> https://github.com/apache/subversion/blob/be229fd54f5860b3140831671efbfd3f7f6fbb0b/subversion/include/svn_error_codes.h
>>
>>> Allow multiple errors to be provided and wrapped in a single object,
>>> which is useful in many situations, and add helpers to determine if any
>>> error in the set matches a particular code.
>>
>> The api appears to require the caller know up front how many errors
>> there will be which seems unlikely to be true in practice. I think a
>> more realistic design would allow callers to push errors as they occur
>> and grow the array accordingly. For example ref_transaction_prepare()
>> would want to return a list of errors, one for each ref that it was
>> unable to lock or which did not match the expected value but it would
>> not know up-front how many errors there were going to be.
>>
>> It would be useful to be able to add context to an error as the stack is
>> unwound. For example if unpack_trees() detects that it would overwrite
>> untracked files it prints a error listing those files. The exact
>> formatting of that message depends on the command being run. That is
>> currently handled by calling setup_unpack_trees_porcelain() with the
>> name of the command before calling unpack_trees(). In a world where
>> unpack_trees() returns a error containing the list of files we would
>> want to customize the message by adding some context before converting
>> it to a string.
>>
>>> Additionally, provide error formatting functions that produce a suitable
>>> localized string for ease of use.
>>
>> I share Emily's concern that this function has to know the details of
>> how to format every error. We could mitigate that somewhat using a
>> switch that calls external helper functions that do the actual formatting
>>
>> switch (e.code) {
>> case GIT_ERR_OBJECT_NOT_FOUND:
>> format_object_not_found(buf, e); /* lives in another file */
>> break;
>> ...
>>
>> I know this is an RFC but I couldn't resist one code comment
>>
>>> +#define GIT_ERROR_SUCCESS(e) (((e).code == GIT_ERROR_BIT_INIT))
>>> +#define GIT_ERROR_SUCCESS_CONSUME(e) ((git_error_free(&(e)).code == GIT_ERROR_BIT_INIT)
>>
>> git_error_free() returns the code as in integer so we don't need ".code"
>> here. Also our coding guidelines would suggest git_error_clear() for the
>> name of that function.
>>
>>
>> In conclusion I like the general idea but have concerns about the
>> verbosity of returning an error struct. It would be helpful to see some
>> examples of this being used to see how it works in practice.
>>
>> Best Wishes
>>
>> Phillip
>>
prev parent reply other threads:[~2024-10-04 9:00 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-30 22:03 [RFC PATCH 0/1] Typed errors brian m. carlson
2024-09-30 22:03 ` [RFC PATCH 1/1] Add a type for errors brian m. carlson
2024-09-30 22:44 ` Junio C Hamano
2024-09-30 23:35 ` brian m. carlson
2024-10-21 12:46 ` Patrick Steinhardt
2024-10-01 15:29 ` Oswald Buddenhagen
2024-10-02 14:01 ` Phillip Wood
2024-10-01 20:31 ` Emily Shaffer
2024-10-02 21:51 ` brian m. carlson
2024-10-02 9:54 ` Phillip Wood
2024-10-02 22:04 ` brian m. carlson
2024-10-02 22:16 ` Eric Sunshine
2024-10-02 22:24 ` brian m. carlson
2024-10-03 5:14 ` Eric Sunshine
2024-10-03 16:05 ` Junio C Hamano
2024-10-03 22:27 ` Eric Sunshine
2024-10-04 0:15 ` brian m. carlson
2024-10-04 9:00 ` phillip.wood123
2024-10-04 12:13 ` Richard Kerry
2024-10-03 16:17 ` Emily Shaffer
2024-10-04 9:00 ` phillip.wood123 [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9731c23c-4383-42c4-83f6-1cf6b25f89d8@gmail.com \
--to=phillip.wood123@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=nasamuffin@google.com \
--cc=oswald.buddenhagen@gmx.de \
--cc=phillip.wood@dunelm.org.uk \
--cc=sandals@crustytoothpaste.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).