Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29386 Discussions

Bug(?): function interface can have parameterized return type, or a "result(...)", but not both

cfrederick
Beginner
544 Views

(See the ~30 line reproducer below/attached. I'm using `ifort 2021.13.1 20240703` and `ifx 2024.2.1 20240711`.)

For a `module function` with the interface in the parent module, and implementation in the submodule, it's often nice to have the declaration and definition lines match [ie `real module function pi() result(p)`]. It's also nice to use `implicit none`.

This works with `real`, but with eg `real(8)` the compiler complains in the submodule that the `result` variable lacks a type.

The workaround we're using for now is to delete the `result(...)` portion of the declaration.

Has anyone else seen this?

I'm not sure if it's a bug exactly, but the error message was not helpful, as there is nothing you can do at the definition site to make this work (that I found).

! Valid combinations for ifort, ifx
! (1) and (4).   Note these match exactly
! (3) and (5).   Note (3) is just (5) but without a result(...) declaration

! Gfortran additionally works with
! (2) and (5).   Note these match exactly


module the_interface
    implicit none
    interface
        real     module function pi() result(p)   ! (1)
        !real(8) module function pi() result(p)   ! (2)
        !real(8) module function pi()             ! (3)
        end function pi
    end interface
end module the_interface


submodule (the_interface) the_impl
    implicit none
contains
    real     module function pi() result(p)       ! (4)
    !real(8) module function pi() result(p)       ! (5)
        p = 22.0 / 7
    end function pi
end submodule the_impl


program main
    use the_interface
    implicit none
    print *, "pi is ", pi()
end program main

 

0 Kudos
5 Replies
andrew_4619
Honored Contributor III
497 Views

Well I agree that it is a bug. There were numerous similar bugs when submodules were first introduced but it seem there is one more...

It shows the same behaviour in IFX 2025.3. Another (and IMO better workaround would be:

module the_interface
    implicit none
    interface
        module function pi() result(p) 
            real(8) :: p
        end function pi
    end interface
end module the_interface
submodule (the_interface) the_impl
    implicit none
    contains
    module function pi() result(p)
        real(8) :: p
        p = 22.0 / 7
    end function pi
end submodule the_impl
program main
    use the_interface
    implicit none
    print *, "pi is ", pi()
end program main

That is my personal preference also as I think a type  declaration as a function pre-fix is anomalous to the general layout of modern Fortran. 

JFH
New Contributor I
455 Views

If I were doing that I would also avoid real(8) in a declaration in favour of either real(dp) where dp had been defined as selected_real_kind(15) or real(kind(1d0), and even more so I wouldn't define a constant called pi as 22.0/7, which is a default real wrong value: 22d0/7 would at least get a double precision value. But a value correct in double precision is acos(-1.0_dp).

0 Kudos
cfrederick
Beginner
378 Views

Thanks for taking the time to reply, JFH.

Perhaps I should have made it clearer that this is a small digestible reproducer, and is meant to demonstrate the mechanisms at work with as little indirection or complication as possible.

Naturally, in our actual code base we use `selected_real_kind`. Pi has nothing to do with anything, I just as easily could have had the function return `1.0`. But I'm glad you clarified that `22/7` is not precisely pi, as that could have been very confusing for some readers.

Cheers

0 Kudos
cfrederick
Beginner
354 Views

Thanks for checking with your ifx version too. Yeah, my team is thinking about a refactor to inside-body type declarations everywhere. The context for this is I'm ensuring `implicit none` everywhere in a massive older codebase, and that turned out to break some functions, but only ones with parameterized return types out front, and `result(...)` vars. Very niche I expect.

0 Kudos
andrew_4619
Honored Contributor III
301 Views

I have a large number of functions in submodules that use result. It just happens I always use the internal declaration. Some years back I wrote a code to extract interfaces so a large number of external subroutines could go in submodules. I found the external form of function declaration a real pain as it creates so many potential variations. At that point they got fully eliminated which was not a big job and was quicker than making the extractor fully featured! IMO when they introduced submodules module function should have been restricted to internal declaration only.

0 Kudos
Reply