I have something like that (simplified skeleton version).
with Ada.Containers.Indefinite_Holders;
package Tests is
type Element is tagged private;
private
type Holder_Content_Root is interface;
package Holders is new
Ada.Containers.Indefinite_Holders
(Element_Type => Holder_Content_Root'Class);
type Element is new Holders.Holder with null record;
end Tests;
package Tests.References is
type Reference (<>) is limited private;
function Get_Reference (Self : aliased in out Element) return Reference;
private
type Reference is limited new Holders.Reference_Type;
end Tests.References;
package body Tests.References is
function Get_Reference (Self : aliased in out Element) return Reference is
begin
return
Result : Reference :=
Reference (Holders.Reference_Type'(Self.Reference))
do
null;
end return;
end Get_Reference;
end Tests.References;
At compile time, I have this error message :
tests-references.adb:14:12: error: initialization of limited object requires aggregate or function call
How can I solve this? Is it a bad idea/dead end to derive from Holders.Reference_Type? How would you do that instead (without using explicit accesses, I’m really bad at memory handling)?
I already tried some AI that only gave me obviously wrong solutions.
Thanks!
You cannot derive a limited type from a non-limited type. Holder is not limited. Remove limited in
type Reference is limited new Holders.Reference_Type;
Thanks but it doesn’t work as Holders.Reference_Type is indeed limited (implicitly by some Ada rule).
If I remove the limited keyword, I get this error message for the type definition:
error: completion of nonlimited type cannot be limited
In fact, my first attempt was without limited as Reference_Type is not explicitly declared as limited 
No, Reference_Type is not limited:
type Reference_Type
(Element : not null access Element_Type) is private
with
Implicit_Dereference => Element;
ARM A.18.18 (17/5)
Yes, I know it’s not declared limited, but this type of declaration (access to / implicit dereference) seems to be considered as limited by the compiler, hence the error message I get if I omit the keyword (at least in the public part, but I can omit it in the private part!).
Or the error message is misleading and there’s something else…
An aspect cannot do what you suggest. Post a complete example illustrating the issue.
Thanks for your help. The exemple is complete. You can try to compile it.
If I use type Reference (<>) is private (and also not limited for the complete definition in the private part), I have this error message:
tests-references.ads:9:09: error: completion of nonlimited type cannot be limited
If I add limited to the public definition of Reference type Reference (<>) is limited private; then I get this error:
tests-references.adb:5:36: error: initialization of limited object requires aggregate or function call
I understand this second error, but not the previous one…
Note: I’m using gnat 16.1.0
Hum, it compiles with gnat 15.3.0 (without limited)… Something broken in 16.1.0 ?
Anyway, thanks for your help.
There is no first error in 16.1.1. If you get it, that is surely a compiler bug.
As for the second one, I am not so sure. It is about type conversions of private types.
You used a “type cloning” for whatever reason. That is the construct:
type Clone is new Original;
First of all that does not work well with generics anyway. Then there is no view conversions of private types. Yet a view conversion is needed for the limited-return-hack (which should never had been introduced). On the other hand the argument of type conversion is not limited in its full view, which you have. Therefore the conversion is allowed to copy.
It looks like compiler bug in GCC 16.1.x, but I am no language lawyer to be certain.
As a remedy wrap the type into a record:
type Reference (Element : not null access Holder_Content_Root'Class) is record
Pointer : Holders.Reference_Type (Element);
end record;
function Get_Reference (Self : aliased in out Element) return Reference is
begin
return
Result : Reference := (Self.Reference.Element, Self.Reference);
do
null;
end return;
end Get_Reference;
It looks awful as it should. 