February 28, 2005 Re: Method resolution sucks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kris | "Kris" <Kris_member@pathlink.com> wrote in message news:cvtmi8$145v$1@digitaldaemon.com... > In article <cvtf29$sri$1@digitaldaemon.com>, Walter says... > >I've modified the error message to be: > > > >C:mars>dmd test > >test.d(9): function test.foo called with argument types: > > (char[],int,int) > >matches both: > > test.foo(char[],int,uint) > >and: > > test.foo(char[],uint,uint) > > > >This will go out in the next update. > > > That certainly cannot make matters worse. The problem, though, is that the compiler can inadvertantly focus one in the wrong direction (in my case it was > the 'inout int' and 'inout uint' that I thought was wrong). That's why, in the error diagnostic above, things irrelevant to the overload matching (the existence of 'inout', any default parameter values, function return values, etc.) are omitted. > It was two days before anyone posted the real crux of the error. Your first post did not reproduce the error. The second one was posted 2/24 at 9:16pm, and Derek replied with the cause of the error at 9:23pm. 7 minutes ain't bad <g>. > I think that indicates a problem that this reworked error message does not address. You did have an issue with the "cast(uint)(c) is not an lvalue" message, however, that was the second error message put out by the compiler. The real error was the first error message (both error messages pointed to the same line). This is the well known "cascading error message" thing, where the compiler discovers an error, issues a correct diagnostic, then makes its best guess at how to patch things up so it can move on. If it guesses wrong (there is no way it can reliably guess write, otherwise it might as well write the program for you!), then more errors come out. The cascading error message problem is common to all compilers that try to recover from errors and continue compiling (it's an especially horrific problem with C++ templates <g>). The way for the user to deal with it is to focus on fixing the first error, and on not worrying about the subsequent errors if they don't make sense. The alternative is for the compiler to just quit on the first error, and the early DMD compiler did that. But users found that unacceptable, and I agreed. If there's another problem you're referring to, I don't know what it might be. > Having said that, better diagnostics are always welcome. Diagnostics are always going to be a work in progress, like any user interface. |
February 28, 2005 Re: Method resolution sucks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Georg Wrede | "Georg Wrede" <georg.wrede@nospam.org> wrote in message news:42225D39.7010302@nospam.org... > > > Matthew wrote: >> "Georg Wrede" <georg.wrede@nospam.org> wrote in message news:42224176.8020809@nospam.org... >> >>> >>>Walter wrote: >>> >>> >>>>For D I opted for a simple 3 level matching system - exact match, match with implicit conversions, no match. >>> >>>The guys forced to do C++ for a living would cry big tears of envy. ;-) >> >> >> <rant> >> Not so. I know you've a smiley there, but I really think this "C++ is >> too complicated, D is superior" is incredibly hasty, not to say >> naive. >> >> I accept that from the compiler writer's perspective, D wins out over C++ in straightforwardness, implementatility, etc.etc. >> >> But I cannot believe everyone simply takes as read that out there, in the real world of large projects and diverse and tricky minds, D can be confidently stated and assumed to be superior. >> >> I'll give you one tiny little issue: D does not have implicit template instantiation. This has potentially enormous ramifications. It may turn out that Walter has another of his brilliant insights and works a way around it, or that we discover techniques with module namespaces and 'standard' utility function conventions that obviate it. But that's all a big maybe. To ignore/dismiss this _at this time_ is just mental. >> >> And there are lots more. We've only scratched the surface of TMP so far. The module model is, AFAICT, still a bit confused/ing. I don't think the issue of dynamic link-units is solved to everyone's satisfaction as yet. There's an ugly amount of coupling. We are yet to see how D's 'slack' implicit conversion handles in big projects with multiple developers and commercial deadlines. >> >> I think the writing of DPD, the maturation of D towards 1.0, and the increasing number and sophistication of libraries like Mango will, over the next several months, inform on this debate. But it is *not* a done deal at the moment, and saying so makes the D community, IMO, look somewhat idiotic. >> >> btw, all the foregoing is not aimed at Georg personally, just at the oft espoused idea that "D's superior to C++". It's not, albiet I look forward to 2005 being the year that it achieves the status of being so, or at least being a highly attractive alternative. > > What can I say? You are right. And most of the things you refer to are, admittedly wishful thinking. No argument there. But it's a little like the football (american) team assembling on the field and murmuring "we will kick ass". Never mind the other guys are better and bigger. It's just what one does to keep up morale. But it's really misleading, both to newbies, who might read such posts and think all is well, and then subsequently be really disheartened and annoyed when they discover all is not quite so rosy. The other mislead is more dangerous: Walter may be mislead into thinking everyone's happy (and, more importantly, working successfully with D) with the current state of play, and that the odd carp from Kris and myself are just noises from people who like to scream a lot. > And dammit, if D ain't gonna kick ass! (One day, that is.) I agree that it has enormous potential. I don't think it's anywhere near realised it yet. > Heck, if we didn't thoroughly believe that, then we'd all skip this forum, read Imperfect C++, etc. and go back to C++. He he. Well, a wise friend once told me that to ally oneself to only one language was folly. In any case, it's boring. I'm interested in D because: (i) this is the one of a very few forums that're not full of complete tw*ts (ii) Walter's overall attitude to IT and DM users is very attractive (iii) I think the idea of D showing up .NET and Java is appealing (iv) the potential for D to be better, or rather to better support, template programming without the necessary intellectual pain that goes on in C++ I do not *believe* that it will become all that it can, anymore than I *believe* my sons will grow up to be Nobel prize-winning physicists, or that Imperfect C++ will eventually be recognised as better for developers than some recent C++ books that like to make the reader feel inferior with all manner of nonsensical intellectual masturbation. I just think these things are not beyond the bounds of reason. > I think we need this "my daddy is stronger than your daddy" attitude. > > (Actually making this explicit and discussing it here may deteriorate the function of such thinking.) :-) I think strength comes from acknowledging one's shortcomings, and either learning to live with / obviate them, or using them as impetus to improve. Pretending that everything's good is the kind of crap we get from large corporations, or, dare I say it, 21st English-speaking governments (Canada and NZ largely excepted). |
February 28, 2005 Re: Method resolution sucks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | In article <1hc00815rv4ri$.mu3h8w8oh3gq.dlg@40tude.net>, Derek Parnell says... [lots of snipping] >> print (cast(char[]) "bork"); >> >> This is daft, Walter. And it hasn't been fixed a year later. > >Kris, what do you think the compiler ought to do in this case, given only the information you have supplied above? >> might cover up with an explicit-type-prefix on "literal" strings (such as >> w"wide-string"). > >And the alternative is ...?? Experience (here) suggests whenever anyone posts their own brand of 'resolution', it often tends to steer discussion in an unproductive direction. Ignoring that completely, here's one approach: string literals are always char[] ~ unless explicitly denoted as something other. The latter could be via the presense of an embedded wide-char (that "\u1234" notion the D website discusses), or a 'w' or 'd' prefix. Walter wasn't keen on the prefix notion, although there are plenty of prefixes already (perhaps that's why?). Regardless, the approach is simple and easy to remember. >> It shouldn't have to be like this. Surely there's a more elegant solution all round, both for the compiler and for the user? Less special-cases is better for everyone. > >Yes, but have you any ideas as to what that might look like? With respect, Derek, I'd rather not go there. There's several big issues bundled up within this arena, and I don't have anything I'd consider bulletproof at this time. Frankly, I'd rather Walter be encouraged into thinking long and hard about a better overall approach. |
February 28, 2005 Re: Method resolution sucks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kris | On Mon, 28 Feb 2005 01:09:43 +0000 (UTC), Kris wrote: > In article <1hc00815rv4ri$.mu3h8w8oh3gq.dlg@40tude.net>, Derek Parnell says... > > [lots of snipping] > >>> print (cast(char[]) "bork"); >>> >>> This is daft, Walter. And it hasn't been fixed a year later. >> >>Kris, what do you think the compiler ought to do in this case, given only the information you have supplied above? > >>> might cover up with an explicit-type-prefix on "literal" strings (such as >>> w"wide-string"). >> >>And the alternative is ...?? > > Experience (here) suggests whenever anyone posts their own brand of 'resolution', it often tends to steer discussion in an unproductive direction. > > Ignoring that completely, here's one approach: string literals are always char[] ~ unless explicitly denoted as something other. The latter could be via the presense of an embedded wide-char (that "\u1234" notion the D website discusses), or a 'w' or 'd' prefix. Walter wasn't keen on the prefix notion, although there are plenty of prefixes already (perhaps that's why?). Regardless, the approach is simple and easy to remember. That would sure simplify things nicely. I'd abide with it. >>> It shouldn't have to be like this. Surely there's a more elegant solution all round, both for the compiler and for the user? Less special-cases is better for everyone. >> >>Yes, but have you any ideas as to what that might look like? > > With respect, Derek, I'd rather not go there. There's several big issues bundled up within this arena, and I don't have anything I'd consider bulletproof at this time. Frankly, I'd rather Walter be encouraged into thinking long and hard about a better overall approach. Fair enough. Hope the approach works. -- Derek Melbourne, Australia 28/02/2005 12:15:32 PM |
February 28, 2005 Re: Method resolution sucks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | In article <cvtoi1$16mn$1@digitaldaemon.com>, Walter says... [snip] >Your first post did not reproduce the error. The second one was posted 2/24 at 9:16pm, and Derek replied with the cause of the error at 9:23pm. 7 minutes ain't bad <g>. <sigh> We're both wrong, Walter. I posted the broken example late Friday afternoon at 5:16pm. Manfred posted the 'compiler perspective' early Saturday evening -- unfortunately, I didn't pick it up until Sunday afternoon, and didn't actually inspect the posting date. Shame on me. We're both off by a day. Is this entirely necessary? >You did have an issue with the "cast(uint)(c) is not an lvalue" message, however, that was the second error message put out by the compiler. The real error was the first error message (both error messages pointed to the same line). This is the well known "cascading error message" thing, where the compiler discovers an error, issues a correct diagnostic, then makes its best guess at how to patch things up so it can move on. If it guesses wrong (there is no way it can reliably guess write, otherwise it might as well write the program for you!), then more errors come out. Yes, yes. It was a red-herring, and we should all know better. But the above might as well be the documentation from the algorithms involved; it doesn't even begin to consider some of very real problems inherent within combined implicit-casting & method-overloading. Does it? Or do you feel there are perhaps no problems there at all? This is an important question, Walter. |
February 28, 2005 Re: Method resolution sucks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kris | "Kris" <Kris_member@pathlink.com> wrote in message news:cvtu6b$1cl3$1@digitaldaemon.com... > In article <cvtoi1$16mn$1@digitaldaemon.com>, Walter says... >> The second one was posted 2/24 at 9:16pm, > We're both wrong, Walter. I posted the broken example late Friday afternoon at 5:16pm. 5:16, my newsreader shows 9:16. Obviously, we're in different timezones! > [...] it doesn't even > begin to consider some of very real problems inherent within combined > implicit-casting & method-overloading. Does it? > Or do you feel there are perhaps no problems there at all? This is an important > question, Walter. I think it would save time if you list the problems as you see them, or if it's in a message I have overlooked (a real possibility, I don't think I'll ever catch up!) please point me to that message. I don't feel the particular example you posted in this thread has problems beyond a confusing error message. |
February 28, 2005 Re: Method resolution sucks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | In article <cvu1in$1gkr$1@digitaldaemon.com>, Walter says... >> We're both wrong, Walter. I posted the broken example late Friday afternoon at 5:16pm. > >5:16, my newsreader shows 9:16. Obviously, we're in different timezones! Imagine! >> [...] it doesn't even >> begin to consider some of very real problems inherent within combined >> implicit-casting & method-overloading. Does it? >> Or do you feel there are perhaps no problems there at all? This is an >important >> question, Walter. > >I think it would save time if you list the problems as you see them, or if it's in a message I have overlooked (a real possibility, I don't think I'll ever catch up!) please point me to that message. I don't feel the particular example you posted in this thread has problems beyond a confusing error message. I've already noted some in a prior post in this thread (today). For more, you might refer to the very examples you used against the issues brought up via the old "alias peek-a-boo game" thread. Those examples are both speculative cases where issues arise over implicit-casting combined with method-overloading. For want of a better term, I'll refer to the latter as ICMO. At that time, you argued such examples were the reason why it was so important for any and all overloaded superclass-methods be /deliberately hidden/ from any subclass ~ and using an 'alias' to (dubiously, IMO) bring them back into scope was the correct solution. I noted at that time my suspicion this usage of 'alias' was a hack. Indeed, it is used as part of an attempt to cover up some of the issues surrounding ICMO. To reiterate some of the other issues, here they are, copied from the prior response to your post (the first one is obviously related to what's described above): =========================================================== Just look at what we (the users) have to do with 'alias' to bring back superclass methods that have had their name overloaded in the subclass? Each of those contrived old examples as to /why/ alias is supposedly necessary are based upon the fragility of combined implicit-casting & overloading within various scenarios. Here's another old & trivial example of this type of bogosity: void print (char[] s); void print (wchar[] s); {print ("bork");} Because the char literal can be implicitly cast to wchar[], the compiler fails. One has to do this instead: print (cast(char[]) "bork"); This is daft, Walter. And it hasn't been fixed a year later. Oh, and let's not forget that D will implicitly, and silently, convert a long argument into an int or byte. Not even a peep from the compiler. MSVC 6 certainly will not allow one to be so reckless. If I drove my car in a similar manner, I'd likely be put in jail. There's many, many more examples. Here's another old one that I always found somewhat amusing: news:cgat6b$1424$1@digitaldaemon.com I'm not saying that implicit-casting is necessarily bad, and I'm not saying that method-overloading is bad. I am saying the combination of the two leads to all sort of nastiness; some of which you've attempted to cover-up by implicitly hiding superclass method-names overloaded by a subclass, and which you just might cover up with an explicit-type-prefix on "literal" strings (such as w"wide-string"). It shouldn't have to be like this. Surely there's a more elegant solution all round, both for the compiler and for the user? Less special-cases is better for everyone. - Kris |
February 28, 2005 Re: Method resolution sucks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kris | On Fri, 25 Feb 2005 05:16:31 +0000 (UTC), Kris wrote: > In article <1vsrqzrq891rl$.heltnytmakww.dlg@40tude.net>, Derek Parnell says... >>Sorry, Kris, but I'm not getting any errors here, except that your example function 'wumpus()' returns a void. Once I changed that to a uint it compiled fine. Windows v0.113 >> >><code> >>uint foo (inout int x) {return 0;} >>uint foo (inout uint x) {return 0;} >> >>uint wumpus() >>{ >>uint y; >> >>return foo(y); >>} >></code> > > OK ~ found out what actually breaks: > > uint foo (char[] s, inout int v, uint r=10) {return 0;} > uint foo (char[] s, inout uint v, uint r=10) {return 0;} > > void bar() > { > char[] s; > int c; > > foo (s, c); // compiles > foo (s, c, 12); // fails > } > > There's some kind of issue with the default assignment ... yet the error message > states "cast(uint)(c) is not an lvalue", along with the other msg about "both > match argument list" > > Again; about as bulletproof as a broken-window I've been doing a little bit more analysis on the actual message given by this situation. Firstly, the messages as report by Kris seem to imply that the "not an lvalue" message appears before the "both match" message. However, using the *code as supplied*, I can only get the "both match" message. There is no "not an lvalue" message. I can however, get the lvalue message if I change the example code to read "uint c;" rather than "int c;", but then it occurs after the "both match" message. However, here is the exact message that I get with the example above... test.d(10): function test.foo overloads uint(char[]s,inout int v,uint r = cast(uint)(10)) and uint(char[]s,inout uint v,uint r = cast(uint)(10)) both match argument list for foo Now if I reformat the message to improve legibility ... test.d(10): function test.foo overloads uint(char[], inout int, uint) and uint(char[], inout uint, uint) both match argument list for foo Then add the (implied) signature for the failing foo call ... test.d(10): function test.foo uint(char[], inout int, int) overloads uint(char[], inout int, uint) and uint(char[], inout uint, uint) both match argument list for foo I find myself asking, "why did the compiler implicitly cast the constant 12 to and int *and* then stopped scanning for matches when it found the first mismatch?" For example, if it had of continued the scanning for *exact* matches, it could have cast the 12 to a uint and found the exact match. So I'm guessing the algorithm for matching goes something like this ... (1) Build a list of all routines in scope that have the same name. -- this gives us two -- uint(in char[], inout int, in uint) uint(in char[], inout uint, in uint) (2) For each item in the list of names above: See if the call in question exactly matches, if so flag it. Otherwise, see if the call in question can be coerced into matching. If so, flag it. (BTW, I'm assuming that matching is done on both data type and storage class ~ in, inout, out.) (3) If there are two or more items in the list flagged, issue the "both match" message. (4) If there are zero items in the list flagged, issue the "no match" message. (5) If there is exactly one item flagged, use this as the target of the call. Using this algorithm, with what we have "( char[], int, 12)", and note that I disregard the return type, the first item "(in char[], inout int, in uint)" does not exactly match because we don't know what to do with the literal yet. But it can be coerced to match, so flag it. The second item "(in char[], inout uint, in uint)" also does not match. And it *cannot* be coerced, because even though we can cast the 12 to a (in uint), we cannot cast the "int c" into a "inout uint" (because by doing so we'd have an lvalue error. So we don't flag the item because it cannot match the call. That leaves with exactly one matched routine. The compiler should have selected "uint foo (char[] s, inout int v, uint r=10) {return 0;}" because that is the only routine that can match the calling arguments without errors. So why did the compiler complain? Because I suspect that the storage class is not really being used as I expect for signature matching. If the routines did not have "inout" then we would have had both routines matching, and the error message would have made better sense. -- Derek Melbourne, Australia 28/02/2005 2:27:18 PM |
February 28, 2005 Re: Method resolution sucks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kris | "Kris" <Kris_member@pathlink.com> wrote in message news:cvu5go$1k2j$1@digitaldaemon.com... > I've already noted some in a prior post in this thread (today). For more, you > might refer to the very examples you used against the issues brought up via the > old "alias peek-a-boo game" thread. Those examples are both speculative cases > where issues arise over implicit-casting combined with method-overloading. For > want of a better term, I'll refer to the latter as ICMO. > > At that time, you argued such examples were the reason why it was so important > for any and all overloaded superclass-methods be /deliberately hidden/ from any > subclass ~ and using an 'alias' to (dubiously, IMO) bring them back into scope > was the correct solution. I noted at that time my suspicion this usage of 'alias' was a hack. Indeed, it is used as part of an attempt to cover up some of > the issues surrounding ICMO. Yes, we discussed that at length. I don't think either of us have changed our minds. > Here's another old & trivial example of this type of bogosity: > > void print (char[] s); > void print (wchar[] s); > > {print ("bork");} > > Because the char literal can be implicitly cast to wchar[], the compiler fails. > One has to do this instead: > > print (cast(char[]) "bork"); > > This is daft, Walter. And it hasn't been fixed a year later. That kind of thing happens when top down type inference meets bottom up type inference. It's on the list of things to fix. (It's technically not really an implicit casting issue. A string literal begins life with no type, the type is inferred from its context. This falls down in the overloading case you mentioned.) > Oh, and let's not forget that D will implicitly, and silently, convert a long > argument into an int or byte. Not even a peep from the compiler. MSVC 6 certainly will not allow one to be so reckless. Actually, it's the defined, standard behavior of both C and C++ to do this. MSVC 6 will allow it without a peep unless you crank up the warning level. At one point I had such disallowed, but it produced more error messages than it was worth, requiring the insertion of many daft cast expressions (and I know how you don't like them with string literals!). Unlike C and C++, implicit conversions of floating point expressions to integral ones is disallowed in D, and that doesn't seem to cause any problems. > There's many, many more examples. Here's another old one that I always found > somewhat amusing: news:cgat6b$1424$1@digitaldaemon.com That's the same issue as you brought up above - which happens first, name lookup or overloading? C++ does it one way, Java the other. D does it the C++ way. C++ can achieve the Java semantics with a 'using' declaration, D provides the same with 'alias'. In fact, D goes further by offering complete control over which functions are overloaded with which by using alias. Java has no such capability. > I'm not saying that implicit-casting is necessarily bad, and I'm not saying that > method-overloading is bad. I am saying the combination of the two leads to all > sort of nastiness; some of which you've attempted to cover-up by implicitly > hiding superclass method-names overloaded by a subclass, I suppose if you look at it from a Java perspective, it might seem like a coverup. But if you look at it from a C++ perspective, it behaves just as one would expect and be used to. Implicit casting has been in C and C++ for a very long time, and it's necessary to cope with the plethora of basic types (Java has a sharply reduced number of basic types, reducing the need for implicit conversions.) > and which you just > might cover up with an explicit-type-prefix on "literal" strings (such as > w"wide-string"). C/C++ use L"wide string". > It shouldn't have to be like this. Surely there's a more elegant solution all > round, both for the compiler and for the user? Less special-cases is better for > everyone. Nobody likes special cases, but they are an inevitable result of conflicting requirements. |
February 28, 2005 Re: Method resolution sucks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | "Derek Parnell" <derek@psych.ward> wrote in message news:1aryxa64qi6wv.1tueiq1jegdq2.dlg@40tude.net... > I find myself asking, "why did the compiler implicitly cast the constant 12 > to and int It didn't. The literal 12 is an int. Hence: C:mars>dmd test test.d(9): function test.foo called with argument types: (char[],int,int) matches both: test.foo(char[],int,uint) and: test.foo(char[],uint,uint) both match with implicit casts, hence the ambiguity error. Also, storage classes (such as inout) are ignored for overload matching, *only* argument types are looked at. |
Copyright © 1999-2021 by the D Language Foundation