diff --git a/docs/src/APIs/datalayouts_api.md b/docs/src/APIs/datalayouts_api.md index c81b3e9257..acea4306dc 100644 --- a/docs/src/APIs/datalayouts_api.md +++ b/docs/src/APIs/datalayouts_api.md @@ -19,3 +19,14 @@ DataLayouts.IJHF DataLayouts.VIHF DataLayouts.VIJHF ``` + +## Internals + +```@docs +check_basetype +is_valid_basetype +first_invalid_primitive_type +replace_basetype +parent_array_type +promote_parent_array_type +``` diff --git a/src/DataLayouts/struct.jl b/src/DataLayouts/struct.jl index f6de344c95..26e612d611 100644 --- a/src/DataLayouts/struct.jl +++ b/src/DataLayouts/struct.jl @@ -24,6 +24,21 @@ is_valid_basetype(::Type{T}, ::Type{<:T}) where {T} = true is_valid_basetype(::Type{T}, ::Type{S}, Ss...) where {T, S} = is_valid_basetype(T, S) && is_valid_basetype(T, Ss...) +""" + first_invalid_primitive_type(::Type{T}, ::Type{S}) + +Returns the first primitive subtype of `S` that cannot be represented using +base type `T`, or `nothing` if `T` is a valid base type for `S`. +""" +first_invalid_primitive_type(::Type{T}, ::Type{S}) where {T, S} = + is_valid_basetype(T, S) ? nothing : + Base.isprimitivetype(S) ? S : + first_invalid_primitive_type(T, fieldtypes(S)...) +first_invalid_primitive_type(::Type{T}, ::Type{S}, Ss...) where {T, S} = + isnothing(first_invalid_primitive_type(T, S)) ? + first_invalid_primitive_type(T, Ss...) : + first_invalid_primitive_type(T, S) + """ check_basetype(::Type{T}, ::Type{S}) @@ -39,7 +54,9 @@ function check_basetype(::Type{T}, ::Type{S}) where {T, S} estr = "Struct type $S has indeterminate size" :(error($estr)) elseif !is_valid_basetype(T, S) - estr = "Struct type $S cannot be represented using base type $T" + P = first_invalid_primitive_type(T, S) + estr = "Struct type $S contains subtype $P, \ + which cannot be represented using base type $T" :(error($estr)) else :(return nothing) @@ -47,8 +64,10 @@ function check_basetype(::Type{T}, ::Type{S}) where {T, S} else isbitstype(T) || error("Base type $T has indeterminate size") isbitstype(S) || error("Struct type $S has indeterminate size") + P = first_invalid_primitive_type(T, S) is_valid_basetype(T, S) || - error("Struct type $S cannot be represented using base type $T") + error("Struct type $S contains subtype $P, \ + which cannot be represented using base type $T") return nothing end end