December 07, 2017
On 7 December 2017 at 03:09, lobo via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On Thursday, 7 December 2017 at 01:21:11 UTC, Nicholas Wilson wrote:
>>
>> I'd like to add an attribute to indicate that the annotated function is only available at compile time so that in cases where the operation is invalid at runtime (strings and concatenation on a GPU for instance) but the result is only used at compile time (for a mixin) the compiler is free to not codegen that function.
>>
>> I can add this to LDC pretty easily, but does anyone else have a use for this (e.g. shrinking binary sizes for mixin heavy codebases) and would benefit having this as a standard thing?
>
>
> Shouldn't the linker do this already?
>
> Once the compiler has CTFE'd the function any call in the code should be replaced with the function evaluation. The linker should then drop the code out of the binary because it really is dead code.
>

It should be possible to add heuristics for this (mark a function as being instantiated and only used at compile-time).  It just doesn't exist yet.

As for normal functions, regardless of protection, they will always be compiled as a function visible outside the CU.  You're either going to rely on LTO support in the compiler, kindly request that DIP45 be given another thought, or write a new DIP that considers another way to control symbol visibility.  But I wouldn't hold my breath on anything happening soon.
December 07, 2017
On Thursday, 7 December 2017 at 21:32:24 UTC, Walter Bright wrote:
> On 12/7/2017 2:07 AM, Nicholas Wilson wrote:
>> Doesn't work for templates.
>
> I don't know how your code is organized, but if the template is instantiated in another file, it won't have code generated for it either.

As a trivial example:

bar.d:
module bar;
string generatesMixin(T)()
{
    return T.stringof ~ " foo;";
}


a.d:
@compute(CompileFor.deviceOnly) module a;

int baz()
{
    mixin(generatesMixin!int());
    return foo;
}

a's symbol table contains `baz` and `generatesMixin!int`. generateMixin deals with strings which are not allowed (global variables are unsupported). This would fail compilation. If `generatesMixin` were to be marked `@ctfeonly`, this would pass.

December 07, 2017
On 7 December 2017 at 13:35, Walter Bright via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> On 12/7/2017 11:41 AM, Manu wrote:
>
>> Misuse of the API; ie, a runtime call, will result in an unsuspecting
>> user getting a surprising link error, rather than a nice compile-time error
>> explaining what they did wrong...
>>
>
> I think Nicholas is talking about functions for which code cannot be generated.
>
> In any case, in C/C++/D if you call functions in .h files (or imports) that are not linked in, you'll get a linker error.
>

Right, but that's what I'm saying; using your solution of putting a
function in a module that's not compiled to inhibit code generation won't
inhibit people from *attempting* to making runtime calls (and getting link
errors)... whereas a compile error trying to runtime-call a function that
shouldn't be runtime-called might be more desirable.
I'm not actually registering support for @ctfeonly, just that I think it's
a pattern that I have wanted and should be supported in some way, and a
compile-time error would be nicer than a link error.


December 07, 2017
On 7 December 2017 at 17:20, Manu <turkeyman@gmail.com> wrote:

> On 7 December 2017 at 13:35, Walter Bright via Digitalmars-d < digitalmars-d@puremagic.com> wrote:
>
>> On 12/7/2017 11:41 AM, Manu wrote:
>>
>>> Misuse of the API; ie, a runtime call, will result in an unsuspecting
>>> user getting a surprising link error, rather than a nice compile-time error
>>> explaining what they did wrong...
>>>
>>
>> I think Nicholas is talking about functions for which code cannot be generated.
>>
>> In any case, in C/C++/D if you call functions in .h files (or imports) that are not linked in, you'll get a linker error.
>>
>
> Right, but that's what I'm saying; using your solution of putting a
> function in a module that's not compiled to inhibit code generation won't
> inhibit people from *attempting* to making runtime calls (and getting link
> errors)... whereas a compile error trying to runtime-call a function that
> shouldn't be runtime-called might be more desirable.
> I'm not actually registering support for @ctfeonly, just that I think it's
> a pattern that I have wanted and should be supported in some way, and a
> compile-time error would be nicer than a link error.
>

I tried this, and was surprised it didn't work:

int ctfeOnly(int x)
{
static assert(__ctfe);
return x + 1;
}

This would probably solve the problem in a satisfying way without an attribute?


December 08, 2017
On Friday, 8 December 2017 at 01:30:13 UTC, Manu wrote:
> I tried this, and was surprised it didn't work:
>
> int ctfeOnly(int x)
> {
> static assert(__ctfe);
> return x + 1;
> }
>
> This would probably solve the problem in a satisfying way without an attribute?

I think that's because __ctfe, despite being magic, is actually a regular variable.

While this looks not too inelegant for a user perspective, I dont know how to handle this from a compiler perspective: filtering by attribute is as easy as "does this function have a UDA ctfeonly? If so, don't code generate it. Generating errors at codegen time is also trivial: when generating a call check to see if the callee is @ctfeonly, if it is give an error message

