OK thank you everyone for your answers.

I noticed that I can write a type constraint which is a union of string | 
*regexp.Regexp.
It's very useful for a function that receives a regexp, or a string that 
will be compiled to a regexp.
In my implementation, I convert the parameter ton any, then I do a type 
switch.

In another function I want to receive a parameter with a type constraint 
which is a union of Equal(T) bool | Compare(T) int
because I want to either use Equal() or Compare() to check the type 
equality, depending on which method is available.
Unfortunately this is not allowed.
I can use the type any, but it is less safe.
As mentioned in this conversation, I decided to implement 2 functions 
instead (1 for each method)


Le samedi 14 mars 2026 à 07:14:39 UTC+1, Kurtis Rader a écrit :

> You wrote:
>
> > This is of course somewhat error prone, you might easily forget a branch 
> or otherwise screw up the logic of your function.
>
> That is precisely my point. If you have to include explicit run-time type 
> checks in your function to support the type polymorphism then you cannot 
> assume the compiler will not allow an unexpected type to leak into your 
> function. Especially since the type signature might be modified without the 
> implementation being updated to correctly handle the new type signature.
>
> On Fri, Mar 13, 2026 at 11:06 PM Axel Wagner <[email protected]> 
> wrote:
>
>>
>> On Sat, 14 Mar 2026 at 06:49, Kurtis Rader <[email protected]> wrote:
>>
>>> I guess I'm showing my age. But if you have to write an explicit run 
>>> time type switch/assertion then you should assume the compile time type 
>>> constraint might allow an unexpected type to "leak" into your function.
>>>
>>
>> I don't understand this assertion. It seems plain untrue to me. If we 
>> allowed you to write `fmt.Stringer | ~string` (and put a SAT solver into 
>> the compiler to do the appropriate checks) but otherwise not changed the 
>> language at all, then this would be accepted by the compiler:
>>
>> func Stringify[T interface{ ~string | fmt.Stringer}](v T) string {
>>     // still have to write the type switch
>>     switch v := any(v).(type) {
>>     case fmt.Stringer:
>>         return v.String()
>>     default:
>>         return reflect.ValueOf(v).String()
>>     }
>> }
>>
>> This is of course somewhat error prone, you might easily forget a branch 
>> or otherwise screw up the logic of your function. But it would mean this is 
>> rejected by the compiler:
>>
>> func main() {
>>     println(Stringify[int](42))
>> }
>>
>> If, instead, you use `T any`, this program would be allowed and panic at 
>> runtime.
>>  
>>
>>> If the O.P.'s example was supported by the compilation toolchain that 
>>> might be impossible, in theory, but I would assume it's still possible if I 
>>> have to write code to disambiguate which type I received.
>>>
>>> -- 
>>> Kurtis Rader
>>> Caretaker of the exceptional canines Junior and Hank
>>>
>>
>
> -- 
> Kurtis Rader
> Caretaker of the exceptional canines Junior and Hank
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/golang-nuts/12e6fa3a-8599-4ff3-8547-84297e53201an%40googlegroups.com.

Reply via email to