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!newsfeed0.kamp.net!newsfeed.kamp.net!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Niklas Holsti Newsgroups: comp.lang.ada Subject: Re: Unexpected discriminant check failure involving access types Date: Mon, 10 Aug 2015 17:33:01 +0300 Organization: Tidorum Ltd Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit X-Trace: individual.net pVoIJblvbuFWBcfc26peWwoy3j8lb1ZU1f7Ba4aABahbgXqrze Cancel-Lock: sha1:Dx6PRZPPCoyTSWFlg27YaMb1XV8= User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 In-Reply-To: Xref: news.eternal-september.org comp.lang.ada:27405 Date: 2015-08-10T17:33:01+03:00 List-Id: 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. 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. 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; -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ .