On Wed, Jul 22, 2026 at 1:30 AM Jakub Jelinek via Gcc <[email protected]> wrote:
>
> On Wed, Jul 22, 2026 at 12:15:44AM +0200, Arsen Arsenović wrote:
> > Interesting, I thought that this specific example was overly favourable
> > to the idea of in-language gradual typing.
> >
> > It's the trivial case where one check is replaced by another check whose
> > result also gets encoded in the type system/current scope.
> >
> > Such a case - converting a check into a check + extra information in the
> > variable type pretty much mechanically - seemed like strictly an
> > improvement to me.
> >
> > In the languages I was mentioning as a reference, as well as in some
> > others like Kotlin, the check alone would mean that 't' gets a narrower
> > type definition in the scope of the then stmt, but this isn't possible
> > in C++, sadly.
> >
> > Note that, at least initially, calling a function that receives a typed
> > tree with an untyped tree should be possible (and result in the compiler
> > automatically adding a runtime check), and calling a function that
> > receives an untyped tree with a typed tree should probably always be
> > possible.  This is indeed what would allow for a gradual change.
> >
> > What was problematic in that example?
>
> All of it?
> Ugly syntax, having to type more than before (and thus having to deal with
> line wrapping more as well), having to introduce new vars for the dyn_cast
> way and being tied to if statements.
> With TREE_CODE/gimple_code/GET_CODE etc., one can choose coding style which
> is most appropriate for a particular case.  If statement or several of
> those, switch case, tables indexed by the codes with extra data.
> One switch is much nicer than having to add 50
>   if (auto a = dyn_cast <...> (t))
>     ...
>   else if (auto b = dyn_cast <...> (t))
>     ...
>   else if (auto c = dyn_cast <...> (t))
>     ...
> not to mention that if you e.g. leave out default: the compiler can
> complain about missing new cases etc.
> But, if you switch on TREE_CODE/gimple_code/GET_CODE etc., if some APIs
> enforce this static typing mess, you need to add a lot of as_a <...>
> (something).  In my experience, in most cases it is in most cases just a
> single use per the corresponding switch case or dyn_cast etc.
> If you want to add temporaries in a switch, you then need to wrap
> code after each case with {} because C++ only allows jumping across
> vacuous initializations (so auto can't be then really used for the
> temporaries otherwise and one has to separately declare and initialize those
> otherwise).
> We have is_a.h in GCC since 2012, I see around 1550 as_a, 1010 dyn_cast
> and 720 is_a uses, several of us had to type a few hundreds of those during
> that time.  I don't remember a single case where this mess would have
> prevented introducing a bug in gcc for me.  I vaguely remember hundreds
> of cases where runtime checking diagnosed bugs, many of those when I was
> writing my patches, significantly more afterwards reported in bugzilla.
> So, to me all this is extra pain for absolutely no gain.
> The thing I like least from these is as_a.  Some APIs (e.g. gimple) have
> overloads for both gimple * and some particular derived class from that,
> gcall *, gswitch *, etc., while others have just the latter, if one uses
> switch on the  gimple_code, then the common thing is as_a, typically just
> once, to make those APIs happy.

I'll note that the overloads with gimple * are "partial transitions"
... on the API
side strongly typed formal arguments are both documentation and a first
line of (compile-time) checking.  Consider

extern tree fold_build2_loc (location_t, enum tree_code, tree, tree,
                             tree CXX_MEM_STAT_INFO);

that the first 'tree' argument is supposed to be a type isn't visible and cannot
be validated at compile-time.

That said, I also believe trying to get tree more strongly typed using C++
is not going to be an improvement.  That might be the fault of C++ though.

Possibly doing sth like

extern tree fold_build2_loc (location_t, enum tree_code, tree_type, tree,
                             tree CXX_MEM_STAT_INFO);

with checking-enabled tree_type expanding to assertion (but otherwise just
being a no-op wrapper), and possibly allowing type assertions and/or
automatic annotation for static analysis might be an improvement?
For the above tree_type and tree would be compatible/assignable just
fine (unlike gassign * and gimple * where this works only one-way and
needs as_a<gassign *> in the other direction).

Richard.

>
>         Jakub
>

Reply via email to