2

To use a subroutine and allow the compiler to check argument mismatch, one needs to place the defintion of that subroutine in a module, for which case, fortan creates an explicit interface for the calling unit to check argumetn mismatch etc.

For stand-alone subroutines that are not contained in a module, we say they have only "implicit interfaces" and no "explicit interfaces", so that the compiler can not check argument mismatch. Why does not the compiler also create "explicit interfaces" for the stand-alone subroutines? What difficulties prevent the compiler from doing this?

Youjun Hu
  • 991
  • 6
  • 18
  • 2
    Some (or perhaps all) compilers (e.g., Intel) generate interfaces if you instruct them. Search for [Intel Fortran programming compiler "gen-interfaces" option](https://www.intel.com/content/www/us/en/develop/documentation/fortran-compiler-oneapi-dev-guide-and-reference/top/compiler-reference/compiler-options/compiler-diagnostic-options/gen-interfaces.html) – Scientist Feb 06 '23 at 03:27
  • @Scientist This gernerates **interface blocks**. You cannot make this to get **explicit interface** for external subprograms. This is quite a different thing. You would have to somehow insert or include the generated interface block to get an explicit interface. – Vladimir F Героям слава Feb 06 '23 at 06:43
  • @VladimirFГероямслава You can instruct the compiler to create interfaces **within** modules that you can subsequently **readily** `use` where needed. – Scientist Feb 06 '23 at 09:01
  • @Scientist Yes, or you could just include the interface blocks into a manually prepared `module` - `end module` file. But that does not fundamentally change it. Providing an explicit interface for an external subprogram is something else. – Vladimir F Героям слава Feb 06 '23 at 09:04
  • You can also place the subroutine inside the `program` after a `contains` keyword. – John Alexiou Feb 28 '23 at 14:47

2 Answers2

1

It simply the way the language works and have always worked since the inception in the 1950s and first standardization in 1960s.

It had little other choice back then, even though some other languages like Algol 68, or later Modula, pioneered the use of modules a decade or more later. Pascal, for example, relied on nesting.

Mind you, modules are a relatively new thing. C++ got them only a few years ago. Otherwise C (and C++) used to include files to allow the compiler to see headers from other source files by including everything into the current file. But implicit interfaces were also an option in original C.

In Fortran, the compilation units are individual program units, not source files. One can write or even automatically generate (e.g. the -gen-interfaces compiler option mentioned in the comments) interface blocks and include them using include files, but this approach is rarely recommendable.

Even though explicit interfaces would theoretically theoretically be possible without modules or included headers, such a concept does not really exist much in the programming world for traditional compiled languages.

The concept of explicit interface was introduced in Fortran 1990. It allows some new ways of calling more advanced forms of Fortran subprograms (array results, assumed shape, optional arguments,...). However it also allows checks that were not possible before. Enforcing such checks would break existing code. The success (and its lack) is to a large extent also based on backward compatibility. You cannot brake existing code so much - it would really be a lot.

Compilers will now often warn you that you are doing something not allowed, that the call of an external subprogram is not conforming, if you allow such warnings and if you enable or do not disable such warnings. But it will always remain a warning and it does not bring you the new possibilities. Legacy codes remain working.

These warnings are also possible at the linking stage, especially when link-time optimizations are used.

1

When we are considering interfaces, we are not talking about some mythical object which may be implicit or explicit.

Consider the two main programs:

program main1
  implicit none (external)

  external sub

  call sub
end program main1

and

program main2
  implicit none (external)

  interface
    subroutine sub()
    end subroutine sub
  end interface

  call sub
end program main2

These two main programs are (perhaps) concerned about the same external subroutine sub. main1 has an implicit interface for sub and main2 has an explicit interface for sub.

Whichever main program we are wondering about, the subroutine sub always has an explicit interface for itself:

subroutine sub()
  implicit none (external)

  call sub
end subroutine sub

I've just defined a (pretty terrible) subroutine called sub. I imagine that's going to be a popular name: next time you want to use that name (don't forget: external procedures are global entities) for an external procedure are you going to use the one I've just defined? If you aren't, how are you going to tell the compiler which sub you are talking about?

Resolution of which external subroutine sub is going to be used is often a problem for the linker, not the compiler. The compiler may never see a particular external procedure so cannot automatically generate for a program unit an explicit interface for an external procedure.1

That said, there are cases where a compiler will do some work for you:

program main3
  implicit none (external)

  external sub
  
  call sub
end program main3

subroutine sub(x)
  implicit none (external)
  real x
end subroutine sub

(as a single file, or separate files, perhaps with specific compiling options) may well prompt your compiler to complain, just as though sub had an explicit interface inside main3.


1 An external procedure can also be defined by means other than Fortran. In such a case, the Fortran compiler doesn't need to even understand it, let alone worry about having to generate an explicit interface for it.

francescalus
  • 30,576
  • 16
  • 61
  • 96
  • All the `external` keywords seem unnecessary. It is my first time to see `implicit none (external)`. What does the `external` in this line mean? – Youjun Hu Feb 07 '23 at 03:00
  • 1
    The main program `main1` could be written as `call sub; end`. It isn't harmful, though, to be more verbose. The `external sub` here is unnecessary (without `implicit none (external)`), but in many cases it is required to explicitly state the EXTERNAL attribute. This (new to F2018) form of the implicit statement says that external subroutines must be stated in the scoping unit (see [this other answer](https://stackoverflow.com/a/66861849/3157076)). – francescalus Feb 07 '23 at 16:36