暫定メモです。
ファイナライザ(デストラクタ)
Fortran 2003 で導入されたオブジェクト指向の仕様のなかに、オブジェクト解放時のの自動呼出し処理としてのファイナライザ(いわゆるデストラクタ)があります。
Modern Fortran Explained の著者の一人マルコム・コーエンが、日本で行った講演の中で、Fortran 2003 ではその仕様に問題があって Fortran 2008 で修正したと述べております。
どこをどう変えたのか調べようと思いつつサボって、私はちょっと把握していません(笑)。 いずれにせよ、仕様が複雑で使い方が難しいと指摘されています。
実際、final 処理の挙動が、派生型変数間の代入時に intel fortran と gfortran で異なることを先に見ました。
ISO Fortran 2008 の規格によれば生の代入文では右辺の式が評価された後に、左辺の変数のファイナライズ処理が行われるとあるので、gfortran の挙動は規格にのっとっていないのではないかと思われました。
参考:ISO Fortran 2008 ドラフト
https://j3-fortran.org/doc/year/10/10-007.pdf
4.5.6.3 When finalization occurs
9 When an intrinsic assignment statement is executed, the variable is finalized after evaluation of expr and before the definition of the variable.
ここでは、また別の例を見てみることにします。
子孫型から先祖型への代入
オブジェクト指向では、派生型の拡張 (extension) で要素成分が増えて大きくなった型からベースとなったより小さい型への代入が出来ます。(継承により生じた子孫型から先祖の型の変数への代入)
大きいものが小さいものに入るのは変な気がしますが、これは暗黙裡に成分の射影が取られて、射影成分が代入されているものと考えられるかと思います。(代入演算子『 = 』は本来は適切ではなく、ディラック的な記号での射影演算子 P の付いた『 =P 』あるいは『 =|P><P| 』と考えられる?)
しかしながら、この場合も代入時のファイナライザ処理が絡んでくるので、代入される変数側でファイナライザ処理が行われるならば、素朴な射影による要素代入イメージは適切ではないかもしれません。
そうして、ここでも intel fortran と gfortran で挙動が違っています。上記の場合と同様 intel fortran はファイナライザを呼び出しますが、gfortran はファイナライザ呼び出さず要素成分の代入処理だけを行います。
規格によれば、代入なので intel fortran の挙動が正しい気がしますが、成分射影のイメージからすれば gfortran の挙動ももっともな気もします。
プログラム例
子孫型変数を先祖型変数に代入する。この時、先祖型は再割り付けされることなく、先祖型のまま、子孫型変数中の先祖型の成分が射影され代入される。
module m_mod
implicit none
type :: t_base
integer :: ix
contains
final :: fin_b
end type t_base
type, extends(t_base) :: t_ext
integer :: iy
contains
final :: fin_e
end type t_ext
contains
subroutine fin_b(this)
type(t_base), intent(in) :: this
print *, 'final:: t_base', this%ix
end subroutine fin_b
subroutine fin_e(this)
type(t_ext), intent(in) :: this
print *, 'final:: t_ext ', this%ix, this%iy
end subroutine fin_e
end module m_mod
program Console6
use m_mod
implicit none
class(t_base), allocatable :: tx
type (t_ext ), allocatable :: ty
tx = t_base(1)
ty = t_ext(2, 3)
print *, tx%ix ! 1
print *, ty%ix, ty%iy ! 2, 3
print *, '****************************'
tx = ty
print *, tx%ix ! 2
! print *, tx%ix, tx%iy ! error
end program Console6
実行結果
intel fortran v.19
1
2 3
****************************
final:: t_base 1
2
gofortran v.7.1.1
1
2 3
****************************
2
結論
このように、比較的単純な代入操作でも処理系ごとの挙動が異なり、脳内イメージともしっくりこないとなると、確かに final 処理は使いにくいと言わざるおえません。便利な機能だと思うのですが。