Dear golang nuts,

I was trying to gain a better understanding of how cgo works internally, 
when I stumbled upon this implementation detail:
https://github.com/golang/go/blob/8db131082d08e497fd8e9383d0ff7715e1bef478/src/runtime/cgocall.go#L628

```
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


-- 
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 golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/7c63b691-a37d-46ae-8843-3d2177ecd3e1n%40googlegroups.com.

Reply via email to