Re: Gradual 'tree' typing and C++
Richard Biener via Gcc <[email protected]> Wed, 22 Jul 2026 09:06:58 +0200
| Newsgroups | gmane.comp.gcc.devel |
|---|---|
| Message-ID | <CAFiYyc0sHsvi71mqZo3yRKRA+q2OUPYEpL9n9Qh+t+xVvjOeWA@mail.gmail.com> |
On Wed, Jul 22, 2026 at 1:30=E2=80=AFAM Jakub Jelinek via Gcc <[email protected].= org> wrote: > > On Wed, Jul 22, 2026 at 12:15:44AM +0200, Arsen Arsenovi=C4=87 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 whos= e > > result also gets encoded in the type system/current scope. > > > > Such a case - converting a check into a check + extra information in th= e > > 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 compile= r > > 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 wit= h > line wrapping more as well), having to introduce new vars for the dyn_cas= t > way and being tied to if statements. > With TREE_CODE/gimple_code/GET_CODE etc., one can choose coding style whi= ch > 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 =3D dyn_cast <...> (t)) > ... > else if (auto b =3D dyn_cast <...> (t)) > ... > else if (auto c =3D 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 th= ose > 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 duri= ng > 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 c= annot 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 >