comp.lang.ada
 help / color / mirror / Atom feed
From: "Markus Schöpflin" <no.spam@spam.spam>
Subject: Re: Unexpected discriminant check failure involving access types
Date: Mon, 10 Aug 2015 16:56:47 +0200
Date: 2015-08-10T16:56:47+02:00	[thread overview]
Message-ID: <55C8BBAF.90300@spam.spam> (raw)
In-Reply-To: d2rr0tF9gd5U1@mid.individual.net

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


  reply	other threads:[~2015-08-10 14:56 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-10 12:38 Unexpected discriminant check failure involving access types Markus Schöpflin
2015-08-10 13:14 ` Mark Lorenzen
2015-08-10 14:20   ` Markus Schöpflin
2015-08-10 19:00     ` Randy Brukardt
2015-08-10 14:33 ` Niklas Holsti
2015-08-10 14:56   ` Markus Schöpflin [this message]
2015-08-10 19:43     ` Niklas Holsti
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox