uhmm, I believe this is not really necessary, you can just take the Val(symbol_value) as f(::Val{symbol_value}) where {symbol_value} = ... and use symbol_value normally inside the function. No eval is needed.
I also believe you do not need this. You can just:
struct MyStruct{MySymbol}
x :: Int
end
f(my_struct :: MyStruct{my_symbol}) where {my_symbol} = ...
This is, you can add a type parameter to a struct without having a field of that type, and the function will specialize on the MyStruct with the specific type parameter, and the type parameter may be a Symbol directly (it does not need to be wrapped in Val), Ints are also an exception to the rule and can be used directly (this is how Array{Float64, 2} works, the 2 is an Int value being used as type parameter).
I really feel like you are over-complicating here.