comp.lang.ada
 help / color / mirror / Atom feed
* GNAT GPL 2013 bug?
@ 2013-08-09  9:47 Dmitry A. Kazakov
  2013-08-09 10:38 ` sbelmont700
  0 siblings, 1 reply; 26+ messages in thread
From: Dmitry A. Kazakov @ 2013-08-09  9:47 UTC (permalink / raw)


ARM 3.9.2(10/2)

"... If the dispatching operation overrides an inherited subprogram, it
shall be subtype conformant with the inherited subprogram."

Does not-null constraint count? To me (I am not a language layer) it does.
But GNAT GPL 2013 (20130314) swallows this:

   type T is tagged null record;
   procedure P (X : access T) is null;

   type S is new T with null record;
   overriding procedure P (X : not null access S) is null;

Which is a bug to me.

P.S. Being subtype conformant to another type (T vs S) is a tricky part.
Presumably "the inherited subprogram" is

   procedure P (X : access T);

after T is replaced by S. Which gives

   procedure P (X : access S);

and this must be subtype conformant to

   overriding procedure P (X : not null access S);

which is not. Is it?

P.P.S. There is of course a deeper issue with any constraints put on or
lifted upon inheritance regarding LSP and substitutability. Because it
might be safe to weaken a constraint (precondition actually). E.g. turning
the example around:

   type T is tagged null record;
   procedure P (X : not null access T);

   type S is new T with null record;
   overriding procedure P (X : access S);

This might be safe as the clients are promised more.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09  9:47 GNAT GPL 2013 bug? Dmitry A. Kazakov
@ 2013-08-09 10:38 ` sbelmont700
  2013-08-09 11:01   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 26+ messages in thread
From: sbelmont700 @ 2013-08-09 10:38 UTC (permalink / raw)


Aren't dispatching access parameters inherently always 'not null' anyway, and the explicit qualifier just an optional readability thing?

-sb

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 10:38 ` sbelmont700
@ 2013-08-09 11:01   ` Dmitry A. Kazakov
  2013-08-09 11:06     ` sbelmont700
                       ` (3 more replies)
  0 siblings, 4 replies; 26+ messages in thread
From: Dmitry A. Kazakov @ 2013-08-09 11:01 UTC (permalink / raw)


On Fri, 9 Aug 2013 03:38:21 -0700 (PDT), sbelmont700@gmail.com wrote:

> Aren't dispatching access parameters inherently always 'not null' anyway,
> and the explicit qualifier just an optional readability thing?

No idea, but since Ada 2005 access T can be null. Is the behavior depends
on whether the parameter is dispatching?

So considering:

   type Q is null record;
   procedure P (X : access Q) is null;

   Y : access Q := null;
begin
   P (Y); -- This is OK (since Ada 2005)

Now add "tagged" to Q:

   type Q is tagged null record;
   procedure P (X : access Q) is null;

   Y : access Q := null;
begin
   P (Y); -- This is not OK?

I didn't searched ARM for this, but if indeed so, this is a language bug to
me.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 11:01   ` Dmitry A. Kazakov
@ 2013-08-09 11:06     ` sbelmont700
  2013-08-09 11:36       ` Dmitry A. Kazakov
  2013-08-09 15:48     ` Adam Beneschan
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 26+ messages in thread
From: sbelmont700 @ 2013-08-09 11:06 UTC (permalink / raw)


In 3.10~13.1/2:

"In addition, the anonymous access subtype defined by the access_definition for a controlling access parameter (see 3.9.2) excludes null."

So apparently yes, adding 'tagged' to Q should make it toss an exception.

-sb

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 11:06     ` sbelmont700
@ 2013-08-09 11:36       ` Dmitry A. Kazakov
  0 siblings, 0 replies; 26+ messages in thread
From: Dmitry A. Kazakov @ 2013-08-09 11:36 UTC (permalink / raw)


On Fri, 9 Aug 2013 04:06:32 -0700 (PDT), sbelmont700@gmail.com wrote:

> In 3.10~13.1/2:
> 
> "In addition, the anonymous access subtype defined by the
> access_definition for a controlling access parameter (see 3.9.2) excludes
> null."
> 
> So apparently yes, adding 'tagged' to Q should make it toss an exception.

package P is
   type Q is private;
   procedure P (X : access Q) is null;
   ...
