Re: Cannot check function address

2022-05-25 Thread frame via Digitalmars-d-learn
On Wednesday, 25 May 2022 at 14:09:31 UTC, Steven Schveighoffer 
wrote:


Yes, he acknowledged that too much was stripped. I also 
verified similar code works.


But the real problem was something else. He is saying in this 
message "why doesn't the compiler recognize that in comparing a 
function to null, I really wanted to compare a function 
*pointer* to null", but I don't see how the compiler can make 
that leap.


Often times, I wish the compiler could just read what I was 
thinking when I wrote the code, so it could give me 
thought-contextual errors but alas, it can't.


-Steve


The real problem was that I was locking my mind that the `fun` 
symbol was unique. In fact it was not. There was another code 
version where the `fun` symbol was declared as exported function 
and some import did read that code. My code was not affected from 
this bug since the call syntax for function and function pointer 
was the same. And I honestly never noticed that the compiler may 
says 'function' or 'function pointer'. It was always the same to 
me.


I should have test it with `__traits(getLocation)` before.


Re: Cannot check function address

2022-05-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/25/22 6:55 AM, user1234 wrote:

On Wednesday, 25 May 2022 at 06:04:10 UTC, frame wrote:

On Wednesday, 25 May 2022 at 05:56:28 UTC, Steven Schveighoffer wrote:

It's a case where the compiler can't divine what you were thinking 
when you wrote that code ;)


I see not in all cases but in mine. If the compiler sees the function 
isn't callable without arguments and it is inside an if-statement or 
`assert()` then it could at least suggest a pointer or ask: are you 
dumb? ;-)


As suggested by others, the reduction is not correct, you have stripped 
too muchbecause this compiles just fine:


Yes, he acknowledged that too much was stripped. I also verified similar 
code works.


But the real problem was something else. He is saying in this message 
"why doesn't the compiler recognize that in comparing a function to 
null, I really wanted to compare a function *pointer* to null", but I 
don't see how the compiler can make that leap.


Often times, I wish the compiler could just read what I was thinking 
when I wrote the code, so it could give me thought-contextual errors but 
alas, it can't.


-Steve


Re: Cannot check function address

2022-05-25 Thread user1234 via Digitalmars-d-learn

On Wednesday, 25 May 2022 at 06:04:10 UTC, frame wrote:
On Wednesday, 25 May 2022 at 05:56:28 UTC, Steven Schveighoffer 
wrote:


It's a case where the compiler can't divine what you were 
thinking when you wrote that code ;)


I see not in all cases but in mine. If the compiler sees the 
function isn't callable without arguments and it is inside an 
if-statement or `assert()` then it could at least suggest a 
pointer or ask: are you dumb? ;-)


As suggested by others, the reduction is not correct, you have 
stripped too muchbecause this compiles just fine:


a.d:
```d
alias F = void function(int);
F f;

static this()
{
assert(!f);
assert(f is null);
}
```

b.d:
```d
import a;

static this()
{
assert(!f);
assert(f is null);
}
```

```sh
$ dmd a.d b.d -main
$ echo $?
$ 0
```


Re: Cannot check function address

2022-05-25 Thread frame via Digitalmars-d-learn
On Wednesday, 25 May 2022 at 05:56:28 UTC, Steven Schveighoffer 
wrote:


It's a case where the compiler can't divine what you were 
thinking when you wrote that code ;)


I see not in all cases but in mine. If the compiler sees the 
function isn't callable without arguments and it is inside an 
if-statement or `assert()` then it could at least suggest a 
pointer or ask: are you dumb? ;-)





Re: Cannot check function address

2022-05-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/25/22 1:40 AM, frame wrote:

This would have been more visible if the compiler just says: "function 
cannot be compared against null, only function pointer". That function 
vs function pointer is too subtle.




It's a case where the compiler can't divine what you were thinking when 
you wrote that code ;)


remember that the expression `fun` where fun is a *function*, and not a 
*function pointer*, is the equivalent of `fun()`.


It can't figure out that you really thought `fun` was a function 
pointer, maybe it thinks that you are missing an overload? Maybe fun 
actually is a no-arg function, and the result isn't comparable against 
null (or maybe it is, and it compiles and does something completely 
different!).


But I'm glad you discovered the issue.

-Steve


Re: Cannot check function address

2022-05-24 Thread frame via Digitalmars-d-learn
On Wednesday, 25 May 2022 at 04:34:43 UTC, Steven Schveighoffer 
wrote:


Well, you can possibly work around the type system, but I don't 
know what the compiler thinks you have there.


This really bothers me and I put this test cases:


```d
static if (isSomeFunction!fun) pragma(msg,...)
static if (isFunctionPointer!fun) pragma(msg,...)
static if (isCallable!fun) pragma(msg,...)
```

It output mostly true except in one case where the compiler 
really sees a function, not a pointer.


