Search code examples
fortranintel-fortran

The name of the module procedure conflicts with a name in the encompassing scoping unit


I'm learning Fortran submodule, this is my code

module name1
    implicit none
    interface
        module subroutine test2(x)
            integer,intent(in) :: x
        end subroutine test2
    end interface
    contains
        subroutine test1(x)
            integer :: x
            call test2(x)
        end
end module name1


module name2
    use name1
    implicit none
    integer :: z = 22
end module name2


submodule(name1) new
    use name2
    contains
        subroutine test2(x)
            integer,intent(in):: x
            integer:: y 
            y = 2
            print *, x+y+z ,'from test2'
        end  
end submodule



program name
    use name2
    implicit none
    call test1(5)
end program name

But while compiling with ifort (IFORT) 2021.3.0 20210609 it shows the following error

test.f90(26): error #6645: The name of the module procedure conflicts with a name in the encompassing scoping unit.   [TEST2]
        subroutine test2(x)
-------------------^
compilation aborted for test.f90 (code 1)

I can't understand what I'm doing wrong. Is it not a valid Fortran submodule use?


Solution

  • When defining the implementation of a procedure in a submodule (a separate module procedure), you need the keyword module.

    The relevant bits of your code would become:

    module name1
      implicit none
      interface
        module subroutine test2(x)
          integer,intent(in) :: x
        end subroutine
      end interface
    end module
    
    submodule(name1) test
      module subroutine test2(x) ! Note the keyword `module`
        integer,intent(in):: x
        integer:: y 
        y = 2
        print *, x+y+z ,'from test2'
      end subroutine
    end submodule
    

    You can also reduce the amount of duplicated code using module procedure, as

    module name1
      implicit none
      interface
        module subroutine test2(x)
          integer,intent(in) :: x
        end subroutine
      end interface
    end module
    
    submodule(name1) test
      module procedure test2
        integer:: y 
        y = 2
        print *, x+y+z ,'from test2'
      end procedure
    end submodule
    

    Using module procedure means you don't have to duplicate the arguments of the procedure (x) or their declarations integer,intent(in):: x.