www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - ctfeonly

reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
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?
Dec 06 2017
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Dec 07, 2017 at 01:21:11AM +0000, Nicholas Wilson via Digitalmars-d
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?
I'd like to have this too. Some of my template-heavy code use a good number of CTFE-only functions that are only called at compile-time. Since they are nested inside the template, they do quickly add up to a lot of dead code in the executable. Having a ctfeonly annotation that tells the compiler not to codegen the (many instantiations of the) function would be greatly welcomed. T -- Let's eat some disquits while we format the biskettes.
Dec 06 2017
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
H. S. Teoh wrote:

 On Thu, Dec 07, 2017 at 01:21:11AM +0000, Nicholas Wilson via 
 Digitalmars-d 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?
I'd like to have this too. Some of my template-heavy code use a good number of CTFE-only functions that are only called at compile-time. Since they are nested inside the template, they do quickly add up to a lot of dead code in the executable. Having a ctfeonly annotation that tells the compiler not to codegen the (many instantiations of the) function would be greatly welcomed. T
this is a hack for something that really should be done in linker, automatically. please, people, let's not turn D into C++! ;-) i mean: this has a short-time benefits, but makes the language more complex, less clear, and completely destroys any incentive to make smartlinking work as intended in case it is broken.
Dec 06 2017
parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Thursday, 7 December 2017 at 02:33:49 UTC, ketmar wrote:
 H. S. Teoh wrote:

 On Thu, Dec 07, 2017 at 01:21:11AM +0000, Nicholas Wilson via 
 Digitalmars-d wrote:
 [...]
I'd like to have this too. Some of my template-heavy code use a good number of CTFE-only functions that are only called at compile-time. Since they are nested inside the template, they do quickly add up to a lot of dead code in the executable. Having a ctfeonly annotation that tells the compiler not to codegen the (many instantiations of the) function would be greatly welcomed. T
this is a hack for something that really should be done in linker, automatically. please, people, let's not turn D into C++! ;-) i mean: this has a short-time benefits, but makes the language more complex, less clear, and completely destroys any incentive to make smartlinking work as intended in case it is broken.
Not all of the generated code goes through a linker ;) For dcompute strings aren't even supported yet! Let alone concatenation. Also not generating the code in the first place means less I/O for the compiler and less work for the linker. I definitely don't want D to become C++. What is smartlinking? This is intended for stuff like code that generates strings for mixins.
Dec 06 2017
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
Nicholas Wilson wrote:

 Also not generating the code in the first place means less I/O for the 
 compiler and less work for the linker.
this is solvable without any additional flags, tho: compiler should just skip codegen phase for any function that is not referenced by another compiled function (except for library case).
 I definitely don't want D to become C++. What is smartlinking?
any decent linker simply drops anything that is not reveferenced. i.e. any function that is not referenced from another function that is definitely included in the binary, will be skipped. as linker knows program entry point, it is able to build reference tree, and do "smart" linking instead of just putting everything into resulting binary.
 This is intended for stuff like code that generates strings for mixins.
as i said, this is something compiler can do automatically, without user's help. we already have too much attributes, i believe, adding even more won't do any good.
Dec 06 2017
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
ketmar wrote:

 Nicholas Wilson wrote:

 Also not generating the code in the first place means less I/O for the 
 compiler and less work for the linker.
