Type check Array vs UnitRange inside a struct

Type checking seems to be off within structs when it comes to Arrays and UnitRanges. Defining a function with an argument that is of type Array forbids supplying a UnitRange as an input. However, when a struct is defined with one of its fields as an Array, it allows populating it with a UnitRange. Is this the intended behavior?

As an example:

#define a function
f(x::Array) = x 

#define a struct
struct F
    x::Array
end

display(f(1:3))

display(F(1:3))

f(1:3) gives a MethodError, whereas F(1:3) is accepted…

This is behaving as expected. No conversion is done upon calling functions unless you define the methods that do the conversions.

When you define a struct without an inner constructor, Julia helpfully defines the constructor methods that do the conversion for you. You can turn this off by supplying an inner constructor.

julia> struct F
           x::Array
       end

julia> methods(F)
# 2 methods for type constructor:
[1] F(x::Array) in Main at REPL[1]:2
[2] F(x) in Main at REPL[1]:2

julia> @which F(1:3)
F(x) in Main at REPL[1]:2

julia> @code_lowered F(1:3)
CodeInfo(
1 ─ %1 = Main.F
β”‚   %2 = Core.fieldtype(%1, 1)
β”‚   %3 = Base.convert(%2, x)
β”‚   %4 = %new(%1, %3)
└──      return %4
)
2 Likes