@@ -27,10 +27,62 @@ function position end
2727position (object, name) = position (typeof (object), name)
2828position (:: Type , pos:: Int ) = Position (pos)
2929position (:: Type , pos:: Position ) = pos
30+
3031function position (type:: Type , name)
31- base_type = unspecify_type_parameters (type)
32- base_type === type && error (" `position` not defined for $type and $name ." )
33- return position (base_type, name)
32+ type′ = unspecify_type_parameters (type)
33+ if type === type′
34+ # Fallback definition that determines the
35+ # position automatically from the supertype of
36+ # the type.
37+ return position_from_supertype (type′, name)
38+ end
39+ return position (type′, name)
40+ end
41+
42+ # Automatically determine the position of a type parameter of a type given
43+ # a supertype and the name of the parameter.
44+ function position_from_supertype (type:: Type , name)
45+ type′ = unspecify_type_parameters (type)
46+ supertype_pos = position (supertype (type′), name)
47+ return position_from_supertype_position (type′, supertype_pos)
48+ end
49+
50+ # Automatically determine the position of a type parameter of a type given
51+ # the supertype and the position of the corresponding parameter in the supertype.
52+ @generated function position_from_supertype_position (
53+ :: Type{T} , supertype_pos:: Position
54+ ) where {T}
55+ T′ = unspecify_type_parameters (T)
56+ # The type parameters of the type as TypeVars.
57+ # TODO : Ideally we would use `get_type_parameters`
58+ # but that sometimes loses TypeVar names:
59+ # https://github.com/ITensor/TypeParameterAccessors.jl/issues/30
60+ type_params = Base. unwrap_unionall (T′). parameters
61+ # The type parameters of the immediate supertype as TypeVars.
62+ # This has TypeVars with names that correspond to the names of
63+ # the TypeVars of the type parameters of `T`, for example:
64+ # ```julia
65+ # julia> struct MyArray{B,A} <: AbstractArray{A,B} end
66+ #
67+ # julia> Base.unwrap_unionall(MyArray).parameters
68+ # svec(B, A)
69+ #
70+ # julia> Base.unwrap_unionall(supertype(MyArray)).parameters
71+ # svec(A, B)
72+ # ```
73+ supertype_params = Base. unwrap_unionall (supertype (T)). parameters
74+ supertype_param = supertype_params[Int (supertype_pos)]
75+ pos = findfirst (param -> (param. name == supertype_param. name), type_params)
76+ if isnothing (pos)
77+ return error (" Position not found." )
78+ end
79+ return :(@inline ; $ (Position (pos)))
80+ end
81+
82+ # Automatically determine the position of a type parameter of a type given
83+ # a supertype and the name of the parameter.
84+ function position_from_supertype (type:: Type , supertype_target:: Type , name)
85+ return position_from_supertype (type, supertype_target, position (supertype_target, name))
3486end
3587
3688function positions (:: Type{T} , pos:: Tuple ) where {T}
0 commit comments