mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00:00
[dev.typeparams] cmd/compile: refactor noder/irgen helpers
This CL refactors the code for invoking the types2 checker and for validating //go:embed directives to be easier to reuse separately. No functional change. Change-Id: I706f4ea4a26b1f1d2f4064befcc0777a1067383d Reviewed-on: https://go-review.googlesource.com/c/go/+/323310 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Dan Scales <danscales@google.com> Trust: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
4b10e4c547
commit
2580e9a160
|
@ -18,9 +18,9 @@ import (
|
|||
"cmd/internal/src"
|
||||
)
|
||||
|
||||
// check2 type checks a Go package using types2, and then generates IR
|
||||
// using the results.
|
||||
func check2(noders []*noder) {
|
||||
// checkFiles configures and runs the types2 checker on the given
|
||||
// parsed source files and then returns the result.
|
||||
func checkFiles(noders []*noder, importer types2.Importer) (posMap, *types2.Package, *types2.Info) {
|
||||
if base.SyntaxErrors() != 0 {
|
||||
base.ErrorExit()
|
||||
}
|
||||
|
@ -42,12 +42,10 @@ func check2(noders []*noder) {
|
|||
terr := err.(types2.Error)
|
||||
base.ErrorfAt(m.makeXPos(terr.Pos), "%s", terr.Msg)
|
||||
},
|
||||
Importer: &gcimports{
|
||||
packages: make(map[string]*types2.Package),
|
||||
},
|
||||
Sizes: &gcSizes{},
|
||||
Importer: importer,
|
||||
Sizes: &gcSizes{},
|
||||
}
|
||||
info := types2.Info{
|
||||
info := &types2.Info{
|
||||
Types: make(map[syntax.Expr]types2.TypeAndValue),
|
||||
Defs: make(map[*syntax.Name]types2.Object),
|
||||
Uses: make(map[*syntax.Name]types2.Object),
|
||||
|
@ -57,12 +55,25 @@ func check2(noders []*noder) {
|
|||
Inferred: make(map[syntax.Expr]types2.Inferred),
|
||||
// expand as needed
|
||||
}
|
||||
pkg, err := conf.Check(base.Ctxt.Pkgpath, files, &info)
|
||||
files = nil
|
||||
|
||||
pkg, err := conf.Check(base.Ctxt.Pkgpath, files, info)
|
||||
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) {
|
||||
importer := &gcimports{
|
||||
packages: make(map[string]*types2.Package),
|
||||
}
|
||||
|
||||
m, pkg, info := checkFiles(noders, importer)
|
||||
|
||||
if base.Flag.G < 2 {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
@ -70,7 +81,7 @@ func check2(noders []*noder) {
|
|||
g := irgen{
|
||||
target: typecheck.Target,
|
||||
self: pkg,
|
||||
info: &info,
|
||||
info: info,
|
||||
posMap: m,
|
||||
objs: make(map[types2.Object]*ir.Name),
|
||||
typs: make(map[types2.Type]*types.Type),
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package noder
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
|
@ -1852,33 +1853,14 @@ func oldname(s *types.Sym) ir.Node {
|
|||
}
|
||||
|
||||
func varEmbed(makeXPos func(syntax.Pos) src.XPos, name *ir.Name, decl *syntax.VarDecl, pragma *pragmas, haveEmbed bool) {
|
||||
if pragma.Embeds == nil {
|
||||
return
|
||||
}
|
||||
|
||||
pragmaEmbeds := pragma.Embeds
|
||||
pragma.Embeds = nil
|
||||
pos := makeXPos(pragmaEmbeds[0].Pos)
|
||||
if len(pragmaEmbeds) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if !haveEmbed {
|
||||
base.ErrorfAt(pos, "go:embed only allowed in Go files that import \"embed\"")
|
||||
return
|
||||
}
|
||||
if len(decl.NameList) > 1 {
|
||||
base.ErrorfAt(pos, "go:embed cannot apply to multiple vars")
|
||||
return
|
||||
}
|
||||
if decl.Values != nil {
|
||||
base.ErrorfAt(pos, "go:embed cannot apply to var with initializer")
|
||||
return
|
||||
}
|
||||
if decl.Type == nil {
|
||||
// Should not happen, since Values == nil now.
|
||||
base.ErrorfAt(pos, "go:embed cannot apply to var without type")
|
||||
return
|
||||
}
|
||||
if typecheck.DeclContext != ir.PEXTERN {
|
||||
base.ErrorfAt(pos, "go:embed cannot apply to var inside func")
|
||||
if err := checkEmbed(decl, haveEmbed, typecheck.DeclContext != ir.PEXTERN); err != nil {
|
||||
base.ErrorfAt(makeXPos(pragmaEmbeds[0].Pos), "%s", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1889,3 +1871,22 @@ func varEmbed(makeXPos func(syntax.Pos) src.XPos, name *ir.Name, decl *syntax.Va
|
|||
typecheck.Target.Embeds = append(typecheck.Target.Embeds, name)
|
||||
name.Embed = &embeds
|
||||
}
|
||||
|
||||
func checkEmbed(decl *syntax.VarDecl, haveEmbed, withinFunc bool) error {
|
||||
switch {
|
||||
case !haveEmbed:
|
||||
return errors.New("go:embed only allowed in Go files that import \"embed\"")
|
||||
case len(decl.NameList) > 1:
|
||||
return errors.New("go:embed cannot apply to multiple vars")
|
||||
case decl.Values != nil:
|
||||
return errors.New("go:embed cannot apply to var with initializer")
|
||||
case decl.Type == nil:
|
||||
// Should not happen, since Values == nil now.
|
||||
return errors.New("go:embed cannot apply to var without type")
|
||||
case withinFunc:
|
||||
return errors.New("go:embed cannot apply to var inside func")
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -390,38 +390,39 @@ func (g *irgen) selector(obj types2.Object) *types.Sym {
|
|||
// particular types is because go/types does *not* report it for
|
||||
// them. So in practice this limitation is probably moot.
|
||||
func (g *irgen) tpkg(typ types2.Type) *types.Pkg {
|
||||
anyObj := func() types2.Object {
|
||||
switch typ := typ.(type) {
|
||||
case *types2.Signature:
|
||||
if recv := typ.Recv(); recv != nil {
|
||||
return recv
|
||||
}
|
||||
if params := typ.Params(); params.Len() > 0 {
|
||||
return params.At(0)
|
||||
}
|
||||
if results := typ.Results(); results.Len() > 0 {
|
||||
return results.At(0)
|
||||
}
|
||||
case *types2.Struct:
|
||||
if typ.NumFields() > 0 {
|
||||
return typ.Field(0)
|
||||
}
|
||||
case *types2.Interface:
|
||||
if typ.NumExplicitMethods() > 0 {
|
||||
return typ.ExplicitMethod(0)
|
||||
}
|
||||
case *types2.TypeParam:
|
||||
return typ.Obj()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if obj := anyObj(); obj != nil {
|
||||
if obj := anyObj(typ); obj != nil {
|
||||
return g.pkg(obj.Pkg())
|
||||
}
|
||||
return types.LocalPkg
|
||||
}
|
||||
|
||||
// anyObj returns some object accessible from typ, if any.
|
||||
func anyObj(typ types2.Type) types2.Object {
|
||||
switch typ := typ.(type) {
|
||||
case *types2.Signature:
|
||||
if recv := typ.Recv(); recv != nil {
|
||||
return recv
|
||||
}
|
||||
if params := typ.Params(); params.Len() > 0 {
|
||||
return params.At(0)
|
||||
}
|
||||
if results := typ.Results(); results.Len() > 0 {
|
||||
return results.At(0)
|
||||
}
|
||||
case *types2.Struct:
|
||||
if typ.NumFields() > 0 {
|
||||
return typ.Field(0)
|
||||
}
|
||||
case *types2.Interface:
|
||||
if typ.NumExplicitMethods() > 0 {
|
||||
return typ.ExplicitMethod(0)
|
||||
}
|
||||
case *types2.TypeParam:
|
||||
return typ.Obj()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *irgen) basic(typ *types2.Basic) *types.Type {
|
||||
switch typ.Name() {
|
||||
case "byte":
|
||||
|
|
Loading…
Reference in a new issue