end P;

How does a client know if null is a valid value here? It could be

private
   type Q is tagged null record;

or

private
   type Q is null record;

Let I pass it to a generic:

generic
   type T is private;
   with procedure P (X : access T) is <>;
package Foo is

How Foo is supposed to know if P should raise with null?

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 11:01   ` Dmitry A. Kazakov
  2013-08-09 11:06     ` sbelmont700
@ 2013-08-09 15:48     ` Adam Beneschan
  2013-08-09 16:11       ` Simon Wright
  2013-08-09 16:03     ` Simon Wright
  2013-08-09 18:55     ` Randy Brukardt
  3 siblings, 1 reply; 26+ messages in thread
From: Adam Beneschan @ 2013-08-09 15:48 UTC (permalink / raw)


On Friday, August 9, 2013 4:01:21 AM UTC-7, Dmitry A. Kazakov wrote:
 
> > Aren't dispatching access parameters inherently always 'not null' anyway,
> > and the explicit qualifier just an optional readability thing?
> 
> No idea, but since Ada 2005 access T can be null. Is the behavior depends
> on whether the parameter is dispatching?
> 
> So considering:
> 
>    type Q is null record;
>    procedure P (X : access Q) is null;
> 
>    Y : access Q := null;
> begin
>    P (Y); -- This is OK (since Ada 2005)
> 
> Now add "tagged" to Q:
> 
>    type Q is tagged null record;
>    procedure P (X : access Q) is null;
> 
>    Y : access Q := null;
> begin
>    P (Y); -- This is not OK?
> 
> I didn't searched ARM for this, but if indeed so, this is a language bug to
> me.

It was a deliberate design decision.  The big difference in your second example isn't just that Q is now tagged; the big difference is that P has become a dispatching procedure, and it dispatches on the argument X.  Passing null for X wouldn't make any sense--what would it dispatch to?  

In this example:

    type Q is tagged null record;
    package Inner is
        procedure P (X : access Q) is null;
    end Inner;

now X can be null, since P isn't dispatching.  In some of the examples in your later post (like the one where Q is private and the full type is a tagged record), there isn't a problem either, since the procedure isn't dispatching.

It has always been the case since Ada 95 that access parameters used for dispatching may not be null.  In Ada 95, actuals for other access parameters weren't allowed to be null either.  In Ada 2005, the language was changed to allow null for access parameters, *except* for those (controlling parameters) which could be dispatched on.  It was also changed to allow "not null".  I believe there was a dilemma when it came to controlling parameters--those still could not be null, but did they want to explicitly require "not null" on them?  The decision was to make those implicitly "not null", which makes some language rules a bit inconsistent but preserved backward compatibility.

                            -- Adam
    
   

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 11:01   ` Dmitry A. Kazakov
  2013-08-09 11:06     ` sbelmont700
  2013-08-09 15:48     ` Adam Beneschan
@ 2013-08-09 16:03     ` Simon Wright
  2013-08-09 18:55     ` Randy Brukardt
  3 siblings, 0 replies; 26+ messages in thread
From: Simon Wright @ 2013-08-09 16:03 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

>    type Q is tagged null record;
>    procedure P (X : access Q) is null;
>
>    Y : access Q := null;
> begin
>    P (Y); -- This is not OK?

dmitry.ada:9:07: warning: null value not allowed here
dmitry.ada:9:07: warning: "Constraint_Error" will be raised at run time
...
raised CONSTRAINT_ERROR : dmitry.ada:9 access check failed

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 15:48     ` Adam Beneschan
@ 2013-08-09 16:11       ` Simon Wright
  2013-08-09 16:52         ` Adam Beneschan
  0 siblings, 1 reply; 26+ messages in thread
From: Simon Wright @ 2013-08-09 16:11 UTC (permalink / raw)


Adam Beneschan <adambeneschan@aol.com> writes:

> In some of the examples in your later post (like the one where Q is
> private and the full type is a tagged record), there isn't a problem
> either, since the procedure isn't dispatching.

