Re: string file = __FILE__ considered harmful (and solution)

2018-06-01 Thread Walter Bright via Digitalmars-d

On 6/1/2018 12:30 AM, Mike Franklin wrote:
I already have a pending PR at https://github.com/dlang/dmd/pull/8310 which I 
can modify to fix for both __LINE__ and __FILE_ if I can get clarification on 
how it *should* work.


I followed up there. Thanks for taking care of this!


Re: string file = __FILE__ considered harmful (and solution)

2018-06-01 Thread Mike Franklin via Digitalmars-d

On Friday, 1 June 2018 at 03:14:11 UTC, Walter Bright wrote:

On 5/30/2018 2:45 PM, John Colvin wrote:

https://run.dlang.io/is/oMe7KQ

Less elegant, but solves the problem of accidental argument 
adding (CallerFile acts as a barrier). Unfortunately, while it 
works in theory, in practice the compiler crashes LOL


Please post bug reports when you find compiler crashes. Thanks!


It's the same issue as this 
(https://issues.dlang.org/show_bug.cgi?id=18916) only for 
__FILE__.


I already have a pending PR at 
https://github.com/dlang/dmd/pull/8310 which I can modify to fix 
for both __LINE__ and __FILE_ if I can get clarification on how 
it *should* work.


Mike


Re: string file = __FILE__ considered harmful (and solution)

2018-05-31 Thread Walter Bright via Digitalmars-d

On 5/30/2018 1:27 AM, FeepingCreature wrote:
There's a very common idiom where in order to report line numbers of an error or 
a log line at the callsite of a function, you pass __FILE__ and __LINE__ as 
default parameters:


void foo(string file = __FILE__, size_t line = __LINE__);

What's wrong with this?

Say you add a string parameter, such as

void foo(string msg, string file = __FILE__, size_t line = __LINE__);

foo("Hello World");

Now when you accidentally grab an old version of the library, your new code will 
still run, but it will believe that it's being called from file "Hello World", 
line 15.


A solution:

  enum E { reserved }

  void foo(E e = E.reserved, string file = __FILE__, size_t line = __LINE__);
  void foo(string msg, E e = E.reserved, string file = __FILE__, size_t line = 
__LINE__);


Re: string file = __FILE__ considered harmful (and solution)

2018-05-31 Thread Walter Bright via Digitalmars-d

On 5/30/2018 2:45 PM, John Colvin wrote:

https://run.dlang.io/is/oMe7KQ

Less elegant, but solves the problem of accidental argument adding (CallerFile 
acts as a barrier). Unfortunately, while it works in theory, in practice the 
compiler crashes LOL


Please post bug reports when you find compiler crashes. Thanks!


Re: string file = __FILE__ considered harmful (and solution)

2018-05-31 Thread Steven Schveighoffer via Digitalmars-d

On 5/31/18 7:14 AM, bauss wrote:

Instead of these hack keywords.

Perhaps a __traits() in the compiler with the information would be 
better suited like:



void foo()
{
     enum caller = __traits(getCaller);

     
}

getCaller would return a compile-time struct with additional information 
about the current module and the module/function it was called from.


How can this be possible? When inside the function, you have no idea 
where you were called from.


-Steve


Re: string file = __FILE__ considered harmful (and solution)

2018-05-31 Thread bauss via Digitalmars-d
On Wednesday, 30 May 2018 at 14:40:50 UTC, Steven Schveighoffer 
wrote:

On 5/30/18 4:27 AM, FeepingCreature wrote:
There's a very common idiom where in order to report line 
numbers of an error or a log line at the callsite of a 
function, you pass __FILE__ and __LINE__ as default parameters:


void foo(string file = __FILE__, size_t line = __LINE__);

What's wrong with this?

Say you add a string parameter, such as

void foo(string msg, string file = __FILE__, size_t line = 
__LINE__);


foo("Hello World");

Now when you accidentally grab an old version of the library, 
your new code will still run, but it will believe that it's 
being called from file "Hello World", line 15. Not good.


Luckily there's a fix. Just stick this in some common header 
file in your project:


struct CallerInfo
{
   string file;
   size_t line;
}

void foo(string msg, CallerInfo caller = CallerInfo(__FILE__, 
__LINE__));


Now you cannot accidentally invoke foo with a string, or in 
fact any type except another instance of CallerInfo.


Awesome idea! Unfortunately, it doesn't work. The __FILE__ and 
__LINE__ there are not from the caller, but from the line that 
defines foo.


See here: https://run.dlang.io/is/siz9YZ

At which point we can shorten this to CallerInfo caller = 
__CALLER__, and be forward compatible for additional 
information about the callsite, such as, say, attributes of 
the calling function.


Hm.. I don't like this too much. Adding more magic to the 
compiler seems unnecessary.


But if we fixed the behavior that causes your idea not to work, 
then we could probably easily define a function like so:


CallerInfo __CALLER__(string file = __FILE__, size_t line = 
__LINE__)

{
return CallerInfo(file, line);
}

-Steve


Instead of these hack keywords.

Perhaps a __traits() in the compiler with the information would 
be better suited like:



void foo()
{
enum caller = __traits(getCaller);


}

getCaller would return a compile-time struct with additional 
information about the current module and the module/function it 
was called from.


Alternatively you can use the following traits.

true/false as secondary argument for whether it should be its 
current module or the call module/function etc. This argument 
should be optional and when omitted should default to the callee.


__FILE__ -- __traits(getFile);
__FILE_FULL_PATH__ -- __traits(getFilePath);
__MODULE__ -- __traits(getModule);
__LINE__  -- __traits(getLine);
__FUNCTION__ -- __traits(getFunction);
__PRETTY_FUNCTION__ -- __traits(getPrettyFunction);


Re: string file = __FILE__ considered harmful (and solution)

2018-05-30 Thread John Colvin via Digitalmars-d
On Wednesday, 30 May 2018 at 14:40:50 UTC, Steven Schveighoffer 
wrote:

On 5/30/18 4:27 AM, FeepingCreature wrote:
There's a very common idiom where in order to report line 
numbers of an error or a log line at the callsite of a 
function, you pass __FILE__ and __LINE__ as default parameters:


void foo(string file = __FILE__, size_t line = __LINE__);

What's wrong with this?

Say you add a string parameter, such as

void foo(string msg, string file = __FILE__, size_t line = 
__LINE__);


foo("Hello World");

Now when you accidentally grab an old version of the library, 
your new code will still run, but it will believe that it's 
being called from file "Hello World", line 15. Not good.


Luckily there's a fix. Just stick this in some common header 
file in your project:


struct CallerInfo
{
   string file;
   size_t line;
}

void foo(string msg, CallerInfo caller = CallerInfo(__FILE__, 
__LINE__));


Now you cannot accidentally invoke foo with a string, or in 
fact any type except another instance of CallerInfo.


Awesome idea! Unfortunately, it doesn't work. The __FILE__ and 
__LINE__ there are not from the caller, but from the line that 
defines foo.


See here: https://run.dlang.io/is/siz9YZ



https://run.dlang.io/is/oMe7KQ

Less elegant, but solves the problem of accidental argument 
adding (CallerFile acts as a barrier). Unfortunately, while it 
works in theory, in practice the compiler crashes LOL


Re: string file = __FILE__ considered harmful (and solution)

2018-05-30 Thread Nick Sabalausky (Abscissa) via Digitalmars-d

On 05/30/2018 10:40 AM, Steven Schveighoffer wrote:


But if we fixed the behavior that causes your idea not to work, then we 
could probably easily define a function like so:


CallerInfo __CALLER__(string file = __FILE__, size_t line = __LINE__)
{
     return CallerInfo(file, line);
}



Love it!


Re: string file = __FILE__ considered harmful (and solution)

2018-05-30 Thread Steven Schveighoffer via Digitalmars-d

On 5/30/18 10:40 AM, Steven Schveighoffer wrote:
But if we fixed the behavior that causes your idea not to work, then we 
could probably easily define a function like so:


CallerInfo __CALLER__(string file = __FILE__, size_t line = __LINE__)
{
     return CallerInfo(file, line);
}


Filed an issue so it's not forgotten:

https://issues.dlang.org/show_bug.cgi?id=18919

-Steve


Re: string file = __FILE__ considered harmful (and solution)

2018-05-30 Thread Steven Schveighoffer via Digitalmars-d

On 5/30/18 4:27 AM, FeepingCreature wrote:
There's a very common idiom where in order to report line numbers of an 
error or a log line at the callsite of a function, you pass __FILE__ and 
__LINE__ as default parameters:


void foo(string file = __FILE__, size_t line = __LINE__);

What's wrong with this?

Say you add a string parameter, such as

void foo(string msg, string file = __FILE__, size_t line = __LINE__);

foo("Hello World");

Now when you accidentally grab an old version of the library, your new 
code will still run, but it will believe that it's being called from 
file "Hello World", line 15. Not good.


Luckily there's a fix. Just stick this in some common header file in 
your project:


struct CallerInfo
{
   string file;
   size_t line;
}

void foo(string msg, CallerInfo caller = CallerInfo(__FILE__, __LINE__));

Now you cannot accidentally invoke foo with a string, or in fact any 
type except another instance of CallerInfo.


Awesome idea! Unfortunately, it doesn't work. The __FILE__ and __LINE__ 
there are not from the caller, but from the line that defines foo.


See here: https://run.dlang.io/is/siz9YZ

At which point we can shorten this to CallerInfo caller = 
__CALLER__, and be forward compatible for additional information about 
the callsite, such as, say, attributes of the calling function.


Hm.. I don't like this too much. Adding more magic to the compiler seems 
unnecessary.


But if we fixed the behavior that causes your idea not to work, then we 
could probably easily define a function like so:


CallerInfo __CALLER__(string file = __FILE__, size_t line = __LINE__)
{
return CallerInfo(file, line);
}

-Steve


Re: string file = __FILE__ considered harmful (and solution)

2018-05-30 Thread FeepingCreature via Digitalmars-d

On Wednesday, 30 May 2018 at 11:59:05 UTC, bauss wrote:
On Wednesday, 30 May 2018 at 08:27:16 UTC, FeepingCreature 
wrote:
There's a very common idiom where in order to report line 
numbers of an error or a log line at the callsite of a 
function, you pass __FILE__ and __LINE__ as default parameters:


[...]


void foo(string file = __FILE__, size_t line = __LINE__)(string 
msg);


Wouldn't this solve it?


No, because a) then you're completely pointlessly making a foo 
for every line it's called in, b) you're not future compatible 
with, say, call column, and c) you get exactly the same problem 
with template value parameters, ie. foo!"some ct argument".


