On a related note, there are other interesting ways to introduce ambiguity with type-bound procedures. These arise because Fortran does not require the passed object to be the first argument in a type bound procedure. Consider
INTEGER :: i = 1
procedure, pass(a) :: EQUALS_1
GENERIC :: ASSIGNMENT(=) => EQUALS_1
END TYPE one
INTEGER :: i = 2
PROCEDURE, PASS(b) :: EQUALS_2
GENERIC :: ASSIGNMENT(=) => EQUALS_2
END TYPE two
SUBROUTINE EQUALS_1(a, b)
CLASS (one), INTENT(OUT) :: a
TYPE (two), INTENT(IN) :: b
a%i = b%i
END SUBROUTINE EQUALS_1
SUBROUTINE EQUALS_2(a, b)
TYPE (one), INTENT(OUT) :: a
CLASS (two), INTENT(IN) :: b
a%i = b%i
END SUBROUTINE EQUALS_2
END MODULE demo
TYPE (one) :: x
TYPE (two) :: y
x = y
END PROGRAM MAIN
The program is illegal due to ambiguity in generic resolution but most compilers I’ve tested will print “In EQUALS_1()”. One compiler produces a very clear error message.
> On Mar 23, 2018, at 5:36 PM, Bill Long <[log in to unmask]> wrote:
> To fill in the missing information Malcolm mentioned, for all three compilers tested, I compiled with no extra options - only what they use as default. That does result in some differences - one of the compilers defaults to a pretty high level of optimization and strictness while a different one defaults to -O0. But all three uniformly compiled the code with no messages and the resulting executions produced identical output.
> The disambiguation problem could be avoided if the specific added by the separate generic interface had a second argument of type integer, rather than type(t).
> However, suppose the programmer, in a separate module that has a USE M extends type(t) by adding a second type-bound specific with an integer second argument to the operator(=) generic specified in the type. If the external generic in M is accessed as part of the generic resolution, then there would be a conflict with the newly added specific in the new module, forcing the user too look through all of the ancestor modules to be sure there was no duplicate specific already available. On the other hand, if the resolution of the generic in the type is limited to type-bound procedures, then the new one can be added without worrying about conflicts in other files. The second option (which appears to be widely implemented) seems more in keeping with the OOP idea of encapsulating information in the type and its extensions. The first preserves the old scheme where generics with the same generic name continue to accrete specifics as they are added, no matter where the new generic statement / interface block appears as long as it is accessible. It seems worthwhile to have a discussion about what sort of environment we want to ensure for OOP programmers. And clearly state the intent in the standard.
>> On Mar 22, 2018, at 7:11 PM, Malcolm Cohen <[log in to unmask]> wrote:
>> That's a good question.
>> I do not think this was intended to conform.
>> Certainly the two generic specifications do not satisfy the rules in (F2008) "18.104.22.168.5 Restrictions on generic declarations", which apply to
>> " every pair of specific procedures that have the same generic identifier within the scope of the identifier"
>> Obviously module m scope includes the ASSIGNMENT(=) specific procedure specified by the INTERFACE.
>> So you ask what is the scope of the type-bound generic, and the answer is:
>> " A generic binding for which the generic-spec is not a generic-name has a scope that consists of all scoping units
>> in which an entity of the type is accessible."
>> I think this wording is not what we meant, because it leads to the surprising results that
>> a) a scoping unit that uses the module and has an entity of the type is not conforming;
>> b) adding "TYPE(T) X" to the module would make it non-conforming.
>> That would be a bit strange.
>> So I think what we meant was "the type or an entity of the type is accessible". As the designer of the feature, it is what I implemented...
>> ...so I think the committees need to examine this possible defect in the language standard and see what, if any, action should be taken.
>> I note that Bill's longer example is unambiguously NOT conforming, as the scoping unit for program m has an entity of the type, and the interface-block-specified generic is also in the scope (made accessible by use association), so violates the generic ambiguity rules. The compilers he tested were also NOT conforming (at least with the options he used) as diagnosis of scoping rule violations is required, and this includes the generic ambiguity rules by reference.
>> The idea that type-bound generics override interface blocks is an interesting idea, but not one that has any support in the standard.
>> ..............Malcolm Cohen, NAG Oxford/Tokyo.
>> -----Original Message-----
>> From: Fortran 90 List <[log in to unmask]> On Behalf Of Vipul Parekh
>> Sent: Friday, March 23, 2018 3:10 AM
>> To: [log in to unmask]
>> Subject: [COMP-FORTRAN-90] Question on overloading defined assignment with a type-bound procedure
>> Does the following code conform to the standard considering the assignment interface as well as a type-bound generic?
>> module m
>> type :: t
>> procedure :: assign_class_t
>> generic :: assignment(=) => assign_class_t
>> end type
>> interface assignment(=)
>> module procedure assign_t
>> end interface
>> subroutine assign_t( this, rhs )
>> type(t), intent(out), allocatable :: this
>> type(t), intent(in) :: rhs
>> end subroutine
>> subroutine assign_class_t( this, rhs )
>> class(t), intent(inout) :: this
>> type(t), intent(in) :: rhs
>> end subroutine
>> end module m
>> Two processors I tried compiled the code with no errors.
>> Vipul Parekh
> Bill Long [log in to unmask]
> Principal Engineer, Fortran Technical Support & voice: 651-605-9024
> Bioinformatics Software Development fax: 651-605-9143
> Cray Inc./ 2131 Lindau Lane/ Suite 1000/ Bloomington, MN 55425