So when GNAT says, at the procedure call, that a null value isn't
allowed and that CE will be raised, it's wrong?


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 16:11       ` Simon Wright
@ 2013-08-09 16:52         ` Adam Beneschan
  2013-08-09 18:25           ` Simon Wright
  0 siblings, 1 reply; 26+ messages in thread
From: Adam Beneschan @ 2013-08-09 16:52 UTC (permalink / raw)


On Friday, August 9, 2013 9:11:35 AM UTC-7, Simon Wright wrote:
  
> > In some of the examples in your later post (like the one where Q is
> > private and the full type is a tagged record), there isn't a problem
> > either, since the procedure isn't dispatching.
> 
> So when GNAT says, at the procedure call, that a null value isn't
> allowed and that CE will be raised, it's wrong?

I just tried it on a case with "type Q is private" [not tagged] and a full definition "type Q is tagged null record", and I didn't get a warning.  In the example you posted, GNAT is correct to display a warning, but your procedure *is* dispatching, and this situation isn't the same as the part of my post that you quoted.

                               -- Adam




^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 16:52         ` Adam Beneschan
@ 2013-08-09 18:25           ` Simon Wright
  2013-08-09 18:39             ` Adam Beneschan
  0 siblings, 1 reply; 26+ messages in thread
From: Simon Wright @ 2013-08-09 18:25 UTC (permalink / raw)


Adam Beneschan <adambeneschan@aol.com> writes:

> On Friday, August 9, 2013 9:11:35 AM UTC-7, Simon Wright wrote:
>   
>> > In some of the examples in your later post (like the one where Q is
>> > private and the full type is a tagged record), there isn't a problem
>> > either, since the procedure isn't dispatching.
>> 
>> So when GNAT says, at the procedure call, that a null value isn't
>> allowed and that CE will be raised, it's wrong?
>
> I just tried it on a case with "type Q is private" [not tagged] and a
> full definition "type Q is tagged null record", and I didn't get a
> warning.  In the example you posted, GNAT is correct to display a
> warning, but your procedure *is* dispatching, and this situation isn't
> the same as the part of my post that you quoted.

I was talking about a slightly different case, corresponding to yours I
think:

   package Dmitry is
      type Q is private;
      procedure P (X : access Q) is null;
   private
      type Q is tagged null record;
   end Dmitry;
   with Dmitry; use Dmitry;
   procedure Test_Dmitry is
      Y : access Q;
   begin
      P (Y);                  ------ dmitry.ada:11
   end Test_Dmitry;

and get (GCC 4.8.1 and GNAT GPL 2013):

gnatmake test_dmitry.adb  -gnat12 -f
gcc -c -gnat12 test_dmitry.adb
dmitry.ada:9:04: warning: variable "Y" is read but never assigned
dmitry.ada:11:07: warning: null value not allowed here
dmitry.ada:11:07: warning: "Constraint_Error" will be raised at run time
gcc -c -gnat12 dmitry.ads
gnatbind -x test_dmitry.ali
gnatlink test_dmitry.ali


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 18:25           ` Simon Wright
@ 2013-08-09 18:39             ` Adam Beneschan
  2013-08-09 19:28               ` Adam Beneschan
  0 siblings, 1 reply; 26+ messages in thread
From: Adam Beneschan @ 2013-08-09 18:39 UTC (permalink / raw)


On Friday, August 9, 2013 11:25:57 AM UTC-7, Simon Wright wrote:

> 
> > On Friday, August 9, 2013 9:11:35 AM UTC-7, Simon Wright wrote:
> 
> >> > In some of the examples in your later post (like the one where Q is
> >> > private and the full type is a tagged record), there isn't a problem
> >> > either, since the procedure isn't dispatching.
> 
> >> So when GNAT says, at the procedure call, that a null value isn't
> >> allowed and that CE will be raised, it's wrong?
> 
> > I just tried it on a case with "type Q is private" [not tagged] and a
> > full definition "type Q is tagged null record", and I didn't get a
> > warning.  In the example you posted, GNAT is correct to display a
> > warning, but your procedure *is* dispatching, and this situation isn't
> > the same as the part of my post that you quoted.
> 
> I was talking about a slightly different case, corresponding to yours I
> think:
> 
>    package Dmitry is
>       type Q is private;
>       procedure P (X : access Q) is null;
>    private
>       type Q is tagged null record;
>    end Dmitry;
> 
>    with Dmitry; use Dmitry;
>    procedure Test_Dmitry is
>       Y : access Q;
>    begin
>       P (Y);                  ------ dmitry.ada:11
>    end Test_Dmitry;
> 
> and get (GCC 4.8.1 and GNAT GPL 2013):
> 
> gnatmake test_dmitry.adb  -gnat12 -f
> gcc -c -gnat12 test_dmitry.adb
> dmitry.ada:9:04: warning: variable "Y" is read but never assigned
> dmitry.ada:11:07: warning: null value not allowed here
> dmitry.ada:11:07: warning: "Constraint_Error" will be raised at run time
> gcc -c -gnat12 dmitry.ads
> gnatbind -x test_dmitry.ali
> gnatlink test_dmitry.ali

OK, that's essentially the same Ada code I was testing.  However, I was using an older version of GNAT when I tried it and didn't get a warning.  Later versions do give a warning.  

Offhand, I do think GNAT is wrong, and that P is not a dispatching procedure.  However, the language rules get a bit murky at times when untagged private types are completed with tagged types, and sometimes the rules have had to be changed because they didn't cover this case adequately.  I'll have to dig a bit further.

                                  -- Adam



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 11:01   ` Dmitry A. Kazakov
                       ` (2 preceding siblings ...)
  2013-08-09 16:03     ` Simon Wright
