mirror of
https://github.com/golang/go
synced 2024-11-26 16:16:57 -07: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"
|
"cmd/internal/src"
|
||||||
)
|
)
|
||||||
|
|
||||||
// check2 type checks a Go package using types2, and then generates IR
|
// checkFiles configures and runs the types2 checker on the given
|
||||||
// using the results.
|
// parsed source files and then returns the result.
|
||||||
func check2(noders []*noder) {
|
func checkFiles(noders []*noder, importer types2.Importer) (posMap, *types2.Package, *types2.Info) {
|
||||||
if base.SyntaxErrors() != 0 {
|
if base.SyntaxErrors() != 0 {
|
||||||
base.ErrorExit()
|
base.ErrorExit()
|
||||||
}
|
}
|
||||||
@ -42,12 +42,10 @@ func check2(noders []*noder) {
|
|||||||
terr := err.(types2.Error)
|
terr := err.(types2.Error)
|
||||||
base.ErrorfAt(m.makeXPos(terr.Pos), "%s", terr.Msg)
|
base.ErrorfAt(m.makeXPos(terr.Pos), "%s", terr.Msg)
|
||||||
},
|
},
|
||||||
Importer: &gcimports{
|
Importer: importer,
|
||||||
packages: make(map[string]*types2.Package),
|
Sizes: &gcSizes{},
|
||||||
},
|
|
||||||
Sizes: &gcSizes{},
|
|
||||||
}
|
}
|
||||||
info := types2.Info{
|
info := &types2.Info{
|
||||||
Types: make(map[syntax.Expr]types2.TypeAndValue),
|
Types: make(map[syntax.Expr]types2.TypeAndValue),
|
||||||
Defs: make(map[*syntax.Name]types2.Object),
|
Defs: make(map[*syntax.Name]types2.Object),
|
||||||
Uses: 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),
|
Inferred: make(map[syntax.Expr]types2.Inferred),
|
||||||
// expand as needed
|
// 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()
|
base.ExitIfErrors()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
base.FatalfAt(src.NoXPos, "conf.Check error: %v", err)
|
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 {
|
if base.Flag.G < 2 {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
@ -70,7 +81,7 @@ func check2(noders []*noder) {
|
|||||||
g := irgen{
|
g := irgen{
|
||||||
target: typecheck.Target,
|
target: typecheck.Target,
|
||||||
self: pkg,
|
self: pkg,
|
||||||
info: &info,
|
info: info,
|
||||||
posMap: m,
|
posMap: m,
|
||||||
objs: make(map[types2.Object]*ir.Name),
|
objs: make(map[types2.Object]*ir.Name),
|
||||||
typs: make(map[types2.Type]*types.Type),
|
typs: make(map[types2.Type]*types.Type),
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package noder
|
package noder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/constant"
|
"go/constant"
|
||||||
"go/token"
|
"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) {
|
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
|
pragmaEmbeds := pragma.Embeds
|
||||||
pragma.Embeds = nil
|
pragma.Embeds = nil
|
||||||
pos := makeXPos(pragmaEmbeds[0].Pos)
|
if len(pragmaEmbeds) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if !haveEmbed {
|
if err := checkEmbed(decl, haveEmbed, typecheck.DeclContext != ir.PEXTERN); err != nil {
|
||||||
base.ErrorfAt(pos, "go:embed only allowed in Go files that import \"embed\"")
|
base.ErrorfAt(makeXPos(pragmaEmbeds[0].Pos), "%s", err)
|
||||||
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")
|
|
||||||
return
|
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)
|
typecheck.Target.Embeds = append(typecheck.Target.Embeds, name)
|
||||||
name.Embed = &embeds
|
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
|
// particular types is because go/types does *not* report it for
|
||||||
// them. So in practice this limitation is probably moot.
|
// them. So in practice this limitation is probably moot.
|
||||||
func (g *irgen) tpkg(typ types2.Type) *types.Pkg {
|
func (g *irgen) tpkg(typ types2.Type) *types.Pkg {
|
||||||
anyObj := func() types2.Object {
|
if obj := anyObj(typ); obj != nil {
|
||||||
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 {
|
|
||||||
return g.pkg(obj.Pkg())
|
return g.pkg(obj.Pkg())
|
||||||
}
|
}
|
||||||
return types.LocalPkg
|
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 {
|
func (g *irgen) basic(typ *types2.Basic) *types.Type {
|
||||||
switch typ.Name() {
|
switch typ.Name() {
|
||||||
case "byte":
|
case "byte":
|
||||||
|
Loading…
Reference in New Issue
Block a user