j3-fortran / generics

BSD 3-Clause "New" or "Revised" License
36 stars 8 forks source link

If a deferred-type is instantiated with an extensible type, and passed a polymorphic object, does the object stay polymorphic? #123

Open aury6623 opened 1 month ago

aury6623 commented 1 month ago

Example:

module m
contains
    function tmpl{T}(obj) result(r)
        type(T) :: obj, r
        r = obj
    end function
end module

use m
type :: mytype
    integer :: x
end type
type, extends(mytype) :: myext
    integer :: y
end type

instantiate tmpl{mytype}
class(mytype), allocatable :: a, b

allocate(myext :: a)
b = tmpl(a)
print *, same_type_as(a, b)

end

After the assignment to b, what is the dynamic type of b? In other words, does same_type_as(a, b) print T or F?

If this was without templates, and tmpl was just a traditional function that took a type(mytype) argument, then the answer would be b has dynamic type mytype and the program would print F. The function invocation would "cast" a, which has dynamic type myext, to the nonpolymorphic dummy argument of type mytype, losing the "polymorphicness" of the object. Then the mytype result would be assigned back to b.

However, for a template, I think it could be useful for the type to retain its polymorphism, and return T. Yes, the template could use a deferred class, however that prevents using intrinsic types with that template.

Lets say you wanted to make a container template. If you want the container to accept both intrinsic types and polymorphic objects (without losing their polymorphicness), you'd have to either make two container templates, one with deferred-type and one with deferred-class, or you'd have to pick one and use a derived type wrapper object to handle the other.

It seems like it should be possible for the compiler to say "this template was instantiated with a non-abstract extensible type, so I'll replace all these TYPE(T) declarations with CLASS(T), ALLOCATABLE to allow polymorphic objects to work". However I'm aware that could come with a performance cost.

Perhaps there could be a mechanism for saying that a deferred type is always non-poymorphic, or always polymorphic, OR "automatic" based on the type used at instantiation. For example, using the syntax from #120, it could be

TYPE, ABSTRACT, DEFERRED :: polymorphic       ! Can only be used with CLASS
TYPE, DEFERRED :: nonpolymorphic              ! Can only be used with TYPE
TYPE, AUTOMATIC, DEFERRED :: possibly_either  ! Can only be used with TYPE, but acts like CLASS if the instantiation type is extensible

I'm not really sure what the best wording for the keywords would be. AUTOMATIC doesn't seem great. But the idea is there!

aury6623 commented 1 month ago

During the meeting today we decided the answer is no and this is not something we have time to look into right now. Maybe later.