@ 2013-08-09 18:55     ` Randy Brukardt
  2013-08-09 19:27       ` Dmitry A. Kazakov
  3 siblings, 1 reply; 26+ messages in thread
From: Randy Brukardt @ 2013-08-09 18:55 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:hrkm713gcc7n$.mep6a9ijq09k.dlg@40tude.net...
> On Fri, 9 Aug 2013 03:38:21 -0700 (PDT), sbelmont700@gmail.com wrote:
...
> Now add "tagged" to Q:
>
>   type Q is tagged null record;
>   procedure P (X : access Q) is null;
>
>   Y : access Q := null;
> begin
>   P (Y); -- This is not OK?
>
> I didn't searched ARM for this, but if indeed so, this is a language bug 
> to
> me.

It's not a bug, but a required compatibility wart. In Ada 95, anonymous 
access always excluded null, and the semantics of dispatching require that 
null is excluded from controlling parameters. Requiring explicit writing of 
"not null" on all controlling parameters would have made all existing Ada 95 
code (like Claw) incompatible with Ada 2005, so that could not be 
considered. The only remaining option was the implicit "not null" for 
controlling parameters. It's not pretty, but there was no other choice. (If 
Ada 95 had had "not null" like it should have, this would not have been a 
problem.)

We tried to require Ada 95 compilers to support "not null" syntactically for 
anonymous parameters (with no semantic meaning), so people could write their 
code sensibly, but we were told that we can't change obsolete standards in 
any way.

                                Randy.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 18:55     ` Randy Brukardt
@ 2013-08-09 19:27       ` Dmitry A. Kazakov
  2013-08-09 20:04         ` Robert A Duff
  0 siblings, 1 reply; 26+ messages in thread
From: Dmitry A. Kazakov @ 2013-08-09 19:27 UTC (permalink / raw)


On Fri, 9 Aug 2013 13:55:40 -0500, Randy Brukardt wrote:

> and the semantics of dispatching require that 
> null is excluded from controlling parameters.

Why? null considered an object is not class-wide, so I see no difference to
plain parameters. null.Foo would be illegal anyway and Foo (null) would be
ambiguous (in presence of several overriding instances).

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 18:39             ` Adam Beneschan
@ 2013-08-09 19:28               ` Adam Beneschan
  2013-08-09 20:05                 ` Robert A Duff
  0 siblings, 1 reply; 26+ messages in thread
From: Adam Beneschan @ 2013-08-09 19:28 UTC (permalink / raw)


On Friday, August 9, 2013 11:39:19 AM UTC-7, Adam Beneschan wrote:

> >    package Dmitry is
> >       type Q is private;
> >       procedure P (X : access Q) is null;
> >    private
> >       type Q is tagged null record;
> >    end Dmitry;
> 
> >    with Dmitry; use Dmitry;
> >    procedure Test_Dmitry is
> >       Y : access Q;
> >    begin
> >       P (Y);                  ------ dmitry.ada:11
> >    end Test_Dmitry;

