comp.lang.ada
 help / color / mirror / Atom feed
From: Niklas Holsti <niklas.holsti@tidorum.invalid>
Subject: Re: Unexpected discriminant check failure involving access types
Date: Mon, 10 Aug 2015 17:33:01 +0300
Date: 2015-08-10T17:33:01+03:00	[thread overview]
Message-ID: <d2rr0tF9gd5U1@mid.individual.net> (raw)
In-Reply-To: <mqa5vs$k1n$1@speranza.aioe.org>

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
       .      @       .

  parent reply	other threads:[~2015-08-10 14:33 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 [this message]
2015-08-10 14:56   ` Markus Schöpflin
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