this is solvable without any additional flags, tho: compiler should just skip codegen phase for any function that is not referenced by another compiled function (except for library case).
p.s.: actually, dmd already creates .a files suitable for smartlinking (otherwise any binary would include the whole libphobos2.a ;-). but for "dmd mycode.d" dmd doesn't do this ('cause it is quite compilcated for non-library case). the whole issue prolly can be solved by "generate smart object files for linking" flag (which will create .a files for everything, so linker can do it's smart work).
Dec 06 2017
parent Johannes Pfau <nospam example.com> writes:
Am Thu, 7 Dec 2017 05:55:54 +0200
schrieb ketmar <ketmar ketmar.no-ip.org>:

 ketmar wrote:
 
 Nicholas Wilson wrote:
  
 Also not generating the code in the first place means less I/O for
 the compiler and less work for the linker.  
this is solvable without any additional flags, tho: compiler should just skip codegen phase for any function that is not referenced by another compiled function (except for library case).
p.s.: actually, dmd already creates .a files suitable for smartlinking (otherwise any binary would include the whole libphobos2.a ;-). but for "dmd mycode.d" dmd doesn't do this ('cause it is quite compilcated for non-library case). the whole issue prolly can be solved by "generate smart object files for linking" flag (which will create .a files for everything, so linker can do it's smart work).
AFAIK there's a design flaw in D which prevents a compiler from doing any such operations without additional user input: Currently you can write code like this: ------------------------------------------------------------------- module mod; private int thisIsNeverUsed() { return 42; } private int thisIsUsed(int a) { return 42 + a; } int someTemplate(T)(T t) { return t.thisIsUsed(); } ------------------------------------------------------------------- Whether thisIsUsed and thisIsNeverUsed actually have to appear in the object file depends on how someTemplate is instantiated. Generally, when compiling module mod you can never know whether thisIsUsed or thisIsNeverUsed are actually required. You can not evaluate the someTemplate template without specifying a concrete type for T. This means neither the compiler nor the linker can remove seemingly unused, private functions. For GDC this means we simply mark all functions as TREE_PUBLIC in the GCC backend. Note that this is also an issue for exporting templates from DLLs on windows. I think the DLL DIP which requires to mark private functions as 'export' if they are used outside outside of the module (even via templates) will fix this problem and allow for some nice optimizations. Until then, smart linking isn't really possible. BTW: The private/export combination probably still wouldn't solve all problems: Maybe you want to mark the whole module as nogc. nogc checking is done in semantic phase, so it will still error about GC usage in functions which later turn out to be only used in CTFE. Detecting this in the linker or compiler backend is too late. So we'd have to detect unexported, unused private functions in semantic. I'm not sure if this is feasible or whether a simple ctfeonly UDA isn't much simpler to implement. Additionally ctfeonly documents intended usage and allows for nice error messages when using a function at runtime. Relying on the linker to remove private, unexported functions can break easily. -- Johannes
Dec 07 2017
prev sibling next sibling parent reply lobo <swamp.lobo gmail.com> writes:
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. bye, lobo
Dec 06 2017
next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Thursday, December 07, 2017 02:09:56 lobo via Digitalmars-d 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.
As I understand it, if you're statically linking it should, but it can't with dynamic linking - at least not right now. With the export improvements that Martin Nowak and Benjamin Thaut want to do (where IIUC, export would then be required for anything in a shared library to be accessible outside it), then it would be possible, but right now, everything gets exported (at least on all systems other than Windows), so none of it can be stripped out as unused, since the linker doesn't know what's actually going to be used. Executables should be in the same boat as static libraries though. Also, I think that in some cases, stuff like ModuleInfo ends up referring to stuff and keeping it around even though it isn't necessarily really used, but I'm not sure. Folks have talked about all kinds of template code and stuff being kept around in binaries even though it was only used at compile time (e.g. stuff like isInputRange), but I don't know how much that's actually true. Personally, I don't care much about binary sizes. I certainly agree that having unused symbols stripped out where possible is a good thing, but AFAIK, it doesn't really matter for most of the stuff I do, and having a binary be 5MiB instead of 1MiB doesn't matter much to me, much as I agree that having the binary smaller is good. It just isn't usually enough disk space or memory to matter much in practice. Clearly, some people care quite a bit about that sort of thing, but I don't know how much it actually matters in practice unless you're doing something with embedded systems. Regardless, needing something like an attribute to tell the compiler to strip stuff out of the binary seems like a hack to me. It may actually be necessary in some cases, but it just feels like it should be unnecessary. - Jonathan M Davis
Dec 06 2017
next sibling parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Thursday, 7 December 2017 at 03:18:57 UTC, Jonathan M Davis 
wrote:
 On Thursday, December 07, 2017 02:09:56 lobo via Digitalmars-d 
 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.
Unfortunately I don't have a linker to do that for me with DCompute.
 Regardless, needing something like an attribute to tell the 
 compiler to strip stuff out of the binary seems like a hack to 
 me. It may actually be necessary in some cases, but it just 
 feels like it should be unnecessary.
Do you have any other ideas about how to achieve this other than an attribute? Having an attribute seems the most simple and straightforward.
Dec 06 2017
next sibling parent meppl <mephisto nordhoff-online.de> writes:
On Thursday, 7 December 2017 at 03:43:42 UTC, Nicholas Wilson 
wrote:
 ...

 Do you have any other ideas about how to achieve this other 
 than an attribute?
 Having an attribute seems the most simple and straightforward.
llvm has "Aggressive Dead Code Elimination"- and "Dead Code Elimination"-switches, who I find interesting. https://llvm.org/docs/Passes.html#transform-passes I remember once I actually stripped off kinda 99% of a statically linked phobos-library with that and I got a small executable who was still working
Dec 06 2017
prev sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Thursday, December 07, 2017 03:43:42 Nicholas Wilson via Digitalmars-d 
wrote:
 On Thursday, 7 December 2017 at 03:18:57 UTC, Jonathan M Davis

 wrote:
 On Thursday, December 07, 2017 02:09:56 lobo via Digitalmars-d

 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.
Unfortunately I don't have a linker to do that for me with DCompute.
 Regardless, needing something like an attribute to tell the
 compiler to strip stuff out of the binary seems like a hack to
 me. It may actually be necessary in some cases, but it just
 feels like it should be unnecessary.
Do you have any other ideas about how to achieve this other than an attribute? Having an attribute seems the most simple and straightforward.
It may be that an attribute is required in at least some cases, but it seems like it shouldn't be and that if the compiler and/or linker isn't smart enough to strip out stuff that's only used at compile time, then it should be fixed to be smart enough. However, too often, there's some detail that's not obvious that makes it so that things can't work they way that it seems like they should. And of course, I have no clue how whatever you're doing works if you're not using a linker with dcompute, so I don't know how it differs from normal. I've never done anything with GPU programming. - Jonathan M Davis
Dec 06 2017
prev sibling parent Johannes Pfau <nospam example.com> writes:
Am Wed, 06 Dec 2017 20:18:57 -0700
schrieb Jonathan M Davis <newsgroup.d jmdavisprog.com>:

 Folks have talked about all kinds of template code and stuff being
 kept around in binaries even though it was only used at compile time
 (e.g. stuff like isInputRange), but I don't know how much that's
 actually true.
You probably never call isInputRange at runtime, so the code is likely stripped. However, TypeInfo of structs used only at CTFE is still generated and not stripped. I remember we once had this problem with gcc.attribute, a module which shouldn't generate any code but generated useless TypeInfo. -- Johannes
Dec 07 2017
prev sibling parent Iain Buclaw <ibuclaw gdcproject.org> writes:
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.
Dec 07 2017
prev sibling next sibling parent reply Mike Franklin <slavo5150 yahoo.com> writes:
On Thursday, 7 December 2017 at 01:21:11 UTC, Nicholas Wilson 
wrote:

 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?
I've thought about this in the past, but never really pursued it much to see if there are already existing facilities in the language to accomplish what I want. I want to enforce that a method is only used at compile time. That is I want either the compiler or the linker to throw an error if I've accidentally used a function at runtime when I only intended it to be used at compile-time. Also, I want the compiler to let me know if my intended-for-compile-time-only function cannot be used at compile-time because I mistakenly made it dependent on something that is only available at runtime. That being said, I want D's features to carry their weight. I would first like to prove that facilities don't already exist or that existing facilities are too cumbersome to accomplish said goal before adding such a feature. Also, my primary motivation for using D is so I can program resource-constrained microcontrollers in a more fun and convenient language than C/C++. I've definitely encountered code-size problems in D, but they were mostly due to the compiler's unnecessary coupling to the runtime, and the way the compiler generated code as the linker couldn't prove that the code was dead (Exhibit A: https://issues.dlang.org/show_bug.cgi?id=14758). I don't yet see how ctfeonly would help with that. Mike
Dec 06 2017
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Thursday, December 07, 2017 03:59:09 Mike Franklin via Digitalmars-d 
wrote:
 Also, I want the
 compiler to let me know if my intended-for-compile-time-only
 function cannot be used at compile-time because I mistakenly made
 it dependent on something that is only available at runtime.
The simplest way to do that is to write a unit test that uses a static assertion. As I understand it, with the way CTFE works, it pretty much can't know whether a function can be called at compile time until it tries, but a unit test can catch it if the function no longer works at compile time. - Jonathan M Davis
Dec 06 2017
next sibling parent reply bauss <jj_1337 live.dk> writes:
On Thursday, 7 December 2017 at 04:45:15 UTC, Jonathan M Davis 
wrote:
As I understand it, with the way CTFE works,
 it pretty much can't know whether a function can be called at 
 compile time until it tries

 - Jonathan M Davis
I think that's the point of the attribute. You tell the compiler that this function can only be called at compile-time and any attempt to call it during run-time would be an error.
Dec 06 2017
parent reply E.S. Quinn <onetruequinn hotmail.com> writes:
On Thursday, 7 December 2017 at 05:53:06 UTC, bauss wrote:
 On Thursday, 7 December 2017 at 04:45:15 UTC, Jonathan M Davis 
 wrote:
 As I understand it, with the way CTFE works,
 it pretty much can't know whether a function can be called at 
 compile time until it tries

 - Jonathan M Davis
I think that's the point of the attribute. You tell the compiler that this function can only be called at compile-time and any attempt to call it during run-time would be an error.
If all you need is a runtime error, you can already put assert(__ctfe); in your function.
Dec 06 2017
next sibling parent Mike Franklin <slavo5150 yahoo.com> writes:
On Thursday, 7 December 2017 at 06:33:42 UTC, E.S. Quinn wrote:

 If all you need is a runtime error, you can already put 
 assert(__ctfe); in your function.
For me, a runtime error is exactly what I want to avoid. Mike
Dec 06 2017
prev sibling parent bauss <jj_1337 live.dk> writes:
On Thursday, 7 December 2017 at 06:33:42 UTC, E.S. Quinn wrote:
 On Thursday, 7 December 2017 at 05:53:06 UTC, bauss wrote:
 On Thursday, 7 December 2017 at 04:45:15 UTC, Jonathan M Davis 
 wrote:
 As I understand it, with the way CTFE works,
 it pretty much can't know whether a function can be called at 
 compile time until it tries

 - Jonathan M Davis
I think that's the point of the attribute. You tell the compiler that this function can only be called at compile-time and any attempt to call it during run-time would be an error.
If all you need is a runtime error, you can already put assert(__ctfe); in your function.
It's to avoid having a run-time error, so something that would produce a run-time call gives a compile-time error.
Dec 08 2017
prev sibling parent reply Mike Franklin <slavo5150 yahoo.com> writes:
On Thursday, 7 December 2017 at 04:45:15 UTC, Jonathan M Davis 
wrote:

 The simplest way to do that is to write a unit test that uses a 
 static assertion. As I understand it, with the way CTFE works, 
 it pretty much can't know whether a function can be called at 
 compile time until it tries, but a unit test can catch it if 
 the function no longer works at compile time.
Not bad, but that is swaying into the cumbersome category. If that's the best we can do, a ctfeonly attribute starts looking pretty good. Mike
Dec 06 2017
next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Thursday, December 07, 2017 07:41:18 Mike Franklin via Digitalmars-d 
wrote:
 On Thursday, 7 December 2017 at 04:45:15 UTC, Jonathan M Davis

 wrote:
 The simplest way to do that is to write a unit test that uses a
 static assertion. As I understand it, with the way CTFE works,
 it pretty much can't know whether a function can be called at
 compile time until it tries, but a unit test can catch it if
 the function no longer works at compile time.
Not bad, but that is swaying into the cumbersome category. If that's the best we can do, a ctfeonly attribute starts looking pretty good.
In the vast majority of cases, when a function is used for CTFE, it's also used during runtime. So, in most cases, you want to ensure that a function works both with CTFE and without, and in those cases something like ctfeonly wouldn't make any sense. In my experience, pretty much the only time that something like ctfeonly would make any sense would be with a function for generating a string mixin. I'm sure that there are folks who have other uses for functions that would only be used during CTFE, but really, CTFE is designed with the idea that functions would be useable both at runtime and at compile time, and most functions that are used during CTFE were not designed just for CTFE. Certainly, trying to test or enforce that a function is only used at compile time is not going to be the common case. - Jonathan M Davis
Dec 07 2017
parent Johannes Pfau <nospam example.com> writes:
Am Thu, 07 Dec 2017 01:32:35 -0700
schrieb Jonathan M Davis <newsgroup.d jmdavisprog.com>:

 
 In the vast majority of cases, when a function is used for CTFE, it's
 also used during runtime. So, in most cases, you want to ensure that
 a function works both with CTFE and without, and in those cases
 something like  ctfeonly wouldn't make any sense. In my experience,
 pretty much the only time that something like  ctfeonly would make
 any sense would be with a function for generating a string mixin.
Not only string mixins. When programming for microcontrollers you want to do as much in CTFE as possible, as space for executable code is severely limited. So you may for example want to use CTFE to generate some lookup tables and similar stuff. Basically the whole 'initialize a variable / constant using CTFE' idiom benefits a lot from such an attribute. -- Johannes
Dec 07 2017
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/6/2017 11:41 PM, Mike Franklin wrote:
 On Thursday, 7 December 2017 at 04:45:15 UTC, Jonathan M Davis wrote:
 
 The simplest way to do that is to write a unit test that uses a static 
 assertion. As I understand it, with the way CTFE works, it pretty much can't 
 know whether a function can be called at compile time until it tries, but a 
 unit test can catch it if the function no longer works at compile time.
Not bad, but that is swaying into the cumbersome category.  If that's the best we can do, a ctfeonly attribute starts looking pretty good.
More and more attributes to do essentially trivial things is cumbersomeness all on its own.
Dec 07 2017
parent Johannes Pfau <nospam example.com> writes:
Am Thu, 7 Dec 2017 13:38:54 -0800
schrieb Walter Bright <newshound2 digitalmars.com>:

 On 12/6/2017 11:41 PM, Mike Franklin wrote:
 On Thursday, 7 December 2017 at 04:45:15 UTC, Jonathan M Davis
 wrote:=20
 The simplest way to do that is to write a unit test that uses a
 static assertion. As I understand it, with the way CTFE works, it
 pretty much can't know whether a function can be called at compile
 time until it tries, but a unit test can catch it if the function
 no longer works at compile time. =20
=20 Not bad, but that is swaying into the cumbersome category.=C2=A0 If that's the best we can do, a ctfeonly attribute starts looking pretty good. =20
=20 More and more attributes to do essentially trivial things is cumbersomeness all on its own.
I think this is more of an optimization UDA than a standard attribute. So it's similar to all the noinline, forceinline, weak, section etc. attributes: https://wiki.dlang.org/Using_GDC#Attributes -- Johannes
Dec 07 2017
prev sibling next sibling parent Stefan Koch <uplink.coder googlemail.com> writes:
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?
Hi Nicholas, I am going to add a feature which will help you in this case; As part of the work I am doing to make templates faster.
Dec 06 2017
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/6/2017 5:21 PM, 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.
Put these functions into a separate import. Then import the file and use the functions at compile time. They will not have code generated for them.
Dec 07 2017
next sibling parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Thursday, 7 December 2017 at 09:34:51 UTC, Walter Bright wrote:
 On 12/6/2017 5:21 PM, 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.
Put these functions into a separate import. Then import the file and use the functions at compile time. They will not have code generated for them.
Doesn't work for templates.
Dec 07 2017
parent reply Walter Bright <newshound2 digitalmars.com> writes:
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.
Dec 07 2017
parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
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.
Dec 07 2017
parent reply Walter Bright <newshound2 digitalmars.com> writes:
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; }
Dec 07 2017
parent Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Friday, 8 December 2017 at 03:41:05 UTC, Walter Bright wrote:
 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;
 }
That requires that I know what instantiations I will have a head of time or I have to maintain a "header file" of named instantiations. Both of which I consider subpar solutions. Also while it may not bloat the GPU binary it will still bloat the host binary.
Dec 07 2017
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On 7 December 2017 at 01:34, Walter Bright via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On 12/6/2017 5:21 PM, 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.
Put these functions into a separate import. Then import the file and use the functions at compile time. They will not have code generated for them.
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...
Dec 07 2017
parent reply Walter Bright <newshound2 digitalmars.com> writes:
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.
Dec 07 2017
next sibling parent reply Manu <turkeyman gmail.com> writes:
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.
Dec 07 2017
parent reply Walter Bright <newshound2 digitalmars.com> writes:
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.
Dec 07 2017
parent reply Manu <turkeyman gmail.com> writes:
On 7 December 2017 at 19:43, Walter Bright via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 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.
Nicholas wants a *compile* error, not a link error.
Dec 08 2017
parent David Nadlinger <code klickverbot.at> writes:
On Friday, 8 December 2017 at 18:59:00 UTC, Manu wrote:
 Nicholas wants a *compile* error, not a link error.
I don't think this is necessarily implied from the original post. Certainly, a linker error would just work fine for the original use case (avoiding unsupported codegen on compute targets). -David
Dec 08 2017
prev sibling parent reply Manu <turkeyman gmail.com> writes:
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?
Dec 07 2017
next sibling parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
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.
Dec 07 2017
parent Manu <turkeyman gmail.com> writes:
On 7 December 2017 at 17:45, Nicholas Wilson via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 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.
Oh, sorry, I forgot key detail! (parens) int ctfeOnly()(int x) ... (in my mind, it was a template function, which means it would instantiate for the ctfe call separately to regular calls(?))
Dec 08 2017
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
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.
Dec 07 2017
next sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
Walter Bright wrote:

 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.
still, why `__ctfe` was designed as variable, and not as `enum ctfe = <bool>;`?
Dec 07 2017
next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
ketmar wrote:

 still, why `__ctfe` was designed as variable, and not as `enum ctfe = 
 <bool>;`?
p.s.: i see only one reason for this rationale: to explicitly prevent people using `static if` to separate CTFE and non-CTFE code (that is, to lessen the chance than function heaves differently in runtime and in compile-time). but that doesn't work, as `if (__ctfe)` allows two completely different code pathes anyway.
Dec 07 2017
prev sibling next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
ketmar wrote:

 still, why `__ctfe` was designed as variable, and not as `enum ctfe = 
 <bool>;`?
ah, sorry, i remembered. that was stupid question. the rationale is: `static if` and `static assert` are processed *before* CTFE phase. i.e. CTFE interpreter never sees them, and cannot do the choice. and on semantic analysis phase it is not known yet if the code is for CTFE or not. that is, to allow `static assert(__ctfe)` to work, the whole semantic phase must be redesigned.
Dec 07 2017
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Dec 08, 2017 at 05:53:37AM +0200, ketmar via Digitalmars-d wrote:
[...]
 still, why `__ctfe` was designed as variable, and not as `enum ctfe = <bool>;`?
https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time T -- I think the conspiracy theorists are out to get us...
Dec 08 2017
prev sibling parent Manu <turkeyman gmail.com> writes:
On 7 December 2017 at 19:49, Walter Bright via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 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.
Sorry, in my mind, it was meant to be a template function...
Dec 08 2017
prev sibling parent reply Mike Franklin <slavo5150 yahoo.com> writes:
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?
Interestingly, if you put `__ctfe` in a function it does seem to work (unless I'm missing something). Check this out. import std.stdio; bool isRunTime() { return !__ctfe; } bool isCompileTime() { static if (!isRunTime()) return __ctfe; else return false; } string onlyCompileTime() { static assert(isCompileTime(), "This function can only be executed at compile time"); assert(isCompileTime(), "This function can only be execute at compile time"); return "onlyCompileTime"; } string onlyRunTime() { // This assert will actually throw an error at compile-time, // if an attempt is made to execute it at compile time. assert(isRunTime(), "This function can only be executed at run time"); return "onlyRunTime"; } void main(string[] args) { static assert(isCompileTime()); static assert (!isRunTime()); assert(!isCompileTime()); assert(isRunTime()); static assert(onlyCompileTime() == "onlyCompileTime"); // Compile-time Error: Good! //static assert(onlyRunTime() == "onlyRunTime"); assert(onlyRunTime() == "onlyRunTime"); // Compile-time Error: Good! // pragma(msg, onlyRunTime()); // I couldn't figure out how to force `onlyCompileTime` to // execute at runtime. That's probably a good thing. } https://run.dlang.io/is/64fRRX I guess this is due to the fact that wrapping `__ctfe` in a function causes it to run at compile-time instead of at...well...compile-time (i.e. https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time) Mike
Dec 07 2017
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
Mike Franklin wrote:

      // I couldn't figure out how to force `onlyCompileTime` to
      // execute at runtime.  That's probably a good thing.
string s = onlyCompileTime(); no compilation errors, runtime assert. that is, it is technically still executed in runtime.
Dec 07 2017
parent Mike Franklin <slavo5150 yahoo.com> writes:
On Friday, 8 December 2017 at 06:39:10 UTC, ketmar wrote:

 no compilation errors, runtime assert. that is, it is 
 technically still executed in runtime.
damnit!
Dec 07 2017
prev sibling next sibling parent =?UTF-8?B?TWljaGHFgg==?= <mmcomando gmail.com> writes:
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?
I once tried to use dmd's -vgc option but it is not so useful when all CTFE funtions to generate D code trigger warnings about GC alcoations. I think such an attribute would silence this warnings, dmd -vgc would be much cleaner then.
Dec 07 2017
prev sibling next sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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
Dec 07 2017
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
Dec 07 2017
parent reply Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Friday, 8 December 2017 at 02:14:09 UTC, H. S. Teoh wrote:
 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
Woaaa... amazing job, Teoh! It seems that no link in the wiki points to that, or I'm wrong? That valuable stuff should be more visible... /Paolo
Dec 08 2017
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Dec 08, 2017 at 11:03:34AM +0000, Paolo Invernizzi via Digitalmars-d
wrote:
 On Friday, 8 December 2017 at 02:14:09 UTC, H. S. Teoh wrote:
 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
Woaaa... amazing job, Teoh! It seems that no link in the wiki points to that, or I'm wrong? That valuable stuff should be more visible...
[...] The reason nothing (official) points to it, is because it's still a draft that hasn't been polished, and some parts may not be 100% accurate. Unfortunately, I haven't had the time to work on finishing it up. But since it's a wiki, if you're up to it, contributions are welcome. :-) T -- Life is unfair. Ask too much from it, and it may decide you don't deserve what you have now either.
Dec 08 2017
prev sibling next sibling parent reply John Colvin <john.loughran.colvin gmail.com> writes:
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?
How would such a thing interact with __traits(compiles, ...) and is-expressions?
Dec 08 2017
parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Friday, 8 December 2017 at 10:46:20 UTC, John Colvin 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?
How would such a thing interact with __traits(compiles, ...) and is-expressions?
VERY good question, I'm not sure. From a purely practical perspective I'd say it should pass __traits(compiles, ...) and is-expressions purely because the kind of things that ctfeonly would be used to cull from the produced binaries are used as is-expressions (e.g. the template lambda that determines isInputRange), although I expect it use to be rare. Ultimately I think this this feature would fall in to the category of "use responsibly" and it would be the responsibility of the user. They could always reflect on the presence of the attribute if need be. From a point of consistency, probably however semantic constraints on things like LDC's magic attributes are done. I'm not sure how that is handled, but I suspect that __traits(compiles,...) does not take it into account. Johan? I will think more on it. Thanks.
Dec 08 2017
parent Stefan Koch <uplink.coder googlemail.com> writes:
On Friday, 8 December 2017 at 11:48:26 UTC, Nicholas Wilson wrote:
 On Friday, 8 December 2017 at 10:46:20 UTC, John Colvin wrote:
 On Thursday, 7 December 2017 at 01:21:11 UTC, Nicholas Wilson 
 wrote:
 [...]
How would such a thing interact with __traits(compiles, ...) and is-expressions?
VERY good question, I'm not sure. From a purely practical perspective I'd say it should pass __traits(compiles, ...) and is-expressions purely because the kind of things that ctfeonly would be used to cull from the produced binaries are used as is-expressions (e.g. the template lambda that determines isInputRange), although I expect it use to be rare. Ultimately I think this this feature would fall in to the category of "use responsibly" and it would be the responsibility of the user. They could always reflect on the presence of the attribute if need be. From a point of consistency, probably however semantic constraints on things like LDC's magic attributes are done. I'm not sure how that is handled, but I suspect that __traits(compiles,...) does not take it into account. Johan? I will think more on it. Thanks.
You might want to wait until Dconf 2018 before you start implementing something. As it happens I am working on a way which will make ctfe-only functions possible (though that's s side-effect rather then the goal)
Dec 08 2017
prev sibling parent Joakim <dlang joakim.fea.st> writes:
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?
This doesn't fulfill everything you're looking for, ie no compile-time error if tried to use at runtime, but isn't this existing idiom good enough? https://github.com/dlang/phobos/blob/master/std/functional.d#L307
Dec 08 2017