From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: a07f3367d7,85d5a13738392342 X-Google-Attributes: gida07f3367d7,public,usenet X-Google-NewGroupId: yes X-Google-Language: ENGLISH,ASCII Path: g2news2.google.com!postnews.google.com!r27g2000prr.googlegroups.com!not-for-mail From: Adam Beneschan Newsgroups: comp.lang.ada Subject: Re: Unknown discriminants with nested records Date: Thu, 16 Jun 2011 17:39:20 -0700 (PDT) Organization: http://groups.google.com Message-ID: References: <1e197c14-a2ff-4867-85be-fda06a10e37b@a7g2000vby.googlegroups.com> NNTP-Posting-Host: 66.126.103.122 Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-Trace: posting.google.com 1308271161 12350 127.0.0.1 (17 Jun 2011 00:39:21 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Fri, 17 Jun 2011 00:39:21 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: r27g2000prr.googlegroups.com; posting-host=66.126.103.122; posting-account=duW0ogkAAABjRdnxgLGXDfna0Gc6XqmQ User-Agent: G2/1.0 X-Google-Web-Client: true X-Google-Header-Order: ARLUEHNKC X-HTTP-UserAgent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618; .NET4.0C),gzip(gfe) Xref: g2news2.google.com comp.lang.ada:20870 Date: 2011-06-16T17:39:20-07:00 List-Id: On Jun 16, 4:53=A0pm, Simon Belmont wrote: > New to ada (2005), and trying to figure out how to create records of > other records with unknown discriminants, e.g. like this: > > package Test_Package is > > =A0 =A0 type Foo_Type (<>) is limited private; =A0-- some record with > unknown discriminants. > > =A0 =A0 t1: Foo_Type :=3D MakeAFooType; -- works fine being built by a > function > > =A0 =A0 type BarType is > =A0 =A0 record > =A0 =A0 =A0B1: Integer; > =A0 =A0 =A0-- other record elements > =A0 =A0 =A0B2: FooType :=3D MakeAFooType; =A0-- Error, unconstrained subt= ype. > =A0 =A0 end record; > > private > > =A0 =A0 type FooType is limited > =A0 =A0 record > =A0 =A0 =A0F1: Integer; > =A0 =A0 end record; > > end Test_Package; > > The (<>) seems to be the defacto way to limit creation to a function, > yet it seemingly precludes you from using it in a nested record. =A0It > seems strange that there is the ability to declare a standalone object > of that type, but trying to nest one within another record throws an > "unconstrained subtype" error; if it knows the constraints one place, > why doesn't it know them several lines down? To start with, it's helpful to post the actual source you tried. Clearly this isn't, since you didn't spell Foo_Type consistently, but the more important problem is that you've stuck the declarations T1 and BarType in the middle of Test_Package where they don't belong. You can't declare T1 to be a Foo_Type at that point, because Foo_Type's definition hasn't been finished. Anyway, I'll assume that T1 and BarType are actually declared in some other package Test_Package_2 that with's and uses Test_Package. The basic problem is this: When Test_Package_2 is elaborated, and it elaborates the definition of T1, it will call MakeAFooType at that point. The discriminants (if any) of the value will then be determined, so T1's discriminants will then be known. But when BarType is elaborated, MakeAFooType isn't called. The use of MakeAFooType here is a *default* expression. When you later declare B : BarType; with no initial expression, MakeAFooType will be called at *that* point, when B is elaborated. It's also possible to declare B with an initial expression like B : BarType :=3D (B1 =3D> 1, B2 =3D> Make_A_Different_Kind_Of_Foo); so that MakeAFooType wouldn't be called at all. So here, the constraints of the B2 component won't be what MakeAFooType would return. Hopefully that will answer your question about "why doesn't it know [the constraints] several lines down". It doesn't know because that syntax doesn't actually result in a function call. The problem here is that since the initial expression on the component is just a *default* and may not be the actual initial expression for a B2 component, the compiler thus doesn't know what constraints a B2 will have. In theory, since it's possible for objects with different constraints to have different sizes, the compiler thus may not know how big a BarType will be, and I think that's the technical reason why this sort of component type is prohibited. (In practice, it might be possible to make this work, since often the size of a FooType won't vary; but it might be hard to do without introducing some incompatible changes in the language. I don't know if any possible language changes have ever been discussed.) As for how to get around this: if it were me, I'd just lose the (<>). The (<>) was intended to define types with unknown discriminants; using it to force initialization functions to be used, when you know there won't really be any discriminants, is using this feature for a purpose for which it wasn't intended, I think. Someone clever found that it works for this purpose, but obviously it doesn't work all the time. Maybe a language feature should be added that allows the user to define a *definite* type that still isn't allowed to be uninitialized. Here's a possible way to force all uses of this type to be initialized: package Test_Package is type Foo_Type is limited private; ... etc. etc. private function Blow_Up return Integer; type Foo_Type is limited record F1 : Integer :=3D Blow_Up; end record; end Test_Package; where Blow_Up is defined like: function Blow_Up return Integer is begin raise Program_Error with "You forgot to initialize your Foo_Type"; return 0; -- never executed end Blow_Up; or something along those lines. This won't be caught at compile time (although some compilers may display a warning that Program_Error will be raised), but a program that declares a variable that is or contains an uninitialized Foo_Type will bomb. > 4. Can anyone point me to the section in the LRM that specifies this > either way? 3.6(10). This is in the section on array types, but the restriction on a component's type applies to record type components too. -- Adam