comp.lang.ada
 help / color / mirror / Atom feed
* Preventing private procedure visibility being made public through extension
@ 2017-05-20 17:33 Jere
  2017-05-20 20:13 ` AdaMagica
                   ` (2 more replies)
  0 siblings, 3 replies; 42+ messages in thread
From: Jere @ 2017-05-20 17:33 UTC (permalink / raw)


I tried to whittle this down to a small example, so forgive 
the uselessness of the example itself.  I'm extending a 
library with some of my own components and I want (if possible) 
to allow my components to interact with the other library 
components as seamlessly as possible.

Say a library provides a tagged type with the following procedure:

Base.ads
*************************************************
package Base is
   
   type Base_Param is tagged null record;
   
   type Base_Type is tagged null record;
   
   procedure Something
      (Obj : in out Base_Type; 
       Value : Base_Param'Class) 
   is null;
   
end Base;

*************************************************

keep in mind declaring the procedure as "is null" is 
just for example sake. In real life it would have a body.

I want to extend both of the types in that package to do some 
extra processing.  In particular, I want to override the 
procedure Something so that it does more than the version 
for Base_Type and so it takes in my derived param class as a
parameter.  I also want to prevent a client from calling the 
inherited version of the procedure Something as it would 
bypass the code I have in my new prototype of the procedure.

I declare the package like this:

Derived.ads
*************************************************
with Base;

package Derived is
   
   type Derived_Param is new Base.Base_Param with null record;
   
   type Derived_Type is new Base.Base_Type with private;
   
   procedure Something
      (Obj : in out Derived_Type; 
       Value : Derived_Param'Class)
   is null;
   
   type More_Derived_Type is new Derived_Type with private;
   
private
   
   type Derived_Type is new Base.Base_Type with null record;
   
   overriding
   procedure Something
      (Obj : in out Derived_Type; 
       Value : Base.Base_Param'Class) 
   is null;
   
   type More_Derived_Type is new Derived_Type with null record;
   
end Derived;

*************************************************

Again, keep in mind this is a simplified example.  
The procedures would do something and the extended 
types would have other params.

This is all well and good.  Variables of Derived_Type 
can only call the version of something that I specified 
publicly and the overriden one cannot be called.

However, variables of More_Derived_Type have public 
visibility to both versions of Something.  I would 
have hoped that the version hidden by Derived_Type 
would keep it hidden, but extending the type makes
the private procedure visible again.

Example main:

main.adb
*************************************************
with Base;
with Derived; use Derived;

procedure Main is
   p : Derived_Param;
   d : Derived_Type;
   m : More_Derived_Type;
begin
   d.Something(p);  -- Works as expected
   m.Something(p);  -- Causes an error due to ambiguity
end Main;
*************************************************

Is there a way for me to prevent extending types from making
the procedure public again?

The error is ambiguous call to "Something"


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-20 17:33 Preventing private procedure visibility being made public through extension Jere
@ 2017-05-20 20:13 ` AdaMagica
  2017-05-20 21:55   ` Jere
  2017-05-20 20:32 ` Dmitry A. Kazakov
  2017-05-21 18:14 ` Robert Eachus
  2 siblings, 1 reply; 42+ messages in thread
From: AdaMagica @ 2017-05-20 20:13 UTC (permalink / raw)


> with Base;
> 
> package Derived is
>    
>    type Derived_Param is new Base.Base_Param with null record;
>    
>    type Derived_Type is new Base.Base_Type with private;
>    
>    procedure Something
>       (Obj : in out Derived_Type; 
>        Value : Derived_Param'Class)
>    is null;
>    
> private
>    
>    type Derived_Type is new Base.Base_Type with null record;
>    
>    overriding
>    procedure Something
>       (Obj : in out Derived_Type; 
>        Value : Base.Base_Param'Class) 
>    is null;
>    
> end Derived;

Here you are wrong. Hiding the overriding does not prevent the client from calling the operation. It nearly makes no difference whether you override an inherited operation in the public or in the private part. (There are a few syntactic diffrences though.)

> *************************************************
> 
> This is all well and good.  Variables of Derived_Type 
> can only call the version of something that I specified 
> publicly and the overriden one cannot be called.

As I said, this is wrong.

> 
> However, variables of More_Derived_Type have public 
> visibility to both versions of Something.  I would 
> have hoped that the version hidden by Derived_Type 
> would keep it hidden, but extending the type makes
> the private procedure visible again.
> 
> Example main:
> 
> main.adb
> *************************************************
> with Base;
> with Derived; use Derived;
> 
> procedure Main is
>    p : Derived_Param;
>    d : Derived_Type;
>    m : More_Derived_Type;
> begin
>    d.Something(p);  -- Works as expected

I think your compiler is in error here. This call is (IMHO) also ambiguous.
Both of these operations are visible here:

   not overriding
   procedure Something
      (Obj : in out Derived_Type;
       Value : Derived_Param'Class);
   
   overriding
   procedure Something
      (Obj : in out Derived_Type;
       Value : Base.Base_Param'Class);

Since your parameter d belongs to both classwide types, it's impossible to decide to which class it has to be converted (implicitly).

>    m.Something(p);  -- Causes an error due to ambiguity
> end Main;
> *************************************************
> 
> Is there a way for me to prevent extending types from making
> the procedure public again?
> 
> The error is ambiguous call to "Something"


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-20 17:33 Preventing private procedure visibility being made public through extension Jere
  2017-05-20 20:13 ` AdaMagica
@ 2017-05-20 20:32 ` Dmitry A. Kazakov
  2017-05-20 22:51   ` Jere
  2017-05-22 21:12   ` Randy Brukardt
  2017-05-21 18:14 ` Robert Eachus
  2 siblings, 2 replies; 42+ messages in thread
From: Dmitry A. Kazakov @ 2017-05-20 20:32 UTC (permalink / raw)


On 2017-05-20 19:33, Jere wrote:

> package Derived is
>     
>     type Derived_Param is new Base.Base_Param with null record;
>     
>     type Derived_Type is new Base.Base_Type with private;
>     
>     procedure Something
>        (Obj : in out Derived_Type;
>         Value : Derived_Param'Class)
>     is null;
>     
>     type More_Derived_Type is new Derived_Type with private;
>     
> private
>     
>     type Derived_Type is new Base.Base_Type with null record;
>     
>     overriding
>     procedure Something
>        (Obj : in out Derived_Type;
>         Value : Base.Base_Param'Class)
>     is null;

This is not private regardless where it appears. When you derive from 
Base_Type that automatically declares Something for Derived_Type. You 
may override its body but that is all you can do. When you declare 
another Something for Derived_Param'Class that overloads the already 
inherited Something and here you are.

> Is there a way for me to prevent extending types from making
> the procedure public again?

It is public. That was the decision made in the package Base. The 
package Derived has no say on that.

----------------------------------
The actual problem you have is parallel types hierarchies. You want to 
derive tied instances of Base_Type'Class and Base_Param'Class.

    Base_Type ----- Base_Param
       |              |
    Derived_Type -- Derived_Param

This requires

1. Full multiple dispatch
2. Dispatch constrained to certain combinations (parallel hierarchies)

This is not supported in Ada (or in any other OO language I am aware of)

A typical workaround is replacing multiple dispatch (pos.1) with a 
cascaded dispatch. I.e. you keep Something class-wide in the second 
parameter. Then you override it as you did. In the body you select the 
parameter type in any desired way (second dispatch).

The drawback is obviously loss of static type checks (pos.2):

    procedure Something
              (  Obj   : in out Derived_Type;
                 Value : Base_Param'Class
              )  is
    begin
       if not Value in Derived_Param then -- or a more relaxed
                                          -- Derived_Param'Class
          raise Constraint_Error with "Value type error";
       end if;
       declare
          Checked_Value : Derived_Param renames Derived_Param (Value);
       begin
          ... -- Go on

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

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-20 20:13 ` AdaMagica
@ 2017-05-20 21:55   ` Jere
  0 siblings, 0 replies; 42+ messages in thread
From: Jere @ 2017-05-20 21:55 UTC (permalink / raw)


On Saturday, May 20, 2017 at 4:13:10 PM UTC-4, AdaMagica wrote:
> > with Base;
> > 
> > package Derived is
> >    
> >    type Derived_Param is new Base.Base_Param with null record;
> >    
> >    type Derived_Type is new Base.Base_Type with private;
> >    
> >    procedure Something
> >       (Obj : in out Derived_Type; 
> >        Value : Derived_Param'Class)
> >    is null;
> >    
> > private
> >    
> >    type Derived_Type is new Base.Base_Type with null record;
> >    
> >    overriding
> >    procedure Something
> >       (Obj : in out Derived_Type; 
> >        Value : Base.Base_Param'Class) 
> >    is null;
> >    
> > end Derived;
> 
> Here you are wrong. Hiding the overriding does not prevent the client from calling the operation. It nearly makes no difference whether you override an inherited operation in the public or in the private part. (There are a few syntactic diffrences though.)
> 
> > *************************************************
> > 
> > This is all well and good.  Variables of Derived_Type 
> > can only call the version of something that I specified 
> > publicly and the overriden one cannot be called.
> 
> As I said, this is wrong.
> 
> > 
> > However, variables of More_Derived_Type have public 
> > visibility to both versions of Something.  I would 
> > have hoped that the version hidden by Derived_Type 
> > would keep it hidden, but extending the type makes
> > the private procedure visible again.
> > 
> > Example main:
> > 
> > main.adb
> > *************************************************
> > with Base;
> > with Derived; use Derived;
> > 
> > procedure Main is
> >    p : Derived_Param;
> >    d : Derived_Type;
> >    m : More_Derived_Type;
> > begin
> >    d.Something(p);  -- Works as expected
> 
> I think your compiler is in error here. This call is (IMHO) also ambiguous.
> Both of these operations are visible here:

Perhaps a compiler bug, but it is even more than just not 
ambiguous, it cannot call the version of the procedure that I 
put in the private section (for variables of type Derived_Type).  

If I declare a variable:

b : Base.Base_Param;

and try to call

d.Something(b);

It will fail with an error:
Expected type "Derived_Param'Class" defined at derived.ads:5
expected type "Derived_Param'Class" defined at derived.ads:5
found type "Base_Param" defined at base.ads:3

I even tried casting b to Base_Param'Class with similar 
results (compiler error).  It is acting like the 
procedure is not publicly visible for variable d.

Now if I didn't have a procedure named Something declared, 
it acts as you described.  Is this a compiler bug?

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-20 20:32 ` Dmitry A. Kazakov
@ 2017-05-20 22:51   ` Jere
  2017-05-21  0:51     ` Jere
  2017-05-21  8:44     ` Dmitry A. Kazakov
  2017-05-22 21:12   ` Randy Brukardt
  1 sibling, 2 replies; 42+ messages in thread
From: Jere @ 2017-05-20 22:51 UTC (permalink / raw)


On Saturday, May 20, 2017 at 4:32:07 PM UTC-4, Dmitry A. Kazakov wrote:
> On 2017-05-20 19:33, Jere wrote:
> > Is there a way for me to prevent extending types from making
> > the procedure public again?
> 
> It is public. That was the decision made in the package Base. The 
> package Derived has no say on that.
> 
> ----------------------------------
> The actual problem you have is parallel types hierarchies. You want to 
> derive tied instances of Base_Type'Class and Base_Param'Class.
> 
>     Base_Type ----- Base_Param
>        |              |
>     Derived_Type -- Derived_Param
> 
> This requires
> 
> 1. Full multiple dispatch
> 2. Dispatch constrained to certain combinations (parallel hierarchies)
> 
> This is not supported in Ada (or in any other OO language I am aware of)

If I understand your definitions correctly, C++ supports this.  It can
fully dispatch on any number of types since dispatch is tied to the
function and not the type itself.  C++ does have its own problems though.

I do know that C++ supports hiding of functions by making them private
in the extending class.  I was hoping Ada did as well.  I don't mind
if dispatching runs the private versions, I can protect against that,
but I didn't want clients using the methods as they break operation
of the extended class.  

I can implement your suggestion from below though.  I don't like the 
loss of static type checking here, but if Ada has not viable options 
here, then that may be what I have to do.

My real issue is with how the constructors for the tagged type in
the library are done.  I want my derived type to work with the 
constructors defined in the library, which means it has to extend
one of the types defined in the library itself.  But I don't want
clients to extend my class and use the inherited constructors from
the base class because they'll break my extended class.

My alternate solution was to use composition, but it really feels
inelegant in this case.  I did:

package Derived is

   type Base_Access is access all Base.Base_Type;

   type Derived_Type is tagged limited private;

   procedure Something
      (Obj : Derived_Type;
       Value : Derived_Param'Class) 
   is null;

   procedure Get_Access(Obj : Derived_Type) return Base_Access;

private

   type Derived_Type is tagged limited record
      Param : Base.Base_Type;
   end record;

end Derived;

and Get_Access just returns Param'Unchecked_Access.
When I want to use the library methods, I use that to
pass back the correct type for them.

I really don't like doing this.  I don't like using
access types for one.  It's also doesn't feel like
a very clean way because you have to do something 
out of the ordinary just to use the class like it was
meant to be.

The actual use case is Gnoga.  All of the constructors
(the Create procedures) require parent to be of type
Gnoga.Gui.Base.Base_Type'Class, but I really want my
Dialog_Type constructor to only accept parents of type
Gnoga.Gui.Window.Window_Type'Class.  But it also has
to publicly extend Gnoga.Gui.Base.Base_Type 
(or I use Gnoga.Gui.View.View_Base_Type) so that
other controls can create themselves in it.  This
opens my type and types that extend it to being
thrashed by calls to Create_From_HTML and so on.
Similar to your suggestion, I can override them and
raise an exception...it just feels clunky.

I was just hoping for something better from a static checking
perspective.  There was a discussion in the Gnoga mailing
list if you are wanting more concrete examples.  I was just
simplifying it for here to see if there was a language
defined way to get what I needed statically.  It sounds like
there isn't.

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-20 22:51   ` Jere
@ 2017-05-21  0:51     ` Jere
  2017-05-21  9:16       ` Chris Moore
  2017-05-21  8:44     ` Dmitry A. Kazakov
  1 sibling, 1 reply; 42+ messages in thread
From: Jere @ 2017-05-21  0:51 UTC (permalink / raw)


On Saturday, May 20, 2017 at 6:51:43 PM UTC-4, Jere wrote:
> On Saturday, May 20, 2017 at 4:32:07 PM UTC-4, Dmitry A. Kazakov wrote:
> > On 2017-05-20 19:33, Jere wrote:
> > > Is there a way for me to prevent extending types from making
> > > the procedure public again?
> > 
> > It is public. That was the decision made in the package Base. The 
> > package Derived has no say on that.
> > 
> > ----------------------------------
> > The actual problem you have is parallel types hierarchies. You want to 
> > derive tied instances of Base_Type'Class and Base_Param'Class.
> > 
> >     Base_Type ----- Base_Param
> >        |              |
> >     Derived_Type -- Derived_Param
> > 
> The actual use case is Gnoga.  All of the constructors
> (the Create procedures) require parent to be of type
> Gnoga.Gui.Base.Base_Type'Class, but I really want my
> Dialog_Type constructor to only accept parents of type
> Gnoga.Gui.Window.Window_Type'Class.  But it also has
> to publicly extend Gnoga.Gui.Base.Base_Type 
> (or I use Gnoga.Gui.View.View_Base_Type) so that
> other controls can create themselves in it.  This
> opens my type and types that extend it to being
> thrashed by calls to Create_From_HTML and so on.
> Similar to your suggestion, I can override them and
> raise an exception...it just feels clunky.
> 
Or perhaps if Ada supported constructors that were not 
dispatchable and that were not inherited that might
also work.  I would need to think about it a bit
to be sure about that though.  Just an off the cuff
thought.


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-20 22:51   ` Jere
  2017-05-21  0:51     ` Jere
@ 2017-05-21  8:44     ` Dmitry A. Kazakov
  2017-05-21 12:19       ` J-P. Rosen
  2017-05-21 20:06       ` Jere
  1 sibling, 2 replies; 42+ messages in thread
From: Dmitry A. Kazakov @ 2017-05-21  8:44 UTC (permalink / raw)


On 2017-05-21 00:51, Jere wrote:
> On Saturday, May 20, 2017 at 4:32:07 PM UTC-4, Dmitry A. Kazakov wrote:
>> On 2017-05-20 19:33, Jere wrote:
>>> Is there a way for me to prevent extending types from making
>>> the procedure public again?
>>
>> It is public. That was the decision made in the package Base. The
>> package Derived has no say on that.
>>
>> ----------------------------------
>> The actual problem you have is parallel types hierarchies. You want to
>> derive tied instances of Base_Type'Class and Base_Param'Class.
>>
>>      Base_Type ----- Base_Param
>>         |              |
>>      Derived_Type -- Derived_Param
>>
>> This requires
>>
>> 1. Full multiple dispatch
>> 2. Dispatch constrained to certain combinations (parallel hierarchies)
>>
>> This is not supported in Ada (or in any other OO language I am aware of)
> 
> If I understand your definitions correctly, C++ supports this.  It can
> fully dispatch on any number of types since dispatch is tied to the
> function and not the type itself.

No. Dispatch cannot be tied to anything but a parameter/result (single 
dispatch) or a combination of (multiple dispatch), just per definition of.

In C++ the dispatching parameter is to the first parameter specified in 
the dotted notation: object.foo().

> I do know that C++ supports hiding of functions by making them private
> in the extending class.

No. That is not possible in C++ either. A public method cannot be made 
private.

In general from the OO point of view, a method cannot be removed because 
it is a property of the class and not of an individual type. It is the 
contract of the class to have a method Foo. All instances of the class 
must have this method. If they don't they are not instances of. Period.

[To support method disallowing the language must support ad-hoc 
superclasses, so that one could split an original class into parts to 
chip the undesired operation away from one part and put the new type in 
that part instead of the whole original class.]

> My real issue is with how the constructors for the tagged type in
> the library are done.  I want my derived type to work with the
> constructors defined in the library, which means it has to extend
> one of the types defined in the library itself.  But I don't want
> clients to extend my class and use the inherited constructors from
> the base class because they'll break my extended class.

These are not constructors proper. Maybe you meant "constructing 
function". There is a huge difference.

Anyway a constructing function being a primitive operation must work, 
exactly because this is an primitive operation which gets overridden. So 
works a constructor proper which is not an operation and cannot be 
called explicitly and when invoked, then implicitly always with its own 
type.

What you have is neither, it is probably an operation to initialize a 
part of the object. Such things are usually made private [to be used in 
a public constructing function].

[Yes it is a huge problem for library designers that Ada does not have 
constructors. Alas, there is no desire to fix that]

> My alternate solution was to use composition, but it really feels
> inelegant in this case.  I did:
> 
> package Derived is
> 
>     type Base_Access is access all Base.Base_Type;
> 
>     type Derived_Type is tagged limited private;
> 
>     procedure Something
>        (Obj : Derived_Type;
>         Value : Derived_Param'Class)
>     is null;
> 
>     procedure Get_Access(Obj : Derived_Type) return Base_Access;

    procedure Get_Access (Obj : Derived_Type)
       return not null access Base_Type;

> private
> 
>     type Derived_Type is tagged limited record
>        Param : Base.Base_Type;

    Param : aliased Base_Type;

>     end record;
> 
> end Derived;
> 
> and Get_Access just returns Param'Unchecked_Access.
> When I want to use the library methods, I use that to
> pass back the correct type for them.
> 
> I really don't like doing this.  I don't like using
> access types for one.  It's also doesn't feel like
> a very clean way because you have to do something
> out of the ordinary just to use the class like it was
> meant to be.

Aggregation + delegation is a decent thing.

If you used anonymous access you would reduce dangers of pointers to zero.

[If Ada supported return by-reference (it existed once in a rudimentary 
form and was removed in Ada 2005), the construct would be even better.]

[If Ada supported interface inheritance, you could inherit interface of 
Base_Type and use Derived_Type where Base_Type is expected calling to 
Get_Access implicitly]

But wait ... you can still call Something on the Base_Type part of 
Derived_Type. So, this resolves exactly *nothing*.

The problem is in the Base_Type'Class.

> The actual use case is Gnoga.  All of the constructors
> (the Create procedures) require parent to be of type
> Gnoga.Gui.Base.Base_Type'Class, but I really want my
> Dialog_Type constructor to only accept parents of type
> Gnoga.Gui.Window.Window_Type'Class.  But it also has
> to publicly extend Gnoga.Gui.Base.Base_Type
> (or I use Gnoga.Gui.View.View_Base_Type) so that
> other controls can create themselves in it.  This
> opens my type and types that extend it to being
> thrashed by calls to Create_From_HTML and so on.
> Similar to your suggestion, I can override them and
> raise an exception...it just feels clunky.

Believe other methods I know and have tried, e.g. involving generics, 
are far worse.

> I was just hoping for something better from a static checking
> perspective.  There was a discussion in the Gnoga mailing
> list if you are wanting more concrete examples.  I was just
> simplifying it for here to see if there was a language
> defined way to get what I needed statically.  It sounds like
> there isn't.

GUI is one of classic examples where multiple dispatch is required. It 
is a fact of reality which cannot be worked around without compromising 
something (no pun intended (:-)).

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

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21  0:51     ` Jere
@ 2017-05-21  9:16       ` Chris Moore
  2017-05-21 22:55         ` Jere
  0 siblings, 1 reply; 42+ messages in thread
From: Chris Moore @ 2017-05-21  9:16 UTC (permalink / raw)


On 21/05/2017 01:51, Jere wrote:

> Or perhaps if Ada supported constructors that were not
> dispatchable and that were not inherited that might
> also work.  I would need to think about it a bit
> to be sure about that though.  Just an off the cuff
> thought.

If you put the constructors in child packages then they aren't inherited.

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21  8:44     ` Dmitry A. Kazakov
@ 2017-05-21 12:19       ` J-P. Rosen
  2017-05-21 12:53         ` Dmitry A. Kazakov
  2017-05-21 20:06       ` Jere
  1 sibling, 1 reply; 42+ messages in thread
From: J-P. Rosen @ 2017-05-21 12:19 UTC (permalink / raw)


Le 21/05/2017 à 10:44, Dmitry A. Kazakov a écrit :
> If Ada supported return by-reference (it existed once in a rudimentary
> form and was removed in Ada 2005)
More precisely: an implicit, hard to understand return by reference was
replaced with an explicit one. If you want return by reference, have a
function that returns "access T".

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21 12:19       ` J-P. Rosen
@ 2017-05-21 12:53         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 42+ messages in thread
From: Dmitry A. Kazakov @ 2017-05-21 12:53 UTC (permalink / raw)


On 2017-05-21 14:19, J-P. Rosen wrote:
> Le 21/05/2017 à 10:44, Dmitry A. Kazakov a écrit :
>> If Ada supported return by-reference (it existed once in a rudimentary
>> form and was removed in Ada 2005)
> More precisely: an implicit, hard to understand return by reference was
> replaced with an explicit one. If you want return by reference, have a
> function that returns "access T".

Well, anonymous access is not same as reference.

1. It lacks implicit dereferencing

2. It overrides assignment operation of T with its own, which never 
should be there in first place

3. It does not transfer the access mode to T. E.g. the out mode of a 
reference to T applies to T itself". For an access type it applies to 
the type access T.

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


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-20 17:33 Preventing private procedure visibility being made public through extension Jere
  2017-05-20 20:13 ` AdaMagica
  2017-05-20 20:32 ` Dmitry A. Kazakov
@ 2017-05-21 18:14 ` Robert Eachus
  2017-05-21 20:21   ` Jere
  2 siblings, 1 reply; 42+ messages in thread
From: Robert Eachus @ 2017-05-21 18:14 UTC (permalink / raw)


On Saturday, May 20, 2017 at 1:33:27 PM UTC-4, Jere wrote:
> I tried to whittle this down to a small example, so forgive 
> the uselessness of the example itself.  I'm extending a 
> library with some of my own components and I want (if possible) 
> to allow my components to interact with the other library 
> components as seamlessly as possible.
> 
> Say a library provides a tagged type with the following procedure:
> 
> Base.ads
> *************************************************
> package Base is
>    
>    type Base_Param is tagged null record;
>    
>    type Base_Type is tagged null record;
>    
>    procedure Something
>       (Obj : in out Base_Type; 
>        Value : Base_Param'Class) 
>    is null;
>    
> end Base;
> 
> *************************************************
...
I think that the problem you are dealing with is the you started with one package and have never let go of that model.  You have two very different access patterns in mind (not access in the Ada sense).  So you need two packages to declare them.  Is there any reason to allow your clients to do anything with Base_Param other than pass it to subroutines you provide?  I think not.  I’m also going to avoid games like the Taft amendment,  Use it if you want to.

generic
  type Object is limited private;  
package Params is
begin
  type Param is limited private;
private
  type Access_Object is access Object;
  type Param is record
    Prev, Next: Access_Object;
  end record;
end Params;

with Params;
package Base is
  type Base_Type is tagged null record;
  type Base_Access is limited private;
  procedure Something
       (Obj : in out Base_Type; 
        Value : Base_Access);
private
  type Base_Access is access Base_Type;
  package My_Params is new Params(Base_Type);
end Base;  

package body Base
  –- declare any necessary operations of Base_Access here that way you only need 
  -- one body 
procedure Something
       (Obj : in out Base_Type; 
        Value : Base_Access)
  is begin null; end Something;
end Base;

I’ve used a mindset of you are going to be maintaining lists, databases or whatever of Base_Type, and would want Base_Type to be derived from Controlled or Limited_Controlled.  If you do need both Base_Type to be tagged, fine.  You will find that the two package model works fine if the classes, as such, are disjoint. But in Ada I have found that two tagged types in the same package eventually lead to madness.  If you have M (say 3) flavors of one type, and N (say 4) of the other, now you have M times N  (twelve_ sets of derived operations that can exist.  Adding another derivation will always break something.  Having the types declared in separate packages allows you to stay sane while trying to maintain the rats nest.  I’ve done the M plus N style with window managers where a dozen deep in one dimension (window manager) and six in another (program logic)  was version 1.0...

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21  8:44     ` Dmitry A. Kazakov
  2017-05-21 12:19       ` J-P. Rosen
@ 2017-05-21 20:06       ` Jere
  2017-05-21 21:07         ` Dmitry A. Kazakov
  2017-05-22 21:17         ` Randy Brukardt
  1 sibling, 2 replies; 42+ messages in thread
From: Jere @ 2017-05-21 20:06 UTC (permalink / raw)


On Sunday, May 21, 2017 at 4:44:27 AM UTC-4, Dmitry A. Kazakov wrote:
> On 2017-05-21 00:51, Jere wrote:
> > On Saturday, May 20, 2017 at 4:32:07 PM UTC-4, Dmitry A. Kazakov wrote:
> >> On 2017-05-20 19:33, Jere wrote:
> > I do know that C++ supports hiding of functions by making them private
> > in the extending class.
> 
> No. That is not possible in C++ either. A public method cannot be made 
> private.
> 
> In general from the OO point of view, a method cannot be removed because 
> it is a property of the class and not of an individual type. It is the 
> contract of the class to have a method Foo. All instances of the class 
> must have this method. If they don't they are not instances of. Period.
> 
> [To support method disallowing the language must support ad-hoc 
> superclasses, so that one could split an original class into parts to 
> chip the undesired operation away from one part and put the new type in 
> that part instead of the whole original class.]
> 
The language supports making them private in the context of the
extending classes.  Take for example:

class Base{
public:
   class Base_Param{};

   void Something(Base_Param Obj){}

};

class Derived : public Base {
private:

   void Something(Base_Param Obj); 
};

class MoreDerived : public Derived{};

The following will not compile:
void run_test(){
   Base::Base_Param b;
   Derived d;

   d.Something(b);
}

nor will
void run_test(){
   Base::Base_Param b;
   MoreDerived m;

   m.Something(b);
}

both will fail with the error: "Something" is a private member of Derived

I'm not saying it is the right design, but it is possible.  You can
always get around it by casting down to type Base (where the function
is public), but that is an explicit action that takes intent.  A 
user just creating a type can't use the function out of the box
because, as the error indicates, it is private for Derived (and
for MoreDerived by extension).

> > My real issue is with how the constructors for the tagged type in
> > the library are done.  I want my derived type to work with the
> > constructors defined in the library, which means it has to extend
> > one of the types defined in the library itself.  But I don't want
> > clients to extend my class and use the inherited constructors from
> > the base class because they'll break my extended class.
> 
> These are not constructors proper. Maybe you meant "constructing 
> function". There is a huge difference.
> 
> Anyway a constructing function being a primitive operation must work, 
> exactly because this is an primitive operation which gets overridden. So 
> works a constructor proper which is not an operation and cannot be 
> called explicitly and when invoked, then implicitly always with its own 
> type.
> 
> What you have is neither, it is probably an operation to initialize a 
> part of the object. Such things are usually made private [to be used in 
> a public constructing function].
> 
> [Yes it is a huge problem for library designers that Ada does not have 
> constructors. Alas, there is no desire to fix that]

You're right, they are not proper constructors.  I haven't found 
anything in Ada yet that gives me that.  At best they are 
initializers.

> > I really don't like doing this.  I don't like using
> > access types for one.  It's also doesn't feel like
> > a very clean way because you have to do something
> > out of the ordinary just to use the class like it was
> > meant to be.
> 
> Aggregation + delegation is a decent thing.
> 
> If you used anonymous access you would reduce dangers of pointers to zero.
> 
Definitely.  I am also worried about someone copying the access
value and holding onto it past the lifetime of the object. I try
to avoid Access types when I can.  I wish there was someway to
actually pass a limited type as a function return that didn't
involve build in place that can initialize.  I just want to be
able to return the limited object out temporarily to access it:

Derived.Get_Base.Some_Procedure

but not allow initialization when I don't intend the function
to do that:

Temp : Base := Derived.Get_Base;  -- didn't really want to allow

As it stands the only option I came up with is something 
kludgy like:

type Derived_Public is tagged limited record
   Parent : Base_Type;
end record;

-- This is the workhorse type
type Derived is new Derived_Public with private;

-- This type is purely for constructor like procedures
type Derived_With_Constructors is 
   new Derived with private;

procedure Constructing_Procedure
   (Obj : in out Derived_With_Constructors);
   
Then people extending it just have to do:

   type More_Derived is new Derived with private;
private
   type More_Derived is new Derived_With_Constructors 
   with null record;

That way, extenders don't publicly provide the Constructor
procedures, but have access to them privately.  Additionally,
I get the Base type via composition so it's procedures won't
stomp on Derived types and I can still use it in the library.

There's probably a better way, but that is what I came up
with.  I don't like it though.

> > The actual use case is Gnoga.  All of the constructors
> > (the Create procedures) require parent to be of type
> > Gnoga.Gui.Base.Base_Type'Class, but I really want my
> > Dialog_Type constructor to only accept parents of type
> > Gnoga.Gui.Window.Window_Type'Class.  But it also has
> > to publicly extend Gnoga.Gui.Base.Base_Type
> > (or I use Gnoga.Gui.View.View_Base_Type) so that
> > other controls can create themselves in it.  This
> > opens my type and types that extend it to being
> > thrashed by calls to Create_From_HTML and so on.
> > Similar to your suggestion, I can override them and
> > raise an exception...it just feels clunky.
> 
> Believe other methods I know and have tried, e.g. involving generics, 
> are far worse.
That's been my experience as well.

 
> > I was just hoping for something better from a static checking
> > perspective.  There was a discussion in the Gnoga mailing
> > list if you are wanting more concrete examples.  I was just
> > simplifying it for here to see if there was a language
> > defined way to get what I needed statically.  It sounds like
> > there isn't.
> 
> GUI is one of classic examples where multiple dispatch is required. It 
> is a fact of reality which cannot be worked around without compromising 
> something (no pun intended (:-)).
> 
Thanks for the responses!


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21 18:14 ` Robert Eachus
@ 2017-05-21 20:21   ` Jere
  2017-05-21 21:09     ` Jeffrey R. Carter
  2017-05-21 21:20     ` Dmitry A. Kazakov
  0 siblings, 2 replies; 42+ messages in thread
From: Jere @ 2017-05-21 20:21 UTC (permalink / raw)


On Sunday, May 21, 2017 at 2:14:23 PM UTC-4, Robert Eachus wrote:
> On Saturday, May 20, 2017 at 1:33:27 PM UTC-4, Jere wrote:
> > I tried to whittle this down to a small example, so forgive 
> > the uselessness of the example itself.  I'm extending a 
> > library with some of my own components and I want (if possible) 
> > to allow my components to interact with the other library 
> > components as seamlessly as possible.
> > 
> > Say a library provides a tagged type with the following procedure:
> > 
> > Base.ads
> > *************************************************
> > package Base is
> >    
> >    type Base_Param is tagged null record;
> >    
> >    type Base_Type is tagged null record;
> >    
> >    procedure Something
> >       (Obj : in out Base_Type; 
> >        Value : Base_Param'Class) 
> >    is null;
> >    
> > end Base;
> > 
> > *************************************************
> ...
> I think that the problem you are dealing with is the you 
> started with one package and have never let go of that 
> model.  You have two very different access patterns in 
> mind (not access in the Ada sense).  So you need two 
> packages to declare them.  Is there any reason to allow 
> your clients to do anything with Base_Param other than 
> pass it to subroutines you provide?  I think not.  I’m 
> also going to avoid games like the Taft amendment,  
> Use it if you want to.

Sorry, that was just an example.  The actual use case has 
them in separate packages, but the problem is the same:

1. I want my type to be usable in the 3rd party library, 
   so I need to extend a type from it or provide access
   to an internal parameter of one of its types.
2. I don't want to provide some of the library type's
   public procedures as they can mess up my derived type
   if called.  Per Dmitry's suggestion, I can provide
   runtime safety, but I was looking for static safety.

At the moment I am leaning using an encapsulating type
that passes back an access to an internal component
so I can still interface to the library.  I just don't
like using access types if I can avoid them.

So something like:

   type My_Type is tagged limited private;
   function Get_Libaray_Component
      (Obj : in out My_Type)
      return not null access Library_Type;
private
   type My_Type is new Other_Library_Type with record
      Base : aliased Library_Type;
   end record;

Then I can call:
Library.Some_Library_Function(My_Var.Get_Library_Component.all);

But none of Other_Library_Type's procedures can be publicly 
called on my extended type, breaking it.

Note that the library I am interfacing with already exists
and is not mine.  I don't want to modify it or else any
code I augment it with won't be usable to others without
them modding their copies as well.


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21 20:06       ` Jere
@ 2017-05-21 21:07         ` Dmitry A. Kazakov
  2017-05-21 22:28           ` Jere
  2017-05-22 13:43           ` AdaMagica
  2017-05-22 21:17         ` Randy Brukardt
  1 sibling, 2 replies; 42+ messages in thread
From: Dmitry A. Kazakov @ 2017-05-21 21:07 UTC (permalink / raw)


On 2017-05-21 22:06, Jere wrote:
> On Sunday, May 21, 2017 at 4:44:27 AM UTC-4, Dmitry A. Kazakov wrote:
>> On 2017-05-21 00:51, Jere wrote:
>>> On Saturday, May 20, 2017 at 4:32:07 PM UTC-4, Dmitry A. Kazakov wrote:
>>>> On 2017-05-20 19:33, Jere wrote:
>>> I do know that C++ supports hiding of functions by making them private
>>> in the extending class.
>>
>> No. That is not possible in C++ either. A public method cannot be made
>> private.
>>
>> In general from the OO point of view, a method cannot be removed because
>> it is a property of the class and not of an individual type. It is the
>> contract of the class to have a method Foo. All instances of the class
>> must have this method. If they don't they are not instances of. Period.
>>
>> [To support method disallowing the language must support ad-hoc
>> superclasses, so that one could split an original class into parts to
>> chip the undesired operation away from one part and put the new type in
>> that part instead of the whole original class.]
>>
> The language supports making them private in the context of the
> extending classes.  Take for example:
> 
> class Base{
> public:
>     class Base_Param{};
> 
>     void Something(Base_Param Obj){}

Something is not a method here. If you make it a method [= Ada's 
primitive operation]:

    virtual void Something (Base_Param Obj);

then your code will stop compiling.

In Ada a non-primitive operation could be disallowed by declaring it 
abstract, just the same.

An Ada example corresponding to yours is this:

    package Base is
       type Base_Type is null record;
       procedure Something (X : in out Base_Type);
    end Base;

    package Derived is
       type Derived_Type is new Base_Type;
       procedure Something (X : in out Derived_Type) is abstract;
    end Derived;

    X : Base_Type;
    Y : Derived_Type;
begin
    Something (X);
    Something (Y); -- This won't compile

> You're right, they are not proper constructors.  I haven't found
> anything in Ada yet that gives me that.  At best they are
> initializers.
> 
>>> I really don't like doing this.  I don't like using
>>> access types for one.  It's also doesn't feel like
>>> a very clean way because you have to do something
>>> out of the ordinary just to use the class like it was
>>> meant to be.
>>
>> Aggregation + delegation is a decent thing.
>>
>> If you used anonymous access you would reduce dangers of pointers to zero.
>>
> Definitely.  I am also worried about someone copying the access
> value and holding onto it past the lifetime of the object.

Anonymous access types are difficult to copy. Accessibility rules were 
made to prevent any unsafe copying. So you will have to break them by 
doing X.all'Unchecked_Access.

> Temp : Base := Derived.Get_Base;  -- didn't really want to allow

This is illegal. It must be either

    Copy : Base := Derived.Get_Base.all;

or

    Reference : Base renames Derived.Get_Base.all;

Both are safe, yet have a very different semantics.

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


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21 20:21   ` Jere
@ 2017-05-21 21:09     ` Jeffrey R. Carter
  2017-05-21 22:46       ` Jere
  2017-05-21 21:20     ` Dmitry A. Kazakov
  1 sibling, 1 reply; 42+ messages in thread
From: Jeffrey R. Carter @ 2017-05-21 21:09 UTC (permalink / raw)


On 05/21/2017 10:21 PM, Jere wrote:
>
> I just don't
> like using access types if I can avoid them.

Of course you can avoid them.

> So something like:
>
>    type My_Type is tagged limited private;
>    function Get_Libaray_Component
>       (Obj : in out My_Type)
>       return not null access Library_Type;
> private
>    type My_Type is new Other_Library_Type with record
>       Base : aliased Library_Type;
>    end record;

There are a finite number of operations defined for Library_Type, and, as you 
said, a smaller number that make sense for your abstraction. So you simply 
define equivalent operations for My_Type that call the appropriate operations 
for Library_Type with the Base component. No access types, simple, safe, and clear.

-- 
Jeff Carter
"I soiled my armor, I was so scared."
Monty Python & the Holy Grail
71


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21 20:21   ` Jere
  2017-05-21 21:09     ` Jeffrey R. Carter
@ 2017-05-21 21:20     ` Dmitry A. Kazakov
  2017-05-21 21:45       ` Jere
  1 sibling, 1 reply; 42+ messages in thread
From: Dmitry A. Kazakov @ 2017-05-21 21:20 UTC (permalink / raw)


On 2017-05-21 22:21, Jere wrote:

> The actual use case has
> them in separate packages, but the problem is the same:

No. Robert meant that when you declare a subprogram in a separate 
package [more precisely after the type's freezing point] it will not 
become a primitive operation. A non-primitive operation is simply not 
inherited and if not visible, is gone. Being not inherited is a very 
important point, it will be rejected for derived types even if visible. 
Consider this:

    package Base is
       type Base_Type is tagged null record;
    end Base;

    package Base_Something is
       procedure Something (X : in out Base_Type; Y : Integer) is null;
    end Base_Something;

    package Derived is
       type Derived_Type is new Base_Type with null record;
    end Derived;

    package Derived_Something is
       procedure Something (X : in out Derived_Type; Y : String) is null;
    end Derived_Something;

    use Base, Derived, Base_Something, Derived_Something;
    X : Base_Type;
    Y : Derived_Type;
begin
    Something (X, 1);   -- OK
    Something (Y, 2);   -- Type error!
    Something (Y, "2"); -- OK

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

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21 21:20     ` Dmitry A. Kazakov
@ 2017-05-21 21:45       ` Jere
  0 siblings, 0 replies; 42+ messages in thread
From: Jere @ 2017-05-21 21:45 UTC (permalink / raw)


On Sunday, May 21, 2017 at 5:20:36 PM UTC-4, Dmitry A. Kazakov wrote:
> On 2017-05-21 22:21, Jere wrote:
> 
> > The actual use case has
> > them in separate packages, but the problem is the same:
> 
> No. Robert meant that when you declare a subprogram in a separate 
> package [more precisely after the type's freezing point] it will not 
> become a primitive operation. A non-primitive operation is simply not 
> inherited and if not visible, is gone. Being not inherited is a very 
> important point, it will be rejected for derived types even if visible. 
> Consider this:
> 
>     package Base is
>        type Base_Type is tagged null record;
>     end Base;
> 
>     package Base_Something is
>        procedure Something (X : in out Base_Type; Y : Integer) is null;
>     end Base_Something;
> 
>     package Derived is
>        type Derived_Type is new Base_Type with null record;
>     end Derived;
> 
>     package Derived_Something is
>        procedure Something (X : in out Derived_Type; Y : String) is null;
>     end Derived_Something;
> 
>     use Base, Derived, Base_Something, Derived_Something;
>     X : Base_Type;
>     Y : Derived_Type;
> begin
>     Something (X, 1);   -- OK
>     Something (Y, 2);   -- Type error!
>     Something (Y, "2"); -- OK
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

Yes, but in the current case, Base_Type is already 
defined in a library with the procedures in 
the same package as the type.  However, this is a good 
point for when I make my own types.

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21 21:07         ` Dmitry A. Kazakov
@ 2017-05-21 22:28           ` Jere
  2017-05-22  8:52             ` Dmitry A. Kazakov
  2017-05-22 13:43           ` AdaMagica
  1 sibling, 1 reply; 42+ messages in thread
From: Jere @ 2017-05-21 22:28 UTC (permalink / raw)


On Sunday, May 21, 2017 at 5:07:13 PM UTC-4, Dmitry A. Kazakov wrote:
> On 2017-05-21 22:06, Jere wrote:
> > On Sunday, May 21, 2017 at 4:44:27 AM UTC-4, Dmitry A. Kazakov wrote:
> >> On 2017-05-21 00:51, Jere wrote:
> >>> On Saturday, May 20, 2017 at 4:32:07 PM UTC-4, Dmitry A. Kazakov wrote:
> >>>> On 2017-05-20 19:33, Jere wrote:
> >>> I do know that C++ supports hiding of functions by making them private
> >>> in the extending class.
> >>
> >> No. That is not possible in C++ either. A public method cannot be made
> >> private.
> >>
> >> In general from the OO point of view, a method cannot be removed because
> >> it is a property of the class and not of an individual type. It is the
> >> contract of the class to have a method Foo. All instances of the class
> >> must have this method. If they don't they are not instances of. Period.
> >>
> >> [To support method disallowing the language must support ad-hoc
> >> superclasses, so that one could split an original class into parts to
> >> chip the undesired operation away from one part and put the new type in
> >> that part instead of the whole original class.]
> >>
> > The language supports making them private in the context of the
> > extending classes.  Take for example:
> > 
> > class Base{
> > public:
> >     class Base_Param{};
> > 
> >     void Something(Base_Param Obj){}
> 
> Something is not a method here. If you make it a method [= Ada's 
> primitive operation]:
> 
>     virtual void Something (Base_Param Obj);
> 
> then your code will stop compiling.

Sort of.  If you change the code to:

class Base{
public:
   class Base_Param{};

   virtual void Something(Base_Param Obj){}

};

class Derived : public Base {
private:

   void Something(Base_Param Obj){
      /*Do something Safe here*/
   }
};

class MoreDerived : public Derived{};

and then

void run_test(){
   Base::Base_Param b;
   MoreDerived m;
   
   m.Something(b);  
   
}

It will correctly fail as Something() is private in the MoreDerived
context.   (ERROR= 'virtual void Derived::Something(Base::Base_Param)'
is private).

However,

void run_test(){
   Base::Base_Param b;
   MoreDerived m;
   
   Base &r = m;
   Base *ptr = &m;
   
   //Dispatching works correctly
   r.Something(b);
   ptr->Something(b);
}

will happily compile.  When you privatize a
virtual method, it needs a body, but it will
still be private when used as a Derived
and MoreDerived type.

You are right that in Ada terms, Something is not
a primitive operation.  C++ doesn't have this requirement
though (I'm guessing they are not equivalent to primitive
operations because of this), so a non virtual method is 
still considered a method (in c++) and can be overriden, it just 
can't dispatch (only virtual functions dispatch in C++).

Sorry if I sound combative, I don't mean to be.  I think
I just am used to different definitions of some terms.
Either way, I get that there is no way to do it in Ada.
I really do appreciate the responses.
 

> An Ada example corresponding to yours is this:
> 
>     package Base is
>        type Base_Type is null record;
>        procedure Something (X : in out Base_Type);
>     end Base;
> 
>     package Derived is
>        type Derived_Type is new Base_Type;
>        procedure Something (X : in out Derived_Type) is abstract;
>     end Derived;
> 
>     X : Base_Type;
>     Y : Derived_Type;
> begin
>     Something (X);
>     Something (Y); -- This won't compile
> 
Yes, I agree, but I don't have control over the base type,
so I am stuck with a tagged type.

> > You're right, they are not proper constructors.  I haven't found
> > anything in Ada yet that gives me that.  At best they are
> > initializers.
> > 
> >>> I really don't like doing this.  I don't like using
> >>> access types for one.  It's also doesn't feel like
> >>> a very clean way because you have to do something
> >>> out of the ordinary just to use the class like it was
> >>> meant to be.
> >>
> >> Aggregation + delegation is a decent thing.
> >>
> >> If you used anonymous access you would reduce dangers of pointers to zero.
> >>
> > Definitely.  I am also worried about someone copying the access
> > value and holding onto it past the lifetime of the object.
> 
> Anonymous access types are difficult to copy. Accessibility rules were 
> made to prevent any unsafe copying. So you will have to break them by 
> doing X.all'Unchecked_Access.
> 
If Get_Access is returning not null access Base.Base_Type, what
prevents someone from doing:

type My_Base_Access is access all Base.Base_Type;

Ptr : My_Base_Access;

and then

Ptr := Some_Variable.Get_Access;

I know you said anonymous access types are difficult to copy,
but the small example I tried in GNAT GPL 2016 allows such
a copy.  Is this a compiler bug?  If not, I think I misunderstood.


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21 21:09     ` Jeffrey R. Carter
@ 2017-05-21 22:46       ` Jere
  2017-05-22 21:24         ` Jeffrey R. Carter
  0 siblings, 1 reply; 42+ messages in thread
From: Jere @ 2017-05-21 22:46 UTC (permalink / raw)


On Sunday, May 21, 2017 at 5:09:59 PM UTC-4, Jeffrey R. Carter wrote:
> On 05/21/2017 10:21 PM, Jere wrote:
> >
> > I just don't
> > like using access types if I can avoid them.
> 
> Of course you can avoid them.
> 
> > So something like:
> >
> >    type My_Type is tagged limited private;
> >    function Get_Libaray_Component
> >       (Obj : in out My_Type)
> >       return not null access Library_Type;
> > private
> >    type My_Type is new Other_Library_Type with record
> >       Base : aliased Library_Type;
> >    end record;
> 
> There are a finite number of operations defined for Library_Type, and, as you 
> said, a smaller number that make sense for your abstraction. So you simply 
> define equivalent operations for My_Type that call the appropriate operations 
> for Library_Type with the Base component. No access types, simple, safe, and clear.

I'll use a more concrete example here.  I created a modal dialog box type
for Gnoga.  My spec looks like:

with Gnoga.Gui.Window;
with Gnoga.Gui.View;
package Gnoga.Gui.Modal_Dialog is

   type Dialog_Type is tagged limited private;
   type Dialog_Access is access all Dialog_Type;
   type Pointer_To_Dialog_Class is access all Dialog_Type'Class;

   procedure Create
      (Dialog : in out Dialog_Type;
       Parent : in out Gnoga.Gui.Window.Window_Type'Class;
       ID     : in     String := "");

private

   type Dialog_Type is new Gnoga.Gui.View.View_Type with record
      Main_View : Gnoga.Gui.View.View_Access := null;
   end record;

end Gnoga.Gui.Modal_Dialog;

and the body:

with Gnoga.Gui.Window;
with Gnoga.Gui.Base;
with Gnoga.Gui.Element;

package body Gnoga.Gui.Modal_Dialog is

   procedure Create
      (Dialog : in out Dialog_Type;
       Parent : in out Gnoga.Gui.Window.Window_Type'Class;
       ID     : in     String := "")
   is
      use type Gnoga.Gui.View.View_Access;
      Old_View : Gnoga.Gui.Base.Pointer_To_Base_Class := Parent.Get_View;
   begin

      if Dialog.Main_View = null then

         -- Create the Dialog
         Gnoga.Gui.View.View_Type(Dialog).Create
            (Parent => Parent,
             ID     => ID);

         -- Creating a view using a window as a parent sets the view as the
         -- window's main view.  This line sets it back to the original.
         Parent.Set_View(Old_View.all);


         -- Configure the Modal Background
         Dialog.Fill_Parent;
         Dialog.Background_Color("Grey");

         -- Set the default show/hide state
         Dialog.Show(False);

         -- Create the main view of the dialog
         Dialog.Main_View := new Gnoga.Gui.View.View_Type;
         Dialog.Main_View.Dynamic;
         Dialog.Main_View.Create(Dialog);
         Dialog.Main_View.Background_Color("White");
         Dialog.Main_View.Position(Gnoga.Gui.Element.Fixed);

         -- Center the view as a default
         Dialog.Center;

      end if;

   end Create;

end Gnoga.Gui.Modal_Dialog;

At this point, I need a clean way to let a client
add components (Buttons, forms, etc.) to the dialog box.

Adding all the operations to Dialog_Type won't help me
since all the components use a Create procedure that
takes a Gnoga.Gui.Base.Base_Type'Class parent.  I don't
want to publicly expose the extension of Dialog_Type
since procedures like Create_From_HTML and such
will really mess with the Dialog_Type.  

My initial solution was to add:

   function Get_View
      (Dialog : in out Dialog_Type)
       return Gnoga.Gui.View.View_Access is
   begin
      return Dialog.Main_View;
   end Get_View;

which is why you see Main_View declare as an
access type internally (it was originally just
a Gnoga.Gui.View.View_Type before).

I don't like this method and am open to other
options.  Basically, I need something to
pass to the Create procedure for any components
added.

The other option I was tossing around was to
instead add a

procedure Add_Component
   (Dialog : in out Dialog_Type;
    Object : in out Gnoga.Gui.Base.Basetype'Class);

but the problem there is the components still
need to call Create on some parent, and for the
dialog box to work, I think it needs to be
the view in my tagged type.

Thoughts?


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21  9:16       ` Chris Moore
@ 2017-05-21 22:55         ` Jere
  0 siblings, 0 replies; 42+ messages in thread
From: Jere @ 2017-05-21 22:55 UTC (permalink / raw)


On Sunday, May 21, 2017 at 5:16:32 AM UTC-4, Chris Moore wrote:
> On 21/05/2017 01:51, Jere wrote:
> 
> > Or perhaps if Ada supported constructors that were not
> > dispatchable and that were not inherited that might
> > also work.  I would need to think about it a bit
> > to be sure about that though.  Just an off the cuff
> > thought.
> 
> If you put the constructors in child packages then they aren't inherited.

Yes, I agree.  In my case, the base type is already provided and the
constructing procedures are in the same package, so that is what
is causing my initial problem.  I don't have control over the library
unfortunately.


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21 22:28           ` Jere
@ 2017-05-22  8:52             ` Dmitry A. Kazakov
  2017-05-22 13:33               ` AdaMagica
  0 siblings, 1 reply; 42+ messages in thread
From: Dmitry A. Kazakov @ 2017-05-22  8:52 UTC (permalink / raw)


On 22/05/2017 00:28, Jere wrote:

> If Get_Access is returning not null access Base.Base_Type, what
> prevents someone from doing:
> 
> type My_Base_Access is access all Base.Base_Type;
> 
> Ptr : My_Base_Access;
> 
> and then
> 
> Ptr := Some_Variable.Get_Access;
> 
> I know you said anonymous access types are difficult to copy,
> but the small example I tried in GNAT GPL 2016 allows such
> a copy.  Is this a compiler bug?  If not, I think I misunderstood.

You can always defeat accessibility checks this or other way. Why should 
anybody declaring an extra access type? You could also create an 
instance of Unchecked_Deallocation on My_Base_Access and then free a 
stack allocated object...

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


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-22  8:52             ` Dmitry A. Kazakov
@ 2017-05-22 13:33               ` AdaMagica
  0 siblings, 0 replies; 42+ messages in thread
From: AdaMagica @ 2017-05-22 13:33 UTC (permalink / raw)


Am Montag, 22. Mai 2017 10:52:42 UTC+2 schrieb Dmitry A. Kazakov:
> 
> You could also create an
> instance of Unchecked_Deallocation on My_Base_Access and then free a
> stack allocated object...

This is one of many ways to make your program erroneous.

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21 21:07         ` Dmitry A. Kazakov
  2017-05-21 22:28           ` Jere
@ 2017-05-22 13:43           ` AdaMagica
  1 sibling, 0 replies; 42+ messages in thread
From: AdaMagica @ 2017-05-22 13:43 UTC (permalink / raw)


Am Sonntag, 21. Mai 2017 23:07:13 UTC+2 schrieb Dmitry A. Kazakov:
> In Ada a non-primitive operation could be disallowed by declaring it 
> abstract, just the same.
> 
> An Ada example corresponding to yours is this:
> 
>     package Base is
>        type Base_Type is null record;

>        procedure Something (X : in out Base_Type);

This is a primitive operation of Base_Type.

>     end Base;
> 
>     package Derived is
>        type Derived_Type is new Base_Type;

Because of being primitive, it's inherited here - and you can override it.
>        procedure Something (X : in out Derived_Type) is abstract;

The difference is that this follows the Ada83 derivation rules, which are quite different from the Ada95 rules of tagged types.

Nevertheless, operations like Something are called "primitive operations". Also the optional overriding indicators can be used on Ada83 derivation.

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-20 20:32 ` Dmitry A. Kazakov
  2017-05-20 22:51   ` Jere
@ 2017-05-22 21:12   ` Randy Brukardt
  2017-05-23  7:38     ` Dmitry A. Kazakov
  1 sibling, 1 reply; 42+ messages in thread
From: Randy Brukardt @ 2017-05-22 21:12 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:ofq943$14v4$1@gioia.aioe.org...
...
> ----------------------------------
> The actual problem you have is parallel types hierarchies. You want to 
> derive tied instances of Base_Type'Class and Base_Param'Class.
>
>    Base_Type ----- Base_Param
>       |              |
>    Derived_Type -- Derived_Param
>
> This requires
>
> 1. Full multiple dispatch
> 2. Dispatch constrained to certain combinations (parallel hierarchies)
>
> This is not supported in Ada (or in any other OO language I am aware of)

Right. Having investigated this, it seems impossible to support in any 
language that is intended to support LSP (which is the backbone of OOP). The 
basic problem is dispatching. In Ada terms, you have a call:

     Something (Classwide_Obj, Othertype_Obj);

where Classwide_Obj is of Root'Class. Now, the problem is that the other 
(usually untagged) parameter is of the wrong type for the routines that you 
dispatch to.

There are various ways you can fix this dynamically (for instance, as you 
noted, with multiple dispatch), but there is no way to have any static 
typing in these cases. But the entire point of doing a "co-derivation" is to 
get static typing, so you're doing a lot of work for very little gain.

Co-derivation probably could be made to work for untagged types (as they 
don't have dispatching to worry about), but it's unclear that enough benefit 
would arise.

Anyway, this is an agenda item for the ARG, but unless someone has an idea 
that hasn't been considered to date it isn't going anywhere.

                         Randy.


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21 20:06       ` Jere
  2017-05-21 21:07         ` Dmitry A. Kazakov
@ 2017-05-22 21:17         ` Randy Brukardt
  2017-05-25  4:06           ` Jere
  1 sibling, 1 reply; 42+ messages in thread
From: Randy Brukardt @ 2017-05-22 21:17 UTC (permalink / raw)


"Jere" <jhb.chat@gmail.com> wrote in message 
news:9cdf04e6-123e-4bd9-b466-77aad00d61bb@googlegroups.com...
...
> Definitely.  I am also worried about someone copying the access
> value and holding onto it past the lifetime of the object. I try
> to avoid Access types when I can.  I wish there was someway to
> actually pass a limited type as a function return that didn't
> involve build in place that can initialize.  I just want to be
> able to return the limited object out temporarily to access it:

That's what generalized references are for. See 4.1.5 in the RM.

                        Randy.


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-21 22:46       ` Jere
@ 2017-05-22 21:24         ` Jeffrey R. Carter
  2017-05-25  3:45           ` Jere
  0 siblings, 1 reply; 42+ messages in thread
From: Jeffrey R. Carter @ 2017-05-22 21:24 UTC (permalink / raw)


On 05/22/2017 12:46 AM, Jere wrote:
>
> I'll use a more concrete example here.  I created a modal dialog box type
> for Gnoga.  My spec looks like:

I gathered from your other posts that you were talking about this.

> with Gnoga.Gui.Window;
> with Gnoga.Gui.View;
> package Gnoga.Gui.Modal_Dialog is
>
>    type Dialog_Type is tagged limited private;
>    type Dialog_Access is access all Dialog_Type;
>    type Pointer_To_Dialog_Class is access all Dialog_Type'Class;
>
>    procedure Create
>       (Dialog : in out Dialog_Type;
>        Parent : in out Gnoga.Gui.Window.Window_Type'Class;
>        ID     : in     String := "");
>
> private
>
>    type Dialog_Type is new Gnoga.Gui.View.View_Type with record
>       Main_View : Gnoga.Gui.View.View_Access := null;
>    end record;
>
> end Gnoga.Gui.Modal_Dialog;

I don't see any reason for the access type in the full view. It could probably 
just be View_Type, but I think it should really be 
Gnoga.Gui.Element.Form.Form_Type, as I'll explain later.

> At this point, I need a clean way to let a client
> add components (Buttons, forms, etc.) to the dialog box.
>
> Adding all the operations to Dialog_Type won't help me
> since all the components use a Create procedure that
> takes a Gnoga.Gui.Base.Base_Type'Class parent.  I don't
> want to publicly expose the extension of Dialog_Type
> since procedures like Create_From_HTML and such
> will really mess with the Dialog_Type.

Right. You need to be able control what the client can do with the dialog, so 
using a View_Access and providing it to the client is a Bad Idea.

> The other option I was tossing around was to
> instead add a
>
> procedure Add_Component
>    (Dialog : in out Dialog_Type;
>     Object : in out Gnoga.Gui.Base.Basetype'Class);

Mostly what people need in such a dialog are buttons and text widgets 
(Text_Type). The former are from Gnoga.Gui.Element.Common and the latter from 
Gnoga.Gui.Element.Form, which is why I think your inner view should be a form. 
You can create buttons with a form as the parent, but you can't create a text 
widget without a form. (This seems wrong to me, but that's how Gnoga is. I've 
often used form widgets but never needed the form functionality.) So as a first 
cut you could only have

procedure Create_Button (Button  : in out Button_Type;
                          Content : in     String := "";
                          ID      : in     String := "");

procedure Create_Text (Text  : in out Text_Type;
                        Size  : in     Positive := 20;
                        Value : in     String   := "";
                        Name  : in     String   := "";
                        ID    : in     String   := "";
                        Label : in     String   := "");

and you'd probably cover 95% of uses. Internally, you'd call Button.Create with 
your form as Parent, and Text.Create with your form as Form. Your client can 
then attach an on-click handler to the buttons and call Value for the text 
widgets. If Label is not null, you would create a label to go with Text with 
Label as its Content.

You might also want to provide a Create_Div that the client could put a bunch of 
text into, and a New_Line for putting things on different lines. So you could 
have dialogs like

+----------------------------------------+
|  You have to authenticate to do that   |
|            __________________________  |
| Password: |__________________________| |
|                                        |
| [ OK ]  [ Cancel ]                     |
+----------------------------------------+

Where the 1st line is a Div, the 2nd a Text_Type (or Password_Type; see below) 
with a label, and the 3rd 2 buttons.

There are a bunch of specialized children of Text_Type, all with the same 
parameter profile for their Create procedures, so you could replace Text_Type 
with Text_Type'Class in Create_Text, and your client would get all of them. This 
would allow a Password_Type as mentioned above.

Most of the things in Element.Common are descended from Base_Type, which doesn't 
have a Create, so you'd have to add others you think useful individually.

Many things in Form are descended from Form_Element_Type, so you could provide

type Kind_ID is (Button,   Checkbox, Color,    Date,  Datetime, Datetime_Local,
                  Email,    File,     Hidden,   Image, Month,    Number,
                  Password, Radio,    Range_ID, Reset, Search,   Submit,
                  Tel,      Text,     Time,     Url,   Week);

procedure Create_Form_Item (Item      : in out Form_Element_Type'Class;
                             Item_Kind : in     Kind_ID;
                             Value     : in     String := "";
                             Name      : in     String := "";
                             ID        : in     String := "");

which would call Create_Element with an appropriate String for Input_Type.

So you'd have to write a number of these Create operations, but there wouldn't 
be too many of them. I'd want to limit what kinds of things a client can put in 
a dialog, and maybe how many of them, too.

But probably if you use Gnoga.Gui.Plugin.jQueryUI.Widget.Dialog_Type with Modal 
=> True you can save yourself the effort.

-- 
Jeff Carter
"We call your door-opening request a silly thing."
Monty Python & the Holy Grail
17


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-22 21:12   ` Randy Brukardt
@ 2017-05-23  7:38     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 42+ messages in thread
From: Dmitry A. Kazakov @ 2017-05-23  7:38 UTC (permalink / raw)


On 22/05/2017 23:12, Randy Brukardt wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:ofq943$14v4$1@gioia.aioe.org...
> ...
>> ----------------------------------
>> The actual problem you have is parallel types hierarchies. You want to
>> derive tied instances of Base_Type'Class and Base_Param'Class.
>>
>>     Base_Type ----- Base_Param
>>        |              |
>>     Derived_Type -- Derived_Param
>>
>> This requires
>>
>> 1. Full multiple dispatch
>> 2. Dispatch constrained to certain combinations (parallel hierarchies)
>>
>> This is not supported in Ada (or in any other OO language I am aware of)
> 
> Right. Having investigated this, it seems impossible to support in any
> language that is intended to support LSP (which is the backbone of OOP). The
> basic problem is dispatching. In Ada terms, you have a call:
> 
>       Something (Classwide_Obj, Othertype_Obj);
> 
> where Classwide_Obj is of Root'Class. Now, the problem is that the other
> (usually untagged) parameter is of the wrong type for the routines that you
> dispatch to.

A rough idea would be to have classes of tuples. The tag is then 
assigned to the tuple of types: (Base_Type, Base_Param) rather than to 
an individual type. The call

    X : Base_Type'Class :=
    Y : Base_Param :=

    Something (X, Y);

would be statically illegal because (X, Y) is not in the class

    (Base_Type x Base_Param)'Class

but in

    Base_Type'Class x Base_Type

Also illegal would be

    X : Derived_Type :=
    Y : Base_Param :=

    Something (X, Y);

Because (Derived_Type, Base_Param) is not in the class either.

One should invent something to flatten tuples and means to produce 
class-wide tuples implicitly and explicitly.

This model is fully statically checkable and supports dispatch.

> There are various ways you can fix this dynamically (for instance, as you
> noted, with multiple dispatch), but there is no way to have any static
> typing in these cases.

Right, but that is rather uninteresting from Ada's and SPARK POV.

> But the entire point of doing a "co-derivation" is to
> get static typing, so you're doing a lot of work for very little gain.

Exactly.

> Co-derivation probably could be made to work for untagged types (as they
> don't have dispatching to worry about), but it's unclear that enough benefit
> would arise.

Right, but that works exactly because there is no class-wide objects of 
untagged types.

> Anyway, this is an agenda item for the ARG, but unless someone has an idea
> that hasn't been considered to date it isn't going anywhere.

Very good.

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

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-22 21:24         ` Jeffrey R. Carter
@ 2017-05-25  3:45           ` Jere
  0 siblings, 0 replies; 42+ messages in thread
From: Jere @ 2017-05-25  3:45 UTC (permalink / raw)


On Monday, May 22, 2017 at 5:24:11 PM UTC-4, Jeffrey R. Carter wrote:
> On 05/22/2017 12:46 AM, Jere wrote:
> > with Gnoga.Gui.Window;
> > with Gnoga.Gui.View;
> > package Gnoga.Gui.Modal_Dialog is
> >
> >    type Dialog_Type is tagged limited private;
> >    type Dialog_Access is access all Dialog_Type;
> >    type Pointer_To_Dialog_Class is access all Dialog_Type'Class;
> >
> >    procedure Create
> >       (Dialog : in out Dialog_Type;
> >        Parent : in out Gnoga.Gui.Window.Window_Type'Class;
> >        ID     : in     String := "");
> >
> > private
> >
> >    type Dialog_Type is new Gnoga.Gui.View.View_Type with record
> >       Main_View : Gnoga.Gui.View.View_Access := null;
> >    end record;
> >
> > end Gnoga.Gui.Modal_Dialog;
> 
> I don't see any reason for the access type in the full view. It could probably 
> just be View_Type, but I think it should really be 
> Gnoga.Gui.Element.Form.Form_Type, as I'll explain later.
In my original attempt, I ended up passing back an access
value via a function.  In order to avoid having to pass
an Unchecked_Access from an aliased parameter, I went
full access type under the hood.  Based on your later example,
I scrapped that.


> 
> > The other option I was tossing around was to
> > instead add a
> >
> > procedure Add_Component
> >    (Dialog : in out Dialog_Type;
> >     Object : in out Gnoga.Gui.Base.Basetype'Class);
> 
> Mostly what people need in such a dialog are buttons and text widgets 
> (Text_Type). The former are from Gnoga.Gui.Element.Common and the latter from 
> Gnoga.Gui.Element.Form, which is why I think your inner view should be a form. 
> You can create buttons with a form as the parent, but you can't create a text 
> widget without a form. (This seems wrong to me, but that's how Gnoga is. I've 
> often used form widgets but never needed the form functionality.) So as a first 
> cut you could only have
> 
> procedure Create_Button (Button  : in out Button_Type;
>                           Content : in     String := "";
>                           ID      : in     String := "");
> 
> procedure Create_Text (Text  : in out Text_Type;
>                         Size  : in     Positive := 20;
>                         Value : in     String   := "";
>                         Name  : in     String   := "";
>                         ID    : in     String   := "";
>                         Label : in     String   := "");
> 
> and you'd probably cover 95% of uses. Internally, you'd call Button.Create with 
> your form as Parent, and Text.Create with your form as Form. Your client can 
> then attach an on-click handler to the buttons and call Value for the text 
> widgets. If Label is not null, you would create a label to go with Text with 
> Label as its Content.
> 
> You might also want to provide a Create_Div that the client could put a bunch of 
> text into, and a New_Line for putting things on different lines. So you could 
> have dialogs like
> 
> <snipped>
>
> So you'd have to write a number of these Create operations, but there wouldn't 
> be too many of them. I'd want to limit what kinds of things a client can put in 
> a dialog, and maybe how many of them, too.
I get that, and I like the idea.  I'm not sure I agree with the
limitations suggested.  I don't see why doing what you suggest
for just a view type wouldn't cover all cases and still limit
access to the internals of the tagged type.  I ended up
thinking on this and playing around with it.  I scrapped the
internal access type, and I then added a new procedure:

procedure Create_Main_View
  (Dialog : in out Dialog_Type;
   View   : in out Gnoga.Gui.View.View_Type:
   ID     : in     String := "");

That way, they can setup whatever view with
whatever components they want and my Dialog_Type
just supplies the Modal operations to use it.
If they have a new custom type already defined,
then they can just create an intermediate view
to hold it and pass that in.  I'm still playing
with it as my kids allow me time, but so far
it has most of my bases covered.  I think
my only snag so far has to do with the
mechanics of width and height parameters.
I'll probably fire up a question in the gnoga
list for that since it is more HTML/Gnoga
based in nature.  I know it isn't exactly
what you suggested, but hopefully it is 
still a good way to go.  I don't want to
fully limit what types can be used in the
dialog because someone might want to do
something complex like a portable file
chooser dialog (for standalone apps).
In cases like those, I would want to be
able to at least help support custom
widget types.  Maybe I am overthinking it
though.

> 
> But probably if you use Gnoga.Gui.Plugin.jQueryUI.Widget.Dialog_Type with Modal 
> => True you can save yourself the effort.

I didn't realize they had added that.  I'll play with it some to 
see how it works out.  I'm still playing with my handmade one
if only to learn more, but this is a good point and I should
experiment with the jquery one.

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-22 21:17         ` Randy Brukardt
@ 2017-05-25  4:06           ` Jere
  2017-05-25 19:39             ` Randy Brukardt
  0 siblings, 1 reply; 42+ messages in thread
From: Jere @ 2017-05-25  4:06 UTC (permalink / raw)


On Monday, May 22, 2017 at 5:17:47 PM UTC-4, Randy Brukardt wrote:
> "Jere" wrote in message 
> ...
> > Definitely.  I am also worried about someone copying the access
> > value and holding onto it past the lifetime of the object. I try
> > to avoid Access types when I can.  I wish there was someway to
> > actually pass a limited type as a function return that didn't
> > involve build in place that can initialize.  I just want to be
> > able to return the limited object out temporarily to access it:
> 
> That's what generalized references are for. See 4.1.5 in the RM.
> 
>                         Randy.

That's a good point. I did end up playing with this and getting
an example working.  After going through Jeffrey's example, I
ended up scrapping the access types altogether, but I do need
to learn to leverage this more in cases where access types 
are necessary.

Side question:

If I have a type (Gnoga'ish example):

type View_Base_Type is new Element_Type with private; --taggeed
type View_Type is new View_Base_Type with private;
procedure Create
  (View   : in out View_Type;
   Parent : in out Base_Type'Class;
   ID     : in     String := "");

-- Excuse any typos, this is hand typed code

And then I extend it:

   type My_Type is new View_Base_Type with private;
   procedure Create
     (Obj    : in out My_Type;
      Parent : in out Window_Type'Class; -- derived from Base_Type'Class
      ID     : in     String := "");

private

   type My_Type is new View_Type with null record;

Sometimes if I subtype or extend My_Type, I get the ambiguous
calls to Create issue due to the inherited Create function
from View_Type.

Since the extension of View_Type was private (I publicly 
extended View_Base_Type), should there still be an 
ambiguity between the Create procedures?  My new
one shouldn't be an override and since the extension
to View_Type is private, it shouldn't be callable
(I'm not in a child package, this would be just
some other unrelated package subtyping or extending
My_Type).  I get that before my extension was public
so making the Create procedure private wasn't an
option, but I had hoped with the full view being
private it wouldn't cause the ambiguity.  I realize
in code that could view the private section the issue
might still be there, but this wouldn't be a package
that can see the private section.


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-25  4:06           ` Jere
@ 2017-05-25 19:39             ` Randy Brukardt
  2017-05-25 22:53               ` Jere
  0 siblings, 1 reply; 42+ messages in thread
From: Randy Brukardt @ 2017-05-25 19:39 UTC (permalink / raw)


Your probably having trouble with the appropriaate view of My_Type. The full 
type of My_Type has both versions of Create (of course), as it inherits from 
View_Type. If you try to extend somewhere where that full view is visible, 
then that extension too will get both Creates. (That includes in the body 
and in any child packages.)

OTOH, an extension somewhere that only has visibility on the private type, 
you should only get one (visible) Create. (But the other one is still 
inherited, it just can't be called directly.)

I could go into more detail if you need that; it would help to have a full 
compilable example in that case so I can see where everything is declared.

                           Randy.


"Jere" <jhb.chat@gmail.com> wrote in message 
news:e9d5050e-1046-4f8a-92e0-feded33f7a50@googlegroups.com...
> On Monday, May 22, 2017 at 5:17:47 PM UTC-4, Randy Brukardt wrote:
>> "Jere" wrote in message
>> ...
>> > Definitely.  I am also worried about someone copying the access
>> > value and holding onto it past the lifetime of the object. I try
>> > to avoid Access types when I can.  I wish there was someway to
>> > actually pass a limited type as a function return that didn't
>> > involve build in place that can initialize.  I just want to be
>> > able to return the limited object out temporarily to access it:
>>
>> That's what generalized references are for. See 4.1.5 in the RM.
>>
>>                         Randy.
>
> That's a good point. I did end up playing with this and getting
> an example working.  After going through Jeffrey's example, I
> ended up scrapping the access types altogether, but I do need
> to learn to leverage this more in cases where access types
> are necessary.
>
> Side question:
>
> If I have a type (Gnoga'ish example):
>
> type View_Base_Type is new Element_Type with private; --taggeed
> type View_Type is new View_Base_Type with private;
> procedure Create
>  (View   : in out View_Type;
>   Parent : in out Base_Type'Class;
>   ID     : in     String := "");
>
> -- Excuse any typos, this is hand typed code
>
> And then I extend it:
>
>   type My_Type is new View_Base_Type with private;
>   procedure Create
>     (Obj    : in out My_Type;
>      Parent : in out Window_Type'Class; -- derived from Base_Type'Class
>      ID     : in     String := "");
>
> private
>
>   type My_Type is new View_Type with null record;
>
> Sometimes if I subtype or extend My_Type, I get the ambiguous
> calls to Create issue due to the inherited Create function
> from View_Type.
>
> Since the extension of View_Type was private (I publicly
> extended View_Base_Type), should there still be an
> ambiguity between the Create procedures?  My new
> one shouldn't be an override and since the extension
> to View_Type is private, it shouldn't be callable
> (I'm not in a child package, this would be just
> some other unrelated package subtyping or extending
> My_Type).  I get that before my extension was public
> so making the Create procedure private wasn't an
> option, but I had hoped with the full view being
> private it wouldn't cause the ambiguity.  I realize
> in code that could view the private section the issue
> might still be there, but this wouldn't be a package
> that can see the private section. 



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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-25 19:39             ` Randy Brukardt
@ 2017-05-25 22:53               ` Jere
  2017-05-25 22:57                 ` Jere
  2017-05-26 20:46                 ` Randy Brukardt
  0 siblings, 2 replies; 42+ messages in thread
From: Jere @ 2017-05-25 22:53 UTC (permalink / raw)


On Thursday, May 25, 2017 at 3:40:01 PM UTC-4, Randy Brukardt wrote:
> Your probably having trouble with the appropriaate view of My_Type. The full 
> type of My_Type has both versions of Create (of course), as it inherits from 
> View_Type. If you try to extend somewhere where that full view is visible, 
> then that extension too will get both Creates. (That includes in the body 
> and in any child packages.)
> 
> OTOH, an extension somewhere that only has visibility on the private type, 
> you should only get one (visible) Create. (But the other one is still 
> inherited, it just can't be called directly.)
> 
> I could go into more detail if you need that; it would help to have a full 
> compilable example in that case so I can see where everything is declared.
> 
>                            Randy.
> 
> 

This might be a better example.  I have 3 tiers:  Base/Derived/More_Derived

More_Derived publicly inherits off of Base but privately inherits off of
Derived. 

Derived provides a Something procedure and More_Derived provides a Something
procedure but uses a different signature and is not overriding (I double
checked by putting "overriding" with it and noted the compiler error).

More_Derived does not have private view of Derived, but GNAT still says
there is a ambiguity.  I don't see how More_Derived has a private
view of Derived, so I think this is a bug, but I might be missing
something.

main.adb
*******************************************
with Base;
with Derived;
with More_Derived;

procedure Main is
   p : Base.Derived_Param;
   
   subtype My_Type is More_Derived.More_Derived_Type;
   
   m : My_Type;
begin
   m.Something(p);  -- ERROR:  ambiguous call to Something
end Main;
*******************************************


base.ads
*************************************************
package Base is

   type Base_Param is tagged null record;
   type Derived_Param is new Base.Base_Param with null record;

   type Base_Type is tagged null record;

end Base;
*************************************************


derived.ads
*************************************************
with Base;

package Derived is

   type Derived_Type is new Base.Base_Type with null record;

   procedure Something
      (Obj   : in out Derived_Type;
       Value :        Base.Base_Param'Class)
   is null;

end Derived;
*************************************************


more_derived.ads
*************************************************
with Base;
with Derived;

package More_Derived is 
   
   type More_Derived_Type is new Base.Base_Type with private;
   
   procedure Something
      (Obj   : in out More_Derived_Type;
       Value :        Base.Derived_Param'Class)
   is null;
   
private
   
   type More_Derived_Type is new Derived.Derived_Type with null record;
   
end More_Derived;
*************************************************

If I don't use the subtype in main.adb, it compiles fine.

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-25 22:53               ` Jere
@ 2017-05-25 22:57                 ` Jere
  2017-05-26 20:46                 ` Randy Brukardt
  1 sibling, 0 replies; 42+ messages in thread
From: Jere @ 2017-05-25 22:57 UTC (permalink / raw)


On Thursday, May 25, 2017 at 6:53:10 PM UTC-4, Jere wrote:
> On Thursday, May 25, 2017 at 3:40:01 PM UTC-4, Randy Brukardt wrote:
> > Your probably having trouble with the appropriaate view of My_Type. The full 
> > type of My_Type has both versions of Create (of course), as it inherits from 
> > View_Type. If you try to extend somewhere where that full view is visible, 
> > then that extension too will get both Creates. (That includes in the body 
> > and in any child packages.)
> > 
> > OTOH, an extension somewhere that only has visibility on the private type, 
> > you should only get one (visible) Create. (But the other one is still 
> > inherited, it just can't be called directly.)
> > 
> > I could go into more detail if you need that; it would help to have a full 
> > compilable example in that case so I can see where everything is declared.
> > 
> >                            Randy.
> > 
> > 
> 
> This might be a better example.  I have 3 tiers:  Base/Derived/More_Derived
> 
> More_Derived publicly inherits off of Base but privately inherits off of
> Derived. 
> 
> Derived provides a Something procedure and More_Derived provides a Something
> procedure but uses a different signature and is not overriding (I double
> checked by putting "overriding" with it and noted the compiler error).
> 
> More_Derived does not have private view of Derived, but GNAT still says
> there is a ambiguity.  I don't see how More_Derived has a private
> view of Derived, so I think this is a bug, but I might be missing
> something.
> 
>  [snipped]
> 
> If I don't use the subtype in main.adb, it compiles fine.

Forgot to mention it is GNAT GPL 2016.  I don't have FSF working on my 
Win10 machine yet to check.


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-25 22:53               ` Jere
  2017-05-25 22:57                 ` Jere
@ 2017-05-26 20:46                 ` Randy Brukardt
  2017-05-26 22:35                   ` Simon Wright
  2017-05-26 22:58                   ` Jeffrey R. Carter
  1 sibling, 2 replies; 42+ messages in thread
From: Randy Brukardt @ 2017-05-26 20:46 UTC (permalink / raw)


Ah, a subtype. GNAT has (or had?)a bug having to do with making things 
visible because of a subtype declaration (I recall someone else running 
across that and having verified it myself). That's just plain wrong, a 
subtype has no effect on what's visible in a prefixed call (or anywhere else 
for that matter, in particular with "use all type").

You ought to have an ambiguity if you tried to call Something in the body of 
More_Derived, but it should be OK in the main subprogram.

I'd skip the subtype and just use the real name of the type. And possibly 
make a bug report to AdaCore.
You could also use a traditional call (More_Derived.Something (M, P);) which 
would avoid the buggy part of GNAT.

                                        Randy.

"Jere" <jhb.chat@gmail.com> wrote in message 
news:62e326e6-dd15-4546-83dc-b1e423327c23@googlegroups.com...
> On Thursday, May 25, 2017 at 3:40:01 PM UTC-4, Randy Brukardt wrote:
>> Your probably having trouble with the appropriaate view of My_Type. The 
>> full
>> type of My_Type has both versions of Create (of course), as it inherits 
>> from
>> View_Type. If you try to extend somewhere where that full view is 
>> visible,
>> then that extension too will get both Creates. (That includes in the body
>> and in any child packages.)
>>
>> OTOH, an extension somewhere that only has visibility on the private 
>> type,
>> you should only get one (visible) Create. (But the other one is still
>> inherited, it just can't be called directly.)
>>
>> I could go into more detail if you need that; it would help to have a 
>> full
>> compilable example in that case so I can see where everything is 
>> declared.
>>
>>                            Randy.
>>
>>
>
> This might be a better example.  I have 3 tiers: 
> Base/Derived/More_Derived
>
> More_Derived publicly inherits off of Base but privately inherits off of
> Derived.
>
> Derived provides a Something procedure and More_Derived provides a 
> Something
> procedure but uses a different signature and is not overriding (I double
> checked by putting "overriding" with it and noted the compiler error).
>
> More_Derived does not have private view of Derived, but GNAT still says
> there is a ambiguity.  I don't see how More_Derived has a private
> view of Derived, so I think this is a bug, but I might be missing
> something.
>
> main.adb
> *******************************************
> with Base;
> with Derived;
> with More_Derived;
>
> procedure Main is
>   p : Base.Derived_Param;
>
>   subtype My_Type is More_Derived.More_Derived_Type;
>
>   m : My_Type;
> begin
>   m.Something(p);  -- ERROR:  ambiguous call to Something
> end Main;
> *******************************************
>
>
> base.ads
> *************************************************
> package Base is
>
>   type Base_Param is tagged null record;
>   type Derived_Param is new Base.Base_Param with null record;
>
>   type Base_Type is tagged null record;
>
> end Base;
> *************************************************
>
>
> derived.ads
> *************************************************
> with Base;
>
> package Derived is
>
>   type Derived_Type is new Base.Base_Type with null record;
>
>   procedure Something
>      (Obj   : in out Derived_Type;
>       Value :        Base.Base_Param'Class)
>   is null;
>
> end Derived;
> *************************************************
>
>
> more_derived.ads
> *************************************************
> with Base;
> with Derived;
>
> package More_Derived is
>
>   type More_Derived_Type is new Base.Base_Type with private;
>
>   procedure Something
>      (Obj   : in out More_Derived_Type;
>       Value :        Base.Derived_Param'Class)
>   is null;
>
> private
>
>   type More_Derived_Type is new Derived.Derived_Type with null record;
>
> end More_Derived;
> *************************************************
>
> If I don't use the subtype in main.adb, it compiles fine. 


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-26 20:46                 ` Randy Brukardt
@ 2017-05-26 22:35                   ` Simon Wright
  2018-05-20 11:22                     ` Simon Wright
  2017-05-26 22:58                   ` Jeffrey R. Carter
  1 sibling, 1 reply; 42+ messages in thread
From: Simon Wright @ 2017-05-26 22:35 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> Ah, a subtype. GNAT has (or had?)a bug having to do with making things
> visible because of a subtype declaration (I recall someone else
> running across that and having verified it myself). That's just plain
> wrong, a subtype has no effect on what's visible in a prefixed call
> (or anywhere else for that matter, in particular with "use all type").
>
> You ought to have an ambiguity if you tried to call Something in the
> body of More_Derived, but it should be OK in the main subprogram.
>
> I'd skip the subtype and just use the real name of the type. And
> possibly make a bug report to AdaCore.
> You could also use a traditional call (More_Derived.Something (M, P);)
> which would avoid the buggy part of GNAT.

Quite right, Randy (GCC 7.1.0, still; has anyone reported this?)

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-26 20:46                 ` Randy Brukardt
  2017-05-26 22:35                   ` Simon Wright
@ 2017-05-26 22:58                   ` Jeffrey R. Carter
  2017-05-30 21:15                     ` Randy Brukardt
  1 sibling, 1 reply; 42+ messages in thread
From: Jeffrey R. Carter @ 2017-05-26 22:58 UTC (permalink / raw)


On 05/26/2017 10:46 PM, Randy Brukardt wrote:
> Ah, a subtype. GNAT has (or had?)a bug having to do with making things
> visible because of a subtype declaration (I recall someone else running
> across that and having verified it myself). That's just plain wrong, a
> subtype has no effect on what's visible in a prefixed call (or anywhere else
> for that matter, in particular with "use all type").

That was me. I wasn't aware that you had verified it as a compiler error.

-- 
Jeff Carter
"Nobody expects the Spanish Inquisition!"
Monty Python's Flying Circus
22

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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-26 22:58                   ` Jeffrey R. Carter
@ 2017-05-30 21:15                     ` Randy Brukardt
  2017-06-02  1:07                       ` Jere
  0 siblings, 1 reply; 42+ messages in thread
From: Randy Brukardt @ 2017-05-30 21:15 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:ogabnv$9hj$1@dont-email.me...
> On 05/26/2017 10:46 PM, Randy Brukardt wrote:
>> Ah, a subtype. GNAT has (or had?)a bug having to do with making things
>> visible because of a subtype declaration (I recall someone else running
>> across that and having verified it myself). That's just plain wrong, a
>> subtype has no effect on what's visible in a prefixed call (or anywhere 
>> else
>> for that matter, in particular with "use all type").
>
> That was me. I wasn't aware that you had verified it as a compiler error.

I don't recall the details anymore, but I'm pretty sure I discussed that 
with someone at AdaCore. (Either in the context of an ACATS test, or just on 
the side of some other conversation.) And they agreed it was wrong. No idea 
if it formally got reported though.

                                             Randy. 



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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-30 21:15                     ` Randy Brukardt
@ 2017-06-02  1:07                       ` Jere
  2017-06-02  7:31                         ` Dmitry A. Kazakov
                                           ` (2 more replies)
  0 siblings, 3 replies; 42+ messages in thread
From: Jere @ 2017-06-02  1:07 UTC (permalink / raw)


On Tuesday, May 30, 2017 at 5:15:20 PM UTC-4, Randy Brukardt wrote:
> "Jeffrey R. Carter" wrote in message 
> > On 05/26/2017 10:46 PM, Randy Brukardt wrote:
> >> Ah, a subtype. GNAT has (or had?)a bug having to do with making things
> >> visible because of a subtype declaration (I recall someone else running
> >> across that and having verified it myself). That's just plain wrong, a
> >> subtype has no effect on what's visible in a prefixed call (or anywhere 
> >> else
> >> for that matter, in particular with "use all type").
> >
> > That was me. I wasn't aware that you had verified it as a compiler error.
> 
> I don't recall the details anymore, but I'm pretty sure I discussed that 
> with someone at AdaCore. (Either in the context of an ACATS test, or just on 
> the side of some other conversation.) And they agreed it was wrong. No idea 
> if it formally got reported though.
> 
>                                              Randy.

Thanks for the verification on that (and thanks to Simon for 
checking a more recent version).  I went to the Adacore website
but it looks like all of their bug submission options require
you to be a paying customer.  I'll have to figure out a way to
report this to Adacore (or is there a different route?).

What are your thoughts on this suggestion:  Generally, constructing
operations don't need to be primitive.  In some other languages,
constructors are not primitive at all and can neither dispatch 
nor be overridden.  It would be nice if Ada provided a more
straightforward way to set a procedure or function as not primitive.
I know you can put them in another package (or a subpackage), but
that leads to really clumsy naming schemes for some packages or
unnecessary extra files.  I don't know enough to say what the
right way to do it would be.  I feel an extra keyword is overkill,
but I don't know if either aspects or attributes would be a viable
alternative ( with Primitive => False or for My_Function'Primitive use False).
It wouldn't need to cause freezing, but just prevent extensions from
inheriting or dispatching to them.

If I am using primitive incorrectly, I apologize.  Hopefully my meaning
is at least decipherable.

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

* Re: Preventing private procedure visibility being made public through extension
  2017-06-02  1:07                       ` Jere
@ 2017-06-02  7:31                         ` Dmitry A. Kazakov
  2017-06-02  8:09                         ` Mark Lorenzen
  2017-06-02 11:31                         ` Simon Wright
  2 siblings, 0 replies; 42+ messages in thread
From: Dmitry A. Kazakov @ 2017-06-02  7:31 UTC (permalink / raw)


On 02/06/2017 03:07, Jere wrote:
> It would be nice if Ada provided a more
> straightforward way to set a procedure or function as not primitive.

I would argue that from theoretical point of view there should be no 
free operations at all. E.g. all operations must be primitive, 
dispatching, all arguments and results always controlled. [*].

> I know you can put them in another package (or a subpackage),

... or if you freeze the type by using it (in a non-trivial manner) 
before declaring the operation.

------------
*  A class-wide operation procedure Foo (X : T'Class) would be 
dispatching on T'Class'Class should you have such object. And in general 
for each type T there is T'Class.

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

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

* Re: Preventing private procedure visibility being made public through extension
  2017-06-02  1:07                       ` Jere
  2017-06-02  7:31                         ` Dmitry A. Kazakov
@ 2017-06-02  8:09                         ` Mark Lorenzen
  2017-06-02 11:31                         ` Simon Wright
  2 siblings, 0 replies; 42+ messages in thread
From: Mark Lorenzen @ 2017-06-02  8:09 UTC (permalink / raw)


On Friday, June 2, 2017 at 3:07:06 AM UTC+2, Jere wrote:
> 
> Thanks for the verification on that (and thanks to Simon for 
> checking a more recent version).  I went to the Adacore website
> but it looks like all of their bug submission options require
> you to be a paying customer.  I'll have to figure out a way to
> report this to Adacore (or is there a different route?).

I think if you are using GNAT GPL you can submit a bug report here:

http://libre.adacore.com/contact/

Regards,

Mark L

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

* Re: Preventing private procedure visibility being made public through extension
  2017-06-02  1:07                       ` Jere
  2017-06-02  7:31                         ` Dmitry A. Kazakov
  2017-06-02  8:09                         ` Mark Lorenzen
@ 2017-06-02 11:31                         ` Simon Wright
  2 siblings, 0 replies; 42+ messages in thread
From: Simon Wright @ 2017-06-02 11:31 UTC (permalink / raw)


Jere <jhb.chat@gmail.com> writes:

> I went to the Adacore website but it looks like all of their bug
> submission options require you to be a paying customer.  I'll have to
> figure out a way to report this to Adacore (or is there a different
> route?).

Email report@adacore.com with GNAT: at the start of your Subject line.

AdaCore may or may not respond.


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

* Re: Preventing private procedure visibility being made public through extension
  2017-05-26 22:35                   ` Simon Wright
@ 2018-05-20 11:22                     ` Simon Wright
  2018-05-20 12:03                       ` Jere
  0 siblings, 1 reply; 42+ messages in thread
From: Simon Wright @ 2018-05-20 11:22 UTC (permalink / raw)


Simon Wright <simon@pushface.org> writes:

> "Randy Brukardt" <randy@rrsoftware.com> writes:
>
>> Ah, a subtype. GNAT has (or had?)a bug having to do with making things
>> visible because of a subtype declaration (I recall someone else
>> running across that and having verified it myself). That's just plain
>> wrong, a subtype has no effect on what's visible in a prefixed call
>> (or anywhere else for that matter, in particular with "use all type").
>>
>> You ought to have an ambiguity if you tried to call Something in the
>> body of More_Derived, but it should be OK in the main subprogram.
>>
>> I'd skip the subtype and just use the real name of the type. And
>> possibly make a bug report to AdaCore.
>> You could also use a traditional call (More_Derived.Something (M, P);)
>> which would avoid the buggy part of GNAT.
>
> Quite right, Randy (GCC 7.1.0, still; has anyone reported this?)

I think it must have been reported, because it's fixed in 8.1.0.

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

* Re: Preventing private procedure visibility being made public through extension
  2018-05-20 11:22                     ` Simon Wright
@ 2018-05-20 12:03                       ` Jere
  0 siblings, 0 replies; 42+ messages in thread
From: Jere @ 2018-05-20 12:03 UTC (permalink / raw)


On Sunday, May 20, 2018 at 7:22:09 AM UTC-4, Simon Wright wrote:
> Simon Wright writes:
> 
> > "Randy Brukardt" writes:
> >
> >> Ah, a subtype. GNAT has (or had?)a bug having to do with making things
> >> visible because of a subtype declaration (I recall someone else
> >> running across that and having verified it myself). That's just plain
> >> wrong, a subtype has no effect on what's visible in a prefixed call
> >> (or anywhere else for that matter, in particular with "use all type").
> >>
> >> You ought to have an ambiguity if you tried to call Something in the
> >> body of More_Derived, but it should be OK in the main subprogram.
> >>
> >> I'd skip the subtype and just use the real name of the type. And
> >> possibly make a bug report to AdaCore.
> >> You could also use a traditional call (More_Derived.Something (M, P);)
> >> which would avoid the buggy part of GNAT.
> >
> > Quite right, Randy (GCC 7.1.0, still; has anyone reported this?)
> 
> I think it must have been reported, because it's fixed in 8.1.0.

I ended up reporting this to them sometime shortly after.  I'm glad the
fix finally made it in!

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

end of thread, other threads:[~2018-05-20 12:03 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-20 17:33 Preventing private procedure visibility being made public through extension Jere
2017-05-20 20:13 ` AdaMagica
2017-05-20 21:55   ` Jere
2017-05-20 20:32 ` Dmitry A. Kazakov
2017-05-20 22:51   ` Jere
2017-05-21  0:51     ` Jere
2017-05-21  9:16       ` Chris Moore
2017-05-21 22:55         ` Jere
2017-05-21  8:44     ` Dmitry A. Kazakov
2017-05-21 12:19       ` J-P. Rosen
2017-05-21 12:53         ` Dmitry A. Kazakov
2017-05-21 20:06       ` Jere
2017-05-21 21:07         ` Dmitry A. Kazakov
2017-05-21 22:28           ` Jere
2017-05-22  8:52             ` Dmitry A. Kazakov
2017-05-22 13:33               ` AdaMagica
2017-05-22 13:43           ` AdaMagica
2017-05-22 21:17         ` Randy Brukardt
2017-05-25  4:06           ` Jere
2017-05-25 19:39             ` Randy Brukardt
2017-05-25 22:53               ` Jere
2017-05-25 22:57                 ` Jere
2017-05-26 20:46                 ` Randy Brukardt
2017-05-26 22:35                   ` Simon Wright
2018-05-20 11:22                     ` Simon Wright
2018-05-20 12:03                       ` Jere
2017-05-26 22:58                   ` Jeffrey R. Carter
2017-05-30 21:15                     ` Randy Brukardt
2017-06-02  1:07                       ` Jere
2017-06-02  7:31                         ` Dmitry A. Kazakov
2017-06-02  8:09                         ` Mark Lorenzen
2017-06-02 11:31                         ` Simon Wright
2017-05-22 21:12   ` Randy Brukardt
2017-05-23  7:38     ` Dmitry A. Kazakov
2017-05-21 18:14 ` Robert Eachus
2017-05-21 20:21   ` Jere
2017-05-21 21:09     ` Jeffrey R. Carter
2017-05-21 22:46       ` Jere
2017-05-22 21:24         ` Jeffrey R. Carter
2017-05-25  3:45           ` Jere
2017-05-21 21:20     ` Dmitry A. Kazakov
2017-05-21 21:45       ` Jere

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