The expresion in an expression function that is a completion freezes. This is implemented by first freezing the return type of the function, and then traversing the analyzed expression and freezing explicitly all type references within. If the expression includes a type conversion between access to interface types we must also freeze the interface types themselves so that dispatch table pointers are properly declared before the expression function.
The following must compile quietly: --- with Gen; package Small is type I1 is interface; type I2 is interface; type I1_Ptr is access all I1'Class; type I2_Ptr is access all I2'Class; type Reference (Data : access I2'Class) is null record; package Instance is new Gen (I1); function Get return Reference; private function Get return Reference is ((Data => I2_Ptr (I1_Ptr'(Instance.Get)))); end; --- generic type Iface is interface; package Gen is function Get return access Iface'Class; end; --- package body Gen is function Get return access Iface'Class is begin return null; end; end; Tested on x86_64-pc-linux-gnu, committed on trunk 2017-04-28 Ed Schonberg <schonb...@adacore.com> * sem_ch6.adb (Freeze_Type_Refs): For an interface conversion node between access types, freeze the designated type as well, so that dispatch table pointers are created in the proper scope, and not in the constructed body of the expression function.
Index: sem_ch6.adb =================================================================== --- sem_ch6.adb (revision 247338) +++ sem_ch6.adb (working copy) @@ -3110,6 +3110,18 @@ end if; end; end if; + + -- Freezing an access type does not freeze the designated + -- type, but freezing conversions between access to interfaces + -- requires that the interface types themselves be frozen, so + -- that dispatch table entities are properly created. + -- Unclear whether a more general rule is needed ??? + + elsif Nkind (Node) = N_Type_Conversion + and then Is_Access_Type (Etype (Node)) + and then Is_Interface (Designated_Type (Etype (Node))) + then + Freeze_Before (N, Designated_Type (Etype (Node))); end if; return OK;