Issue 783: IDL types are ambiguous with inheritance (orb_revision) Source: (, ) Nature: Uncategorized Issue Severity: Significant Summary: Summary: What is the return type of parent(), short or long? The spec does not say whether the inherited ::y::y::z takes precedence, or whether it is ::x::z. The scope resolution rules don"t mention how to resolve such an ambiguity. The spec should be updated to state that ::x::z takes precedence (IDL example in corresponding archive "issue783") Resolution: Close noting that this has been explained in Revised Chapter 3. Revised Text: Actions taken: November 25, 1997: received issue January 5, 1998: issue moved from C++ to ORB Revision February 23, 1999: closed issue Discussion: closed issue End of Annotations:===== Return-Path: X-Authentication-Warning: tigger.dstc.edu.au: michi owned process doing -bs Date: Tue, 25 Nov 1997 10:41:41 +1000 (EST) From: Michi Henning Reply-To: Michi Henning To: issues@omg.org Subject: IDL types are ambiguous with inheritance Hi, a recent discussion in comp.object.corba raised this. Consider the following IDL: module y { interface y { typedef short z; }; }; module x { typedef long z; interface x: y::y { z parent(); }; }; The question is, what is the return type of parent(), short or long? As far as I can see, the spec does not say whether the inherited ::y::y::z takes precedence, or whether it is ::x::z. The scope resolution rules don't mention how to resolve such an ambiguity. I believe the spec should be updated to state that ::x::z takes precedence. Rationale: Giving precedence to ::x::z is in line with ANSI C++ for the analogous case with class definitions. The advantage of giving precedence to ::x::z is that I am never in doubt about the return type of parent(). Consider the case where ::y::y::z takes precedence instead. Assume that module y pre-exists, and I am creating module x which re-uses some parts of module y. If ::y::y::z takes precedence, I do not know what the return type of parent() will be unless I exhaustively examine all inherited scopes for types called z. Only if none of the base interfaces define a type z do I know that parent() *really* returns a long. Moreover, if ::y::y::z takes precedence, I *cannot* use the name z for my own type ::x::z inside an interface in module x, because it will *always* be overridden by the inherited type z. Finally, with ::y::y::z taking precedence, adding a new type definition to a base interface some time later could change the meaning of operations in derived interfaces. For example, adding ::y::y::z after module x is complete would inadvertently change the return type of parent() from long to short. None of these problems arise if ::x::z takes precedence, so I think the spec should be updated accordingly. Thanks go to Jonathan Biggar for discussing this with me. Cheers, Michi. -- Michi Henning +61 7 33654310 DSTC Pty Ltd +61 7 33654311 (fax) University of Qld 4072 michi@dstc.edu.au AUSTRALIA http://www.dstc.edu.au/BDU/staff/michi-henning.html Return-Path: From: "Daniel R. Frantz" To: "'Michi Henning'" Cc: "'issues@omg.org'" Subject: RE: IDL types are ambiguous with inheritance Date: Tue, 25 Nov 1997 10:42:06 -0500 >-----Original Message----- >From: Michi Henning [SMTP:michi@dstc.edu.au] >Sent: Monday, November 24, 1997 7:42 PM >To: issues@omg.org >Subject: IDL types are ambiguous with inheritance > >Hi, > >a recent discussion in comp.object.corba raised this. Consider the >following IDL: > >module y { > interface y { > typedef short z; > }; >}; > >module x { > typedef long z; > interface x: y::y { > z parent(); > }; >}; > >The question is, what is the return type of parent(), short or long? > >As far as I can see, the spec does not say whether the inherited ::y::y::z >takes precedence, or whether it is ::x::z. The scope resolution rules >don't mention how to resolve such an ambiguity. Hmmm... Am I missing something? What about this quotation from the spec: 3.6 Inheritance An interface can be derived from another interface, which is then called a base interface of the derived interface. A derived interface, like all interfaces, may declare new elements (constants, types, attributes, exceptions, and operations). In addition, unless redefined in the derived interface, the elements of a base interface can be referred to as if they were elements of the derived interface. The name resolution operator ("::") may be used to refer to a base element explicitly; this permits reference to a name that has been redefined in the derived interface. A derived interface may redefine any of the type, constant, and exception names which have been inherited; the scope rules for such names are described in "CORBA Module" on page 3-33. And on page 3-33, there is: Type names defined in a scope are available for immediate use within that scope. In particular, see "Constructed Types" on page 3-25 on cycles in type definitions. A name can be used in an unqualified form within a particular scope; it will be resolved by successively searching farther out in enclosing scopes. Once an unqualified name is used in a scope, it cannot be redefined (i.e., if one has used a name defined in an enclosing scope in the current scope, one cannot then redefine a version of the name in the current scope). Such redefinitions yield a compilation error. Did you mean something else, Michi? Dan Return-Path: Sender: jon@biggar.org Date: Tue, 25 Nov 1997 09:33:11 -0800 From: Jonathan Biggar To: "Daniel R. Frantz" CC: "'Michi Henning'" , "'issues@omg.org'" Subject: Re: IDL types are ambiguous with inheritance References: <01BCF98E.C6C73EB0@jimv.beasys.com> Dan, you have the two quotes right, but nothing in them specifies which one takes precedence over the other when searching outside the current scope to resolve an unqualified name. Michi and I believe that the scope resolution algorithm from 3-33 should take precedence, because the C++ spec does it that way, and it avoids problems with changes to the IDL of base interfaces changing the meaning of a derived interface. Jon Daniel R. Frantz wrote: > Hmmm... Am I missing something? What about this quotation from the spec: > > 3.6 Inheritance > > An interface can be derived from another interface, which is then > called a base interface of the derived interface. A derived > interface, like all interfaces, may declare new elements > (constants, types, attributes, exceptions, and operations). In > addition, unless redefined in the derived interface, the elements > of a base interface can be referred to as if they were elements of > the derived interface. The name resolution operator ("::") may be > used to refer to a base element explicitly; this permits reference > to a name that has been redefined in the derived interface. A derived > interface may redefine any of the type, constant, and exception names > which have been inherited; the scope rules for such names are described > in "CORBA Module" on page 3-33. > > And on page 3-33, there is: > > Type names defined in a scope are available for immediate use within that > scope. In particular, see "Constructed Types" on page 3-25 on cycles in > type definitions. > > A name can be used in an unqualified form within a particular scope; it > will be resolved by successively searching farther out in enclosing > scopes. Once an unqualified name is used in a scope, it cannot be > redefined (i.e., if one has used a name defined in an enclosing scope in > the current scope, one cannot then redefine a version of the name in the > current scope). Such redefinitions yield a compilation error. > > Did you mean something else, Michi? > > Dan Return-Path: From: "Daniel R. Frantz" To: "'Jonathan Biggar'" Cc: "'orb_revision@omg.org'" , "'Michi Henning'" Subject: RE: IDL types are ambiguous with inheritance Date: Tue, 25 Nov 1997 13:35:41 -0500 I'm moving a discussion to this list because issues@omg.org is intended merely to state an issue, not to discuss it and Juergen has already picked it up. I shouldn't have responded in "issues" in the first place. Discussion is properly the role of the core rtf list (orb_revision@omg.org). I've included (indented) the entire last message from Jonathan (which also had my previous reply) in this message to establish a bit of context to others on this list who might not have seen the "issues" topic, even though I usually hate quotes of an entire series. Dan -----Original Message----- From: Jonathan Biggar [SMTP:jon@biggar.org] Sent: Tuesday, November 25, 1997 12:33 PM To: Daniel R. Frantz Cc: 'Michi Henning'; 'issues@omg.org' Subject: Re: IDL types are ambiguous with inheritance Dan, you have the two quotes right, but nothing in them specifies which one takes precedence over the other when searching outside the current scope to resolve an unqualified name. I guess I don't see the two as being different. I read both (not just page 33) as saying that the redefinition takes precedence. How can it be interpreted differently? Specifically, the first quote includes: In addition, unless redefined in the derived interface, the elements of a base interface can be referred to as if they were elements of the derived interface. The name resolution operator ("::") may be used to refer to a base element explicitly; this permits reference to a name that has been redefined in the derived interface. This implies to me that if there is no redefinition, unqualified name refers to the base the base class element (it can be referred to without the resolution operator). It further says that if there is a redefinition, to use the base element you must explicitly scope it. The only way I can interpret this is that the unscoped use refers to the local definition. This is equivalent to page 33. You guys have been around a lot longer than I have so maybe you can tell me how this interpretation is wrong or how the words can be taken differently. I'm really puzzled. Michi and I believe that the scope resolution algorithm from 3-33 should take precedence, because the C++ spec does it that way, and it avoids problems with changes to the IDL of base interfaces changing the meaning of a derived interface. Since I can't see a conflict, this is moot. I agree with your statement that it should be done this way. I also believe it was designed this way from the start so that it would fit not only with C++ (which wasn't defined till later) but all other languages that use any kind of scoping. Daniel R. Frantz wrote: > Hmmm... Am I missing something? What about this quotation from the spec: > > 3.6 Inheritance > > An interface can be derived from another interface, which is then > called a base interface of the derived interface. A derived > interface, like all interfaces, may declare new elements > (constants, types, attributes, exceptions, and operations). In > addition, unless redefined in the derived interface, the elements > of a base interface can be referred to as if they were elements of > the derived interface. The name resolution operator ("::") may be > used to refer to a base element explicitly; this permits reference > to a name that has been redefined in the derived interface. A derived > interface may redefine any of the type, constant, and exception names > which have been inherited; the scope rules for such names are described > in "CORBA Module" on page 3-33. > > And on page 3-33, there is: > > Type names defined in a scope are available for immediate use within that > scope. In particular, see "Constructed Types" on page 3-25 on cycles in > type definitions. > > A name can be used in an unqualified form within a particular scope; it > will be resolved by successively searching farther out in enclosing > scopes. Once an unqualified name is used in a scope, it cannot be > redefined (i.e., if one has used a name defined in an enclosing scope in > the current scope, one cannot then redefine a version of the name in the > current scope). Such redefinitions yield a compilation error. > > Did you mean something else, Michi? > > Dan Return-Path: To: Jonathan Biggar cc: "Daniel R. Frantz" , "'Michi Henning'" , "'issues@omg.org'" Subject: Re: IDL types are ambiguous with inheritance Date: Wed, 26 Nov 1997 10:33:15 +1000 From: Stephen Crawley > Dan, you have the two quotes right, but nothing in them specifies which one > takes precedence > over the other when searching outside the current scope to resolve an > unqualified name. I think that the correct reading of the quoted sections of the CORBA IDL spec is that the inherited names take precedence over the names in the enclosing scope. I base this on the wording of the following sentence of 3.6: In addition, unless redefined in the derived interface, the elements of a base interface can be referred to as if they were elements of the derived interface. Note, there is no other qualification apart from "unless redefined in the derived interface". Thus, by the normal nested scoping rules, elements of the derived interface would take precedence over any names declared in surrounding scopes. If the consensus is that the C++ model should prevail, the spec needs to be changed. However, I'd prefer to see the current model prevail, with the proviso that a decent IDL compiler should issue a warning message when an inherited name obscures a name declared in an enclosing scope. IMO, it is equally easy to misread the IDL no matter which of the two names takes precedence. It just depends which bit of IDL you read first. The argument that adding a declaration in a base interface shouldn't affect the derived interfaces is a bit far fetched. Making changes to base "classes" with lots of derived "classes" is always problematical. [This sort of mess is why I think that allowing implicit name overriding in language is a bad idea. But most language designers would disagree with me on that :-)] -- Steve Return-Path: X-Authentication-Warning: tigger.dstc.edu.au: michi owned process doing -bs Date: Wed, 26 Nov 1997 14:38:19 +1000 (EST) From: Michi Henning To: Stephen Crawley cc: Jonathan Biggar , "Daniel R. Frantz" , issues@omg.org Subject: Re: IDL types are ambiguous with inheritance On Wed, 26 Nov 1997, Stephen Crawley wrote: > > Dan, you have the two quotes right, but nothing in them specifies which one > > takes precedence > > over the other when searching outside the current scope to resolve an > > unqualified name. > > I think that the correct reading of the quoted sections of the CORBA IDL > spec is that the inherited names take precedence over the names in the > enclosing scope. I base this on the wording of the following sentence > of 3.6: > > In addition, unless redefined in the derived interface, the elements > of a base interface can be referred to as if they were elements of > the derived interface. > > Note, there is no other qualification apart from "unless redefined > in the derived interface". Thus, by the normal nested scoping rules, > elements of the derived interface would take precedence over any > names declared in surrounding scopes. Hmmm... I'm not sure this says what you say it says, at least not unambiguously ;-) > In addition, unless redefined in the derived interface, the elements > of a base interface can be referred to as if they were elements of > the derived interface. This does *not* say which one takes precedence. Instead, it says two things: - A name defined in a base interface is visible in the scope of the derived interface, and therefore a name defined in the derived interface can hide a name in the base interface. - If a name in the derived interface hides a name in the base interface, you can get at the base interface name by using qualification. I still insist that the current spec does *not* resolve the ambiguity I outlined. In particular, the crucial point is that - A name defined in an enclosing scope can be referred to without qualification, as can a name defined in a base interface. The question is therefore "if the same name is defined in both, which name takes precedence?" I can't find words that would answer this question anywhere, no matter how hard I look. > If the consensus is that the C++ model should prevail, the spec needs > to be changed. However, I'd prefer to see the current model prevail, > with the proviso that a decent IDL compiler should issue a warning > message when an inherited name obscures a name declared in an enclosing > scope. I *very* strongly recommend against this. The C++ interpretation (which is the opposite) makes sense, and is correct (my personal opinion only). Regardless of my personal opinion though, I think a deviation from the C++ scope resolution rules is bad - IDL is too similar to C++ in most respects to justify gratuitous deviations. If you accept that either interpretation can be made to work, then it makes sense to stick with what C++ does... > IMO, it is equally easy to misread the IDL no matter which of the two > names takes precedence. It just depends which bit of IDL you read first. > The argument that adding a declaration in a base interface shouldn't > affect the derived interfaces is a bit far fetched. Making changes to > base "classes" with lots of derived "classes" is always problematical. There is a difference between changing something that is already there, and adding something new. In the rational I gave, it is sufficient to *add* a typedef to change the meaning of a derived interface. I have sympathy that the "fragile base class argument" is weak, and should not be given more weight than it deserves. However, I consider the following *very* serious: #include "some_existing_spec.idl" module x { typedef string<5> short_string; interface foo: some_existing_spec::some_interface { short_string get_short_string(); }; }; I think it is *most definitely* bad if in the above IDL, get_short_string() returns a string of length 178, just because some existing spec that 178 was a good length for a short string. This is simply revolting. And please, don't tell me that I can get around this by moving the typedef into the scope of interface foo - that's not an acceptable solution, because other interface in module x may need to use the same type themselves, and moreover, exchange data items of that type. Cheers, Michi. Copyright 1997 Michi Henning. All rights reserved. -- Michi Henning +61 7 33654310 DSTC Pty Ltd +61 7 33654311 (fax) University of Qld 4072 michi@dstc.edu.au AUSTRALIA http://www.dstc.edu.au/BDU/staff/michi-henning.html Return-Path: X-Authentication-Warning: tigger.dstc.edu.au: michi owned process doing -bs Date: Fri, 28 Nov 1997 10:57:44 +1000 (EST) From: Michi Henning To: Stephen Crawley cc: Jonathan Biggar , "Daniel R. Frantz" , issues@omg.org Subject: Re: IDL types are ambiguous with inheritance On Wed, 26 Nov 1997, Michi Henning wrote: > I still insist that the current spec does *not* resolve the ambiguity > I outlined. > > [ ... ] > > I can't find words that would answer this question anywhere, no matter > how hard I look. I still stand by this - the spec is ambiguous. However, after some discussion on comp.object.corba, I found that I misread the ANSI C++ spec, and that in fact the interpretation suggested by Stephen is correct. > Regardless of my personal opinion though, I think a deviation from the C++ > scope resolution rules is bad - IDL is too similar to C++ in most respects > to justify gratuitous deviations. If you accept that either interpretation > can be made to work, then it makes sense to stick with what C++ does... I still stand by this too - IDL should do it the way C++ does. Unfortunately, my claim about the C++ rules was wrong :-( My apologies for any confusion this may have caused. Michi. PS: I'll go and turn myself into a toothbrush now - how embarrassing... Michi Henning wrote in comp.object.corba: > I looked again in the ANSI C++ spec. The relevant section is 3.4.1, > "Unqualified name look up", on page 3-9. > > To my dismay, I found that I misread this the first time I looked > :-( > Here is the relevant example from the spec: > > namespace M { > class B { }; > } > namespace N { > class Y: public M::B { > class X { > int a[i]; > }; > }; > } > > In this example, the question is how the lookup for "i" proceeds > (which is analogous to the typedef IDL example I quoted). > > The spec says: > > // The following scopes are searched for a declaration of i: > // 1) scope of class N::Y::X, before the use of i > // 2) scope of class N::Y, before the definition of N::Y::X > // 3) scope of N::Y's base class M::B > // 4) scope of namespace N, before the definition of N::Y > // 5) global scope, before the definition of N > > The important point here is that M::B is searched *before* N. > > This is contrary to what I stated earlier. My apologies - I simply > misread > the spec the first time round :-( I also tried it with my trusty C++ > compiler and obviously must have made some mistake, because when I > try it > now, the compiler does it exactly as it should... > > So, I stand corrected - the scope of the base interface takes > precedence over the enclosing scope. > > With foot in mouth :-( > > Michi. -- Michi Henning +61 7 33654310 DSTC Pty Ltd +61 7 33654311 (fax) University of Qld 4072 michi@dstc.edu.au AUSTRALIA http://www.dstc.edu.au/BDU/staff/michi-henning.html