I realize the above is not exactly the requested feature so…here you go:
macro params(struct_expr)
name = struct_expr.args[2]
fields = @view struct_expr.args[3].args[2:2:end]
params = []
for i in 1:length(fields)
x = fields[i]
T = gensym()
if x isa Symbol
push!(params, T)
fields[i] = :($x::$T)
elseif x.head == :(::)
abstr = x.args[2]
var = x.args[1]
push!(params, :($T <: $abstr))
fields[i] = :($var::$T)
end
end
if name isa Symbol && length(params) > 0
struct_expr.args[2] = :($name{$(params...)})
elseif name.head == :curly
append!(struct_expr.args[2].args, params)
else
error("Unidentified type definition.")
end
esc(struct_expr)
end
julia> @params struct MyType
a::Integer
b
end
julia> MyType(1,2)
MyType{Int64,Int64}(1, 2)
julia> MyType(1.0,2)
ERROR: MethodError: no method matching MyType(::Float64, ::Int64)
Closest candidates are:
MyType(::##360<:Integer, ::##361) where {##360<:Integer, ##361} at REPL[2]:2
Stacktrace:
[1] top-level scope at none:0