Dear golang nuts,
I was trying to gain a better understanding of how cgo works internally, when I stumbled upon this implementation detail:
```
case kindStruct:
st := (*structtype)(unsafe.Pointer(t))
if !indir {
if len(st.Fields) != 1 {
throw("can't happen")
}
cgoCheckArg(st.Fields[0].Typ, p, st.Fields[0].Typ.Kind_&kindDirectIface == 0, top, msg)
return
}
```
This is inside the function where an argument passed to C is checked for whether it is/contains a pointer to memory containing unpinned go pointers. In this specific switch-case, the type of the object being checked is a struct (t.Kind_ is kindStruct). Furthermore,
this is the !indir-branch, which indicates that p is actually the struct itself and not a pointer to it, i.e. the entire struct is stored within p, and the struct has only one field. My question is specifically about the the recursive call
`cgoCheckArg(st.Fields[0].Typ, p, st.Fields[0].Typ.Kind_&kindDirectIface == 0, top, msg)`
I don't understand why it should be possible here for the third ("indir") argument to be true? What would be a case in which this being set to true is not contradictory?
When the structs' field's type is not a kindDirectIface, the recursive call is performed with arguments (st.Fields[0].Typ, p, true, ...). That means, we are indicating that p is a pointer to a value of type st.Fields[0].Typ. But in the current, enclosing call of the function, we are in the "!indir"-branch, meaning that p is exactly the struct value, which is exactly the value of its first (and only) field. So we know p is semantically of type st.Fields[0].Typ, not of type "pointer to st.Fields[0].Typ". Isn't this a contradiction? How can p be both a pointer to a st.Fields[0].Typ and be equal to a struct whose only field has type st.Fields[0].Typ?
The only explanation I can see is that either st.Fields[0].Typ.Kind_&kindDirectIface == 0 is (almost) always false in practice, and this line catches a very special case, or that there are cases in which st.Fields[0].Typ contains the value "type Bar" even though the actual field's value is semantically "pointer to Bar" and not "Bar".
I apologize for the admittedly extremely specific question. I would really appreciate if someone who is knowledgable about the internals could have a look at this.
Thanks a lot for your time.
Best Regards,
JC