go.tools/go/types: give Label objects a non-nil Package() too.
New invariant: all user-defined objects have an associated package. Added a check of this invariant to stdlib_test. LGTM=gri R=gri CC=golang-codereviews https://golang.org/cl/104170043
This commit is contained in:
parent
6db8a00c75
commit
47c0a8f0c3
|
|
@ -131,7 +131,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.Labele
|
||||||
case *ast.LabeledStmt:
|
case *ast.LabeledStmt:
|
||||||
// declare non-blank label
|
// declare non-blank label
|
||||||
if name := s.Label.Name; name != "_" {
|
if name := s.Label.Name; name != "_" {
|
||||||
lbl := NewLabel(s.Label.Pos(), name)
|
lbl := NewLabel(s.Label.Pos(), check.pkg, name)
|
||||||
if alt := all.Insert(lbl); alt != nil {
|
if alt := all.Insert(lbl); alt != nil {
|
||||||
check.softErrorf(lbl.pos, "label %s already declared", name)
|
check.softErrorf(lbl.pos, "label %s already declared", name)
|
||||||
check.reportAltDecl(alt)
|
check.reportAltDecl(alt)
|
||||||
|
|
|
||||||
|
|
@ -201,8 +201,8 @@ type Label struct {
|
||||||
object
|
object
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLabel(pos token.Pos, name string) *Label {
|
func NewLabel(pos token.Pos, pkg *Package, name string) *Label {
|
||||||
return &Label{object{pos: pos, name: name, typ: Typ[Invalid]}}
|
return &Label{object{pos: pos, pkg: pkg, name: name, typ: Typ[Invalid]}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Builtin represents a built-in function.
|
// A Builtin represents a built-in function.
|
||||||
|
|
|
||||||
|
|
@ -174,8 +174,25 @@ func typecheck(t *testing.T, path string, filenames []string) {
|
||||||
// typecheck package files
|
// typecheck package files
|
||||||
var conf Config
|
var conf Config
|
||||||
conf.Error = func(err error) { t.Error(err) }
|
conf.Error = func(err error) { t.Error(err) }
|
||||||
conf.Check(path, fset, files, nil)
|
info := Info{Uses: make(map[*ast.Ident]Object)}
|
||||||
|
conf.Check(path, fset, files, &info)
|
||||||
pkgCount++
|
pkgCount++
|
||||||
|
|
||||||
|
// Perform checks of API invariants.
|
||||||
|
|
||||||
|
// All Objects have a package, except predeclared ones.
|
||||||
|
errorError := Universe.Lookup("error").Type().Underlying().(*Interface).ExplicitMethod(0) // (error).Error
|
||||||
|
for id, obj := range info.Uses {
|
||||||
|
predeclared := obj == Universe.Lookup(obj.Name()) || obj == errorError
|
||||||
|
if predeclared == (obj.Pkg() != nil) {
|
||||||
|
posn := fset.Position(id.Pos())
|
||||||
|
if predeclared {
|
||||||
|
t.Errorf("%s: predeclared object with package: %s", posn, obj)
|
||||||
|
} else {
|
||||||
|
t.Errorf("%s: user-defined object without package: %s", posn, obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pkgFilenames returns the list of package filenames for the given directory.
|
// pkgFilenames returns the list of package filenames for the given directory.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue