Add x/config/cli - #2423
Add x/config/cli#2423nolag wants to merge 6 commits into
Conversation
📊 API Diff Results
|
|
Copilot review says it's done, but didn't post here. It left two comments. The first was because Copilot didn't know about generic methods in Go (get with the times, 1.27 released on Aug 19th changed that). Second was
Claude says it's wrong, and we have a test to prove it. I agree with Claude.
|
…emove list, map and set validations for later PRs. Remove redundant test coverage. Redo comments and divide everything up clearer.
|
|
||
| // RegisterOption customizes one [Binder.Register] call. None exist yet; the parameter lets options be added without | ||
| // breaking callers. | ||
| type RegisterOption[T any] struct { |
There was a problem hiding this comment.
Nit: this doesn't need to be generic since it doesn't return anything anymore
There was a problem hiding this comment.
It's intentional. The function that will create them wants to ensure the input was the same type as the root.
The one I have in mind right now is for profiles. It'll allow you to say things like "this is the default for EVM with chain ID 1, this is for 2 etc". The T ensures that the profile belongs to the config you provided Register.
There was a problem hiding this comment.
Profile's signature
func Profile[T any, K comparable, S any](selector func(*T) *K, profiles map[K]S) RegisterOption[T]
an example use is here
Without the generics returned, you could use profile for the wrong struct. It's unlikely, but possible to do. The generics on the returned RegisterOption forces you to start at the config your registering.
It's still possible to do something wrong if you don't navigate the object itself, but that would be much more intentional. It would be caught (and so would others without the safeguard), but it makes most errors compilation instead of runtime this way.
There was a problem hiding this comment.
Above is subject to some change, I'm evaluating an alternative.
There was a problem hiding this comment.
What makes something "wrong" to use though, if that's not backed by the type system?
I'm still digesting the rest, but it seems like targetEntry[T] would connect the dots, and prevent those implementations from having to type cast themselves - did that not work for some reason?
There was a problem hiding this comment.
Wrong in my mind is if something can be a complier error but becomes a runtime error. Eg: In this case, I passed a selector function that expects a different type than the main config to be the entry.
I don't get how targetEntry would be generic. Binder holds it, but binder can bind to different types for different commands.
I don't get what you mean by implementations casting it, do you mean specifying T?
There was a problem hiding this comment.
Draft for profiles, note I haven't fully reviewed the AI code or comments yet, but the examples seem good enough to demonstrate usage. I may iterate a bit more on the exact API.
This PR is based on a few others that add support for lists and maps as CLI and env vars, the set flag being added, and namespaces. None of them should show up in that PR, so profiles is issolated, but if sourinding code doesn't align with this PR, that's why.
There was a problem hiding this comment.
Can you please document what T is in this context? It reads like an arbitrary additional constraint, and my intuition was apparently way off.
No description provided.