The underlying type is defined recursively
<https://golang.org/ref/spec#Types>:

Each type T has an underlying type: If T is one of the predeclared boolean,
> numeric, or string types, or a type literal, the corresponding underlying
> type is T itself. Otherwise, T's underlying type is *the underlying type
> of the type* to which T refers in its type declaration.


 (emphasis mine). From a type-system perspective, there is no real
difference between these two types. The Go type system treats them the same.

So, if you need to differentiate between them, you have to go back from the
types-level to the AST level. That's unfortunately a bit difficult, AFAIK.
I think you have to use the `token.Pos` of the `*TypeName` and then
traverse the `ast.File`s of the package until you find that position. That
should give you an `ast.TypeSpec`, which can tell you if its `Type` field
is an identifier, or a type literal. Not super ergonomic, but AFAIK the
only way.

On Tue, Sep 21, 2021 at 3:47 PM 'Sebastien Binet' via golang-nuts <
golang-nuts@googlegroups.com> wrote:

> hi there,
>
> I am a bit confused by go/types and defined named types:
>
> https://play.golang.org/p/izESp473jOq
>
> the above link shows a program using the go/types package and shows how
> the four types T0, T1, T2 and T3:
>
> ```
> package p
>
> type T0 struct { F int}
> type T1 struct { T0 }
> type T2 T1
> type T3 T0
> ```
>
> map to types defined in go/types:
>
> T0: type p.T0 struct{F int} -- obj=*types.TypeName typ=*types.Named --
> under=*types.Struct
> T1: type p.T1 struct{p.T0}  -- obj=*types.TypeName typ=*types.Named --
> under=*types.Struct
> T2: type p.T2 struct{p.T0}  -- obj=*types.TypeName typ=*types.Named --
> under=*types.Struct
> T3: type p.T3 struct{F int} -- obj=*types.TypeName typ=*types.Named --
> under=*types.Struct
>
> how would I use go/types to differentiate between T1 and T2?
> they are 2 named types whose underlying types are (eventually):
>  'struct { T0 }'
>
> but, from the doc string of Type.Underlying:
> ```
> // Underlying returns the underlying type of a type
> // w/o following forwarding chains. Only used by
> // client packages (here for backward-compatibility).
> ```
>
> I was actually expecting to get:
> - *types.Struct for t1.Underlying()
> - *types.Named  for t2.Underlying()
>
> so: how could I differentiate between a named type that's defined from
> another named type and one that's defined (directly) from a struct ?
>
>
> --
> 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/CEFLY6WPOVY6.1VEGTAPD57RSO%40clrinfopc42
> .
>

-- 
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/CAEkBMfHU%3DeYODRyy48XM0F1-u4xDd6F-LKVsLcThXkDRcUOADQ%40mail.gmail.com.

Reply via email to