Re: string file = __FILE__ considered harmful (and solution)

2018-05-30 Thread bauss via Digitalmars-d

On Wednesday, 30 May 2018 at 08:27:16 UTC, FeepingCreature wrote:
There's a very common idiom where in order to report line 
numbers of an error or a log line at the callsite of a 
function, you pass __FILE__ and __LINE__ as default parameters:


[...]


void foo(string file = __FILE__, size_t line = __LINE__)(string 
msg);


Wouldn't this solve it?



Re: string file = __FILE__ considered harmful (and solution)

2018-05-30 Thread FeepingCreature via Digitalmars-d
Shit it doesn't work, I only checked if it compiled; it gives the 
wrong file/line number.


NEVERMIND ALL


Re: string file = __FILE__ considered harmful (and solution)

2018-05-30 Thread rikki cattermole via Digitalmars-d

On 30/05/2018 8:27 PM, FeepingCreature wrote:
There's a very common idiom where in order to report line numbers of an 
error or a log line at the callsite of a function, you pass __FILE__ and 
__LINE__ as default parameters:


void foo(string file = __FILE__, size_t line = __LINE__);

What's wrong with this?

Say you add a string parameter, such as

void foo(string msg, string file = __FILE__, size_t line = __LINE__);

foo("Hello World");

Now when you accidentally grab an old version of the library, your new 
code will still run, but it will believe that it's being called from 
file "Hello World", line 15. Not good.


Luckily there's a fix. Just stick this in some common header file in 
your project:


struct CallerInfo
{
   string file;
   size_t line;
}

void foo(string msg, CallerInfo caller = CallerInfo(__FILE__, __LINE__));

Now you cannot accidentally invoke foo with a string, or in fact any 
type except another instance of CallerInfo.


This is such a basic type that it really belongs in phobos, arguably 
object.d. At which point we can shorten this to CallerInfo caller = 
__CALLER__, and be forward compatible for additional information about 
the callsite, such as, say, attributes of the calling function.


ooo I have another solution.

Use a named argument[0]!

[0] https://github.com/rikkimax/DIPs/blob/named_args/DIPs/DIP1xxx-RC.md