Topic: [Proposal] noreturn_t


Author: tommi.hoynalanmaa@iki.fi (=?UTF-8?B?VG9tbWkgSMO2eW7DpGzDpG5tYWE=?=)
Date: Sun, 5 Nov 2006 00:51:33 GMT
Raw View
Andrei Alexandrescu (See Website For Email) kirjoitti:
> Tommi H=C3=B6yn=C3=A4l=C3=A4nmaa wrote:
>> This is a question about the execution flow and not about the result=20
>> type of a function. There would be no values whose type is noreturn_t.
>> So "noreturn" should be an attribute of a function like the throw=20
>> specifications.
>=20
> The point of the idea was different. Yes, values of that type cannot=20
> exist, but the properties of the static type control the expressiveness=
=20
> of the idioms in which the type could take part. And precisely because=20
> values of that "none" type can never exist, there is considerable stati=
c=20
> freedom with regard to the static properties of that type, which confer=
s=20
> it remarkable expressiveness.

But isn't "none" roughly equivalent to the void result type in C++?
Function that returns nothing has also a result type that contains no=20
values. Or does it have some other result type? I think this type should=20
also be at the bottom of the type hierarchy.

>> There could be another attribute "mustreturn" to indicate that a=20
>> function has to return. "mustreturn" and "noreturn" would be mutually=20
>> exclusive.
>=20
> I guess mustreturn is simply a static incarnation of the nothrow idea.=20
> Things get tricky when we start thinking of mustreturn as a guarantee=20
> that the function doesn't enter infinite loops - it wouldn't generally=20
> be quite possible to demonstrate that a function violates that=20
> assumption :o).

We could define "mustreturn" e.g. so that
1) A "mustreturn" function may call only other "mustreturn" functions
or
2) A "mustreturn" function may not call any "noreturn" functions.
Infinite loops and things like that would not be considered at all.
The semantics of "mustreturn" would be a bit unclear this way because it=20
would be possible that a "mustreturn" function executes an infinite time.

However, it may be that "mustreturn" is not worth implementing.

--=20
Tommi H=C3=B6yn=C3=A4l=C3=A4nmaa
s=C3=A4hk=C3=B6posti / e-mail: tommi.hoynalanmaa@iki.fi
kotisivu / homepage: http://www.iki.fi/tohoyn/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: SeeWebsiteForEmail@erdani.org ("Andrei Alexandrescu (See Website For Email)")
Date: Sun, 5 Nov 2006 03:14:26 GMT
Raw View
Tommi H=C3=B6yn=C3=A4l=C3=A4nmaa wrote:
> Andrei Alexandrescu (See Website For Email) kirjoitti:
>> Tommi H=C3=B6yn=C3=A4l=C3=A4nmaa wrote:
>>> This is a question about the execution flow and not about the result=20
>>> type of a function. There would be no values whose type is noreturn_t.
>>> So "noreturn" should be an attribute of a function like the throw=20
>>> specifications.
>>
>> The point of the idea was different. Yes, values of that type cannot=20
>> exist, but the properties of the static type control the=20
>> expressiveness of the idioms in which the type could take part. And=20
>> precisely because values of that "none" type can never exist, there is=
=20
>> considerable static freedom with regard to the static properties of=20
>> that type, which confers it remarkable expressiveness.
>=20
> But isn't "none" roughly equivalent to the void result type in C++?
> Function that returns nothing has also a result type that contains no=20
> values. Or does it have some other result type? I think this type shoul=
d=20
> also be at the bottom of the type hierarchy.

There are similarities between void and none, but also obvious=20
differences. I think we've beaten this horse long enough :o).

>>> There could be another attribute "mustreturn" to indicate that a=20
>>> function has to return. "mustreturn" and "noreturn" would be mutually=
=20
>>> exclusive.
>>
>> I guess mustreturn is simply a static incarnation of the nothrow idea.=
=20
>> Things get tricky when we start thinking of mustreturn as a guarantee=20
>> that the function doesn't enter infinite loops - it wouldn't generally=
=20
>> be quite possible to demonstrate that a function violates that=20
>> assumption :o).
>=20
> We could define "mustreturn" e.g. so that
> 1) A "mustreturn" function may call only other "mustreturn" functions
> or
> 2) A "mustreturn" function may not call any "noreturn" functions.
> Infinite loops and things like that would not be considered at all.
> The semantics of "mustreturn" would be a bit unclear this way because i=
t=20
> would be possible that a "mustreturn" function executes an infinite tim=
e.
>=20
> However, it may be that "mustreturn" is not worth implementing.