> > gcc -c -gnat12 test_dmitry.adb
> > dmitry.ada:9:04: warning: variable "Y" is read but never assigned
> > dmitry.ada:11:07: warning: null value not allowed here
> > dmitry.ada:11:07: warning: "Constraint_Error" will be raised at run time

> Offhand, I do think GNAT is wrong, and that P is not a dispatching procedure.  However, the language rules get a bit murky at times when untagged private types are completed with tagged types, and sometimes the rules have had to be changed because they didn't cover this case adequately.  I'll have to dig a bit further.

OK, it turns out GNAT is right; AI95-183 says that P is dispatching.  I don't particularly like that, since it seems to make the behavior, from the caller's point of view, dependent on what's in the private part that the caller isn't supposed to have to know about.  It was probably OK, though, if the only effect was that a call to P might actually call some other P in some other package.  However, now that the "not null" rules on anonymous access parameters have changed, I think this *is* a problem, since now you can't tell whether a null value is allowed for the access parameter without peeking into the private part.  (I think AI95-183 was answered before the "not null" feature was proposed.)  So there seems to be a privacy breakage here.

A possible solution: Add a rule that if an untagged private type has a full definition that is tagged, then in any primitive operations declared in the visible part with controlling access parameters, the access parameters must be declared with *explicit* null exclusions.  This means that the example suggested by Dmitry and Simon would be caught early--the package specification would be disallowed.  This wouldn't be backward-compatible.  I'm guessing that in practice, this might require modifications to approximately zero code.  

                             -- Adam


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 19:27       ` Dmitry A. Kazakov
@ 2013-08-09 20:04         ` Robert A Duff
  2013-08-10  6:51           ` Dmitry A. Kazakov
  0 siblings, 1 reply; 26+ messages in thread
From: Robert A Duff @ 2013-08-09 20:04 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> Why? null considered an object is not class-wide, so I see no difference to
> plain parameters. null.Foo would be illegal anyway and Foo (null) would be
> ambiguous (in presence of several overriding instances).

    type T is tagged ...;
    type A is access T'Class;
    procedure P (X: access T);

    X : A := null;
    P(X); -- This is a dispatching call, so it needs to look at
          -- X.all'Tag, which doesn't exist.

- Bob


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 19:28               ` Adam Beneschan
@ 2013-08-09 20:05                 ` Robert A Duff
  2013-08-09 20:30                   ` Adam Beneschan
  0 siblings, 1 reply; 26+ messages in thread
From: Robert A Duff @ 2013-08-09 20:05 UTC (permalink / raw)


Adam Beneschan <adambeneschan@aol.com> writes:

> It was probably OK, though, if the only effect was that a call to P
> might actually call some other P in some other package.

For clients outside the package?  I don't think that would be OK.
But I don't see how it can happen, since you can't do 'Class on
the private view.

- Bob



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 20:05                 ` Robert A Duff
@ 2013-08-09 20:30                   ` Adam Beneschan
  2013-08-09 21:35                     ` Simon Wright
  2013-08-10 15:10                     ` Shark8
  0 siblings, 2 replies; 26+ messages in thread
From: Adam Beneschan @ 2013-08-09 20:30 UTC (permalink / raw)


On Friday, August 9, 2013 1:05:54 PM UTC-7, Robert A Duff wrote:
> Adam Beneschan writes:
> 
> > It was probably OK, though, if the only effect was that a call to P
> > might actually call some other P in some other package.
> 
> For clients outside the package?  I don't think that would be OK.
> But I don't see how it can happen, since you can't do 'Class on
> the private view.

Yes, that's a good point.

