Declaring or creating an object of abstract type is not permitted. The rationale is that one might invoke what appears to be a type-bound procedure that isn’t actually available.
I have a code for nonlinear least squares that uses both forward and reverse (coroutine) communication.
A clean way to organize the code would be to use a polymorphic argument with an abstract base type. The type would have bindings for procedures to compute the function and Jacobian, factor the Jacobian, calculate the Newton move and gradient, and various other calculations for Aitken acceleration, Levenberg-Marquardt stabilization, etc. The desideratum whether to use forward or reverse communication for a particular computation would be whether the relevant procedure is deferred.
The alternative is to use default NULL() procedure pointer components.
If instantiating objects of abstract type were permitted, it would be necessary to add a DEFERRED intrinsic function to determine whether a type-bound procedure could be invoked. An alternative to allowing objects of abstract type would be to remove the constraint that reqiures a type with a deferred binding to have the ABSTRACT attribute.
One cannot start with a base type that has no bindings and then extend it to provide the bindings because the code cannot invoke the bindings using objects of the base type. One could provide bindings to “dummy” routines that do nothing in the base type and use EXTENDS_TYPE_OF .and. .not. SAME_TYPE_AS to determine whether to use forward or reverse communication. This is uglier than a simple DEFERRED intrinsic function. It’s also not as reliable because one might have extended the type and not overridden the type-bound procedures with ones that actually do something useful. Of course, one could include a collection of flags in the type to indicate whether to use forward or reverse communication for each action, but this is even more ugly and unreliable.