I also don't think "mustreturn" has much value. For a host of=20
theoretical and practical reasons, "nothrow" is much more worthy=20
focusing on.


Andrei

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: tommi.hoynalanmaa@iki.fi (=?ISO-8859-1?Q?Tommi_H=F6yn=E4l=E4nmaa?=)
Date: Wed, 1 Nov 2006 22:31:51 GMT
Raw View
Tommi H=F6yn=E4l=E4nmaa kirjoitti:
> There could be another attribute "mustreturn" to indicate that a=20
> function has to return. "mustreturn" and "noreturn" would be mutually=20
> exclusive.
> Then
> - A function with neither of the return attributes would be compatible=20
> with the corresponding function type with or without "noreturn" or=20
> "mustreturn" attributes.

It would be semantically more reasonable to change this rule so that a=20
function with neither of the return attributes would not be compatible=20
with the corresponding function type with the "noreturn" attribute. If=20
we declare a function pointer with a type that has the "noreturn"=20
attribute then the values of this pointer should be guaranteed not to=20
return.

Probably the rule should be changed for "mustreturn" in the same way.=20
The semantics of "mustreturn" are more unclear, though.

> - A function with "noreturn" attribute would not be compatible with the=
=20
> corresponding function type with the "mustreturn" attribute.
> - A function with "mustreturn" attribute would not be compatible with=20
> the corresponding function type with the "noreturn" attribute.
>=20


--=20
Tommi H=F6yn=E4l=E4nmaa
s=E4hk=F6posti / e-mail: tommi.hoynalanmaa@iki.fi
kotisivu / homepage: http://www.iki.fi/tohoyn/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: tommi.hoynalanmaa@iki.fi (=?ISO-8859-1?Q?Tommi_H=F6yn=E4l=E4nmaa?=)
Date: Sun, 29 Oct 2006 01:06:49 GMT
Raw View
Andrei Polushin kirjoitti:
> I propose to add a special type, std::noreturn_t, to indicate that
> function does never return.
>=20
> Actually, some compilers have the similar feature, known as either
> __declspec(noreturn) or __attribute__ ((noreturn)), but it is used
> primarily for optimization purposes and does not affect language.

This is a question about the execution flow and not about the result=20
type of a function. There would be no values whose type is noreturn_t.
So "noreturn" should be an attribute of a function like the throw=20
specifications.

"noreturn" and other attributes should be part of the type of the=20
function (i.e. function pointer type), not the type of the result value.

BTW, there should also be attribute "pure" to indicate that a function=20
has no side effects. A pure function would not be allowed to call any=20
non-pure functions or to change global variables. GCC implements "pure"=20
and "const" attributes for pure functions.

C++ should also have a standardized syntax for the (standard) function=20
attributes. Perhaps something like

   void myfunc(int a, char b) attributes(noreturn)

A function with the pure attribute would be compatible with the=20
corresponding function type with or without the pure attribute. A=20
function without the pure attribute would not be compatible with
the corresponding function type with the pure attribute.

There could be another attribute "mustreturn" to indicate that a=20
function has to return. "mustreturn" and "noreturn" would be mutually=20
exclusive.
Then
- A function with neither of the return attributes would be compatible=20
with the corresponding function type with or without "noreturn" or=20
"mustreturn" attributes.
- A function with "noreturn" attribute would not be compatible with the=20
corresponding function type with the "mustreturn" attribute.
- A function with "mustreturn" attribute would not be compatible with=20
the corresponding function type with the "noreturn" attribute.

--=20
Tommi H=F6yn=E4l=E4nmaa
s=E4hk=F6posti / e-mail: tommi.hoynalanmaa@iki.fi
kotisivu / homepage: http://www.iki.fi/tohoyn/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: SeeWebsiteForEmail@erdani.org ("Andrei Alexandrescu (See Website For Email)")
Date: Sun, 29 Oct 2006 04:22:50 GMT
Raw View
Tommi H=F6yn=E4l=E4nmaa wrote:
> Andrei Polushin kirjoitti:
>> I propose to add a special type, std::noreturn_t, to indicate that
>> function does never return.
>>
>> Actually, some compilers have the similar feature, known as either
>> __declspec(noreturn) or __attribute__ ((noreturn)), but it is used
>> primarily for optimization purposes and does not affect language.
>=20
> This is a question about the execution flow and not about the result=20
> type of a function. There would be no values whose type is noreturn_t.
> So "noreturn" should be an attribute of a function like the throw=20
> specifications.

The point of the idea was different. Yes, values of that type cannot=20
exist, but the properties of the static type control the expressiveness=20
of the idioms in which the type could take part. And precisely because=20
values of that "none" type can never exist, there is considerable static=20
freedom with regard to the static properties of that type, which confers=20
it remarkable expressiveness.

> "noreturn" and other attributes should be part of the type of the=20
> function (i.e. function pointer type), not the type of the result value.
>=20
> BTW, there should also be attribute "pure" to indicate that a function=20
> has no side effects. A pure function would not be allowed to call any=20
> non-pure functions or to change global variables. GCC implements "pure"=
=20
> and "const" attributes for pure functions.

Pure is a good comparison point with no-return as it is purely (no pun=20
intended) related to a flow property of the function, with (to the best=20
of my imagination) is not related to its type.

> A function with the pure attribute would be compatible with the=20
> corresponding function type with or without the pure attribute. A=20
> function without the pure attribute would not be compatible with
> the corresponding function type with the pure attribute.
>=20
> There could be another attribute "mustreturn" to indicate that a=20
> function has to return. "mustreturn" and "noreturn" would be mutually=20
> exclusive.

I guess mustreturn is simply a static incarnation of the nothrow idea.=20
Things get tricky when we start thinking of mustreturn as a guarantee=20
that the function doesn't enter infinite loops - it wouldn't generally=20
be quite possible to demonstrate that a function violates that=20
assumption :o).


Andrei

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Andrei Polushin" <polushin@gmail.com>
Date: Sun, 22 Oct 2006 12:09:10 CST
Raw View
Hi,

I propose to add a special type, std::noreturn_t, to indicate that
function does never return.

Actually, some compilers have the similar feature, known as either
__declspec(noreturn) or __attribute__ ((noreturn)), but it is used
primarily for optimization purposes and does not affect language.

I suggest using it for strict type checking too, so std::noreturn_t
is not an "attribute", but a type that affects a function signature.

In addition, I suggest the "throw" expression to return "noreturn_t"
instead of "void", see rationale and use case below.

Use cases
---------

Starting from the simplest problem, consider the following code,
which does not compile:

    // never returns
    void throw_out_of_range(size_type n, size_type m)
    {
        ostringstream os;
        os << "value " << n << " is out of range [0," << m << ")";
        throw out_of_range(os.str());
    }

    // throws if n is out of range [0,size)
    reference at(size_type n)
    {
        if (0 <= n && n < size()) {
            return data[n];
        }
        throw_out_of_range(n, size());
        // *error: function "at" should return a value*
    }

Yes, we can revert the "if" condition to avoid an error, but why we
need to? Anyway, another example (adapted from boost::lexical_cast):

    // never returns
    void throw_io_failure()
    {
        throw ios_base::failure("I/O failure");
    }

    // throws if I/O failed
    char get(const char* prompt) {
        char c;
        if (!(cout << prompt && cin >> c)) {
            throw_io_failure();
        }
        // *warning: potentially uninitialized variable returned*
        return c;
    }

Thus we have a spurious warning.

In the following case we will see no warning, where it should be:

    int f()
    {
        abort();

        // *no warning about unreachable code*
        int n = 22;
        return n;
    }

More serious case, when the function returns, but nobody expects this:

    void hello()
    {
       cout << "Hello, World!" << endl;
    }

    set_unexpected(hello);
    unexpected();
    // execution continues after call to unexpected ?

