go/src/cmd/compile/internal/noder/irgen.go

275 lines
8.1 KiB
Go
Raw Normal View History

// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package noder
import (
"fmt"
"os"
"cmd/compile/internal/base"
"cmd/compile/internal/dwarfgen"
"cmd/compile/internal/ir"
"cmd/compile/internal/syntax"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"cmd/compile/internal/types2"
"cmd/internal/src"
)
// checkFiles configures and runs the types2 checker on the given
// parsed source files and then returns the result.
func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) {
if base.SyntaxErrors() != 0 {
base.ErrorExit()
}
// setup and syntax error reporting
var m posMap
files := make([]*syntax.File, len(noders))
for i, p := range noders {
m.join(&p.posMap)
files[i] = p.file
}
// typechecking
importer := gcimports{
packages: make(map[string]*types2.Package),
}
conf := types2.Config{
GoVersion: base.Flag.Lang,
IgnoreLabels: true, // parser already checked via syntax.CheckBranches mode
CompilerErrorMessages: true, // use error strings matching existing compiler errors
AllowTypeLists: true, // remove this line once all tests use type set syntax
Error: func(err error) {
terr := err.(types2.Error)
base.ErrorfAt(m.makeXPos(terr.Pos), "%s", terr.Msg)
},
Importer: &importer,
Sizes: &gcSizes{},
}
info := &types2.Info{
Types: make(map[syntax.Expr]types2.TypeAndValue),
Defs: make(map[*syntax.Name]types2.Object),
Uses: make(map[*syntax.Name]types2.Object),
Selections: make(map[*syntax.SelectorExpr]*types2.Selection),
Implicits: make(map[syntax.Node]types2.Object),
Scopes: make(map[syntax.Node]*types2.Scope),
Inferred: make(map[syntax.Expr]types2.Inferred),
// expand as needed
}
pkg := types2.NewPackage(base.Ctxt.Pkgpath, "")
importer.check = types2.NewChecker(&conf, pkg, info)
err := importer.check.Files(files)
base.ExitIfErrors()
if err != nil {
base.FatalfAt(src.NoXPos, "conf.Check error: %v", err)
}
return m, pkg, info
}
// check2 type checks a Go package using types2, and then generates IR
// using the results.
func check2(noders []*noder) {
m, pkg, info := checkFiles(noders)
if base.Flag.G < 2 {
os.Exit(0)
}
g := irgen{
target: typecheck.Target,
self: pkg,
info: info,
posMap: m,
objs: make(map[types2.Object]*ir.Name),
typs: make(map[types2.Type]*types.Type),
}
g.generate(noders)
if base.Flag.G < 3 {
os.Exit(0)
}
}
[dev.typeparams] cmd/compile: add derived types and subdictionaries to dictionaries This is code in progress to generate the two main other types of entries in dictionaries: - all types in the instantiated function derived from the type arguments (which are currently concrete, but will eventually be gcshapes) - pointers (i.e. mainly the unique name) to all needed sub-dictionaries In order to generate these entries, we now generate cached information gfInfo about generic functions/methods that can be used for creating the instantiated dictionaries. We use the type substituter to compute the right type args for instantiated sub-dictionaries. If infoPrintMode is changed to true, the code prints out all the information gathered about generic functions, and also the entries in all the dictionaries that are instantiated. The debug mode also prints out the locations where we need main dictionaries in non-instantiated functions. Other changes: - Moved the dictionary generation back to stencil.go from reflect.go, since we need to do extra analysis for the new dictionary entries. In the process, made getInstantiation generate both the function instantiation and the associated dictionary. - Put in small change for now in reflect.go, so that we don't try generate separate dictionaries for Value[T].get and the auto-generated (*Value[T]).get. The auto-generated wrapper shouldn't really need a dictionary. - Detected, but not handling yet, a new case which needs dictionaries - closures that have function params or captured variables whose types are derived from type arguments. - Added new tests in dictionaryCapture for use of method value/expressions in generic functions and for mutually recursive generic functions. Change-Id: If0cbde8805a9f673a23f5ec798769c85c9c5359b Reviewed-on: https://go-review.googlesource.com/c/go/+/327311 Trust: Dan Scales <danscales@google.com> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
2021-06-07 18:13:15 -07:00
// gfInfo is information gathered on a generic function.
type gfInfo struct {
tparams []*types.Type
derivedTypes []*types.Type
[dev.typeparams] cmd/compile: start using sub-dictionary entries where needed Added new struct instInfo for information about an instantiation (of a generic function/method with gcshapes or concrete types). We use this to remember the dictionary param node, the nodes where sub-dictionaries need to be used, etc. The instInfo map replaces the Stencil map in Package. Added code to access sub-dictionary entries at the appropriate call sites. We are currently still calculating the corresponding main dictionary, even when we really only need a sub-dictionary. I'll clean that up in a follow-up CL. Added code to deal with "generic" closures (closures that reference some generic variables/types). We decided that closures will share the same dictionary as the containing function (accessing the dictionary via a closure variable). So, the getGfInfo function now traverses all the nodes of each closure in a function that it is analyzing, so that a function's dictionary has all the entries needed for all its closures as well. Also, the instInfo of a closure is largely shared with its containing function. A good test for generic closures already exists with orderedmap.go. Other improvements: - Only create sub-dictionary entries when the function/method call/value or closure actually has type params in it. Added new test file subdict.go with an example where a generic method has an instantiated method call that does not depend not have type params. Change-Id: I691b9dc024a89d2305fcf1d8ba8540e53c9d103f Reviewed-on: https://go-review.googlesource.com/c/go/+/331516 Trust: Dan Scales <danscales@google.com> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
2021-06-28 18:04:58 -07:00
// Nodes in generic function that requires a subdictionary. Includes
// method and function calls (OCALL), function values (OFUNCINST), method
// values/expressions (OXDOT).
[dev.typeparams] cmd/compile: add derived types and subdictionaries to dictionaries This is code in progress to generate the two main other types of entries in dictionaries: - all types in the instantiated function derived from the type arguments (which are currently concrete, but will eventually be gcshapes) - pointers (i.e. mainly the unique name) to all needed sub-dictionaries In order to generate these entries, we now generate cached information gfInfo about generic functions/methods that can be used for creating the instantiated dictionaries. We use the type substituter to compute the right type args for instantiated sub-dictionaries. If infoPrintMode is changed to true, the code prints out all the information gathered about generic functions, and also the entries in all the dictionaries that are instantiated. The debug mode also prints out the locations where we need main dictionaries in non-instantiated functions. Other changes: - Moved the dictionary generation back to stencil.go from reflect.go, since we need to do extra analysis for the new dictionary entries. In the process, made getInstantiation generate both the function instantiation and the associated dictionary. - Put in small change for now in reflect.go, so that we don't try generate separate dictionaries for Value[T].get and the auto-generated (*Value[T]).get. The auto-generated wrapper shouldn't really need a dictionary. - Detected, but not handling yet, a new case which needs dictionaries - closures that have function params or captured variables whose types are derived from type arguments. - Added new tests in dictionaryCapture for use of method value/expressions in generic functions and for mutually recursive generic functions. Change-Id: If0cbde8805a9f673a23f5ec798769c85c9c5359b Reviewed-on: https://go-review.googlesource.com/c/go/+/327311 Trust: Dan Scales <danscales@google.com> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
2021-06-07 18:13:15 -07:00
subDictCalls []ir.Node
// Nodes in generic functions that are a conversion from a typeparam/derived
// type to a specific interface.
itabConvs []ir.Node
[dev.typeparams] cmd/compile: add derived types and subdictionaries to dictionaries This is code in progress to generate the two main other types of entries in dictionaries: - all types in the instantiated function derived from the type arguments (which are currently concrete, but will eventually be gcshapes) - pointers (i.e. mainly the unique name) to all needed sub-dictionaries In order to generate these entries, we now generate cached information gfInfo about generic functions/methods that can be used for creating the instantiated dictionaries. We use the type substituter to compute the right type args for instantiated sub-dictionaries. If infoPrintMode is changed to true, the code prints out all the information gathered about generic functions, and also the entries in all the dictionaries that are instantiated. The debug mode also prints out the locations where we need main dictionaries in non-instantiated functions. Other changes: - Moved the dictionary generation back to stencil.go from reflect.go, since we need to do extra analysis for the new dictionary entries. In the process, made getInstantiation generate both the function instantiation and the associated dictionary. - Put in small change for now in reflect.go, so that we don't try generate separate dictionaries for Value[T].get and the auto-generated (*Value[T]).get. The auto-generated wrapper shouldn't really need a dictionary. - Detected, but not handling yet, a new case which needs dictionaries - closures that have function params or captured variables whose types are derived from type arguments. - Added new tests in dictionaryCapture for use of method value/expressions in generic functions and for mutually recursive generic functions. Change-Id: If0cbde8805a9f673a23f5ec798769c85c9c5359b Reviewed-on: https://go-review.googlesource.com/c/go/+/327311 Trust: Dan Scales <danscales@google.com> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
2021-06-07 18:13:15 -07:00
}
[dev.typeparams] cmd/compile: start using sub-dictionary entries where needed Added new struct instInfo for information about an instantiation (of a generic function/method with gcshapes or concrete types). We use this to remember the dictionary param node, the nodes where sub-dictionaries need to be used, etc. The instInfo map replaces the Stencil map in Package. Added code to access sub-dictionary entries at the appropriate call sites. We are currently still calculating the corresponding main dictionary, even when we really only need a sub-dictionary. I'll clean that up in a follow-up CL. Added code to deal with "generic" closures (closures that reference some generic variables/types). We decided that closures will share the same dictionary as the containing function (accessing the dictionary via a closure variable). So, the getGfInfo function now traverses all the nodes of each closure in a function that it is analyzing, so that a function's dictionary has all the entries needed for all its closures as well. Also, the instInfo of a closure is largely shared with its containing function. A good test for generic closures already exists with orderedmap.go. Other improvements: - Only create sub-dictionary entries when the function/method call/value or closure actually has type params in it. Added new test file subdict.go with an example where a generic method has an instantiated method call that does not depend not have type params. Change-Id: I691b9dc024a89d2305fcf1d8ba8540e53c9d103f Reviewed-on: https://go-review.googlesource.com/c/go/+/331516 Trust: Dan Scales <danscales@google.com> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
2021-06-28 18:04:58 -07:00
// instInfo is information gathered on an gcshape (or fully concrete)
// instantiation of a function.
type instInfo struct {
fun *ir.Func // The instantiated function (with body)
dictParam *ir.Name // The node inside fun that refers to the dictionary param
gf *ir.Name // The associated generic function
gfInfo *gfInfo
startSubDict int // Start of dict entries for subdictionaries
startItabConv int // Start of dict entries for itab conversions
dictLen int // Total number of entries in dictionary
[dev.typeparams] cmd/compile: start using sub-dictionary entries where needed Added new struct instInfo for information about an instantiation (of a generic function/method with gcshapes or concrete types). We use this to remember the dictionary param node, the nodes where sub-dictionaries need to be used, etc. The instInfo map replaces the Stencil map in Package. Added code to access sub-dictionary entries at the appropriate call sites. We are currently still calculating the corresponding main dictionary, even when we really only need a sub-dictionary. I'll clean that up in a follow-up CL. Added code to deal with "generic" closures (closures that reference some generic variables/types). We decided that closures will share the same dictionary as the containing function (accessing the dictionary via a closure variable). So, the getGfInfo function now traverses all the nodes of each closure in a function that it is analyzing, so that a function's dictionary has all the entries needed for all its closures as well. Also, the instInfo of a closure is largely shared with its containing function. A good test for generic closures already exists with orderedmap.go. Other improvements: - Only create sub-dictionary entries when the function/method call/value or closure actually has type params in it. Added new test file subdict.go with an example where a generic method has an instantiated method call that does not depend not have type params. Change-Id: I691b9dc024a89d2305fcf1d8ba8540e53c9d103f Reviewed-on: https://go-review.googlesource.com/c/go/+/331516 Trust: Dan Scales <danscales@google.com> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
2021-06-28 18:04:58 -07:00
// Map from nodes in instantiated fun (OCALL, OCALLMETHOD, OFUNCINST, and
// OMETHEXPR) to the associated dictionary entry for a sub-dictionary
dictEntryMap map[ir.Node]int
}
type irgen struct {
target *ir.Package
self *types2.Package
info *types2.Info
posMap
objs map[types2.Object]*ir.Name
typs map[types2.Type]*types.Type
marker dwarfgen.ScopeMarker
cmd/compile: get instantiated generic types working with interfaces Get instantiatiated generic types working with interfaces, including typechecking assignments to interfaces and instantiating all the methods properly. To get it all working, this change includes: - Add support for substituting in interfaces in subster.typ() - Fill in the info for the methods for all instantiated generic types, so those methods will be available for later typechecking (by the old typechecker) when assigning an instantiated generic type to an interface. We also want those methods available so we have the list when we want to instantiate all methods of an instantiated type. We have both for instantiated types encountered during the initial noder phase, and for instantiated types created during stenciling of a function/method. - When we first create a fully-instantiated generic type (whether during initial noder2 pass or while instantiating a method/function), add it to a list so that all of its methods will also be instantiated. This is needed so that an instantiated type can be assigned to an interface. - Properly substitute type names in the names of instantiated methods. - New accessor methods for types.Type.RParam. - To deal with generic types which are empty structs (or just don't use their type params anywhere), we want to set HasTParam if a named type has any type params that are not fully instantiated, even if the type param is not used in the type. - In subst.typ() and elsewhere, always set sym.Def for a new forwarding type we are creating, so we always create a single unique type for each generic type instantiation. This handles recursion within a type, and also recursive relationships across many types or methods. We remove the seen[] hashtable, which was serving the same purpose, but for subst.typ() only. We now handle all kinds of recursive types. - We don't seem to need to force types.CheckSize() on created/substituted generic types anymore, so commented out for now. - Add an RParams accessor to types2.Signature, and also a new exported types2.AsSignature() function. Change-Id: If6c5dd98427b20bfe9de3379cc16f83df9c9b632 Reviewed-on: https://go-review.googlesource.com/c/go/+/298449 Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Dan Scales <danscales@google.com> Reviewed-by: Robert Griesemer <gri@golang.org>
2021-03-03 13:33:27 -08:00
// Fully-instantiated generic types whose methods should be instantiated
instTypeList []*types.Type
dnum int // for generating unique dictionary variables
[dev.typeparams] cmd/compile: add derived types and subdictionaries to dictionaries This is code in progress to generate the two main other types of entries in dictionaries: - all types in the instantiated function derived from the type arguments (which are currently concrete, but will eventually be gcshapes) - pointers (i.e. mainly the unique name) to all needed sub-dictionaries In order to generate these entries, we now generate cached information gfInfo about generic functions/methods that can be used for creating the instantiated dictionaries. We use the type substituter to compute the right type args for instantiated sub-dictionaries. If infoPrintMode is changed to true, the code prints out all the information gathered about generic functions, and also the entries in all the dictionaries that are instantiated. The debug mode also prints out the locations where we need main dictionaries in non-instantiated functions. Other changes: - Moved the dictionary generation back to stencil.go from reflect.go, since we need to do extra analysis for the new dictionary entries. In the process, made getInstantiation generate both the function instantiation and the associated dictionary. - Put in small change for now in reflect.go, so that we don't try generate separate dictionaries for Value[T].get and the auto-generated (*Value[T]).get. The auto-generated wrapper shouldn't really need a dictionary. - Detected, but not handling yet, a new case which needs dictionaries - closures that have function params or captured variables whose types are derived from type arguments. - Added new tests in dictionaryCapture for use of method value/expressions in generic functions and for mutually recursive generic functions. Change-Id: If0cbde8805a9f673a23f5ec798769c85c9c5359b Reviewed-on: https://go-review.googlesource.com/c/go/+/327311 Trust: Dan Scales <danscales@google.com> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
2021-06-07 18:13:15 -07:00
// Map from generic function to information about its type params, derived
// types, and subdictionaries.
gfInfoMap map[*types.Sym]*gfInfo
[dev.typeparams] cmd/compile: start using sub-dictionary entries where needed Added new struct instInfo for information about an instantiation (of a generic function/method with gcshapes or concrete types). We use this to remember the dictionary param node, the nodes where sub-dictionaries need to be used, etc. The instInfo map replaces the Stencil map in Package. Added code to access sub-dictionary entries at the appropriate call sites. We are currently still calculating the corresponding main dictionary, even when we really only need a sub-dictionary. I'll clean that up in a follow-up CL. Added code to deal with "generic" closures (closures that reference some generic variables/types). We decided that closures will share the same dictionary as the containing function (accessing the dictionary via a closure variable). So, the getGfInfo function now traverses all the nodes of each closure in a function that it is analyzing, so that a function's dictionary has all the entries needed for all its closures as well. Also, the instInfo of a closure is largely shared with its containing function. A good test for generic closures already exists with orderedmap.go. Other improvements: - Only create sub-dictionary entries when the function/method call/value or closure actually has type params in it. Added new test file subdict.go with an example where a generic method has an instantiated method call that does not depend not have type params. Change-Id: I691b9dc024a89d2305fcf1d8ba8540e53c9d103f Reviewed-on: https://go-review.googlesource.com/c/go/+/331516 Trust: Dan Scales <danscales@google.com> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
2021-06-28 18:04:58 -07:00
// Map from a name of function that been instantiated to information about
// its instantiated function, associated generic function/method, and the
// mapping from IR nodes to dictionary entries.
instInfoMap map[*types.Sym]*instInfo
// dictionary syms which we need to finish, by writing out any itabconv
// entries.
dictSymsToFinalize []*delayInfo
}
type delayInfo struct {
gf *ir.Name
targs []*types.Type
sym *types.Sym
off int
}
func (g *irgen) generate(noders []*noder) {
types.LocalPkg.Name = g.self.Name()
types.LocalPkg.Height = g.self.Height()
typecheck.TypecheckAllowed = true
// Prevent size calculations until we set the underlying type
// for all package-block defined types.
types.DeferCheckSize()
// At this point, types2 has already handled name resolution and
// type checking. We just need to map from its object and type
// representations to those currently used by the rest of the
// compiler. This happens mostly in 3 passes.
// 1. Process all import declarations. We use the compiler's own
// importer for this, rather than types2's gcimporter-derived one,
// to handle extensions and inline function bodies correctly.
//
// Also, we need to do this in a separate pass, because mappings are
// instantiated on demand. If we interleaved processing import
// declarations with other declarations, it's likely we'd end up
// wanting to map an object/type from another source file, but not
// yet have the import data it relies on.
declLists := make([][]syntax.Decl, len(noders))
Outer:
for i, p := range noders {
g.pragmaFlags(p.file.Pragma, ir.GoBuildPragma)
for j, decl := range p.file.DeclList {
switch decl := decl.(type) {
case *syntax.ImportDecl:
g.importDecl(p, decl)
default:
declLists[i] = p.file.DeclList[j:]
continue Outer // no more ImportDecls
}
}
}
// 2. Process all package-block type declarations. As with imports,
// we need to make sure all types are properly instantiated before
// trying to map any expressions that utilize them. In particular,
// we need to make sure type pragmas are already known (see comment
// in irgen.typeDecl).
//
// We could perhaps instead defer processing of package-block
// variable initializers and function bodies, like noder does, but
// special-casing just package-block type declarations minimizes the
// differences between processing package-block and function-scoped
// declarations.
for _, declList := range declLists {
for _, decl := range declList {
switch decl := decl.(type) {
case *syntax.TypeDecl:
g.typeDecl((*ir.Nodes)(&g.target.Decls), decl)
}
}
}
types.ResumeCheckSize()
// 3. Process all remaining declarations.
for _, declList := range declLists {
g.target.Decls = append(g.target.Decls, g.decls(declList)...)
}
if base.Flag.W > 1 {
for _, n := range g.target.Decls {
s := fmt.Sprintf("\nafter noder2 %v", n)
ir.Dump(s, n)
}
}
// Check for unusual case where noder2 encounters a type error that types2
// doesn't check for (e.g. notinheap incompatibility).
base.ExitIfErrors()
typecheck.DeclareUniverse()
for _, p := range noders {
// Process linkname and cgo pragmas.
p.processPragmas()
// Double check for any type-checking inconsistencies. This can be
// removed once we're confident in IR generation results.
syntax.Crawl(p.file, func(n syntax.Node) bool {
g.validate(n)
return false
})
}
// Create any needed stencils of generic functions
g.stencil()
[dev.typeparams] cmd/compile: get export/import of generic types & functions working The general idea is that we now export/import typeparams, typeparam lists for generic types and functions, and instantiated types (instantiations of generic types with either new typeparams or concrete types). This changes the export format -- the next CL in the stack adds the export versions and checks for it in the appropriate places. We always export/import generic function bodies, using the same code that we use for exporting/importing the bodies of inlineable functions. To avoid complicated scoping, we consider all type params as unique and give them unique names for types1. We therefore include the types2 ids (subscripts) in the export format and re-create on import. We always access the same unique types1 typeParam type for the same typeparam name. We create fully-instantiated generic types and functions in the original source package. We do an extra NeedRuntimeType() call to make sure that the correct DWARF information is written out. We call SetDupOK(true) for the functions/methods to have the linker automatically drop duplicate instantiations. Other miscellaneous details: - Export/import of typeparam bounds works for methods (but not typelists) for now, but will change with the typeset changes. - Added a new types.Instantiate function roughly analogous to the types2.Instantiate function recently added. - Always access methods info from the original/base generic type, since the methods of an instantiated type are not filled in (in types2 or types1). - New field OrigSym in types.Type to keep track of base generic type that instantiated type was based on. We use the generic type's symbol (OrigSym) as the link, rather than a Type pointer, since we haven't always created the base type yet when we want to set the link (during types2 to types1 conversion). - Added types2.AsTypeParam(), (*types2.TypeParam).SetId() - New test minimp.dir, which tests use of generic function Min across packages. Another test stringimp.dir, which also exports a generic function Stringify across packages, where the type param has a bound (Stringer) as well. New test pairimp.dir, which tests use of generic type Pair (with no methods) across packages. - New test valimp.dir, which tests use of generic type (with methods and related functions) across packages. - Modified several other tests (adder.go, settable.go, smallest.go, stringable.go, struct.go, sum.go) to export their generic functions/types to show that generic functions/types can be exported successfully (but this doesn't test import). Change-Id: Ie61ce9d54a46d368ddc7a76c41399378963bb57f Reviewed-on: https://go-review.googlesource.com/c/go/+/319930 Trust: Dan Scales <danscales@google.com> Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
2021-04-13 15:37:36 -07:00
// Remove all generic functions from g.target.Decl, since they have been
// used for stenciling, but don't compile. Generic functions will already
// have been marked for export as appropriate.
j := 0
for i, decl := range g.target.Decls {
[dev.typeparams] cmd/compile: support generic types (with stenciling of method calls) A type may now have a type param in it, either because it has been composed from a function type param, or it has been declared as or derived from a reference to a generic type. No objects or types with type params can be exported yet. No generic type has a runtime descriptor (but will likely eventually be associated with a dictionary). types.Type now has an RParam field, which for a Named type can specify the type params (in order) that must be supplied to fully instantiate the type. Also, there is a new flag HasTParam to indicate if there is a type param (TTYPEPARAM) anywhere in the type. An instantiated generic type (whether fully instantiated or re-instantiated to new type params) is a defined type, even though there was no explicit declaration. This allows us to handle recursive instantiated types (and improves printing of types). To avoid the need to transform later in the compiler, an instantiation of a method of a generic type is immediately represented as a function with the method as the first argument. Added 5 tests on generic types to test/typeparams, including list.go, which tests recursive generic types. Change-Id: Ib7ff27abd369a06d1c8ea84edc6ca1fd74bbb7c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/292652 Trust: Dan Scales <danscales@google.com> Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Dan Scales <danscales@google.com> Reviewed-by: Robert Griesemer <gri@golang.org>
2021-02-11 10:50:20 -08:00
if decl.Op() != ir.ODCLFUNC || !decl.Type().HasTParam() {
g.target.Decls[j] = g.target.Decls[i]
j++
}
}
g.target.Decls = g.target.Decls[:j]
}
func (g *irgen) unhandled(what string, p poser) {
base.FatalfAt(g.pos(p), "unhandled %s: %T", what, p)
panic("unreachable")
}