Menu

#911 Covariance of elements of arrays does not induce the covariance of the arrays

open
nobody
None
compiler
2023-09-17
2019-09-21
No

With the 'Child' Type inheriting from the 'Parent' Type:
- A 'As Child' argument can be passed to a procedure expecting a 'As Parent' parameter.
- But a '() As Child' argument must not be passed to a procedure expecting a '() As Parent' parameter. Instead, the compiler must output an error message like 'error 58: Type mismatch, at parameter ...'

Bug example:

Type Parent
  Dim As Integer I = 1
End Type

Type Child Extends Parent
  Dim As Integer J = 2
  Dim As Integer K = 3
End Type

Sub print_parent_element (Byref item As Parent)
  Print "     " & item.I;
End Sub

Sub print_parent_array (array() As Parent)
  For n As Integer = Lbound(array) To Ubound(array)
    Print "     " & array(n).I;
  Next n
  Print
End Sub

Dim As Child array(0 To 6)

For n As Integer = Lbound(array) To Ubound(array)
  print_parent_element(array(n))  '' OK (covariance)
Next n
Print
print_parent_array(array())  '' NOK (no covariance), expected 'error 58: Type mismatch, at parameter 1 ...'
Print

Sleep

Output:

     1     1     1     1     1     1     1
     1     2     3     1     2     3     1

See also on forum the post at:
https://www.freebasic.net/forum/viewtopic.php?p=264415#p264415
and the following posts.

Related

Bugs: #817

Discussion

  • fxm (freebasic.net)

    When passing (to a procedure) an array of derived-type elements instead of base-type elements, a simple fix could be applied to fix the problem of address calculation of elements:
    - the calculation of the address of each array element could use the 'element_len' field in the descriptor and no longer the size of the declared parameter type.

    From the previous example thus modified (see the 'print_parent_array(() As Parent))' Sub)
    For fbc rev 1.07, use 'fb_ArrayGetDesc()' instead of 'FBC.ArrayDescriptorPtr()' for fbc rev 1.08 as here:

    #include "fbc-int/array.bi"
    
    Type Parent
      Dim As Integer I = 1
    End Type
    
    Type Child Extends Parent
      Dim As Integer J = 2
      Dim As Integer K = 3
    End Type
    
    Sub print_parent_element (Byref item As Parent)
      Print "     " & item.I;
    End Sub
    
    Sub print_parent_array (array() As Parent)
      Dim as FBC.FBARRAY ptr pd = FBC.ArrayDescriptorPtr(array())
      Dim as Parent ptr p
      For n as integer = lbound(array) to ubound(array)
        p = pd->index_ptr + pd->element_len * n
        Print "     " & p->I;
      Next
    End Sub
    
    Dim As Child array(0 To 6)
    
    For n As Integer = Lbound(array) To Ubound(array)
      print_parent_element(array(n))  '' OK (covariance)
    Next n
    Print
    print_parent_array(array())  '' OK (even for arrays)
    Print
    
    Sleep
    

    Output:

         1     1     1     1     1     1     1
         1     1     1     1     1     1     1
    

    Therefore using:
    p = pd->index_ptr + pd->element_len * n
    instead of:
    p = pd->index_ptr + sizeof(Parent) * n

     

    Last edit: fxm (freebasic.net) 2019-09-22
  • fxm (freebasic.net)

    This could be even applied systematically to all arrays passed as parameters to procedures.

    This would solve other problems like passing a zstring array to a procedure .
    See the other bug reports BUG #650 and BUG #867.

     
  • Jeff Marshall

    Jeff Marshall - 2023-09-17
    • But a '() As Child' argument must not be passed to a procedure expecting a '() As Parent' parameter. Instead, the compiler must output an error message like 'error 58: Type mismatch, at parameter ...'

    In fbc version 1.10, as of commit [3eef323cdc9a866a0c9bbc130f88950d35363f00] with the fix of [#817], the type mismatch is detected and the error message is given.

     

    Related

    Bugs: #817
    Commit: [3eef32]


Log in to post a comment.