In the last case, we can know the problem at compile time, imagine
set_unexpected() will accept only handlers that never return:

    namespace std
    {
        typedef noreturn_t (*unexpected_handler)();

        unexpected_handler set_unexpected(unexpected_handler f);
    }

    void hello()
    {
       cout << "Hello, World!" << endl;
    }

    std::noreturn_t bye()
    {
       cout << "Bye, World!" << endl;
       // *error: "bye" should never return*
    }

    set_unexpected(hello); // cannot cast to unexpected_handler
    set_unexpected(bye);   // ok


Compatibility
-------------

1. Existing C++ implementations that do not check for non-returning
   functions, may declare a no-op type:

    namespace std
    {
        typedef void noreturn_t;
    }

2. The existing code will fail to compile if it takes the address of
   function redeclared with std::noreturn_t return type:

    typedef void (*handler)();
    void abort_workaround() { abort(); }

    handler h = &abort;             // error: cannot convert
    handler h = &abort_workaround;  // ok: workaround

   This incompatibility is intentional.

3. Similarly, set_unexpected() etc. will not accept address of
   functions that return void, which is also intentional.

4. All control paths of a function that never returns should end
   with a call to a function that never returns, or with a throw
   statement. This is the direct intent.


Throw expression and noreturn_t
-------------------------------

Throw expression should return std::noreturn_t instead of void, and
the type noreturn_t should be convertible to bool:

    namespace std
    {
        struct noreturn_t {
            operator bool() { return false; }
        };
    }

This allows a Perl-like syntax for checking return value:

    cin >> c || throw io_failure("Cannot read from cin");

(Idea inspired by recent posting of Alf P. Steinbach in c.l.c++.m:
http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/85b034283152115e/ee9b31479b8c1e0e?#ee9b31479b8c1e0e
)

The name "noreturn_t" is inspired by std::nothrow_t.


Conclusion
----------

Having noreturn_t, we achieve:

    - better compile-time control path analysis,
    - better runtime error checking syntax,
    - easier optimizable code,

Is it useful? I'm waiting for your comments.


--
Andrei Polushin

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Alberto Ganesh Barbati <AlbertoBarbati@libero.it>
Date: Sun, 22 Oct 2006 14:19:36 CST
Raw View
Andrei Polushin ha scritto:
>
> I propose to add a special type, std::noreturn_t, to indicate that
> function does never return.
>
> <snip>
>
> Conclusion
> ----------
>
> Having noreturn_t, we achieve:
>
>     - better compile-time control path analysis,
>     - better runtime error checking syntax,
>     - easier optimizable code,
>
> Is it useful? I'm waiting for your comments.

Even if it's a change that might break backward compatibility, I like it
and find it useful. Just three comments:

1) I would not allow implementations to define std::noreturn_t as a
typedef to void. In fact I would explicitly disallow such possibility.
If we allow it, the code:

     typedef std::noreturn_t (*doesnt_return)();
     void set_handler(doesnt_return f);

     void bye();
     set_handler(bye);

might compile on a conforming compiler and not on another conforming
compiler.

2) About set_unexpected and set_terminate, I think that changing
signatures of existing library function is unacceptable. I would just
add overloads. That would rip a little hole in the system, but otherwise
it looks like a showstopper to me.

3) I am a bit concerned with the implicit conversion to bool. Although I
don't dislike the perl-like syntax, having an implicit conversion would
make the entire proposal pointless, because you might then use
noreturn_t in a lot more places than we actually want. Even the idiom
"implicit conversion to unspecified-bool-type" (as used tr1::shared_ptr,
for example) is not good enough, IMHO. I don't see any alternative
except to explicitly allow built-in operator || and && (and *only* them,
no overloads!) to take as their second operand an expression of type
noreturn_t.

Just my 2 eurocent,

Ganesh

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail@erdani.org>
Date: Sun, 22 Oct 2006 19:38:07 CST
Raw View
Andrei Polushin wrote:
> I propose to add a special type, std::noreturn_t, to indicate that
> function does never return.
>
> Actually, some compilers have the similar feature, known as either
> __declspec(noreturn) or __attribute__ ((noreturn)), but it is used
> primarily for optimization purposes and does not affect language.

