Developer Guide and Reference

ID 767251
Date 10/31/2024
Public
Document Table of Contents

Examples of Intrinsic Assignment to Polymorphic Variables

Intrinsic assignment to an allocatable polymorphic variable is allowed. The variable must be type compatible with the expression and of the same rank. If it is allocated but the dynamic type differs from that of the expression, it is deallocated. If it is not allocated or becomes deallocated, it is allocated with the dynamic type and kind types of the expression.

Syntax:

assignment-stmt is variable = expr

variable is an allocatable polymorphic and expr is not necessarily an allocatable, but variable and expr must be type compatible.

A polymorphic entity that is not an unlimited polymorphic entity is type compatible with entities of the same declared type or any of its extensions. Even though an unlimited polymorphic entity is not considered to have a declared type, it is type compatible with all entities.

variable and expr must be of the same rank.

If expr is a scalar and variable is allocated, then expr is treated as an array with the same bounds as variable, so the bounds of variable would remain unchanged.

In the examples below, we have the following types:

Type type1
End type

Type type2
End type

Type, extends(type1) :: type3
End type 

Example of same type and same size:

If variable is the same type and size as expr then just do the assignment.

Class(type1), allocatable :: var
Class(type1), allocatable :: expr
Allocate(expr, source=type1())
Allocate(var, source=type1())
var = expr             ! No deallocation of var, simple assignment

Example of same type and different size:

If variable is the same type as expr but their sizes are not the same then deallocate var, reallocate it, and then do the assignment.

Class(type1), allocatable :: var(:)
Class(type1), allocatable :: expr(:)
Allocate(var(5), source=type1())
Allocate(expr(6), source=type1())
var = expr             ! var deallocated and then
                       ! allocated to the size of expr - then
                       ! the usual assignment is performed

Example of different types or shape and same size:

If variable and expr are of different types or shapes but of the same size, then do the assignment and update the type/bounds of var to be same as that of expr, only if type1 and type3 are type compatible.

Class(type1), allocatable :: var(:,:)
Class(type1), allocatable :: expr(:,:)
Allocate(var(2,3), source=type1())
Allocate(expr(3,2), source=type3())
var = expr             ! No deallocation
                       ! simple assignment with var 
                       ! bounds updated

Example of different types or shape and different size:

If variable and expr are of different types or shapes and of different sizes, then deallocate var and allocate it with the same type and shape as expr, only if type1 and type3 are type compatible.

Class(type1), allocatable :: var(:,:)
Class(type3), allocatable :: expr(:,:)
Allocate(var(2,4), source=type1())
Allocate(expr(3,3), source=type3())
var = expr             ! var deallocated and then
                       ! allocated to the size of expr and
                       ! then the usual assignment var
                       ! has dynamic type set to type3

Example of incompatible types on Left-Hand Side (LHS) and Right-Hand Side (RHS):

If LHS and RHS are type incompatible then you get an error.

Class(type1), allocatable :: var
Class(type2), allocatable :: expr
Allocate(var,source=type1())
Allocate(expr,source=type2())
var = expr             ! This is an error

Example of unallocated allocatable polymorphic on the LHS:

If var is unallocated then allocate var with same dynamic type, shape, and size as expr.

Class(*), allocatable :: var(:)
var = [5, 6, 7, 8]                ! This is valid

Example of unlimited polymorphic on the LHS:

Unlimited polymorphic allocatable on the LHS is type compatible with any type. If var is of a different size than expr, var is deallocated and then allocated with the type and shape of expr.

Class(*), allocatable :: var
Class(type2), allocatable :: expr
Allocate(var, source=type1())
Allocate(expr, source=type2())
var = expr              ! var is an unlimited polymorphic
                        ! so it is type compatible with 
                        ! any type expr