On Sun, Jun 14, 2020 at 4:20 AM Andrei Alexandrescu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
On 6/13/20 12:08 AM, Manu wrote:
> On Sat, Jun 13, 2020 at 2:05 PM Walter Bright via Digitalmars-d
> <digitalmars-d@puremagic.com <mailto:digitalmars-d@puremagic.com>> wrote:
>
>     On 6/12/2020 8:25 PM, Andrei Alexandrescu wrote:
>      > On 6/12/20 8:54 PM, Walter Bright wrote:
>      >> On 6/12/2020 5:17 PM, Andrei Alexandrescu wrote:
>      >>> Not sure about that part - if linkage was static by means of
>     using the
>      >>> "static" keyword, multiple definitions may not be merged. (I
>     may be wrong,
>      >>> please correct me.) Consider:
>      >>>
>      >>> static inline int fun() {
>      >>>      static int x;
>      >>>      return ++x;
>      >>> }
>      >>>
>      >>> In C++, each translation unit containing a definition of fun()
>     will have a
>      >>> distinct address for x. I don't see how the bodies of those
>     functions can be
>      >>> merged.
>      >>
>      >> They are not merged in D, for the simple reason that
>     ModuleA.fun() and
>      >> ModuleB.fun() will have different (mangled) names presented to
>     the linker.
>      >
>      > For D the question is if they are merged if the function is
>     defined in a .di
>      > file and imported in two other modules.
>
>     If the di file is mentioned on the command line to the compiler
>
>
> It's not, that's literally the point of a .di file.
>
>     , yes (1)
>     instance of it appears in the executable. Otherwise, (0) instances
>     of it appear
>     in the executable. There are never 2 or more instances in the
>     executable.
>
>
> Exactly. And this is not a useful design.

All I can say is if that and/or other wrinkles prevent header-only
libraries definition and use, yes, not a useful design.

So Manu, is the top-level goal "I want header-only libraries in D"?

It is one among multiple use cases in that category. It's essentially the one I describe by use-case #1.
That is one useful case. It's not limited to that though, it comes up in various situations.

For instance, I do a lot with DLL's... it's typical to load a DLL, and then bind to a single function that creates an instance of some object that the DLL provides. From there, further calls into the library are via the object vtable.
From this point, there are a few design pressures that lead to inline functions:
1. v-calls are slow, and trivial operations (ie, getters/setters) should just be inlines where it makes sense. Cross-module calls are not desirable.
2. DLL's ABI is essentially part of the API, and changes to the ABI are breaking changes to the lib.
  - Skilled design is to have fewer virtual functions that 'do stuff', with flexibility in how it's called and lots of soft-extensibility option arguments.
    * Enhancement to a lib can be made by adding a new item to an enum, rather than breaking the ABI.
  - This broad style of function is inconvenient for users, and typical use cases often wrap these work functions up in convenience inline calls, to automate a complex calling scheme.
3. Such libraries are installed by the package manager in some location, along with their 'headers', which root path is automatically added in a build script somewhere.
  - It is not the job of the application's build environment to determine what functions it calls from a lib and then cherry-pick source files from the lib and include them into the applications build... that creates compile-time couplings which are awkward at best, and naturally break-down over time. It self-defeats the use of DLL's.

A build system might not even know how to identify the paths to a particular library's random source files, and it shouldn't be the client's responsibility to understand a lib's source tree. It's hard to know what source files you need to include and build... I probably don't call every function in the lib; I don't want to include the source for a DLL into my application; that's self-defeating.

TL;DR, right now, I care about DLL's, and inline functions are an essential part of DLL-based libraries.

It doesn't end there though either; there are so many cases where a reference to a lib should not create a 'hard' coupling between projects. I have often had situations involving 'optional' functionality; if a call is never made, then the dependency beneath that call isn't inferred on the client. An inline with no references naturally doesn't pull the dependency reference into the binary unless it's actually called. You could argue for stripping to solve that case, but that's a much more brittle and unsatisfying solution.