Thanks, now the difference is clear to me, Adam was right. I 
guess I have forgotten some version-switch somewhere and it tries 
to compile none-suitable code which will be never used in runtime 
at this point.


This would have been more visible if the compiler just says: 
"function cannot be compared against null, only function 
pointer". That function vs function pointer is too subtle.




Re: Cannot check function address

2022-05-24 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/25/22 12:16 AM, frame wrote:

On Wednesday, 25 May 2022 at 03:41:17 UTC, Steven Schveighoffer wrote:

This is a compiler bug, at least I think so. Since the compiler is 
misbehaving, it's not clear how to make it behave.


-Steve


Well, ok, it's not my top priority and dustmite seems to run better on 
Unix - which I need to port anyway some time but not now.


But it must be possible to check if the function pointer is valid in 
Assembler? But I'm not familiar with asm to do it correctly - I would be 
very appreciative if someone could post an example how to do it in D.


So far, thank you for your time.


Well, you can possibly work around the type system, but I don't know 
what the compiler thinks you have there.


```d
assert(*(cast(void**)) !is null);
```

-Steve


Re: Cannot check function address

2022-05-24 Thread frame via Digitalmars-d-learn
On Wednesday, 25 May 2022 at 03:41:17 UTC, Steven Schveighoffer 
wrote:


This is a compiler bug, at least I think so. Since the compiler 
is misbehaving, it's not clear how to make it behave.


-Steve


Well, ok, it's not my top priority and dustmite seems to run 
better on Unix - which I need to port anyway some time but not 
now.


But it must be possible to check if the function pointer is valid 
in Assembler? But I'm not familiar with asm to do it correctly - 
I would be very appreciative if someone could post an example how 
to do it in D.


So far, thank you for your time.


Re: Cannot check function address

2022-05-24 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/24/22 11:14 PM, frame wrote:

On Wednesday, 25 May 2022 at 02:42:26 UTC, Steven Schveighoffer wrote:



try:

pragma(msg, typeof(fun));


Outputs:
```
extern (C) void function(...)
```


OK, so it's a function pointer.



But the compiler would complain if I call it as a type? And how could it 
call it later without an address to it - this works.


You don't need an address to call it. The compiler shouldn't complain at 
all, nor should it decide to think you are calling it without parentheses.




D should never call a function pointer without parentheses.


I'm very good in finding weird bugs ;-) Unfortunately, I cannot make an 
example. I already tried some changes/simplifications but cannot 
reproduce it outside the project.


I have encountered bugs like this (which disappear with seemingly 
unrelated removals). They are hard to deal with.


Have you tried [dustmite](https://code.dlang.org/packages/dustmite)? It 
can reduce D code down automatically to a smaller example, but be warned 
that if you get the condition wrong, and your code base is huge, it can 
take hours/days to whittle down to something that isn't what you want.


You can file a bug without a full example, just note that you have 
verified via the pragma(msg) statement above that the symbol is indeed a 
function pointer, and that compiler is trying to call it without 
explicit parentheses.


However, without a complete example, it's going to be hard to find/fix.

But how can I help the compiler to use it as correct type? On invocation 
with arguments all works fine, but checking if the pointer is not null 
fails. It not even works with an assignment. Could some `static if()` 
maybe help or some asm trick?


This is a compiler bug, at least I think so. Since the compiler is 
misbehaving, it's not clear how to make it behave.


-Steve


Re: Cannot check function address

2022-05-24 Thread frame via Digitalmars-d-learn
On Wednesday, 25 May 2022 at 02:42:26 UTC, Steven Schveighoffer 
wrote:


Just to be pedantic, you tried that call in the *exact place* 
the assert is failing to compile? D can be weird/surprising 
about name lookups.


Yes, of course ;-)



try:

pragma(msg, typeof(fun));


Outputs:
```
extern (C) void function(...)
```



If I do:

```d
extern(C) void foo(string) {}

pragma(msg, typeof(foo));
pragma(msg, typeof());
```

I get:

extern (C) void(string param)
extern (C) void function(string param)

The first is a function (yes, they have a type), and the latter 
is a function pointer.


But the compiler would complain if I call it as a type? And how 
could it call it later without an address to it - this works.



D should never call a function pointer without parentheses.


I'm very good in finding weird bugs ;-) Unfortunately, I cannot 
make an example. I already tried some changes/simplifications but 
cannot reproduce it outside the project.


But how can I help the compiler to use it as correct type? On 
invocation with arguments all works fine, but checking if the 
pointer is not null fails. It not even works with an assignment. 
Could some `static if()` maybe help or some asm trick?


Re: Cannot check function address

2022-05-24 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/24/22 10:06 PM, frame wrote:


Sorry, this was not affront, it was meant as my POV that you may have 
problems to get my problem because I have (as usually) forgot to make 
this more visible that some code was truncated.


