CORBA 2.4 introduced forward declarations for IDL structures
and unions in support of recursive structures, deprecating the
prior practice of anonymous types.
Also allowed were sequences of forward-declared structures
("incomplete types"), which could then be used as members in
defining the structure. Currently, it is only allowed to use
incomplete types in the actual definition of the type itself.
As an example in section 3.11.2.3 demonstrates, this does
allow indirect recursion – but only if the incomplete types
are nested, as in [first example]
struct Foo;
typedef sequence<Foo> FooSeq;
struct Foo {
struct Bar
{
FooSeq fs;
}
b;
};
Specifically not allowed – and this is the point of this
issue – is the seemingly more intuitive definition of
[second example]
struct Foo;
typedef sequence<Foo> FooSeq;
struct Bar
{
FooSeq fs;
}
;
struct Foo
{
Bar b;
}
;
Currently, the spec says that, "sequence members that are
recursive must refer to an incomplete type currently under
definition," and thus Bar is not allowed to use FooSeq as
a member.
However, the second example is, in effect, no different than
the first. In the first example, "Foo::Bar" is a well-defined
stand-alone type that can be used elsewhere (e.g., as a
structure member or operation parameter).
If a developer intends to use both structures, the second
example makes this much clearer, as it syntactically elevates
"Foo::Bar" from a mere sub-type to an "independent" structure.
Therefore, I would like to change the current wording of
section 3.11.2.3 to allow the second example. A proposed
update is below.
This issue is all the more urgent because another available
specification, the "Deployment and Configuration of
Component-based Distributed Applications," depends on it,
by using two IDL structures that mutually and indirectly
recurse, effectively using [third example]
struct Package;
typedef sequence<Package> PackageSeq;
struct Assembly;
typedef sequence<Assembly> AssemblySeq;
struct Package
{
AssemblySeq as;
}
;
struct Assembly
{
PackageSeq ps;
}
;
In reality, the IDL in question is a bit more complicated,
using some intermediate structures, which makes rewriting
the IDL without this mutual recursion impractical and
non-intuitive – also because both "Package" and "Assembly"
are meant to be potentially top-level, stand-alone items.
Some might argue that the IDL restriction existed before
the "Deployment" specification was adopted, and that CORBA
should not be changed just because some later spec
willingly (or rather, naively) used buggy IDL.
So let me make some more arguments in favor of my request.
First, as explained above, IDL already allows for indirect
recursion. It just requires nesting.
Second, defining structures as a "side-effect" of a member
declaration is ugly, only marginally better than anonymous
types. Allowing the type definition of a member to stand
by itself is, in my opinion, much cleaner.
Third, indirect recursion between non-nested types is no
more difficult to implement in an ORB than indirect recursion
between nested types.
In fact, some existing ORB products already have no problem
with indirect recursion, and are able to compile the IDL
from the third example, resulting in correct code. The code
works fine with Mico, TAO, JacORB and Combat, all of which
apparently neglect to implement the check that "sequence
members that are recursive must refer to an incomplete type
currently under definition."
OmniORB does issue a diagnostic, but simply removing the
check, and making another trivial change to its IDL compiler,
results in correct C++ code.
Four, the existing IDL syntax, TypeCodes, CDR marshalling
rules, and Interface Repository all allow indirect recursion
to exist. In fact, it is already possible to create the
above data types using the Interface Repository and
TypeCode interfaces – as well as to create instances
using DynamicAny, and to marshal them.
With this background, I suggest to remove the statement
that prevents indirect recursion between non-nested
structures and unions.
Proposed resolution:
In section 3.12.2.3, change paragraphs (counting each IDL
code example as a single paragraph) 10 to 12 (page 3-42)
from
If a recursive structure or union member is used,
sequence members that are recursive must refer to
an incomplete type currently under definition. For
example
struct Foo;
typedef sequence<Foo> FooSeq;
struct Bar
{
long value;
FooSeq chain; // Illegal, Foo is not an enclosing
}
; // struct or union.
Compilers shall issue a diagnostic if this rule is
violated.
to
If a sequence member of a structure or union refers
to an incomplete type, the structure or union itself
remains incomplete until the member's definition is
completed. For example
struct Foo;
typedef sequence<Foo> FooSeq;
struct Bar
{
long value;
FooSeq chain; // Use of incomplete type
}
; // Bar itself remains incomplete
struct Foo
{
// ...
}
; // Foo and Bar are complete
Thank you for listening. Also thanks to Jeff Parsons
and Boris Kolpakov from Vanderbilt University for
researching this issue.
We, the submitters of the "Deployment" specification,
genuinely believe that indirect recursion is useful,
and its lack (and having to work around) would take
considerable value from the specification.
I am uncomfortable arguing to change another spec
to fix ours. But one spec has to change, and I believe
that indirect recursion is a useful feature that already
(unwillingly) exists in many ORBs, that it is no more
problematic to implement than the existing means of
recursion, and that the resulting data types are already
valid when obtained from the TypeCode or Interface
Repository interfaces.
Considering the conflict of available specifications,
I am tempted to flag this issue as urgent. Andrew, is
that even possible, given that there is no active Core
RTF?