It doesn't seem particularly useful to declare an untagged private type whose full type is something that only the package, or a child package, could derive types from.  Unfortunately, Ada doesn't have the concept of a "tagged type from which nothing can be derived".  That concept would be useful so that one could declare a type derived from Ada.Finalization.Controlled or some other tagged type, but declare that no other types may be derived from it, so that *new* operations declared for the type wouldn't have to be dispatching.  Then the language could decree that an untagged private type couldn't be completed by a tagged type unless it were underivable, and then the dispatching issue wouldn't arise at all.  (And one could declare operations of more than one such type, since they wouldn't be dispatching operations; this is what led to the original AI95-183 issue.)  I wish I or someone else had thought of that back in 1997.

                               -- Adam

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 20:30                   ` Adam Beneschan
@ 2013-08-09 21:35                     ` Simon Wright
  2013-08-10 15:10                     ` Shark8
  1 sibling, 0 replies; 26+ messages in thread
From: Simon Wright @ 2013-08-09 21:35 UTC (permalink / raw)


Adam Beneschan <adambeneschan@aol.com> writes:

> It doesn't seem particularly useful to declare an untagged private
> type whose full type is something that only the package, or a child
> package, could derive types from.

Ada.Containers manage to make derivation impractical quite well, by
having a large number of functions with controlling parameters! In fact,
I think containers in general are something you wouldn't really want to
derive from; and (in the case I fell over - I needed set-like properties
for vectors) I only needed 9 subprograms and cursors, so composition did
the trick.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 20:04         ` Robert A Duff
@ 2013-08-10  6:51           ` Dmitry A. Kazakov
  2013-08-12 16:52             ` Adam Beneschan
  2013-08-12 20:12             ` Randy Brukardt
  0 siblings, 2 replies; 26+ messages in thread
From: Dmitry A. Kazakov @ 2013-08-10  6:51 UTC (permalink / raw)


On Fri, 09 Aug 2013 16:04:02 -0400, Robert A Duff wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> Why? null considered an object is not class-wide, so I see no difference to
>> plain parameters. null.Foo would be illegal anyway and Foo (null) would be
>> ambiguous (in presence of several overriding instances).
> 
>     type T is tagged ...;
>     type A is access T'Class;
>     procedure P (X: access T);
> 
>     X : A := null;
>     P(X); -- This is a dispatching call, so it needs to look at
>           -- X.all'Tag, which doesn't exist.

Does is matter why Constraint_Error raised?

I can "dispatch" on null anyway:

   type T is tagged null record;
   procedure P (X : T) is null;
   procedure R (X : access T'Class);

   procedure R (X : access T'Class) is
   begin
     X.P;
   end R;

Putting null exclusion on primitive operations does not solve the problem
(if there is any). It is too late. Dispatch happens before them. It seems
that rather access T'CLass should be constrained to not null access
T'Class.

BTW, why Ada 2005 used incompatible null-exclusion instead of compatible
null-permission, e.g.

   procedure P (X : null or access T); -- I accept null

or something like that?

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-09 20:30                   ` Adam Beneschan
  2013-08-09 21:35                     ` Simon Wright
@ 2013-08-10 15:10                     ` Shark8
  1 sibling, 0 replies; 26+ messages in thread
From: Shark8 @ 2013-08-10 15:10 UTC (permalink / raw)


On Friday, August 9, 2013 2:30:40 PM UTC-6, Adam Beneschan wrote:
> 
> It doesn't seem particularly useful to declare an untagged private type whose full type is something that only the package, or a child package, could derive types from.

I think I used this in one of my starts for a PostScript Interpreter. Postscript objects forming a hierarchy and all. So it could be useful if you are implementing something which has a common set of properties in implementation that are irrelevant to the actual client.

> Unfortunately, Ada doesn't have the concept of a "tagged type from which nothing can be derived".  That concept would be useful so that one could declare a type derived from Ada.Finalization.Controlled or some other tagged type, but declare that no other types may be derived from it, so that *new* operations declared for the type wouldn't have to be dispatching.

Good point; but on the flipside there's lots of workarounds for final objects in Java. So a choice either way has problems. IMO.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-10  6:51           ` Dmitry A. Kazakov
@ 2013-08-12 16:52             ` Adam Beneschan
  2013-08-12 17:03               ` Dmitry A. Kazakov
  2013-08-12 20:12             ` Randy Brukardt
  1 sibling, 1 reply; 26+ messages in thread
From: Adam Beneschan @ 2013-08-12 16:52 UTC (permalink / raw)


On Friday, August 9, 2013 11:51:34 PM UTC-7, Dmitry A. Kazakov wrote:
> On Fri, 09 Aug 2013 16:04:02 -0400, Robert A Duff wrote:

> I can "dispatch" on null anyway:
> 
>    type T is tagged null record;
>    procedure P (X : T) is null;
>    procedure R (X : access T'Class);
> 
>    procedure R (X : access T'Class) is
>    begin
>      X.P;
>    end R;

But I could write

   procedure R (X : access T'Class) is
   begin
      if X = null then
         -- take some special default action
      else
         X.P;
      end if;
   end R;

The point is that when a caller calls R, the above procedure is simply called.  So it will work to call it with a null parameter; the code in R may later run into a Constraint_Error or not, depending on how it's written, but there's no problem calling R.  But when P is called, the dispatching occurs *at* *that* *point*, before any code in any of the P procedures is executed; if the parameter is null, the dispatch cannot work.

I'm really not clear at all on what point you're trying to make.

                             -- Adam


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-12 16:52             ` Adam Beneschan
@ 2013-08-12 17:03               ` Dmitry A. Kazakov
  2013-08-12 17:20                 ` Adam Beneschan
  0 siblings, 1 reply; 26+ messages in thread
