D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 14161 - UFCS call does not abide by scope
Summary: UFCS call does not abide by scope
Status: RESOLVED INVALID
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P1 enhancement
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-02-10 03:59 UTC by Richard (Rikki) Andrew Cattermole
Modified: 2015-02-10 16:45 UTC (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Richard (Rikki) Andrew Cattermole 2015-02-10 03:59:13 UTC
If global function declared as same name to a local function pointer, UFCS will call the global function.

Discovered: http://forum.dlang.org/post/qgtyvxurlgbrctjvnzlv@forum.dlang.org
> import std.stdio;
> 
> void f(int a) {
>      writeln("it's a function! : ", a);
> }
> 
> void main() {
>      auto f = function (int a) {writeln("It's a variable! : ", a);};
>      5.f();
>      f(5);
> }
> 
> Output:
> 
> it's a function! : 5
> It's a variable! : 5
Comment 1 Fyodor Ustinov 2015-02-10 04:11:15 UTC
Moreover. If the function is not defined (only pointer), I get 
this error:

aa.d(5): Error: no property 'f' for type 'int'

when try use 5.f();
Comment 2 Ketmar Dark 2015-02-10 11:38:27 UTC
not a bug. UFCS is designed to ignore local definitions.

http://dlang.org/function.html#pseudo-member
Comment 3 Fyodor Ustinov 2015-02-10 12:47:40 UTC
I think this code should generate warning as least.
Comment 4 Ketmar Dark 2015-02-10 12:57:04 UTC
please, open ER for it. this is definitely not a bug, so it shouldn't be opened as *bug* report, especially with the current subj. and then please close this as "notabug" again.
Comment 5 Steven Schveighoffer 2015-02-10 15:13:27 UTC
Actually, don't open another enhancement request, it will be closed as invalid as well. The case you are trying to solve was already considered specifically inside the spec and described as invalid. Only module-level UFCS functions will be considered, and this is intentional.
Comment 6 Ketmar Dark 2015-02-10 15:21:49 UTC
Fyodor is not talking about "fixing" UFCS. what he talking about is issuing a warning when there is local declaration with the same name as global one, and global one was chosen by UFCS.

here compiler should issue warning that "global 'f' chosen for UFCS instead of local one". yes, this is by spec, but sometimes people forgetting about this and expecting local call. the code compiles fine, but does wrong things, and this can be very puzzling.

yet this is against the "D is only for smarts", so i don't think that such warning will be added. the standard answer to this is "use lint tool instead" — as for some other warnings that affects newcomers, who don't want to run lint each time. D is inherently hostile to newcomers.
Comment 7 bearophile_hugs 2015-02-10 15:40:30 UTC
(In reply to Ketmar Dark from comment #6)

> here compiler should issue warning that "global 'f' chosen for UFCS instead
> of local one". yes, this is by spec, but sometimes people forgetting about
> this and expecting local call.

This code prints "foo2" without warnings and errors:

import std.stdio;
void foo() { writeln("foo1"); }
void main() {
    void foo() { writeln("foo2"); }
    foo();
}


while this gives a shadowing error message:


struct Foo { int x; }
void main() {
    int x;
    Foo f;
    with (f)
        x++;
}


test.d(6): Error: with symbol test.Foo.x is shadowing local symbol test.main.x


In theory this looks like the first case, where a local function (pointer) silently shadows a module-level function:

import std.stdio;
void foo(int a) {
     writeln("it's a function! : ", a);
}
void main() {
     auto foo = (int a) { writeln("It's a variable! : ", a); };
     5.foo();
     foo(5);
}


But this behaviour looks a little surprising. So perhaps in this case specifc it's better to give a shadowing error (with a warning/deprecation phase first), to avoid ambiguity. Like with() when no actual ambiguity is present in the code, no error message should be generated.
Comment 8 Ketmar Dark 2015-02-10 15:50:18 UTC
i don't think that shadowing globals should always generate warning. i believe that it's enough to generate warning only when there is possible UFCS shadowing.

so:

import std.stdio;
void foo(int a) {
     writeln("it's a function! : ", a);
}
void main() {
     auto foo = (int a) { writeln("It's a variable! : ", a); };
     //5.foo();
     foo(5);
}

no warning.

but with uncommented `5.foo();` there should be a warning.

shadowing global functions with locals is not a big deal in a good written code, but remembering that UFCS ignores locals and picks globals instead is something that should better be told by the compiler.
Comment 9 Steven Schveighoffer 2015-02-10 16:37:24 UTC
(In reply to bearophile_hugs from comment #7)

> But this behaviour looks a little surprising. So perhaps in this case
> specifc it's better to give a shadowing error (with a warning/deprecation
> phase first), to avoid ambiguity. Like with() when no actual ambiguity is
> present in the code, no error message should be generated.

Shadowing is only allowed on global scope. The reasons are simple:

1. You often have little control over what modules you import define.
2. You can use '.' to distinguish between your local symbol and the global one.

(In reply to Ketmar Dark from comment #8)
> i don't think that shadowing globals should always generate warning. i
> believe that it's enough to generate warning only when there is possible
> UFCS shadowing.

I am not of the opinion that UFCS is so special we need to bend over backwards to make it work in all cases. The underlying request that must be implemented before we even consider adding a warning for a conflict is that you need to be able to use UFCS on function pointers or even nested or member functions. I don't think we should even do that, and without that, there isn't a point for a warning here. There is always the possibility to use normal function call syntax.
Comment 10 Ketmar Dark 2015-02-10 16:45:22 UTC
ah, the normal D attitude. "beginners sux!" (c) pascal/Cubic Team