On Fri, Jun 12, 2020 at 11:25 PM Andrei Alexandrescu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
On 6/8/20 2:14 AM, Manu wrote:
> In C/C++, inline says that a function will be emit to the binary only
> when it is called, and the function is marked with internal linkage (it
> is not visible to the linker from the symbol table)

By my recollection this is not the case for C++, at all.

* "inline" does NOT change a function's linkage in C++. You may have
inline functions with internal linkage (static inline) or (default)
external linkage. This is important because e.g. defining a static
variable in an extern inline function will have the same address in all
calls to the function.

It absolutely changes the linkage.
I believe it uses what LLVM calls 'ChooseOne' in its code generator, I don't know about 'standard' linker terminology, if such a thing exists.

It's clearly in the spec too:
"""
  1. There may be more than one definition of an inline function or variable in the program as long as each definition appears in a different translation unit and (for non-static inline functions and variables) all definitions are identical. For example, an inline function or an inline variable may be defined in a header file that is #include'd in multiple source files.
"""

If not for that link flag, you receive a "multiply declared symbol" error.

If the above is correct, a D language feature dedicated to inlining
should do the following:

* Always emit the function body in the .di file if ever asked to
generate it.

Your sentence is unclear, but I think we agree.
I like how I describe this better: "The function must be emit to the _calling_ CU"

* Never complain about duplicate symbols if an inline function has
duplicate definitions.

And as I have been saying: "It must have the appropriate linker flag" (again, I think LLVM calls it "ChooseOne")

Then compilers can decide on specific inlining strategies using the
language feature as a hint.

Correct. Except in the case I described as case #3, in which it would be useful to have SOME WAY, to 'force inline' and receive an error if it failed.
I described this in case #3 like some sort of an AST inline; the inline is performed in the front-end as some sort of AST macro, then we can have complete confidence it happened, and error if not.
This is a DIFFERENT THING than 'inline' generally, and I would describe it as "force" inline, and suggested `pragma(inline, force)`.

D does ALL of the above already for templates, so this is not a
difficult feature to implement. In fact we use this technique (e.g. in
druntime) by spelling inline as "()". Consider:

int func(int) { ... body ... }

Let's make this inline:

int func()(int) { ... body ... }

Done.

Except for the sea of edge cases when you supply `func` to generic code that was expecting a function.
This is a sloppy and unsatisfying work-around.

In D there's one additional implication of body availability - the
function is eligible for CTFE. I think any adjustment to the extant
inline pragma needs to make this a top-level consideration.

I think this will work naturally with no changes today. If a function definition is present in a di file, you can CTFE call it, but (unless we fix inline) you can not call it at runtime (because no code will be emit anywhere).