Source file src/cmd/compile/internal/noder/types.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 noder
     6  
     7  import (
     8  	"cmd/compile/internal/base"
     9  	"cmd/compile/internal/ir"
    10  	"cmd/compile/internal/typecheck"
    11  	"cmd/compile/internal/types"
    12  	"cmd/compile/internal/types2"
    13  	"cmd/internal/src"
    14  	"strings"
    15  )
    16  
    17  func (g *irgen) pkg(pkg *types2.Package) *types.Pkg {
    18  	switch pkg {
    19  	case nil:
    20  		return types.BuiltinPkg
    21  	case g.self:
    22  		return types.LocalPkg
    23  	case types2.Unsafe:
    24  		return types.UnsafePkg
    25  	}
    26  	return types.NewPkg(pkg.Path(), pkg.Name())
    27  }
    28  
    29  var universeAny = types2.Universe.Lookup("any").Type()
    30  
    31  // typ converts a types2.Type to a types.Type, including caching of previously
    32  // translated types.
    33  func (g *irgen) typ(typ types2.Type) *types.Type {
    34  	// Defer the CheckSize calls until we have fully-defined a
    35  	// (possibly-recursive) top-level type.
    36  	types.DeferCheckSize()
    37  	res := g.typ1(typ)
    38  	types.ResumeCheckSize()
    39  
    40  	// Finish up any types on typesToFinalize, now that we are at the top of a
    41  	// fully-defined (possibly recursive) type. fillinMethods could create more
    42  	// types to finalize.
    43  	for len(g.typesToFinalize) > 0 {
    44  		l := len(g.typesToFinalize)
    45  		info := g.typesToFinalize[l-1]
    46  		g.typesToFinalize = g.typesToFinalize[:l-1]
    47  		types.DeferCheckSize()
    48  		g.fillinMethods(info.typ, info.ntyp)
    49  		types.ResumeCheckSize()
    50  	}
    51  	return res
    52  }
    53  
    54  // typ1 is like typ, but doesn't call CheckSize, since it may have only
    55  // constructed part of a recursive type. Should not be called from outside this
    56  // file (g.typ is the "external" entry point).
    57  func (g *irgen) typ1(typ types2.Type) *types.Type {
    58  	// See issue 49583: the type checker has trouble keeping track of aliases,
    59  	// but for such a common alias as any we can improve things by preserving a
    60  	// pointer identity that can be checked when formatting type strings.
    61  	if typ == universeAny {
    62  		return types.AnyType
    63  	}
    64  	// Cache type2-to-type mappings. Important so that each defined generic
    65  	// type (instantiated or not) has a single types.Type representation.
    66  	// Also saves a lot of computation and memory by avoiding re-translating
    67  	// types2 types repeatedly.
    68  	res, ok := g.typs[typ]
    69  	if !ok {
    70  		res = g.typ0(typ)
    71  		// Calculate the size for all concrete types seen by the frontend.
    72  		// This is the replacement for the CheckSize() calls in the types1
    73  		// typechecker. These will be deferred until the top-level g.typ().
    74  		if res != nil && !res.IsUntyped() && !res.IsFuncArgStruct() && !res.HasTParam() {
    75  			types.CheckSize(res)
    76  		}
    77  		g.typs[typ] = res
    78  	}
    79  	return res
    80  }
    81  
    82  // instTypeName2 creates a name for an instantiated type, base on the type args
    83  // (given as types2 types).
    84  func (g *irgen) instTypeName2(name string, targs *types2.TypeList) string {
    85  	rparams := make([]*types.Type, targs.Len())
    86  	for i := range rparams {
    87  		rparams[i] = g.typ(targs.At(i))
    88  	}
    89  	return typecheck.InstTypeName(name, rparams)
    90  }
    91  
    92  // typ0 converts a types2.Type to a types.Type, but doesn't do the caching check
    93  // at the top level.
    94  func (g *irgen) typ0(typ types2.Type) *types.Type {
    95  	switch typ := typ.(type) {
    96  	case *types2.Basic:
    97  		return g.basic(typ)
    98  	case *types2.Named:
    99  		// If tparams is set, but targs is not, typ is a base generic
   100  		// type. typ is appearing as part of the source type of an alias,
   101  		// since that is the only use of a generic type that doesn't
   102  		// involve instantiation. We just translate the named type in the
   103  		// normal way below using g.obj().
   104  		if typ.TypeParams() != nil && typ.TypeArgs() != nil {
   105  			// typ is an instantiation of a defined (named) generic type.
   106  			// This instantiation should also be a defined (named) type.
   107  			// types2 gives us the substituted type in t.Underlying()
   108  			// The substituted type may or may not still have type
   109  			// params. We might, for example, be substituting one type
   110  			// param for another type param.
   111  			//
   112  			// When converted to types.Type, typ has a unique name,
   113  			// based on the names of the type arguments.
   114  			instName := g.instTypeName2(typ.Obj().Name(), typ.TypeArgs())
   115  			s := g.pkg(typ.Obj().Pkg()).Lookup(instName)
   116  
   117  			// Make sure the base generic type exists in type1 (it may
   118  			// not yet if we are referecing an imported generic type, as
   119  			// opposed to a generic type declared in this package). Make
   120  			// sure to do this lookup before checking s.Def, in case
   121  			// s.Def gets defined while importing base (if an imported
   122  			// type). (Issue #50486).
   123  			base := g.obj(typ.Origin().Obj())
   124  
   125  			if s.Def != nil {
   126  				// We have already encountered this instantiation.
   127  				// Use the type we previously created, since there
   128  				// must be exactly one instance of a defined type.
   129  				return s.Def.Type()
   130  			}
   131  
   132  			if base.Class == ir.PAUTO {
   133  				// If the base type is a local type, we want to pop
   134  				// this instantiated type symbol/definition when we
   135  				// leave the containing block, so we don't use it
   136  				// incorrectly later.
   137  				types.Pushdcl(s)
   138  			}
   139  
   140  			// Create a forwarding type first and put it in the g.typs
   141  			// map, in order to deal with recursive generic types
   142  			// (including via method signatures). Set up the extra
   143  			// ntyp information (Def, RParams, which may set
   144  			// HasTParam) before translating the underlying type
   145  			// itself, so we handle recursion correctly.
   146  			ntyp := typecheck.NewIncompleteNamedType(g.pos(typ.Obj().Pos()), s)
   147  			g.typs[typ] = ntyp
   148  
   149  			// If ntyp still has type params, then we must be
   150  			// referencing something like 'value[T2]', as when
   151  			// specifying the generic receiver of a method, where
   152  			// value was defined as "type value[T any] ...". Save the
   153  			// type args, which will now be the new typeparams of the
   154  			// current type.
   155  			//
   156  			// If ntyp does not have type params, we are saving the
   157  			// non-generic types used to instantiate this type. We'll
   158  			// use these when instantiating the methods of the
   159  			// instantiated type.
   160  			targs := typ.TypeArgs()
   161  			rparams := make([]*types.Type, targs.Len())
   162  			for i := range rparams {
   163  				rparams[i] = g.typ1(targs.At(i))
   164  			}
   165  			ntyp.SetRParams(rparams)
   166  			//fmt.Printf("Saw new type %v %v\n", instName, ntyp.HasTParam())
   167  
   168  			// Save the symbol for the base generic type.
   169  			ntyp.SetOrigType(base.Type())
   170  			ntyp.SetUnderlying(g.typ1(typ.Underlying()))
   171  			if typ.NumMethods() != 0 {
   172  				// Save a delayed call to g.fillinMethods() (once
   173  				// potentially recursive types have been fully
   174  				// resolved).
   175  				g.typesToFinalize = append(g.typesToFinalize,
   176  					&typeDelayInfo{
   177  						typ:  typ,
   178  						ntyp: ntyp,
   179  					})
   180  			}
   181  			return ntyp
   182  		}
   183  		obj := g.obj(typ.Obj())
   184  		if obj.Op() != ir.OTYPE {
   185  			base.FatalfAt(obj.Pos(), "expected type: %L", obj)
   186  		}
   187  		return obj.Type()
   188  
   189  	case *types2.Array:
   190  		return types.NewArray(g.typ1(typ.Elem()), typ.Len())
   191  	case *types2.Chan:
   192  		return types.NewChan(g.typ1(typ.Elem()), dirs[typ.Dir()])
   193  	case *types2.Map:
   194  		return types.NewMap(g.typ1(typ.Key()), g.typ1(typ.Elem()))
   195  	case *types2.Pointer:
   196  		return types.NewPtr(g.typ1(typ.Elem()))
   197  	case *types2.Signature:
   198  		return g.signature(nil, typ)
   199  	case *types2.Slice:
   200  		return types.NewSlice(g.typ1(typ.Elem()))
   201  
   202  	case *types2.Struct:
   203  		fields := make([]*types.Field, typ.NumFields())
   204  		for i := range fields {
   205  			v := typ.Field(i)
   206  			f := types.NewField(g.pos(v), g.selector(v), g.typ1(v.Type()))
   207  			f.Note = typ.Tag(i)
   208  			if v.Embedded() {
   209  				f.Embedded = 1
   210  			}
   211  			fields[i] = f
   212  		}
   213  		return types.NewStruct(g.tpkg(typ), fields)
   214  
   215  	case *types2.Interface:
   216  		embeddeds := make([]*types.Field, typ.NumEmbeddeds())
   217  		j := 0
   218  		for i := range embeddeds {
   219  			// TODO(mdempsky): Get embedding position.
   220  			e := typ.EmbeddedType(i)
   221  
   222  			// With Go 1.18, an embedded element can be any type, not
   223  			// just an interface.
   224  			embeddeds[j] = types.NewField(src.NoXPos, nil, g.typ1(e))
   225  			j++
   226  		}
   227  		embeddeds = embeddeds[:j]
   228  
   229  		methods := make([]*types.Field, typ.NumExplicitMethods())
   230  		for i := range methods {
   231  			m := typ.ExplicitMethod(i)
   232  			mtyp := g.signature(types.FakeRecv(), m.Type().(*types2.Signature))
   233  			methods[i] = types.NewField(g.pos(m), g.selector(m), mtyp)
   234  		}
   235  
   236  		return types.NewInterface(g.tpkg(typ), append(embeddeds, methods...), typ.IsImplicit())
   237  
   238  	case *types2.TypeParam:
   239  		// Save the name of the type parameter in the sym of the type.
   240  		// Include the types2 subscript in the sym name
   241  		pkg := g.tpkg(typ)
   242  		// Create the unique types1 name for a type param, using its context
   243  		// with a function, type, or method declaration. Also, map blank type
   244  		// param names to a unique name based on their type param index. The
   245  		// unique blank names will be exported, but will be reverted during
   246  		// types2 and gcimporter import.
   247  		assert(g.curDecl != "")
   248  		nm := typecheck.TparamExportName(g.curDecl, typ.Obj().Name(), typ.Index())
   249  		sym := pkg.Lookup(nm)
   250  		if sym.Def != nil {
   251  			// Make sure we use the same type param type for the same
   252  			// name, whether it is created during types1-import or
   253  			// this types2-to-types1 translation.
   254  			return sym.Def.Type()
   255  		}
   256  		tp := types.NewTypeParam(sym, typ.Index())
   257  		nname := ir.NewDeclNameAt(g.pos(typ.Obj().Pos()), ir.OTYPE, sym)
   258  		sym.Def = nname
   259  		nname.SetType(tp)
   260  		tp.SetNod(nname)
   261  		// Set g.typs[typ] in case the bound methods reference typ.
   262  		g.typs[typ] = tp
   263  
   264  		bound := g.typ1(typ.Constraint())
   265  		tp.SetBound(bound)
   266  		return tp
   267  
   268  	case *types2.Union:
   269  		nt := typ.Len()
   270  		tlist := make([]*types.Type, nt)
   271  		tildes := make([]bool, nt)
   272  		for i := range tlist {
   273  			t := typ.Term(i)
   274  			tlist[i] = g.typ1(t.Type())
   275  			tildes[i] = t.Tilde()
   276  		}
   277  		return types.NewUnion(tlist, tildes)
   278  
   279  	case *types2.Tuple:
   280  		// Tuples are used for the type of a function call (i.e. the
   281  		// return value of the function).
   282  		if typ == nil {
   283  			return (*types.Type)(nil)
   284  		}
   285  		fields := make([]*types.Field, typ.Len())
   286  		for i := range fields {
   287  			fields[i] = g.param(typ.At(i))
   288  		}
   289  		t := types.NewStruct(types.LocalPkg, fields)
   290  		t.StructType().Funarg = types.FunargResults
   291  		return t
   292  
   293  	default:
   294  		base.FatalfAt(src.NoXPos, "unhandled type: %v (%T)", typ, typ)
   295  		panic("unreachable")
   296  	}
   297  }
   298  
   299  // fillinMethods fills in the method name nodes and types for a defined type with at
   300  // least one method. This is needed for later typechecking when looking up methods of
   301  // instantiated types, and for actually generating the methods for instantiated
   302  // types.
   303  func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) {
   304  	targs2 := typ.TypeArgs()
   305  	targs := make([]*types.Type, targs2.Len())
   306  	for i := range targs {
   307  		targs[i] = g.typ1(targs2.At(i))
   308  	}
   309  
   310  	methods := make([]*types.Field, typ.NumMethods())
   311  	for i := range methods {
   312  		m := typ.Method(i)
   313  		recvType := deref2(types2.AsSignature(m.Type()).Recv().Type())
   314  		var meth *ir.Name
   315  		imported := false
   316  		if m.Pkg() != g.self {
   317  			// Imported methods cannot be loaded by name (what
   318  			// g.obj() does) - they must be loaded via their
   319  			// type.
   320  			meth = g.obj(recvType.(*types2.Named).Obj()).Type().Methods().Index(i).Nname.(*ir.Name)
   321  			// XXX Because Obj() returns the object of the base generic
   322  			// type, we have to still do the method translation below.
   323  			imported = true
   324  		} else {
   325  			meth = g.obj(m)
   326  		}
   327  		assert(recvType == types2.Type(typ))
   328  		if imported {
   329  			// Unfortunately, meth is the type of the method of the
   330  			// generic type, so we have to do a substitution to get
   331  			// the name/type of the method of the instantiated type,
   332  			// using m.Type().RParams() and typ.TArgs()
   333  			inst2 := g.instTypeName2("", typ.TypeArgs())
   334  			name := meth.Sym().Name
   335  			i1 := strings.Index(name, "[")
   336  			i2 := strings.Index(name[i1:], "]")
   337  			assert(i1 >= 0 && i2 >= 0)
   338  			// Generate the name of the instantiated method.
   339  			name = name[0:i1] + inst2 + name[i1+i2+1:]
   340  			newsym := meth.Sym().Pkg.Lookup(name)
   341  			var meth2 *ir.Name
   342  			if newsym.Def != nil {
   343  				meth2 = newsym.Def.(*ir.Name)
   344  			} else {
   345  				meth2 = ir.NewNameAt(meth.Pos(), newsym)
   346  				rparams := types2.AsSignature(m.Type()).RecvTypeParams()
   347  				tparams := make([]*types.Type, rparams.Len())
   348  				// Set g.curDecl to be the method context, so type
   349  				// params in the receiver of the method that we are
   350  				// translating gets the right unique name. We could
   351  				// be in a top-level typeDecl, so save and restore
   352  				// the current contents of g.curDecl.
   353  				savedCurDecl := g.curDecl
   354  				g.curDecl = typ.Obj().Name() + "." + m.Name()
   355  				for i := range tparams {
   356  					tparams[i] = g.typ1(rparams.At(i))
   357  				}
   358  				g.curDecl = savedCurDecl
   359  				assert(len(tparams) == len(targs))
   360  				ts := typecheck.Tsubster{
   361  					Tparams: tparams,
   362  					Targs:   targs,
   363  				}
   364  				// Do the substitution of the type
   365  				meth2.SetType(ts.Typ(meth.Type()))
   366  				newsym.Def = meth2
   367  			}
   368  			meth = meth2
   369  		}
   370  		methods[i] = types.NewField(meth.Pos(), g.selector(m), meth.Type())
   371  		methods[i].Nname = meth
   372  	}
   373  	ntyp.Methods().Set(methods)
   374  	if !ntyp.HasTParam() && !ntyp.HasShape() {
   375  		// Generate all the methods for a new fully-instantiated type.
   376  		typecheck.NeedInstType(ntyp)
   377  	}
   378  }
   379  
   380  func (g *irgen) signature(recv *types.Field, sig *types2.Signature) *types.Type {
   381  	tparams2 := sig.TypeParams()
   382  	tparams := make([]*types.Field, tparams2.Len())
   383  	for i := range tparams {
   384  		tp := tparams2.At(i).Obj()
   385  		tparams[i] = types.NewField(g.pos(tp), g.sym(tp), g.typ1(tp.Type()))
   386  	}
   387  
   388  	do := func(typ *types2.Tuple) []*types.Field {
   389  		fields := make([]*types.Field, typ.Len())
   390  		for i := range fields {
   391  			fields[i] = g.param(typ.At(i))
   392  		}
   393  		return fields
   394  	}
   395  	params := do(sig.Params())
   396  	results := do(sig.Results())
   397  	if sig.Variadic() {
   398  		params[len(params)-1].SetIsDDD(true)
   399  	}
   400  
   401  	return types.NewSignature(g.tpkg(sig), recv, tparams, params, results)
   402  }
   403  
   404  func (g *irgen) param(v *types2.Var) *types.Field {
   405  	return types.NewField(g.pos(v), g.sym(v), g.typ1(v.Type()))
   406  }
   407  
   408  func (g *irgen) sym(obj types2.Object) *types.Sym {
   409  	if name := obj.Name(); name != "" {
   410  		return g.pkg(obj.Pkg()).Lookup(obj.Name())
   411  	}
   412  	return nil
   413  }
   414  
   415  func (g *irgen) selector(obj types2.Object) *types.Sym {
   416  	pkg, name := g.pkg(obj.Pkg()), obj.Name()
   417  	if types.IsExported(name) {
   418  		pkg = types.LocalPkg
   419  	}
   420  	return pkg.Lookup(name)
   421  }
   422  
   423  // tpkg returns the package that a function, interface, struct, or typeparam type
   424  // expression appeared in.
   425  //
   426  // Caveat: For the degenerate types "func()", "interface{}", and
   427  // "struct{}", tpkg always returns LocalPkg. However, we only need the
   428  // package information so that go/types can report it via its API, and
   429  // the reason we fail to return the original package for these
   430  // particular types is because go/types does *not* report it for
   431  // them. So in practice this limitation is probably moot.
   432  func (g *irgen) tpkg(typ types2.Type) *types.Pkg {
   433  	if obj := anyObj(typ); obj != nil {
   434  		return g.pkg(obj.Pkg())
   435  	}
   436  	return types.LocalPkg
   437  }
   438  
   439  // anyObj returns some object accessible from typ, if any.
   440  func anyObj(typ types2.Type) types2.Object {
   441  	switch typ := typ.(type) {
   442  	case *types2.Signature:
   443  		if recv := typ.Recv(); recv != nil {
   444  			return recv
   445  		}
   446  		if params := typ.Params(); params.Len() > 0 {
   447  			return params.At(0)
   448  		}
   449  		if results := typ.Results(); results.Len() > 0 {
   450  			return results.At(0)
   451  		}
   452  	case *types2.Struct:
   453  		if typ.NumFields() > 0 {
   454  			return typ.Field(0)
   455  		}
   456  	case *types2.Interface:
   457  		if typ.NumExplicitMethods() > 0 {
   458  			return typ.ExplicitMethod(0)
   459  		}
   460  	case *types2.TypeParam:
   461  		return typ.Obj()
   462  	}
   463  	return nil
   464  }
   465  
   466  func (g *irgen) basic(typ *types2.Basic) *types.Type {
   467  	switch typ.Name() {
   468  	case "byte":
   469  		return types.ByteType
   470  	case "rune":
   471  		return types.RuneType
   472  	}
   473  	return *basics[typ.Kind()]
   474  }
   475  
   476  var basics = [...]**types.Type{
   477  	types2.Invalid:        new(*types.Type),
   478  	types2.Bool:           &types.Types[types.TBOOL],
   479  	types2.Int:            &types.Types[types.TINT],
   480  	types2.Int8:           &types.Types[types.TINT8],
   481  	types2.Int16:          &types.Types[types.TINT16],
   482  	types2.Int32:          &types.Types[types.TINT32],
   483  	types2.Int64:          &types.Types[types.TINT64],
   484  	types2.Uint:           &types.Types[types.TUINT],
   485  	types2.Uint8:          &types.Types[types.TUINT8],
   486  	types2.Uint16:         &types.Types[types.TUINT16],
   487  	types2.Uint32:         &types.Types[types.TUINT32],
   488  	types2.Uint64:         &types.Types[types.TUINT64],
   489  	types2.Uintptr:        &types.Types[types.TUINTPTR],
   490  	types2.Float32:        &types.Types[types.TFLOAT32],
   491  	types2.Float64:        &types.Types[types.TFLOAT64],
   492  	types2.Complex64:      &types.Types[types.TCOMPLEX64],
   493  	types2.Complex128:     &types.Types[types.TCOMPLEX128],
   494  	types2.String:         &types.Types[types.TSTRING],
   495  	types2.UnsafePointer:  &types.Types[types.TUNSAFEPTR],
   496  	types2.UntypedBool:    &types.UntypedBool,
   497  	types2.UntypedInt:     &types.UntypedInt,
   498  	types2.UntypedRune:    &types.UntypedRune,
   499  	types2.UntypedFloat:   &types.UntypedFloat,
   500  	types2.UntypedComplex: &types.UntypedComplex,
   501  	types2.UntypedString:  &types.UntypedString,
   502  	types2.UntypedNil:     &types.Types[types.TNIL],
   503  }
   504  
   505  var dirs = [...]types.ChanDir{
   506  	types2.SendRecv: types.Cboth,
   507  	types2.SendOnly: types.Csend,
   508  	types2.RecvOnly: types.Crecv,
   509  }
   510  
   511  // deref2 does a single deref of types2 type t, if it is a pointer type.
   512  func deref2(t types2.Type) types2.Type {
   513  	if ptr := types2.AsPointer(t); ptr != nil {
   514  		t = ptr.Elem()
   515  	}
   516  	return t
   517  }
   518  

View as plain text