From: Dmitry A. Kazakov @ 2013-08-12 17:03 UTC (permalink / raw)


On Mon, 12 Aug 2013 09:52:29 -0700 (PDT), Adam Beneschan wrote:

> On Friday, August 9, 2013 11:51:34 PM UTC-7, Dmitry A. Kazakov wrote:
>> On Fri, 09 Aug 2013 16:04:02 -0400, Robert A Duff wrote:
> 
>> I can "dispatch" on null anyway:
>> 
>>    type T is tagged null record;
>>    procedure P (X : T) is null;
>>    procedure R (X : access T'Class);
>> 
>>    procedure R (X : access T'Class) is
>>    begin
>>      X.P;
>>    end R;
> 
> But I could write
> 
>    procedure R (X : access T'Class) is
>    begin
>       if X = null then
>          -- take some special default action
>       else
>          X.P;
>       end if;
>    end R;
> 
> The point is that when a caller calls R, the above procedure is simply
> called.  So it will work to call it with a null parameter; the code in R
> may later run into a Constraint_Error or not, depending on how it's
> written, but there's no problem calling R.  But when P is called, the
> dispatching occurs *at* *that* *point*, before any code in any of the P
> procedures is executed;

It is irrelevant for the client (= user = program semantics) where that
check is placed, an implementation detail, nothing more.

> if the parameter is null, the dispatch cannot
> work.
> 
> I'm really not clear at all on what point you're trying to make.

That implied null-exclusion for controlling parameters does not change/save
anything. Just added language weirdness that

   "access T" is subtype conformant to "not null access T" depending on T

!, for apparently no gain.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-12 17:03               ` Dmitry A. Kazakov
@ 2013-08-12 17:20                 ` Adam Beneschan
  2013-08-12 18:34                   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 26+ messages in thread
From: Adam Beneschan @ 2013-08-12 17:20 UTC (permalink / raw)


On Monday, August 12, 2013 10:03:14 AM UTC-7, Dmitry A. Kazakov wrote:

> That implied null-exclusion for controlling parameters does not change/save
> anything. Just added language weirdness that
> 
>    "access T" is subtype conformant to "not null access T" depending on T
> 
> !, for apparently no gain.

Well, from the point of view of dynamic semantics, a call to a dispatching subprogram *has* to fail if given a null parameter.  There's no way around this.  So, dynamically, it's going to behave like a null-excluding access type no matter what.  From a static-semantics point of view, the language designers could have decreed that the parameter is *not* implicitly a null-excluding parameter even though it behaves like one at run-time.  That's a choice they could have made, although then someone else probably would have considered this to be "language weirdness".  They just can't win.

                               -- Adam


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-12 17:20                 ` Adam Beneschan
@ 2013-08-12 18:34                   ` Dmitry A. Kazakov
  0 siblings, 0 replies; 26+ messages in thread
From: Dmitry A. Kazakov @ 2013-08-12 18:34 UTC (permalink / raw)


On Mon, 12 Aug 2013 10:20:05 -0700 (PDT), Adam Beneschan wrote:

> On Monday, August 12, 2013 10:03:14 AM UTC-7, Dmitry A. Kazakov wrote:
> 
>> That implied null-exclusion for controlling parameters does not change/save
>> anything. Just added language weirdness that
>> 
>>    "access T" is subtype conformant to "not null access T" depending on T
>> 
>> !, for apparently no gain.
> 
> Well, from the point of view of dynamic semantics, a call to a dispatching
> subprogram *has* to fail if given a null parameter.

A dispatching call, you mean, and not fail, but propagate Constraint_Error.
And that does not imply that a non-dispatching call have to. Semantically
they are different.

> There's no way around this.

Actually there is one. Access type is a by-value type. As such it could
have non-tagged classes, using the standard scheme:

   T -> Value
   T'Class -> (T'Tag, Value)

So null access T'Class would become (T'Tag, null) rather than bare null.
Which would make it possible to dispatch on it without assuming that the
target body is always (begin raise Constraint_Error; end). Not that
dispatching on null would be terribly useful, of course...

> So, dynamically, it's going to behave like a null-excluding access
> type no matter what.

Yes, though, as I said, it is because of access T'Class. It is not because
there is something wrong with access T. Smoke and mirrors.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-10  6:51           ` Dmitry A. Kazakov
  2013-08-12 16:52             ` Adam Beneschan
@ 2013-08-12 20:12             ` Randy Brukardt
  2013-08-13  6:43               ` Dmitry A. Kazakov
  1 sibling, 1 reply; 26+ messages in thread
From: Randy Brukardt @ 2013-08-12 20:12 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:k71biho5pjg7.16zreugtnwyc6$.dlg@40tude.net...
> On Fri, 09 Aug 2013 16:04:02 -0400, Robert A Duff wrote:
...
> BTW, why Ada 2005 used incompatible null-exclusion instead of compatible
> null-permission, e.g.
>
>   procedure P (X : null or access T); -- I accept null
>
> or something like that?

Because that would make the syntax for named access and anonymous access 
different, or would simply move the incompatibility to named access types.

The difference between the default behavior for anonymous and named access 
in Ada 95 was unjustifiable once we had null exclusions. That meant we had 
to break something, and the least painful was the implicit "not null" on 
controlling access parameters (something best avoided anyway, IMHO).

                                  Randy.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: GNAT GPL 2013 bug?
  2013-08-12 20:12             ` Randy Brukardt
@ 2013-08-13  6:43               ` Dmitry A. Kazakov
  0 siblings, 0 replies; 26+ messages in thread
From: Dmitry A. Kazakov @ 2013-08-13  6:43 UTC (permalink / raw)


On Mon, 12 Aug 2013 15:12:51 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:k71biho5pjg7.16zreugtnwyc6$.dlg@40tude.net...
>> On Fri, 09 Aug 2013 16:04:02 -0400, Robert A Duff wrote:
> ...
>> BTW, why Ada 2005 used incompatible null-exclusion instead of compatible
>> null-permission, e.g.
>>
>>   procedure P (X : null or access T); -- I accept null
>>
>> or something like that?
> 
> Because that would make the syntax for named access and anonymous access 
> different,

Which is anyway, considering the qualifier "all", modes "out", "in out" not
available for anonymous access. It has very little in common with named
access beyond sharing the word "access".

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2013-08-13  6:43 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-09  9:47 GNAT GPL 2013 bug? Dmitry A. Kazakov
2013-08-09 10:38 ` sbelmont700
2013-08-09 11:01   ` Dmitry A. Kazakov
2013-08-09 11:06     ` sbelmont700
2013-08-09 11:36       ` Dmitry A. Kazakov
2013-08-09 15:48     ` Adam Beneschan
2013-08-09 16:11       ` Simon Wright
2013-08-09 16:52         ` Adam Beneschan
2013-08-09 18:25           ` Simon Wright
2013-08-09 18:39             ` Adam Beneschan
2013-08-09 19:28               ` Adam Beneschan
2013-08-09 20:05                 ` Robert A Duff
2013-08-09 20:30                   ` Adam Beneschan
2013-08-09 21:35                     ` Simon Wright
2013-08-10 15:10                     ` Shark8
2013-08-09 16:03     ` Simon Wright
2013-08-09 18:55     ` Randy Brukardt
2013-08-09 19:27       ` Dmitry A. Kazakov
2013-08-09 20:04         ` Robert A Duff
2013-08-10  6:51           ` Dmitry A. Kazakov
2013-08-12 16:52             ` Adam Beneschan
2013-08-12 17:03               ` Dmitry A. Kazakov
2013-08-12 17:20                 ` Adam Beneschan
2013-08-12 18:34                   ` Dmitry A. Kazakov
2013-08-12 20:12             ` Randy Brukardt
2013-08-13  6:43               ` Dmitry A. Kazakov

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