This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFC: Enhancing ObjC message lookup in the presence of protocols


Ziemowit Laski wrote:

> On 20 Oct 2004, at 1.06, d.ayers@inode.at wrote:
> 
> 
>>>On 19 Oct 2004, at 12.56, d.ayers@inode.at wrote:
>>>
>>>
>>>>>So, '[clsP2 name]' above should result in the compiler telling you
>>>>>'found -name instead of +name in protocol(s)', and then using '-
>>>>>(NSString *)name' out of Proto2.
>>>>
>>>> We are not guessing what kind of object clsP2 contains. We
>>>> would be using the information we do have about Proto2 to
>>>> constrain the fallback to the instance method search.
>>>
>>> But the most you can say about Proto2 in your example is that
>>> none of the root classes that you have seen adopt it. Does that
>>> mean that _no_ root class in your program adopts it and/or
>>> provides the methods that Proto2 requires?
>>
>>As far as the compiler is concerned, yes!  Just like:
>>
>>@interface MyRoot
>>@end
>>@interface MyClass
> 
> 
> You mean '@interface MyClass: MyRoot', right? Otherwise your 
> subsequent argument doesn't make sense.

Yes, excuse me (again).

> 
> 
>>-method1;
>>@end
>>
>>means that no root class implements method1.  If non is seen by the
>>compiler then it should  warn if it sees:
>>
>>void func(Class cls)
>>{
>>  [cls method1];  /* no method found */
>>}
>>
>>as it correctly does.  It doesn't make assumptions about whether there
>>could be some other root class that may implement method1 that it 
>>hasn't
>>seen yet.  But once it does, it will not warn.
> 
> 
> But you're messaging an unadorned 'Class' here, so you immediately
> fall back to the hash table lookup. This is not related to our
> discussion.
> 

It was meant as an analogy.  All I was trying to say with that example
is that the compiler always only knows what it has seen so far and acts
upon that.  This was in response to "Does that mean that _no_ root class
in your program adopts it...".  No it doesn't mean that, yet it does
mean the compiler should be free to act upon the information it has seen
so fat.  My point was it should suffice that the compiler knows that at
least one root class adopts it.  Once it knows that, I feel it's
legitimate to assume that we should use the prototype of the instance
method of the, before using the global class hash table.  We had earlier
agreed on /always/ using the instance method.  I'm proposing to use the
information to constrain the drop back.