I don't know how to do that for a `static assert(__ctfe);`. That would require changes and semantic analysis in the front end which I am much less familiar with.
December 07, 2017
On Thu, Dec 07, 2017 at 07:20:57PM -0700, Jonathan M Davis via Digitalmars-d wrote: [...]
> In spite of the fact that CTFE is done at compile time, __ctfe is a runtime thing - it's just that it's runtime from the perspective of CTFE. So, stuff like static if or static assert doesn't work. You have to use if or a ternary operator or some other runtime conditional, though it's a common misunderstanding that __ctfe is used with static if, and people screw it up all the time. I don't know why it's a runtime thing rather than a compile time thing though. There's probably a good reason for it, but at first glance, it seems like a rather weird choice.
[...]

Sigh:

	https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time


T

-- 
Everybody talks about it, but nobody does anything about it!  -- Mark Twain
December 07, 2017
On Thursday, December 07, 2017 17:30:13 Manu via Digitalmars-d wrote:
> On 7 December 2017 at 17:20, Manu <turkeyman@gmail.com> wrote:
> > On 7 December 2017 at 13:35, Walter Bright via Digitalmars-d <
> >
> > digitalmars-d@puremagic.com> wrote:
> >> On 12/7/2017 11:41 AM, Manu wrote:
> >>> Misuse of the API; ie, a runtime call, will result in an unsuspecting user getting a surprising link error, rather than a nice compile-time error explaining what they did wrong...
> >>
> >> I think Nicholas is talking about functions for which code cannot be generated.
> >>
> >> In any case, in C/C++/D if you call functions in .h files (or imports) that are not linked in, you'll get a linker error.
> >
> > Right, but that's what I'm saying; using your solution of putting a
> > function in a module that's not compiled to inhibit code generation
> > won't
> > inhibit people from *attempting* to making runtime calls (and getting
> > link errors)... whereas a compile error trying to runtime-call a
> > function that shouldn't be runtime-called might be more desirable.
> > I'm not actually registering support for @ctfeonly, just that I think
> > it's a pattern that I have wanted and should be supported in some way,
> > and a compile-time error would be nicer than a link error.
>
> I tried this, and was surprised it didn't work:
>
> int ctfeOnly(int x)
> {
> static assert(__ctfe);
> return x + 1;
> }
>
> This would probably solve the problem in a satisfying way without an attribute?

In spite of the fact that CTFE is done at compile time, __ctfe is a runtime thing - it's just that it's runtime from the perspective of CTFE. So, stuff like static if or static assert doesn't work. You have to use if or a ternary operator or some other runtime conditional, though it's a common misunderstanding that __ctfe is used with static if, and people screw it up all the time. I don't know why it's a runtime thing rather than a compile time thing though. There's probably a good reason for it, but at first glance, it seems like a rather weird choice.

- Jonathan M Davis

December 07, 2017
On 12/7/2017 3:41 PM, Nicholas Wilson wrote:
> On Thursday, 7 December 2017 at 21:32:24 UTC, Walter Bright wrote:
>> On 12/7/2017 2:07 AM, Nicholas Wilson wrote:
>>> Doesn't work for templates.
>>
>> I don't know how your code is organized, but if the template is instantiated in another file, it won't have code generated for it either.
> 
> As a trivial example:
> 
> bar.d:
> module bar;
> string generatesMixin(T)()
> {
>      return T.stringof ~ " foo;";
> }
> 
> 
> a.d:
> @compute(CompileFor.deviceOnly) module a;
> 
> int baz()
> {
>      mixin(generatesMixin!int());
>      return foo;
> }
> 
> a's symbol table contains `baz` and `generatesMixin!int`. generateMixin deals with strings which are not allowed (global variables are unsupported). This would fail compilation. If `generatesMixin` were to be marked `@ctfeonly`, this would pass.
> 

bar.d:
module bar;
string generateString(T)()
{
    return T.stringof ~ " foo;";
}

enum s = generateString!int();

a.d:
@compute(CompileFor.deviceOnly) module a;

int baz()
{
    import bar;
    bar.s;
    return foo;
}
December 07, 2017
On 12/7/2017 5:20 PM, Manu wrote:
> Right, but that's what I'm saying; using your solution of putting a function in a module that's not compiled to inhibit code generation won't inhibit people from *attempting* to making runtime calls (and getting link errors)... whereas a compile error trying to runtime-call a function that shouldn't be runtime-called might be more desirable.

That's exactly what happens if you put a declaration in a .h file, call the function, and don't link in the implementation. I don't see the difference.
December 07, 2017
On 12/7/2017 5:30 PM, Manu wrote:
> I tried this, and was surprised it didn't work:
> 
> int ctfeOnly(int x)
> {
> static assert(__ctfe);
> return x + 1;
> }

The error is:

test2.d(3): Error: variable __ctfe cannot be read at compile time
test2.d(3):        while evaluating: static assert(__ctfe)

because static asserts are evaluated when the function is semantically analyzed, not when it is executed.