www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 10574] New: "auto ref" fails to match when IFTI succeeds (strip to level const)

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10574

           Summary: "auto ref" fails to match when IFTI succeeds (strip to
                    level const)
           Product: D
           Version: unspecified
          Platform: All
        OS/Version: All
            Status: NEW
          Keywords: rejects-valid
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: monarchdodra gmail.com



Basically, an "immutable(int[])" will not match "auto ref T[]", when it does
match "T[]".

Example:

//--------
import std.stdio;

version(all)
{
    void foo(T)(auto ref T[] i)
    {
        writeln(typeof(i).stringof);
    }
}
else
{
    void foo(T)(T[] i)
    {
        writeln(typeof(i).stringof);
    }
    void foo(T)(ref T[] i)
    {
        writeln(typeof(i).stringof);
    }
}

void main()
{
    immutable(int[]) i;
    foo(i);
}
//--------

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 08 2013
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10574


Steven Schveighoffer <schveiguy yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |schveiguy yahoo.com



12:10:26 PDT ---
For clarification, the error displayed for the given code is:

Error: template testautoref.foo(T)(auto ref T[] i) cannot deduce template
function from argument types !()(immutable(int[]))

And it does match immutable(int)[].  As implied, if you change to
version(none), it does indeed work.

const(int[]) also fails.

A workaround that seems to work, but I don't really like it, is to add
overloads for immutable(T[]) and const(T[])

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 08 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10574


Martin Nowak <code dawg.eu> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |code dawg.eu



Just an educated guess. The problem seems to be that the value is a L-value so
the  signature becomes (ref T[]) which cannot match immutable(int[]).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 08 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10574





 Just an educated guess. The problem seems to be that the value is a L-value so
 the  signature becomes (ref T[]) which cannot match immutable(int[]).
That's exactly the current compiler's behavior. "auto ref" always behave as "ref" parameter against lvalue argument `i`, then T[] cannot deduce type T from immutable(int[]). -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 08 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10574






 Just an educated guess. The problem seems to be that the value is a L-value so
 the  signature becomes (ref T[]) which cannot match immutable(int[]).
That's exactly the current compiler's behavior. "auto ref" always behave as "ref" parameter against lvalue argument `i`, then T[] cannot deduce type T from immutable(int[]).
More generally, it seems auto ref will never operate a cast on an lvalue *even if* the parameter is not templatized. This is strange because auto ref *will* do it for RValues. Here is another (reduced) example that shows it. //---- void foo()(auto ref long a); void main() { int get(); int a; foo(get()); //Fine, rvalue int is cast to long foo(a); //Nope! } //---- main.d(7): Error: template main.foo does not match any function template declaration. Candidates are: main.d(1): main.foo()(auto ref long a) main.d(7): Error: template main.foo()(auto ref long a) cannot deduce template function from argument types !()(int) //---- I also spotted this (which, IMO, is even more problematic): //---- struct S { property long get(); alias get this; } void foo()(auto ref long a); void main() { S s; foo(S()); //Fine. foo(s); //Nope! } //---- This time, it gives the "cryptic" error: main.d(14): Error: s.get() is not an lvalue => But that's strange: foo takes by auto ref... what do I care about lvalue? Because s is an Lvalue, it would appear the auto ref is "primed" to take by ref. It then fails when an actual Rvalue is given. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 09 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10574




07:17:57 PDT ---


 That's exactly the current compiler's behavior. "auto ref"  always behave as
 "ref" parameter against lvalue argument `i`, then T[] cannot deduce type T from
 immutable(int[]).
To the user, auto ref should really mean "use ref if possible, otherwise do not" In other words, I think auto ref should be the equivalent of having two identical templates, one with ref, and one without. Because IFTI can do some implicit casting, and implicit casting changes lvalues to rvalues, I think the rule is incorrect. The algorithm should be: If lvalue, then try ref. If that does not work, try non-ref version. If that does not work, error. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 11 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10574






 
 That's exactly the current compiler's behavior. "auto ref"  always behave as
 "ref" parameter against lvalue argument `i`, then T[] cannot deduce type T from
 immutable(int[]).
To the user, auto ref should really mean "use ref if possible, otherwise do not" In other words, I think auto ref should be the equivalent of having two identical templates, one with ref, and one without. Because IFTI can do some implicit casting, and implicit casting changes lvalues to rvalues, I think the rule is incorrect.
For the record (without putting any words in Kenji's mouth), I think he was just stating what the compiler was *doing*, and why the code was rejected. I don't think he meant to say that the current behavior was correct. Kenji, could you confirm that this is what you meant? That this is a correct "rejects-valid" ? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 11 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10574





 For the record (without putting any words in Kenji's mouth), I think he was
 just stating what the compiler was *doing*, and why the code was rejected. I
 don't think he meant to say that the current behavior was correct.
 
 Kenji, could you confirm that this is what you meant? That this is a correct
 "rejects-valid" ?
No, indeed I just talked about the current compiler's work, but I'm sure that current behavior is correct. The main point is what "auto ref" is doing - it's ref-ness deduction. If given argument is an lvalue, auto ref parameter would become ref. If it's an rvalue, would become non-ref. Nothing else is done. Type deduction and ref-ness deduction are completely orthogonal. It means that the combination of each deduction results might finally reject given argument. It's exactly what happened in the OP code. So I can say it's expected behavior. I believe that one language feature (in here "auto ref") should do just one thing correctly. Orthogonality between each features could reduce language's "special case", and combining them would bring abundant usage. For example, when you use "auto ref", the ref-ness deduction reliably avoids copy-construction of given argument. A brief conclusion is: "auto ref" is not a magic parameter. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 11 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10574






 For the record (without putting any words in Kenji's mouth), I think he was
 just stating what the compiler was *doing*, and why the code was rejected. I
 don't think he meant to say that the current behavior was correct.
 
 Kenji, could you confirm that this is what you meant? That this is a correct
 "rejects-valid" ?
No, indeed I just talked about the current compiler's work, but I'm sure that current behavior is correct. The main point is what "auto ref" is doing - it's ref-ness deduction. If given argument is an lvalue, auto ref parameter would become ref. If it's an rvalue, would become non-ref. Nothing else is done. Type deduction and ref-ness deduction are completely orthogonal. It means that the combination of each deduction results might finally reject given argument. It's exactly what happened in the OP code. So I can say it's expected behavior.
I strongly disagree. The argument of "ref-ness deduction" should be applied *after* type deduction. though. Applying it *before* makes no sense. Having a function that accepts an RValue of type U, yet reject an LValue of type U, is unheard of. It is strongly anti-expected. Finally, regardless of "how" auto ref works, this definitely goes against "what" auto ref is trying to solve: Writing functions that can take either by value or by ref, without having to write overloads. As is, the only solution here is to *not* use auto ref, but instead, write ref/value overloads: auto ref => Failed to provide solution it was designed for => design is flawed. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 11 2013
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10574




11:32:46 PDT ---

 The main point is what "auto ref" is doing - it's ref-ness deduction.
 If given argument is an lvalue, auto ref parameter would become ref. If it's an
 rvalue, would become non-ref. Nothing else is done.
 Type deduction and ref-ness deduction are completely orthogonal. It means that
 the combination of each deduction results might finally reject given argument.
 It's exactly what happened in the OP code.
I agree that was what auto-ref is supposed to do, but in this case, it's hurting more than helping. I can't think of a valid reason to forbid this, can you? This bug report should be changed to an enhancement, though (and the description appropriately modified). -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 11 2013