There is precedent in the Cecil language as well (the "none" type).

> Throw expression should return std::noreturn_t instead of void, and
> the type noreturn_t should be convertible to bool:

Actually the type noreturn_t should be convertible to any other type.
That makes it the bottom of the type hierarchy, where it belongs.

I implemented and used such a type in existing C++, and found it
marginally useful. I personally don't think it's a compelling feature to
add to the language.


Andrei

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Mon, 23 Oct 2006 01:12:06 GMT
Raw View
Andrei Alexandrescu (See Website For Email) ha scritto:
> Andrei Polushin wrote:
>> I propose to add a special type, std::noreturn_t, to indicate that
>> function does never return.
>>
>> Actually, some compilers have the similar feature, known as either
>> __declspec(noreturn) or __attribute__ ((noreturn)), but it is used
>> primarily for optimization purposes and does not affect language.
>
> There is precedent in the Cecil language as well (the "none" type).
>
>> Throw expression should return std::noreturn_t instead of void, and
>> the type noreturn_t should be convertible to bool:
>
> Actually the type noreturn_t should be convertible to any other type.
> That makes it the bottom of the type hierarchy, where it belongs.

Why? IMHO it should behave like void, in the sense that it should not be
convertible to any type (except, possibly, void itself) so that you
cannot put it by mistake into an expression. I would also disallow the
possibility to explicitly convert an expression to noreturn_t (something
that you can do with void).

> I implemented and used such a type in existing C++, and found it
> marginally useful. I personally don't think it's a compelling feature to
> add to the language.

It was marginally useful because you implemented it in existing C++! The
proposal is only meaningful if the compiler is able to exploit the added
information for:

>>     - better compile-time control path analysis,
>>     - better runtime error checking syntax,
>>     - easier optimizable code,

BTW: I guess the OP meant to say "better *compile-time* error checking
syntax" not runtime. There's no syntax checking happening at runtime...

Ganesh

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: jdennett@acm.org (James Dennett)
Date: Mon, 23 Oct 2006 01:40:02 GMT
Raw View
Alberto Ganesh Barbati wrote:
> Andrei Alexandrescu (See Website For Email) ha scritto:
>> Andrei Polushin wrote:
>>> I propose to add a special type, std::noreturn_t, to indicate that
>>> function does never return.
>>>
>>> Actually, some compilers have the similar feature, known as either
>>> __declspec(noreturn) or __attribute__ ((noreturn)), but it is used
>>> primarily for optimization purposes and does not affect language.
>>
>> There is precedent in the Cecil language as well (the "none" type).
>>
>>> Throw expression should return std::noreturn_t instead of void, and
>>> the type noreturn_t should be convertible to bool:
>>
>> Actually the type noreturn_t should be convertible to any other type.
>> That makes it the bottom of the type hierarchy, where it belongs.
>
> Why? IMHO it should behave like void, in the sense that it should not be
> convertible to any type (except, possibly, void itself) so that you
> cannot put it by mistake into an expression. I would also disallow the
> possibility to explicitly convert an expression to noreturn_t (something
> that you can do with void).

Typewise, I suspect it should behave like the existing
"no return" part of the language, namely "throw".

return true?throw a:foo;

is currently legal, but not because throw a has a type
that converts to anything -- rather, because if the
expression has a value at all then it was foo that was
evaluated, and so its type is used.

-- James

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: John Nagle <nagle@animats.com>
Date: Sun, 22 Oct 2006 23:45:25 CST
Raw View
James Dennett wrote:
> Alberto Ganesh Barbati wrote:
>
>>Andrei Alexandrescu (See Website For Email) ha scritto:
>>
>>>Andrei Polushin wrote:
>>>
>>>>I propose to add a special type, std::noreturn_t, to indicate that
>>>>function does never return.

   It's not a compelling feature, but if added, it needs to be
part of the declaration, not the implementation, where
the caller can see it.

   Realistically, though, it doesn't have much optimization
value.  Functions that don't return tend not to be called
many times. (You could potentially have a function
that never returned normally, but could throw an exception.
This might be useful when starting up some task which
normally runs forever but could fail, throw, and be restarted
by its caller.)

    John Nagle
    Animats

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]