OK, sorry to read into that ;)

I tried your suggestion, as replied to Adam - the symbol is unique and 
it shows that correct location. It's not different from the error message.


Just to be pedantic, you tried that call in the *exact place* the assert 
is failing to compile? D can be weird/surprising about name lookups.




However, this error has nothing to do with `assert()`. In fact the 
compiler allows nothing than invocation or this error will be triggered. 
Even that fails:


The compiler is treating `fun` not as a function pointer, but as a 
function. However, the type looks correct to me. I tried a simple 
example on run.dlang.io, even with multiple modules, and seems to work 
as expected.




```d
// same error:
auto test = cast(void*)fun;
```



try:

pragma(msg, typeof(fun));

If I do:

```d
extern(C) void foo(string) {}

pragma(msg, typeof(foo));
pragma(msg, typeof());
```

I get:

extern (C) void(string param)
extern (C) void function(string param)

The first is a function (yes, they have a type), and the latter is a 
function pointer.


So that might give a clue whether the compiler thinks `fun` is a 
function or a function pointer. D should *never* call a function pointer 
without parentheses.


If you get the latter, yet your assert fails, then that is most 
certainly a compiler bug. Again, important that you do this in the exact 
place the assert fails to ensure the same name lookup situation.


-Steve


Re: Cannot check function address

2022-05-24 Thread frame via Digitalmars-d-learn

On Tuesday, 24 May 2022 at 22:18:44 UTC, Adam D Ruppe wrote:

There's a big difference between a function and a function 
pointer.


Could you please clarify in this context?

`Fun` is basically generated by code like that:
```d
extern (Windows) void* GetProcAddress(void*, const char*);
auto fn = cast(T)GetProcAddress(lib, mangledName.toStringz);
```

If it is a function, you get its address with the & operator. 
But if it is supposed to be a function pointer, something is 
wrong with the declaration...


I have no idea what the correct term is but the debugger says 
`fun` is:

(if that `assert()` is removed and it compiles):
```
Type: void function(...)*
Value: 0x  null
```

I can get some address with `` but deferencing then fails:
```d
auto addr = 
assert(*addr); // Error: expression `*addr` of type `extern (C) 
void(...)` does not have a boolean value

```


Re: Cannot check function address

2022-05-24 Thread frame via Digitalmars-d-learn
On Wednesday, 25 May 2022 at 01:23:56 UTC, Steven Schveighoffer 
wrote:


"of course" I have no idea what your real code looks like, 
unless you post the real code.


While I get the point of trying to slim down the example to 
something postable, a very common problem with this kind of 
self-trimming is that you end up trimming out the problematic 
code. Why? Because if you noticed the problematic code, you 
wouldn't be posting here, you would just fix it. This, in fact, 
happens to me frequently.


Now, it's also possible that there is an actual compiler bug 
here, it certainly seems like it could be, but a full 
(non-)working example would be useful.


I still highly recommend trying code like:

```d
import std.traits;
pragma(msg, fullyQualifiedName!fun);
```

