[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [objc-improvements] Just remembered something about multiple method
Re: [objc-improvements] Just remembered something about multiple method signatures...
Mon, 08 Sep 2003 12:44:03 +0200
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5b) Gecko/20030827
Ziemowit Laski wrote:
On Saturday, Sep 6, 2003, at 00:54 US/Pacific, David Ayers wrote:
Class1: -(id)test1Float:(float)f int:(int)i;
Class2: -(Object *)test1Float:(float)f int:(int)i;
In the old case, you could get a warning about the compiler picking
the wrong prototype but the results were correct.
In this particular case, the compiler picked a method signature out of
a hat that happened to work in that the intended codegen occurred.
But just because the "results were correct" in this case does not make
the compiler correct. :-( In fact, all you need to do here is add
Class3: -(void)test1Float:(float)f int:(int)i;
to see just how "incorrect" things can get. :-)
:-) but this protoype is not just a conflicting prototype, it's an
outright incompatible prototype, and as I believe Steve Naroff already
suggested, it may be wiser to emit a hard error when prototypes are not
just conflicting but really incompatible rather than second guessing any
But the new IMP promotion for id typed receivers will promote them
to doubles and clobber not only of the float but all following
arguments as well
I absolutely agree with you in that using the IMP prototype can also
result in "bad" (i.e., unintended) codegen.
The 'IMP' assumption *will* result in "bad" code generation as soon as
either return type or arguments contain floats. There is absolutly no
ambiguity in that.
If you're given a set of competing method signatures, each of them
with conflicting codegen requirements, there is absolutely no way you
can win here. :-( In the end, the user will simply have to type the
receiver more strongly (possibly by casting it at the call site) to
pick the intended signature, and I really don't see any other way out
of this predicament.
Yes! So let's not assume anything in this case, let's make it a hard
error. Assuming 'IMP' will to break more code than picking one did.
So why did I bother with this IMP thing here? There are two reasons:
(1) I wanted a consistent failure mode. In your test1Float:int:
example above, you see how the compiler may wind up picking a
different signature as more and more test1Float:int: methods are added
to the mix. The signature that gets picked may happen to "work" in
some cases and not work in others
Try my example with the old behavior. Change the order of the
declaration. You will see that the old behavior (eventhough possibly
not generating the warning) /always/ generates correct code because the
test1Float:int: were 'compatible' even though they were conflicting in
the exact return type.
(due to the float<->int promotions that both you and I discussed).
There is no 'float'<->'int' promotion. The varadic processing of 'IMP'
promotes all floats to doubles. So the reciever will always get a
double value instead of the expected float, yet it will not fit into the
parameter. The code must break in all cases.
Of course, the IMP signature may also either work or not work :-);
but at least now, it will do so consistently as new incarnations of
test1Float:int: are pulled in from who knows where. So choosing IMP
preserves consistency of the outcome regardless of the number/kind of
conflicting signatures chosen.
No, the IMP assumption will break /all/ methods that expect float
arguments, but have conflicting prototypes, even if they were
compatible. There is no way for it to do the "right thing" anymore in
the case of float arguments. (In fact there is no way to do the right
thing for any return types that have a different size than id either.)
I'd love to have a fallback mechanism that is as simple, elegant and
consistent as this.
(2) After making its method signature selection, the compiler should
be able to proceed as gracefully as possible. These are, after all,
warnings rather than errors. However, if a signature with return type
'void' is picked, the compiler will subsequently issue a hard error if
the program attempts to use the return value of the message.
In the case of conflicting prototypes that are actually incompatible, as
the 'void'/'id' return type example, the hard error is a "Good Thing"!
In fact the /real/ issue is that it could potentially pick the prototype
that declares the 'id' return value, but the message is actually sent to
the object that doesn't return anything. That will most like result in
a runtime error or undefined behavior at least. In this case the better
solution would be a hard compile time error.
A milder version of this occurs when the compiler produces a string of
warnings about incompatible pointer types of arguments; these warnings
are purely a result of the fact that there was a conflict to begin
with, and tend to confuse users (as evidenced by bug reports filed
against Apple's gcc).
Please reconsider the validity of these bug reports. If the compiler
cannot determine the correct prototype to generate code for, the
developer must provide a meaning full cast (and potential runtime checks
with alternative execution paths where each path casts the reciever to
the corresponding type and the compiler can then generate code for the
correct prototype in the corresponding paths.
We are trying to find an elegant way to generate correct code for
ambiguous declarations. The more I think about it, the less I like even
this compromise. I'm starting to lean heavily toward emiting a hard
error where prototypes are not just conflicting but also incompatible,
as this means that the compiler is forced to generate bad code for some
cases. And the case you qoute with conflicting return types 'id'/'void'
would definitely fall into that category. This behavior should meet
your requirement of having a "consistent failure mode".
I think that your suggestion about itteratively comparing the return
value and then the arguments before falling back to varadic
processing might be a good solution, as long as 'compatible' return
values/arguments are "merged" to a general type (such as id/class)
before falling back to varadic processing. (The warnings should
remain, and if you like, with a flag to turn them off :-) )
Doing this will increase the probability (vs. both the current and the
IMP approaches) that the compiler will happen to do "the right thing"
(codegen-wise) when encountering conflicts, although of course it
won't make it a certainty -- no scheme can do that. The down side is
that this scheme lacks the simple elegance (and hence end-user
understandability) of the IMP approach. :-(
The conflicting declarations ('id'/'void' return type), the IMP
assumption tries to generate code for is far more serious that the
conflicting but compatible declarations that were handled correctly by
the previous behavior. We would be exchanging one set of errors for
another. Even worse, the prototype conflicts we are breaking can have a
lot more validity than the new ones we'd be allowing. (see the
covariant/contravariant return type/arguments discussion on gnustep-discuss)
Thanks to Chris Hanson (very much appreciated the clairification) I
understand that this issue wasn't as apparent on G5/Dawin as it would be
on other architectures. But none the less these are serious issues.
PS: The "overkill" solution to this is:
a) to generate code for adding something like the
b) generate code for all seen prototypes
c) select the code path at runtime
But I'd definitely would prefer to emit hard errors and require
casting. In this case, adding support for 'Class <MyProtocol>' should
accompany that change in behavior. I'm looking into this, but as I'm
rather new to compiler hacking it might take a bit, before I come up
- [objc-improvements] Just remembered something about multiple method signatures..., Ziemowit Laski, 2003/09/05
- Re: [objc-improvements] Just remembered something about multiple method signatures..., David Ayers, 2003/09/06
- Re: [objc-improvements] Just remembered something about multiple method signatures..., Chris Hanson, 2003/09/07
- Re: [objc-improvements] Just remembered something about multiple method signatures..., Ziemowit Laski, 2003/09/07
- Re: [objc-improvements] Just remembered something about multiplemethod signatures..., Alexander Malmberg, 2003/09/08
- Re: [objc-improvements] Just remembered something about multiplemethod signatures..., Ziemowit Laski, 2003/09/08
- Re: [objc-improvements] Just remembered something about multiplemethod signatures..., Richard Frith-Macdonald, 2003/09/09
- Re: [objc-improvements] Just remembered something about multiplemethod signatures..., David Ayers, 2003/09/09
- Re: [objc-improvements] Just remembered something about multiplemethod signatures..., Ziemowit Laski, 2003/09/09
- Re: [objc-improvements] Just remembered something about multiplemethod signatures..., Nicola Pero, 2003/09/09