[snip]
>>>> What I'm trying to show is that "to look through protocols" in
>>>> the case of 'Class <protocol>' should heed the information we
>>>> have about the protocols when taking into account the sematics
>>>> of instance methods of root classes.
>>>>
>>>> You initially disliked the idea of "protocols adopted by root 
>>>> classes". In the absence of this infomormation, I conceeded to
>>>> at least add the instance methods search for all protocols,
>>>> eventhough this approach will induce false positives as
>>>> described above. You implicitly affirmed in this thread that we
>>>> should adorn protocols with the status "adopted by root
>>>> classes" to handle the global class cache correctly. Now I'm 
>>>> saying, if we have the infomation with the protocol, why not
>>>> also use it for lookup of protocol qualified classes to
>>>> constrain the instance method search for adorned protocols.
>>>>
>>>> We "know" that no class has adopted the protocol as a root
>>>> protocol if it's not adorned.
>>>
>>> But do you know that none of the root classes (even in your own 
>>> translation unit, let alone others) nevertheless provide the
>>> method you're looking for?
>>
>> All the compiler knows and should know, is what it has seen (see 
>> example above). If it sees more applicable prototypes then it
>> should (and does) take them into account.
>>
>>
>>>For your approach to be fully consistent, shouldn't you _always_ check
>>>which protocols are adopted where?  For example, given
>>>
>>>   id <Foo, Bar, Baz> obj;
>>>   [obj mess];
>>>
>>>shouldn't you check whether Foo, Bar and Baz have been adopted by some
>>>class somewhere, root or non-root?  I really don't think we want to go
>>>down this path, not least because this would entail changing the
>>>long-established semantics of message dispatch. :-(
>>
>> Why do you think I'm inferring that there should be some 
>> root/non-root handling here? I definitely didn't mean to. 'obj' is 
>> an object, and it should only concern itself with instance methods.
>>  There are no implicit semantics with respect to root classes or 
>> class methods.
> 
> 
> Your proposal introduces the principle of actually checking where a
> given protocol is adopted when messaging an opaque receiver,
> and so you should apply this principle consistently.
> 

My proposal intends to take into account the special semantics of
instance methods of root classes with respect to protocols adopted by
such root classes.  This indeed includes adorning the protocol dependent
on where its used and then using that information when that protocol is
used with a protocol qualified opaque 'Class' reference.  There are no
special semantics for the opaque 'id' case where this 'principle' could
be applied consistently.

> 
>>>> I think you're implying that "we may have not seen the
>>>>header that does", and therefor we shouldn't be using that
>>>>information.
>>>
>>>Not when we're messaging an opaque receiver such as 'Class' or 'id'.
>>>Aside from
>>>collecting encountered method signatures in our global hash tables, we
>>>shouldn't
>>>make any assumptions about the type of the receiver (and, therefore,
>>>whether the
>>>root class of the receiver's hierarchy adopts a given protocol or 
>>>not).
>>>
>>
>>I am not making assumptions about the 'Class' other than consistently
>>transfering the existing assumptions that we make in analogous cases:
>>
>>@interace MyRoot
>>- method1;
>>@end
>>@interface MyClass : MyRoot
>>- method2;
>>@end
>>
>>void func1(Class cls)
>>{
>>  [cls method1]; /* OK */
>>  [cls method2]; /* No method found */
>>}
>>
>>If the compiler sees that a root class declares method1 (an instance
>>method) it also inserts it into the class hash list, as it /knows/ that
>>some root class implements it.
> 
> 
> Yes, but that's because it is messaging an opaque receiver, so it is 
> satisfied with _any_ class method it can find, including instance
> methods of root classes.
>

The point was...

> 
>> If it doesn't see it in a root class (ie. method2) then it warns.
>> It is irrelevant whether later in the translation unit it sees:
>>
>>@interface MyRoot (extensions)
>>- method2;
>>@end
>>
>>which include method2 in the class hash list and from then on will not
>>warn about that message being sent to 'Class cls' anymore:
>>
>>void func2(Class cls)
>>{
>>  [cls method1]; /* OK */
>>  [cls method2]; /* OK */
>>}
>>

... that the compiler only know what it knows so far.  And because it
hasn't seen a root class adopting the protocol yet would be sufficient
to constrain the fallback lookup into the /instance/ methods of the
protocol and rely on the global /class/ hash table instead.

>>
>>> Anyway, I think we're sort of circling the drain here. :-) I'll 
>>> update my patch to fix the type comparison snafus you found. I
>>> think that I'll also populate the hash tables with methods from
>>> protocols, including handling of forward-declared protocols
>>> adopted by root classes.
>>>
>>
>> Populating the class hash with instance methods of protocols 
>> unconstrained is better than not populating them at all.
> 
> 
> Well, no, I never suggested that all instance methods of protocols 
> should be inserted into the class hash table.
> 
> 
>> But I still think we should do better especially since you have now
>> conceeded to collecting the information we need.
> 
> 
> The reason I agreed to collecting the information is to handle the
> case of forward-declared protocols. Come to think of it, though,
> doing this is probably not worth the candle (since you should really
> declare a protocol before using it), so I'll omit it from my patch,
> at least for now.
> 

Please don't.  It may not be relevant in practice as I can't think of a
good reason why anyone should merely forward declare a protocol, have a
class adopt it and then declare it, but you never know how people write
their headers and what circumstances result in defining the order they
are included.

> I suspect we will not reach an agreement here on the whole "protocols
>  adopted by root classes" business, so I ask that you defer it till
> another patch.
> 

Possibly.  Maybe we could find some time to talk this over on the phone
(I've tried a few times but somehow it's always been the wrong time).
For know, please go ahead with marking the protocols and only populating
the class hash with the instance methods when a root class adopts it and
leave the fallback lookup of the instance methods of protocols
unconditionally.

Cheers,
David


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]