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=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!mx02.eternal-september.org!feeder.eternal-september.org!aioe.org!.POSTED!not-for-mail From: =?UTF-8?B?TWFya3VzIFNjaMO2cGZsaW4=?= Newsgroups: comp.lang.ada Subject: Re: Unexpected discriminant check failure involving access types Date: Mon, 10 Aug 2015 16:56:47 +0200 Organization: Aioe.org NNTP Server Message-ID: <55C8BBAF.90300@spam.spam> References: NNTP-Posting-Host: MdpKeRr+sx3LK7JQiK5aNw.user.speranza.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit X-Complaints-To: abuse@aioe.org User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 X-Notice: Filtered by postfilter v. 0.8.2 Xref: news.eternal-september.org comp.lang.ada:27407 Date: 2015-08-10T16:56:47+02:00 List-Id: Am 10.08.2015 um 16:33 schrieb Niklas Holsti: > On 15-08-10 15:38 , Markus Schöpflin wrote: >> Given the following piece of code: >> >> ---%<--- >> 1 procedure TEST >> 2 is >> 3 type T is (T1, T2); >> 4 >> 5 type RECORD_T (X : T := T1) is record >> 6 null; >> 7 end record; >> 8 >> 9 type PTR_T is access RECORD_T; >> 10 >> 11 FOO : RECORD_T; >> 12 FOO_PTR : constant PTR_T := new RECORD_T; >> 13 >> 14 FOO1 : constant RECORD_T := (X => T1); >> 15 FOO2 : constant RECORD_T := (X => T2); >> 16 begin >> 17 FOO := FOO1; >> 18 FOO := FOO2; >> 19 >> 20 FOO_PTR.all := FOO1; >> 21 FOO_PTR.all := FOO2; >> 22 end; >> --->%--- >> >> When compiled and executed, I get: >> >> > ./test >> >> raised CONSTRAINT_ERROR : test.adb:21 discriminant check failed >> >> Can anyone please explain me why I get a discriminant check error when >> using access types? I would have expected it to work the same as for the >> non-access case. > > This is a consequence of RM 4.8(6/3): "... If the designated type is > composite, then the subtype of the created object is the designated subtype > when the designated subtype is constrained or there is an ancestor of the > designated type that has a constrained partial view; otherwise, the created > object is constrained by its initial value (even if the designated subtype is > unconstrained with defaults)." > > In other words, the object FOO_PTR.all is constrained and it is not possible > to change its discriminants -- the default value given to the discriminant X, > which means that FOO is unconstrained, does not have the same effect on an > allocated object. OK, understood. > The AARM motivates this rule as follows: "All objects created by an allocator > are aliased, and most aliased composite objects need to be constrained so that > access subtypes work reasonably." In other words, there could be a > declarations like > > type PTR_T1_T is access all RECORD_T (X => T1); > FOO_T1_PTR : PTR_T1_T; > > and statements > > FOO_T1_PTR := PTR_T1_T (FOO_PTR); > > Now FOO_PTR and FOO_T1_PTR point to the same object (the allocated one), with > X = T1. If the program could now change FOO_PTR.all.X to T2, the subtype of > FOO_T1_PTR would be a lie, because the referenced object would now have X = T2. Makes sense. But right now I'm surprised that FOO_T1_PTR := PTR_T1_T (FOO_PTR); is actually allowed. Consider: FOO : aliased RECORD_T; FOO_T1_PTR : PTR_T1_T := PTR_T1_T'(FOO'Access); There you get the (expected) error that the "object subtype must statically match the designated subtype". > The only work-around I know of is to enclose the discriminated record in > another record, such as: > > type HOLDER_T is record > R : RECORD_T; > end record; > > type PTR_T is access HOLDER_T; Thankfully, in my case the solution was even more simple, as we were able to eliminate the access type altogether. Thanks for your detailed explanation, Markus