discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [objc-improvements] Just remembered something about multiplemethod s


From: Steve Naroff
Subject: Re: [objc-improvements] Just remembered something about multiplemethod signatures...
Date: Tue, 9 Sep 2003 12:46:30 -0700

The same could be argued about many of the warnings issued for normal c.
Fortunately, gcc already supports this behavior: just give it the
-Werror option.

Exactly.

I think this discussion is entering into a rathole that was intentionally avoided when the language was designed (and the compiler was written).

The only way to bring sanity to such ambiguities is to add argument overloading (which may be interesting, but more involved than the discussion at hand).

Trying to measure the degree to which two signatures differ is a tricky business (and very subjective). For example, the following code is incorrect:

[snaroff:~] snaroff% cat xx.m

#include <Foundation/Foundation.h>

@interface A : NSObject
- foo:(A*)arg;
- bar;
@end

@interface B : NSObject
- foo:(B*)arg;
- car;
@end

main()
{
  A *objA = [[A alloc] init];
  B *objB = [[B alloc] init];
  id xx = objB;

  [objA foo:objB]; // valid warning...needs an A
  [objB foo:objA]; // valid warning...needs a B
  [xx foo:objA];   // ambiguious (doesn't know what it needs).
}

Even though the compiler can generate "correct" code (in terms of stack allocation/offsets/representation), it cannot tell you what you need to know in the last case (that foo: is expecting a B). As a result, running the code will crash if the "car" message is sent (i.e. the message will not be recognized).

My point: Type correctness isn't just a code generation issue. The language/compiler is also responsible for making sure the type contract is preserved (which it cannot do properly when "id" is heavily used with overloaded selectors).

I think we should:

#1: Make sure the compiler internal cast is consistent with the method the compiler says it is using. Zem's hack to diverge for the case of void is incorrect. If the compiler picks the selector with a void return type (and the program tries to use the result), it should fail.

#2: Continue to consider these ambiguities warnings. If the user wants to fix these, the language and compiler have the tools (-Werror and strong typing).

#3: Potentially improve the UI (i.e. error messages) that stem from the funny internal casting of objc_msgSend(). That is...try and avoid forcing the user from understanding the calling convention (that is runtime/abi dependent).

#4: Consider adding argument overloading for a future release.

snaroff

On Sep 9, 2003, at 5:39 AM, Alexander Malmberg wrote:

Ziemowit Laski wrote:
On Monday, Sep 8, 2003, at 16:19 US/Pacific, Alexander Malmberg wrote:
David Ayers wrote:
Ziemowit Laski wrote:
On Saturday, Sep 6, 2003, at 00:54 US/Pacific, David Ayers wrote:
[snip]
In this case, it didn't just "happen to work".

Sure it did.  You just happened to have two signatures that didn't
differ by that much.

It is no coincidence that the prototypes differed only slightly, and
only in the type of an object. Of the conflicts the new warnings expose
in GNUstep (and all apps and libraries I've tested, and libFoundation),
all except one are of this type.

Throw in

    -(double)test1Float:(int)f int:(float)i;
    -(void)test1Float:(float)f int:(int)i;
    -(struct foo)test1Float:(struct bar)f int:(int)i;

and now tell me that it still happens to work. :-)

Note "In this case"; obviously, the results will be different if you
look at a different case. :)

[snip]
This is a good comparison of the _effect_ of the two approaches.
However,
the IMP approach does not attempt to guess

Not true. It guesses that the return type is "id".

or infer anything from
anything
-- IMP is used whenever there are conflicting methods (or no methods),
period.
I would argue that this simplicity is a virtue, from the end-users'
viewpoint. :-)

Picking one "randomly" is also simple (arguably even more simple) from
the user's pov:

If the prototypes don't really conflict, the compiler will do the right
thing. Otherwise, it might break.

I'd rather explain this to a new user than the type promotion rules for
variadic functions.

[snip]
Theoretical objections aside, can you point me to a specific case in
actual
code (in GNUStep or elsewhere) where where the new IMP "behavior" breaks
"compatibility"?

Yes, eg.:

-(NSComparisonResult)compare:(NSNumber *)decimalNumber
-(NSComparisonResult)compare:(id)anObject

The old code would pick one randomly and get the return type right. The
new code will guess that the return type is id. Of course, on most
systems, this will "just happen" to work anyway. GNUstep runs on many
systems, though. :)

[snip]
:-) 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

I disagree. A warning and almost any behavior is better than a hard
error.

Only if you're an expert user (the joke about the car designed by UNIX
gurus comes
to mind).  If you're a developer learning Objective-C, you'll either
ignore the
warnings at your peril, or file bugs about mysterious errors and
warnings produced
by the compiler.

The same could be argued about many of the warnings issued for normal c.
Fortunately, gcc already supports this behavior: just give it the
-Werror option.

- Alexander Malmberg





reply via email to

[Prev in Thread] Current Thread [Next in Thread]