Source file src/go/internal/gcimporter/ureader.go

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package gcimporter
     6  
     7  import (
     8  	"go/token"
     9  	"go/types"
    10  	"internal/godebug"
    11  	"internal/pkgbits"
    12  	"sort"
    13  )
    14  
    15  // A pkgReader holds the shared state for reading a unified IR package
    16  // description.
    17  type pkgReader struct {
    18  	pkgbits.PkgDecoder
    19  
    20  	fake fakeFileSet
    21  
    22  	ctxt    *types.Context
    23  	imports map[string]*types.Package // previously imported packages, indexed by path
    24  
    25  	// lazily initialized arrays corresponding to the unified IR
    26  	// PosBase, Pkg, and Type sections, respectively.
    27  	posBases []string // position bases (i.e., file names)
    28  	pkgs     []*types.Package
    29  	typs     []types.Type
    30  
    31  	// laterFns holds functions that need to be invoked at the end of
    32  	// import reading.
    33  	laterFns []func()
    34  
    35  	// ifaces holds a list of constructed Interfaces, which need to have
    36  	// Complete called after importing is done.
    37  	ifaces []*types.Interface
    38  }
    39  
    40  // later adds a function to be invoked at the end of import reading.
    41  func (pr *pkgReader) later(fn func()) {
    42  	pr.laterFns = append(pr.laterFns, fn)
    43  }
    44  
    45  // readUnifiedPackage reads a package description from the given
    46  // unified IR export data decoder.
    47  func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[string]*types.Package, input pkgbits.PkgDecoder) *types.Package {
    48  	pr := pkgReader{
    49  		PkgDecoder: input,
    50  
    51  		fake: fakeFileSet{
    52  			fset:  fset,
    53  			files: make(map[string]*fileInfo),
    54  		},
    55  
    56  		ctxt:    ctxt,
    57  		imports: imports,
    58  
    59  		posBases: make([]string, input.NumElems(pkgbits.RelocPosBase)),
    60  		pkgs:     make([]*types.Package, input.NumElems(pkgbits.RelocPkg)),
    61  		typs:     make([]types.Type, input.NumElems(pkgbits.RelocType)),
    62  	}
    63  	defer pr.fake.setLines()
    64  
    65  	r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
    66  	pkg := r.pkg()
    67  	r.Bool() // TODO(mdempsky): Remove; was "has init"
    68  
    69  	for i, n := 0, r.Len(); i < n; i++ {
    70  		// As if r.obj(), but avoiding the Scope.Lookup call,
    71  		// to avoid eager loading of imports.
    72  		r.Sync(pkgbits.SyncObject)
    73  		assert(!r.Bool())
    74  		r.p.objIdx(r.Reloc(pkgbits.RelocObj))
    75  		assert(r.Len() == 0)
    76  	}
    77  
    78  	r.Sync(pkgbits.SyncEOF)
    79  
    80  	for _, fn := range pr.laterFns {
    81  		fn()
    82  	}
    83  
    84  	for _, iface := range pr.ifaces {
    85  		iface.Complete()
    86  	}
    87  
    88  	// Imports() of pkg are all of the transitive packages that were loaded.
    89  	var imps []*types.Package
    90  	for _, imp := range pr.pkgs {
    91  		if imp != nil && imp != pkg {
    92  			imps = append(imps, imp)
    93  		}
    94  	}
    95  	sort.Sort(byPath(imps))
    96  	pkg.SetImports(imps)
    97  
    98  	pkg.MarkComplete()
    99  	return pkg
   100  }
   101  
   102  // A reader holds the state for reading a single unified IR element
   103  // within a package.
   104  type reader struct {
   105  	pkgbits.Decoder
   106  
   107  	p *pkgReader
   108  
   109  	dict *readerDict
   110  }
   111  
   112  // A readerDict holds the state for type parameters that parameterize
   113  // the current unified IR element.
   114  type readerDict struct {
   115  	// bounds is a slice of typeInfos corresponding to the underlying
   116  	// bounds of the element's type parameters.
   117  	bounds []typeInfo
   118  
   119  	// tparams is a slice of the constructed TypeParams for the element.
   120  	tparams []*types.TypeParam
   121  
   122  	// derived is a slice of types derived from tparams, which may be
   123  	// instantiated while reading the current element.
   124  	derived      []derivedInfo
   125  	derivedTypes []types.Type // lazily instantiated from derived
   126  }
   127  
   128  func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {
   129  	return &reader{
   130  		Decoder: pr.NewDecoder(k, idx, marker),
   131  		p:       pr,
   132  	}
   133  }
   134  
   135  func (pr *pkgReader) tempReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {
   136  	return &reader{
   137  		Decoder: pr.TempDecoder(k, idx, marker),
   138  		p:       pr,
   139  	}
   140  }
   141  
   142  func (pr *pkgReader) retireReader(r *reader) {
   143  	pr.RetireDecoder(&r.Decoder)
   144  }
   145  
   146  // @@@ Positions
   147  
   148  func (r *reader) pos() token.Pos {
   149  	r.Sync(pkgbits.SyncPos)
   150  	if !r.Bool() {
   151  		return token.NoPos
   152  	}
   153  
   154  	// TODO(mdempsky): Delta encoding.
   155  	posBase := r.posBase()
   156  	line := r.Uint()
   157  	col := r.Uint()
   158  	return r.p.fake.pos(posBase, int(line), int(col))
   159  }
   160  
   161  func (r *reader) posBase() string {
   162  	return r.p.posBaseIdx(r.Reloc(pkgbits.RelocPosBase))
   163  }
   164  
   165  func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) string {
   166  	if b := pr.posBases[idx]; b != "" {
   167  		return b
   168  	}
   169  
   170  	var filename string
   171  	{
   172  		r := pr.tempReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase)
   173  
   174  		// Within types2, position bases have a lot more details (e.g.,
   175  		// keeping track of where //line directives appeared exactly).
   176  		//
   177  		// For go/types, we just track the file name.
   178  
   179  		filename = r.String()
   180  
   181  		if r.Bool() { // file base
   182  			// Was: "b = token.NewTrimmedFileBase(filename, true)"
   183  		} else { // line base
   184  			pos := r.pos()
   185  			line := r.Uint()
   186  			col := r.Uint()
   187  
   188  			// Was: "b = token.NewLineBase(pos, filename, true, line, col)"
   189  			_, _, _ = pos, line, col
   190  		}
   191  		pr.retireReader(r)
   192  	}
   193  	b := filename
   194  	pr.posBases[idx] = b
   195  	return b
   196  }
   197  
   198  // @@@ Packages
   199  
   200  func (r *reader) pkg() *types.Package {
   201  	r.Sync(pkgbits.SyncPkg)
   202  	return r.p.pkgIdx(r.Reloc(pkgbits.RelocPkg))
   203  }
   204  
   205  func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types.Package {
   206  	// TODO(mdempsky): Consider using some non-nil pointer to indicate
   207  	// the universe scope, so we don't need to keep re-reading it.
   208  	if pkg := pr.pkgs[idx]; pkg != nil {
   209  		return pkg
   210  	}
   211  
   212  	pkg := pr.newReader(pkgbits.RelocPkg, idx, pkgbits.SyncPkgDef).doPkg()
   213  	pr.pkgs[idx] = pkg
   214  	return pkg
   215  }
   216  
   217  func (r *reader) doPkg() *types.Package {
   218  	path := r.String()
   219  	switch path {
   220  	case "":
   221  		path = r.p.PkgPath()
   222  	case "builtin":
   223  		return nil // universe
   224  	case "unsafe":
   225  		return types.Unsafe
   226  	}
   227  
   228  	if pkg := r.p.imports[path]; pkg != nil {
   229  		return pkg
   230  	}
   231  
   232  	name := r.String()
   233  
   234  	pkg := types.NewPackage(path, name)
   235  	r.p.imports[path] = pkg
   236  
   237  	return pkg
   238  }
   239  
   240  // @@@ Types
   241  
   242  func (r *reader) typ() types.Type {
   243  	return r.p.typIdx(r.typInfo(), r.dict)
   244  }
   245  
   246  func (r *reader) typInfo() typeInfo {
   247  	r.Sync(pkgbits.SyncType)
   248  	if r.Bool() {
   249  		return typeInfo{idx: pkgbits.Index(r.Len()), derived: true}
   250  	}
   251  	return typeInfo{idx: r.Reloc(pkgbits.RelocType), derived: false}
   252  }
   253  
   254  func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types.Type {
   255  	idx := info.idx
   256  	var where *types.Type
   257  	if info.derived {
   258  		where = &dict.derivedTypes[idx]
   259  		idx = dict.derived[idx].idx
   260  	} else {
   261  		where = &pr.typs[idx]
   262  	}
   263  
   264  	if typ := *where; typ != nil {
   265  		return typ
   266  	}
   267  
   268  	var typ types.Type
   269  	{
   270  		r := pr.tempReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx)
   271  		r.dict = dict
   272  
   273  		typ = r.doTyp()
   274  		assert(typ != nil)
   275  		pr.retireReader(r)
   276  	}
   277  	// See comment in pkgReader.typIdx explaining how this happens.
   278  	if prev := *where; prev != nil {
   279  		return prev
   280  	}
   281  
   282  	*where = typ
   283  	return typ
   284  }
   285  
   286  func (r *reader) doTyp() (res types.Type) {
   287  	switch tag := pkgbits.CodeType(r.Code(pkgbits.SyncType)); tag {
   288  	default:
   289  		errorf("unhandled type tag: %v", tag)
   290  		panic("unreachable")
   291  
   292  	case pkgbits.TypeBasic:
   293  		return types.Typ[r.Len()]
   294  
   295  	case pkgbits.TypeNamed:
   296  		obj, targs := r.obj()
   297  		name := obj.(*types.TypeName)
   298  		if len(targs) != 0 {
   299  			t, _ := types.Instantiate(r.p.ctxt, name.Type(), targs, false)
   300  			return t
   301  		}
   302  		return name.Type()
   303  
   304  	case pkgbits.TypeTypeParam:
   305  		return r.dict.tparams[r.Len()]
   306  
   307  	case pkgbits.TypeArray:
   308  		len := int64(r.Uint64())
   309  		return types.NewArray(r.typ(), len)
   310  	case pkgbits.TypeChan:
   311  		dir := types.ChanDir(r.Len())
   312  		return types.NewChan(dir, r.typ())
   313  	case pkgbits.TypeMap:
   314  		return types.NewMap(r.typ(), r.typ())
   315  	case pkgbits.TypePointer:
   316  		return types.NewPointer(r.typ())
   317  	case pkgbits.TypeSignature:
   318  		return r.signature(nil, nil, nil)
   319  	case pkgbits.TypeSlice:
   320  		return types.NewSlice(r.typ())
   321  	case pkgbits.TypeStruct:
   322  		return r.structType()
   323  	case pkgbits.TypeInterface:
   324  		return r.interfaceType()
   325  	case pkgbits.TypeUnion:
   326  		return r.unionType()
   327  	}
   328  }
   329  
   330  func (r *reader) structType() *types.Struct {
   331  	fields := make([]*types.Var, r.Len())
   332  	var tags []string
   333  	for i := range fields {
   334  		pos := r.pos()
   335  		pkg, name := r.selector()
   336  		ftyp := r.typ()
   337  		tag := r.String()
   338  		embedded := r.Bool()
   339  
   340  		fields[i] = types.NewField(pos, pkg, name, ftyp, embedded)
   341  		if tag != "" {
   342  			for len(tags) < i {
   343  				tags = append(tags, "")
   344  			}
   345  			tags = append(tags, tag)
   346  		}
   347  	}
   348  	return types.NewStruct(fields, tags)
   349  }
   350  
   351  func (r *reader) unionType() *types.Union {
   352  	terms := make([]*types.Term, r.Len())
   353  	for i := range terms {
   354  		terms[i] = types.NewTerm(r.Bool(), r.typ())
   355  	}
   356  	return types.NewUnion(terms)
   357  }
   358  
   359  func (r *reader) interfaceType() *types.Interface {
   360  	methods := make([]*types.Func, r.Len())
   361  	embeddeds := make([]types.Type, r.Len())
   362  	implicit := len(methods) == 0 && len(embeddeds) == 1 && r.Bool()
   363  
   364  	for i := range methods {
   365  		pos := r.pos()
   366  		pkg, name := r.selector()
   367  		mtyp := r.signature(nil, nil, nil)
   368  		methods[i] = types.NewFunc(pos, pkg, name, mtyp)
   369  	}
   370  
   371  	for i := range embeddeds {
   372  		embeddeds[i] = r.typ()
   373  	}
   374  
   375  	iface := types.NewInterfaceType(methods, embeddeds)
   376  	if implicit {
   377  		iface.MarkImplicit()
   378  	}
   379  
   380  	// We need to call iface.Complete(), but if there are any embedded
   381  	// defined types, then we may not have set their underlying
   382  	// interface type yet. So we need to defer calling Complete until
   383  	// after we've called SetUnderlying everywhere.
   384  	//
   385  	// TODO(mdempsky): After CL 424876 lands, it should be safe to call
   386  	// iface.Complete() immediately.
   387  	r.p.ifaces = append(r.p.ifaces, iface)
   388  
   389  	return iface
   390  }
   391  
   392  func (r *reader) signature(recv *types.Var, rtparams, tparams []*types.TypeParam) *types.Signature {
   393  	r.Sync(pkgbits.SyncSignature)
   394  
   395  	params := r.params()
   396  	results := r.params()
   397  	variadic := r.Bool()
   398  
   399  	return types.NewSignatureType(recv, rtparams, tparams, params, results, variadic)
   400  }
   401  
   402  func (r *reader) params() *types.Tuple {
   403  	r.Sync(pkgbits.SyncParams)
   404  
   405  	params := make([]*types.Var, r.Len())
   406  	for i := range params {
   407  		params[i] = r.param()
   408  	}
   409  
   410  	return types.NewTuple(params...)
   411  }
   412  
   413  func (r *reader) param() *types.Var {
   414  	r.Sync(pkgbits.SyncParam)
   415  
   416  	pos := r.pos()
   417  	pkg, name := r.localIdent()
   418  	typ := r.typ()
   419  
   420  	return types.NewParam(pos, pkg, name, typ)
   421  }
   422  
   423  // @@@ Objects
   424  
   425  func (r *reader) obj() (types.Object, []types.Type) {
   426  	r.Sync(pkgbits.SyncObject)
   427  
   428  	assert(!r.Bool())
   429  
   430  	pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj))
   431  	obj := pkgScope(pkg).Lookup(name)
   432  
   433  	targs := make([]types.Type, r.Len())
   434  	for i := range targs {
   435  		targs[i] = r.typ()
   436  	}
   437  
   438  	return obj, targs
   439  }
   440  
   441  func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
   442  
   443  	var objPkg *types.Package
   444  	var objName string
   445  	var tag pkgbits.CodeObj
   446  	{
   447  		rname := pr.tempReader(pkgbits.RelocName, idx, pkgbits.SyncObject1)
   448  
   449  		objPkg, objName = rname.qualifiedIdent()
   450  		assert(objName != "")
   451  
   452  		tag = pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
   453  		pr.retireReader(rname)
   454  	}
   455  
   456  	if tag == pkgbits.ObjStub {
   457  		assert(objPkg == nil || objPkg == types.Unsafe)
   458  		return objPkg, objName
   459  	}
   460  
   461  	// Ignore local types promoted to global scope (#55110).
   462  	if _, suffix := splitVargenSuffix(objName); suffix != "" {
   463  		return objPkg, objName
   464  	}
   465  
   466  	if objPkg.Scope().Lookup(objName) == nil {
   467  		dict := pr.objDictIdx(idx)
   468  
   469  		r := pr.newReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1)
   470  		r.dict = dict
   471  
   472  		declare := func(obj types.Object) {
   473  			objPkg.Scope().Insert(obj)
   474  		}
   475  
   476  		switch tag {
   477  		default:
   478  			panic("weird")
   479  
   480  		case pkgbits.ObjAlias:
   481  			pos := r.pos()
   482  			typ := r.typ()
   483  			declare(newAliasTypeName(pos, objPkg, objName, typ))
   484  
   485  		case pkgbits.ObjConst:
   486  			pos := r.pos()
   487  			typ := r.typ()
   488  			val := r.Value()
   489  			declare(types.NewConst(pos, objPkg, objName, typ, val))
   490  
   491  		case pkgbits.ObjFunc:
   492  			pos := r.pos()
   493  			tparams := r.typeParamNames()
   494  			sig := r.signature(nil, nil, tparams)
   495  			declare(types.NewFunc(pos, objPkg, objName, sig))
   496  
   497  		case pkgbits.ObjType:
   498  			pos := r.pos()
   499  
   500  			obj := types.NewTypeName(pos, objPkg, objName, nil)
   501  			named := types.NewNamed(obj, nil, nil)
   502  			declare(obj)
   503  
   504  			named.SetTypeParams(r.typeParamNames())
   505  
   506  			underlying := r.typ().Underlying()
   507  
   508  			// If the underlying type is an interface, we need to
   509  			// duplicate its methods so we can replace the receiver
   510  			// parameter's type (#49906).
   511  			if iface, ok := underlying.(*types.Interface); ok && iface.NumExplicitMethods() != 0 {
   512  				methods := make([]*types.Func, iface.NumExplicitMethods())
   513  				for i := range methods {
   514  					fn := iface.ExplicitMethod(i)
   515  					sig := fn.Type().(*types.Signature)
   516  
   517  					recv := types.NewVar(fn.Pos(), fn.Pkg(), "", named)
   518  					methods[i] = types.NewFunc(fn.Pos(), fn.Pkg(), fn.Name(), types.NewSignature(recv, sig.Params(), sig.Results(), sig.Variadic()))
   519  				}
   520  
   521  				embeds := make([]types.Type, iface.NumEmbeddeds())
   522  				for i := range embeds {
   523  					embeds[i] = iface.EmbeddedType(i)
   524  				}
   525  
   526  				newIface := types.NewInterfaceType(methods, embeds)
   527  				r.p.ifaces = append(r.p.ifaces, newIface)
   528  				underlying = newIface
   529  			}
   530  
   531  			named.SetUnderlying(underlying)
   532  
   533  			for i, n := 0, r.Len(); i < n; i++ {
   534  				named.AddMethod(r.method())
   535  			}
   536  
   537  		case pkgbits.ObjVar:
   538  			pos := r.pos()
   539  			typ := r.typ()
   540  			declare(types.NewVar(pos, objPkg, objName, typ))
   541  		}
   542  	}
   543  
   544  	return objPkg, objName
   545  }
   546  
   547  func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
   548  
   549  	var dict readerDict
   550  
   551  	{
   552  		r := pr.tempReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1)
   553  		if implicits := r.Len(); implicits != 0 {
   554  			errorf("unexpected object with %v implicit type parameter(s)", implicits)
   555  		}
   556  
   557  		dict.bounds = make([]typeInfo, r.Len())
   558  		for i := range dict.bounds {
   559  			dict.bounds[i] = r.typInfo()
   560  		}
   561  
   562  		dict.derived = make([]derivedInfo, r.Len())
   563  		dict.derivedTypes = make([]types.Type, len(dict.derived))
   564  		for i := range dict.derived {
   565  			dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()}
   566  		}
   567  
   568  		pr.retireReader(r)
   569  	}
   570  	// function references follow, but reader doesn't need those
   571  
   572  	return &dict
   573  }
   574  
   575  func (r *reader) typeParamNames() []*types.TypeParam {
   576  	r.Sync(pkgbits.SyncTypeParamNames)
   577  
   578  	// Note: This code assumes it only processes objects without
   579  	// implement type parameters. This is currently fine, because
   580  	// reader is only used to read in exported declarations, which are
   581  	// always package scoped.
   582  
   583  	if len(r.dict.bounds) == 0 {
   584  		return nil
   585  	}
   586  
   587  	// Careful: Type parameter lists may have cycles. To allow for this,
   588  	// we construct the type parameter list in two passes: first we
   589  	// create all the TypeNames and TypeParams, then we construct and
   590  	// set the bound type.
   591  
   592  	r.dict.tparams = make([]*types.TypeParam, len(r.dict.bounds))
   593  	for i := range r.dict.bounds {
   594  		pos := r.pos()
   595  		pkg, name := r.localIdent()
   596  
   597  		tname := types.NewTypeName(pos, pkg, name, nil)
   598  		r.dict.tparams[i] = types.NewTypeParam(tname, nil)
   599  	}
   600  
   601  	typs := make([]types.Type, len(r.dict.bounds))
   602  	for i, bound := range r.dict.bounds {
   603  		typs[i] = r.p.typIdx(bound, r.dict)
   604  	}
   605  
   606  	// TODO(mdempsky): This is subtle, elaborate further.
   607  	//
   608  	// We have to save tparams outside of the closure, because
   609  	// typeParamNames() can be called multiple times with the same
   610  	// dictionary instance.
   611  	//
   612  	// Also, this needs to happen later to make sure SetUnderlying has
   613  	// been called.
   614  	//
   615  	// TODO(mdempsky): Is it safe to have a single "later" slice or do
   616  	// we need to have multiple passes? See comments on CL 386002 and
   617  	// go.dev/issue/52104.
   618  	tparams := r.dict.tparams
   619  	r.p.later(func() {
   620  		for i, typ := range typs {
   621  			tparams[i].SetConstraint(typ)
   622  		}
   623  	})
   624  
   625  	return r.dict.tparams
   626  }
   627  
   628  func (r *reader) method() *types.Func {
   629  	r.Sync(pkgbits.SyncMethod)
   630  	pos := r.pos()
   631  	pkg, name := r.selector()
   632  
   633  	rparams := r.typeParamNames()
   634  	sig := r.signature(r.param(), rparams, nil)
   635  
   636  	_ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go.
   637  	return types.NewFunc(pos, pkg, name, sig)
   638  }
   639  
   640  func (r *reader) qualifiedIdent() (*types.Package, string) { return r.ident(pkgbits.SyncSym) }
   641  func (r *reader) localIdent() (*types.Package, string)     { return r.ident(pkgbits.SyncLocalIdent) }
   642  func (r *reader) selector() (*types.Package, string)       { return r.ident(pkgbits.SyncSelector) }
   643  
   644  func (r *reader) ident(marker pkgbits.SyncMarker) (*types.Package, string) {
   645  	r.Sync(marker)
   646  	return r.pkg(), r.String()
   647  }
   648  
   649  // pkgScope returns pkg.Scope().
   650  // If pkg is nil, it returns types.Universe instead.
   651  //
   652  // TODO(mdempsky): Remove after x/tools can depend on Go 1.19.
   653  func pkgScope(pkg *types.Package) *types.Scope {
   654  	if pkg != nil {
   655  		return pkg.Scope()
   656  	}
   657  	return types.Universe
   658  }
   659  
   660  // newAliasTypeName returns a new TypeName, with a materialized *types.Alias if supported.
   661  func newAliasTypeName(pos token.Pos, pkg *types.Package, name string, rhs types.Type) *types.TypeName {
   662  	// When GODEBUG=gotypesalias=1 or unset, the Type() of the return value is a
   663  	// *types.Alias. Copied from x/tools/internal/aliases.NewAlias.
   664  	switch godebug.New("gotypesalias").Value() {
   665  	case "", "1":
   666  		tname := types.NewTypeName(pos, pkg, name, nil)
   667  		_ = types.NewAlias(tname, rhs) // form TypeName -> Alias cycle
   668  		return tname
   669  	}
   670  	return types.NewTypeName(pos, pkg, name, rhs)
   671  }
   672  

View as plain text