inside the place where your assert is failing. To me, if it's 
using the expected symbol for `fun` (or whatever it's called), 
then it should print the definition you expect from the module 
you expect. If not, maybe there is a name conflict, and it's 
picking the wrong one? These problems can be tricky to find.


-Steve


Sorry, this was not affront, it was meant as my POV that you may 
have problems to get my problem because I have (as usually) 
forgot to make this more visible that some code was truncated.


I tried your suggestion, as replied to Adam - the symbol is 
unique and it shows that correct location. It's not different 
from the error message.


However, this error has nothing to do with `assert()`. In fact 
the compiler allows nothing than invocation or this error will be 
triggered. Even that fails:


```d
// same error:
auto test = cast(void*)fun;
```



Re: Cannot check function address

2022-05-24 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/24/22 6:10 PM, frame wrote:

On Tuesday, 24 May 2022 at 19:09:52 UTC, Steven Schveighoffer wrote:

This doesn't seem valid for module-level code, assert is an 
instruction, not a declaration.

...
Try `std.traits.fullyQualifiedName!fun` to see where it's coming from.

expected 5 got 0 suggests it is finding some other fun, as a.fun only 
takes a single parameter.


Of course this `assert()` is actually inside `static this()` and there 
is only one declaration. I just want to show that the used symbol and 
call is the same.


"of course" I have no idea what your real code looks like, unless you 
post the real code.


While I get the point of trying to slim down the example to something 
postable, a very common problem with this kind of self-trimming is that 
you end up trimming out the problematic code. Why? Because if you 
noticed the problematic code, you wouldn't be posting here, you would 
just fix it. This, in fact, happens to me frequently.


Now, it's also possible that there is an actual compiler bug here, it 
certainly seems like it could be, but a full (non-)working example would 
be useful.


I still highly recommend trying code like:

```d
import std.traits;
pragma(msg, fullyQualifiedName!fun);
```

inside the place where your assert is failing. To me, if it's using the 
expected symbol for `fun` (or whatever it's called), then it should 
print the definition you expect from the module you expect. If not, 
maybe there is a name conflict, and it's picking the wrong one? These 
problems can be tricky to find.


-Steve


Re: Cannot check function address

2022-05-24 Thread Adam D Ruppe via Digitalmars-d-learn

On Tuesday, 24 May 2022 at 22:10:21 UTC, frame wrote:
To also anwser to Adam: no, this symbol is unique. The first 
line of the error says:


```
Error: function `a.fun(string param)` is not callable using 
argument types `()`.

```


There's a big difference between a function and a function 
pointer.


This error message says "function". But the code you showed as a 
function pointer.


If it were a function pointer, the error would be:

```
Error: function pointer `a()` is not callable using argument types
(int)`
```


So there is clearly some kind of mix up here.


The point is, it shouldn't be called in this line anyway?


If it is a function, you get its address with the & operator. But 
if it is supposed to be a function pointer, something is wrong 
with the declaration...


Re: Cannot check function address

2022-05-24 Thread Alain De Vos via Digitalmars-d-learn

Just looking at the error, are 2.098.1 & 2.100 , 100% compatible ?


Re: Cannot check function address

2022-05-24 Thread frame via Digitalmars-d-learn
On Tuesday, 24 May 2022 at 19:09:52 UTC, Steven Schveighoffer 
wrote:


This doesn't seem valid for module-level code, assert is an 
instruction, not a declaration.

...
Try `std.traits.fullyQualifiedName!fun` to see where it's 
coming from.


expected 5 got 0 suggests it is finding some other fun, as 
a.fun only takes a single parameter.


Of course this `assert()` is actually inside `static this()` and 
there is only one declaration. I just want to show that the used 
symbol and call is the same.


Also this is **working** code. I just put the `assert()` there to 
ensure the function isn't called by a race condition before it 
was loaded (module constructors often have cyclic dependency, so 
I cannot put this in a more clean way).


Those asserts() are set in:

module A: module constructor
module B: some function

To also anwser to Adam: no, this symbol is unique. The first line 
of the error says:


```
Error: function `a.fun(string param)` is not callable using 
argument types `()`.

```

**Note that I have changed the actual module name and signature, 
it has orginal 5 arguments and very long names.**


The point is, it shouldn't be called in this line anyway?


Re: Cannot check function address

2022-05-24 Thread Adam Ruppe via Digitalmars-d-learn

On Tuesday, 24 May 2022 at 18:54:33 UTC, frame wrote:
Usually that works fine as shown in module A but for some 
reason not in module B.


Do you have some other definition of fun somewhere?


Re: Cannot check function address

2022-05-24 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/24/22 3:09 PM, Steven Schveighoffer wrote:

assert is an instruction, not a declaration.


errr it's a *statement*, not a declaration.

-Steve


Re: Cannot check function address

2022-05-24 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/24/22 2:54 PM, frame wrote:

I have a function slot that may be loaded via a shared library.
I want to check if that function has an address but compiler (DMD 2.100, 
Windows) instead tries to invocate the function?


```d
// --- module a:
alias F = extern (C) void function(string param);
F fun = someLibLoad!F("name");

assert(fun !is null); // compiles (also works in runtime)


This doesn't seem valid for module-level code, assert is an instruction, 
not a declaration.




// --- module b:
import a;

// same code:
//
// error: missing argument for parameter #1: ... with 2.098.1 or
// error: too few arguments, expected `5`, got `0` ... with 2.100
assert(fun !is null);
```

Usually that works fine as shown in module A but for some reason not in 
module B.
Workaround ideas? I tried casting to void* or ptrdiff_t but the compiler 
always tries to call the function -.-


`expected 5 got 0` suggests it is finding some other `fun`, as `a.fun` 
only takes a single parameter.


Try `std.traits.fullyQualifiedName!fun` to see where it's coming from.

-Steve


Cannot check function address

2022-05-24 Thread frame via Digitalmars-d-learn

I have a function slot that may be loaded via a shared library.
I want to check if that function has an address but compiler (DMD 
2.100, Windows) instead tries to invocate the function?


```d
// --- module a:
alias F = extern (C) void function(string param);
F fun = someLibLoad!F("name");

assert(fun !is null); // compiles (also works in runtime)

// --- module b:
import a;

// same code:
//
// error: missing argument for parameter #1: ... with 2.098.1 or
// error: too few arguments, expected `5`, got `0` ... with 2.100
assert(fun !is null);
```

Usually that works fine as shown in module A but for some reason 
not in module B.
Workaround ideas? I tried casting to void* or ptrdiff_t but the 
compiler always tries to call the function -.-