[m-rev.] IO error type

Peter Wang novalazy at gmail.com
Thu Aug 18 12:46:50 AEST 2022

On Wed, 17 Aug 2022 19:31:26 +1000 Julien Fischer <jfischer at opturion.com> wrote:
> On Wed, 17 Aug 2022, Peter Wang wrote:
> >    :- type system_error.
> >
> >    :- func make_io_error(system_error, string) = io.error.
> >
> >    :- pred get_system_error(io.error::in, system_error::out)
> >        is semidet.
> >
> > That is, to introduce a backend/platform specific system_error type,
> > and add a field for system_errors in the io.error type.
> > (It would still be possible to construct an io.error without a
> > system_error value.)
> That was my preferred approach as well, however on Windows there is
> samll wrinkle with this: some of the system error codes we return are
> *not* errno values but instead are system error codes (e.g. of the kind
> returned by GetLastError()). So at least on Windows, if you embed a raw
> system error in an io.error, you have the additional problem of having
> to know what kind of error code it is.

Can we reserve a bit in the system_error? Otherwise we need another
field in io.error, which is fine as well.

> (This is not a problem with the existing code, since all error codes
> are turned into error messages fairly close to the point where they
> occur, and at those points we know what kind of error code it is.)
> Looking a bit closer: the calls to GetLastError() occur pretty much
> in the dir module, so maybe we can re-arrange how it handles errors
> to avoid that?

Someone may want to implement more of the standard library using native
Windows APIs. It would be worse for maintainability but it is (or was?)
necessary to access longer path names; not sure if there are other

> > If we add your suggestion to allow converting an io.error to a name,
> > we might have:
> >
> > 	% Returns a standard error name if the given error corresponds
> > 	% to a system error known to the Mercury system, e.g. "ENOENT"
> > 	% (or possibly the name of a Java or C# exception?).
> Given that C# and Java exceptions are usually arranged in a class
> hierarchy, which name would you return?

I was thinking the class name of the exception object, e.g.
for C#, e.GetType().Name returns "FileNotFoundException"
for Java, e.getClass().getName() returns "java.io.FileNotFoundException"

> > 	% Fails if the error is not a system error, or if the error is
> > 	% not one recognised by the Mercury system.
> > 	%
> >    :- pred get_error_name(io.error::in, string::out)
> > 	is semidet.
> >
> > 	% As above, but takes a system_error instead.
> > 	%
> >    :- pred get_system_error_name(system_error::in, string::out)
> > 	is semidet.
> My preference would be for the standard library to simply give access
> the the system error value and leave it for other system-specific
> libraries (e.g. the POSIX binding) to provide further facilities for
> examining it.

I'd rather not pull in the posix library for various reasons:
  - using anything from extras is a bit of a pain, not worth it for
    small projects
  - not sure about the code quality
  - breaks compilation on other platforms/grades


More information about the reviews mailing list