diff --git a/third_party/BUILD b/third_party/BUILD index 2beec65ec66..cd376959766 100644 --- a/third_party/BUILD +++ b/third_party/BUILD @@ -23,7 +23,6 @@ filegroup( "//third_party/forked/etcd237/pkg/fileutil:all-srcs", "//third_party/forked/etcd237/wal:all-srcs", "//third_party/forked/golang/expansion:all-srcs", - "//third_party/forked/golang/go/types:all-srcs", "//third_party/forked/golang/reflect:all-srcs", "//third_party/forked/golang/template:all-srcs", "//third_party/forked/gonum/graph:all-srcs", diff --git a/third_party/forked/golang/go/types/BUILD b/third_party/forked/golang/go/types/BUILD deleted file mode 100644 index df42eff853d..00000000000 --- a/third_party/forked/golang/go/types/BUILD +++ /dev/null @@ -1,56 +0,0 @@ -licenses(["notice"]) - -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "api.go", - "assignments.go", - "builtins.go", - "call.go", - "check.go", - "conversions.go", - "decl.go", - "errors.go", - "eval.go", - "expr.go", - "exprstring.go", - "initorder.go", - "labels.go", - "lookup.go", - "methodset.go", - "object.go", - "objset.go", - "operand.go", - "ordering.go", - "package.go", - "predicates.go", - "resolver.go", - "return.go", - "scope.go", - "selection.go", - "sizes.go", - "stmt.go", - "type.go", - "typestring.go", - "typexpr.go", - "universe.go", - ], - importpath = "k8s.io/kubernetes/third_party/forked/golang/go/types", - visibility = ["//visibility:public"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/third_party/forked/golang/go/types/README b/third_party/forked/golang/go/types/README deleted file mode 100644 index c0c93fef360..00000000000 --- a/third_party/forked/golang/go/types/README +++ /dev/null @@ -1,7 +0,0 @@ -This is go/types forked from go@236abdb46b (just after 1.10) and cherry-picked -1006f703ffc, which fixes https://github.com/golang/go/issues/23712. - -It can be removed when all builders are >= go1.11. - -Do *not* update this to newer code if https://github.com/golang/go/issues/23914 -has not been fixed! diff --git a/third_party/forked/golang/go/types/api.go b/third_party/forked/golang/go/types/api.go deleted file mode 100644 index 9908f5c9738..00000000000 --- a/third_party/forked/golang/go/types/api.go +++ /dev/null @@ -1,376 +0,0 @@ -// Copyright 2012 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 types declares the data types and implements -// the algorithms for type-checking of Go packages. Use -// Config.Check to invoke the type checker for a package. -// Alternatively, create a new type checker with NewChecker -// and invoke it incrementally by calling Checker.Files. -// -// Type-checking consists of several interdependent phases: -// -// Name resolution maps each identifier (ast.Ident) in the program to the -// language object (Object) it denotes. -// Use Info.{Defs,Uses,Implicits} for the results of name resolution. -// -// Constant folding computes the exact constant value (constant.Value) -// for every expression (ast.Expr) that is a compile-time constant. -// Use Info.Types[expr].Value for the results of constant folding. -// -// Type inference computes the type (Type) of every expression (ast.Expr) -// and checks for compliance with the language specification. -// Use Info.Types[expr].Type for the results of type inference. -// -// For a tutorial, see https://golang.org/s/types-tutorial. -// -package types - -import ( - "bytes" - "fmt" - "go/ast" - "go/constant" - "go/token" -) - -// An Error describes a type-checking error; it implements the error interface. -// A "soft" error is an error that still permits a valid interpretation of a -// package (such as "unused variable"); "hard" errors may lead to unpredictable -// behavior if ignored. -type Error struct { - Fset *token.FileSet // file set for interpretation of Pos - Pos token.Pos // error position - Msg string // error message - Soft bool // if set, error is "soft" -} - -// Error returns an error string formatted as follows: -// filename:line:column: message -func (err Error) Error() string { - return fmt.Sprintf("%s: %s", err.Fset.Position(err.Pos), err.Msg) -} - -// An Importer resolves import paths to Packages. -// -// CAUTION: This interface does not support the import of locally -// vendored packages. See https://golang.org/s/go15vendor. -// If possible, external implementations should implement ImporterFrom. -type Importer interface { - // Import returns the imported package for the given import path. - // The semantics is like for ImporterFrom.ImportFrom except that - // dir and mode are ignored (since they are not present). - Import(path string) (*Package, error) -} - -// ImportMode is reserved for future use. -type ImportMode int - -// An ImporterFrom resolves import paths to packages; it -// supports vendoring per https://golang.org/s/go15vendor. -// Use go/importer to obtain an ImporterFrom implementation. -type ImporterFrom interface { - // Importer is present for backward-compatibility. Calling - // Import(path) is the same as calling ImportFrom(path, "", 0); - // i.e., locally vendored packages may not be found. - // The types package does not call Import if an ImporterFrom - // is present. - Importer - - // ImportFrom returns the imported package for the given import - // path when imported by a package file located in dir. - // If the import failed, besides returning an error, ImportFrom - // is encouraged to cache and return a package anyway, if one - // was created. This will reduce package inconsistencies and - // follow-on type checker errors due to the missing package. - // The mode value must be 0; it is reserved for future use. - // Two calls to ImportFrom with the same path and dir must - // return the same package. - ImportFrom(path, dir string, mode ImportMode) (*Package, error) -} - -// A Config specifies the configuration for type checking. -// The zero value for Config is a ready-to-use default configuration. -type Config struct { - // If IgnoreFuncBodies is set, function bodies are not - // type-checked. - IgnoreFuncBodies bool - - // If FakeImportC is set, `import "C"` (for packages requiring Cgo) - // declares an empty "C" package and errors are omitted for qualified - // identifiers referring to package C (which won't find an object). - // This feature is intended for the standard library cmd/api tool. - // - // Caution: Effects may be unpredictable due to follow-on errors. - // Do not use casually! - FakeImportC bool - - // If Error != nil, it is called with each error found - // during type checking; err has dynamic type Error. - // Secondary errors (for instance, to enumerate all types - // involved in an invalid recursive type declaration) have - // error strings that start with a '\t' character. - // If Error == nil, type-checking stops with the first - // error found. - Error func(err error) - - // An importer is used to import packages referred to from - // import declarations. - // If the installed importer implements ImporterFrom, the type - // checker calls ImportFrom instead of Import. - // The type checker reports an error if an importer is needed - // but none was installed. - Importer Importer - - // If Sizes != nil, it provides the sizing functions for package unsafe. - // Otherwise SizesFor("gc", "amd64") is used instead. - Sizes Sizes - - // If DisableUnusedImportCheck is set, packages are not checked - // for unused imports. - DisableUnusedImportCheck bool -} - -// Info holds result type information for a type-checked package. -// Only the information for which a map is provided is collected. -// If the package has type errors, the collected information may -// be incomplete. -type Info struct { - // Types maps expressions to their types, and for constant - // expressions, also their values. Invalid expressions are - // omitted. - // - // For (possibly parenthesized) identifiers denoting built-in - // functions, the recorded signatures are call-site specific: - // if the call result is not a constant, the recorded type is - // an argument-specific signature. Otherwise, the recorded type - // is invalid. - // - // The Types map does not record the type of every identifier, - // only those that appear where an arbitrary expression is - // permitted. For instance, the identifier f in a selector - // expression x.f is found only in the Selections map, the - // identifier z in a variable declaration 'var z int' is found - // only in the Defs map, and identifiers denoting packages in - // qualified identifiers are collected in the Uses map. - Types map[ast.Expr]TypeAndValue - - // Defs maps identifiers to the objects they define (including - // package names, dots "." of dot-imports, and blank "_" identifiers). - // For identifiers that do not denote objects (e.g., the package name - // in package clauses, or symbolic variables t in t := x.(type) of - // type switch headers), the corresponding objects are nil. - // - // For an anonymous field, Defs returns the field *Var it defines. - // - // Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos() - Defs map[*ast.Ident]Object - - // Uses maps identifiers to the objects they denote. - // - // For an anonymous field, Uses returns the *TypeName it denotes. - // - // Invariant: Uses[id].Pos() != id.Pos() - Uses map[*ast.Ident]Object - - // Implicits maps nodes to their implicitly declared objects, if any. - // The following node and object types may appear: - // - // node declared object - // - // *ast.ImportSpec *PkgName for imports without renames - // *ast.CaseClause type-specific *Var for each type switch case clause (incl. default) - // *ast.Field anonymous parameter *Var - // - Implicits map[ast.Node]Object - - // Selections maps selector expressions (excluding qualified identifiers) - // to their corresponding selections. - Selections map[*ast.SelectorExpr]*Selection - - // Scopes maps ast.Nodes to the scopes they define. Package scopes are not - // associated with a specific node but with all files belonging to a package. - // Thus, the package scope can be found in the type-checked Package object. - // Scopes nest, with the Universe scope being the outermost scope, enclosing - // the package scope, which contains (one or more) files scopes, which enclose - // function scopes which in turn enclose statement and function literal scopes. - // Note that even though package-level functions are declared in the package - // scope, the function scopes are embedded in the file scope of the file - // containing the function declaration. - // - // The following node types may appear in Scopes: - // - // *ast.File - // *ast.FuncType - // *ast.BlockStmt - // *ast.IfStmt - // *ast.SwitchStmt - // *ast.TypeSwitchStmt - // *ast.CaseClause - // *ast.CommClause - // *ast.ForStmt - // *ast.RangeStmt - // - Scopes map[ast.Node]*Scope - - // InitOrder is the list of package-level initializers in the order in which - // they must be executed. Initializers referring to variables related by an - // initialization dependency appear in topological order, the others appear - // in source order. Variables without an initialization expression do not - // appear in this list. - InitOrder []*Initializer -} - -// TypeOf returns the type of expression e, or nil if not found. -// Precondition: the Types, Uses and Defs maps are populated. -// -func (info *Info) TypeOf(e ast.Expr) Type { - if t, ok := info.Types[e]; ok { - return t.Type - } - if id, _ := e.(*ast.Ident); id != nil { - if obj := info.ObjectOf(id); obj != nil { - return obj.Type() - } - } - return nil -} - -// ObjectOf returns the object denoted by the specified id, -// or nil if not found. -// -// If id is an anonymous struct field, ObjectOf returns the field (*Var) -// it uses, not the type (*TypeName) it defines. -// -// Precondition: the Uses and Defs maps are populated. -// -func (info *Info) ObjectOf(id *ast.Ident) Object { - if obj := info.Defs[id]; obj != nil { - return obj - } - return info.Uses[id] -} - -// TypeAndValue reports the type and value (for constants) -// of the corresponding expression. -type TypeAndValue struct { - mode operandMode - Type Type - Value constant.Value -} - -// TODO(gri) Consider eliminating the IsVoid predicate. Instead, report -// "void" values as regular values but with the empty tuple type. - -// IsVoid reports whether the corresponding expression -// is a function call without results. -func (tv TypeAndValue) IsVoid() bool { - return tv.mode == novalue -} - -// IsType reports whether the corresponding expression specifies a type. -func (tv TypeAndValue) IsType() bool { - return tv.mode == typexpr -} - -// IsBuiltin reports whether the corresponding expression denotes -// a (possibly parenthesized) built-in function. -func (tv TypeAndValue) IsBuiltin() bool { - return tv.mode == builtin -} - -// IsValue reports whether the corresponding expression is a value. -// Builtins are not considered values. Constant values have a non- -// nil Value. -func (tv TypeAndValue) IsValue() bool { - switch tv.mode { - case constant_, variable, mapindex, value, commaok: - return true - } - return false -} - -// IsNil reports whether the corresponding expression denotes the -// predeclared value nil. -func (tv TypeAndValue) IsNil() bool { - return tv.mode == value && tv.Type == Typ[UntypedNil] -} - -// Addressable reports whether the corresponding expression -// is addressable (https://golang.org/ref/spec#Address_operators). -func (tv TypeAndValue) Addressable() bool { - return tv.mode == variable -} - -// Assignable reports whether the corresponding expression -// is assignable to (provided a value of the right type). -func (tv TypeAndValue) Assignable() bool { - return tv.mode == variable || tv.mode == mapindex -} - -// HasOk reports whether the corresponding expression may be -// used on the lhs of a comma-ok assignment. -func (tv TypeAndValue) HasOk() bool { - return tv.mode == commaok || tv.mode == mapindex -} - -// An Initializer describes a package-level variable, or a list of variables in case -// of a multi-valued initialization expression, and the corresponding initialization -// expression. -type Initializer struct { - Lhs []*Var // var Lhs = Rhs - Rhs ast.Expr -} - -func (init *Initializer) String() string { - var buf bytes.Buffer - for i, lhs := range init.Lhs { - if i > 0 { - buf.WriteString(", ") - } - buf.WriteString(lhs.Name()) - } - buf.WriteString(" = ") - WriteExpr(&buf, init.Rhs) - return buf.String() -} - -// Check type-checks a package and returns the resulting package object and -// the first error if any. Additionally, if info != nil, Check populates each -// of the non-nil maps in the Info struct. -// -// The package is marked as complete if no errors occurred, otherwise it is -// incomplete. See Config.Error for controlling behavior in the presence of -// errors. -// -// The package is specified by a list of *ast.Files and corresponding -// file set, and the package path the package is identified with. -// The clean path must not be empty or dot ("."). -func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, info *Info) (*Package, error) { - pkg := NewPackage(path, "") - return pkg, NewChecker(conf, fset, pkg, info).Files(files) -} - -// AssertableTo reports whether a value of type V can be asserted to have type T. -func AssertableTo(V *Interface, T Type) bool { - m, _ := assertableTo(V, T) - return m == nil -} - -// AssignableTo reports whether a value of type V is assignable to a variable of type T. -func AssignableTo(V, T Type) bool { - x := operand{mode: value, typ: V} - return x.assignableTo(nil, T, nil) // config not needed for non-constant x -} - -// ConvertibleTo reports whether a value of type V is convertible to a value of type T. -func ConvertibleTo(V, T Type) bool { - x := operand{mode: value, typ: V} - return x.convertibleTo(nil, T) // config not needed for non-constant x -} - -// Implements reports whether type V implements interface T. -func Implements(V Type, T *Interface) bool { - f, _ := MissingMethod(V, T, true) - return f == nil -} diff --git a/third_party/forked/golang/go/types/assignments.go b/third_party/forked/golang/go/types/assignments.go deleted file mode 100644 index 98c9e121b05..00000000000 --- a/third_party/forked/golang/go/types/assignments.go +++ /dev/null @@ -1,335 +0,0 @@ -// Copyright 2013 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. - -// This file implements initialization and assignment checks. - -package types - -import ( - "go/ast" - "go/token" -) - -// assignment reports whether x can be assigned to a variable of type T, -// if necessary by attempting to convert untyped values to the appropriate -// type. context describes the context in which the assignment takes place. -// Use T == nil to indicate assignment to an untyped blank identifier. -// x.mode is set to invalid if the assignment failed. -func (check *Checker) assignment(x *operand, T Type, context string) { - check.singleValue(x) - - switch x.mode { - case invalid: - return // error reported before - case constant_, variable, mapindex, value, commaok: - // ok - default: - unreachable() - } - - if isUntyped(x.typ) { - target := T - // spec: "If an untyped constant is assigned to a variable of interface - // type or the blank identifier, the constant is first converted to type - // bool, rune, int, float64, complex128 or string respectively, depending - // on whether the value is a boolean, rune, integer, floating-point, complex, - // or string constant." - if T == nil || IsInterface(T) { - if T == nil && x.typ == Typ[UntypedNil] { - check.errorf(x.pos(), "use of untyped nil in %s", context) - x.mode = invalid - return - } - target = Default(x.typ) - } - check.convertUntyped(x, target) - if x.mode == invalid { - return - } - } - // x.typ is typed - - // spec: "If a left-hand side is the blank identifier, any typed or - // non-constant value except for the predeclared identifier nil may - // be assigned to it." - if T == nil { - return - } - - if reason := ""; !x.assignableTo(check.conf, T, &reason) { - if reason != "" { - check.errorf(x.pos(), "cannot use %s as %s value in %s: %s", x, T, context, reason) - } else { - check.errorf(x.pos(), "cannot use %s as %s value in %s", x, T, context) - } - x.mode = invalid - } -} - -func (check *Checker) initConst(lhs *Const, x *operand) { - if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] { - if lhs.typ == nil { - lhs.typ = Typ[Invalid] - } - return - } - - // rhs must be a constant - if x.mode != constant_ { - check.errorf(x.pos(), "%s is not constant", x) - if lhs.typ == nil { - lhs.typ = Typ[Invalid] - } - return - } - assert(isConstType(x.typ)) - - // If the lhs doesn't have a type yet, use the type of x. - if lhs.typ == nil { - lhs.typ = x.typ - } - - check.assignment(x, lhs.typ, "constant declaration") - if x.mode == invalid { - return - } - - lhs.val = x.val -} - -func (check *Checker) initVar(lhs *Var, x *operand, context string) Type { - if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] { - if lhs.typ == nil { - lhs.typ = Typ[Invalid] - } - return nil - } - - // If the lhs doesn't have a type yet, use the type of x. - if lhs.typ == nil { - typ := x.typ - if isUntyped(typ) { - // convert untyped types to default types - if typ == Typ[UntypedNil] { - check.errorf(x.pos(), "use of untyped nil in %s", context) - lhs.typ = Typ[Invalid] - return nil - } - typ = Default(typ) - } - lhs.typ = typ - } - - check.assignment(x, lhs.typ, context) - if x.mode == invalid { - return nil - } - - return x.typ -} - -func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type { - if x.mode == invalid || x.typ == Typ[Invalid] { - return nil - } - - // Determine if the lhs is a (possibly parenthesized) identifier. - ident, _ := unparen(lhs).(*ast.Ident) - - // Don't evaluate lhs if it is the blank identifier. - if ident != nil && ident.Name == "_" { - check.recordDef(ident, nil) - check.assignment(x, nil, "assignment to _ identifier") - if x.mode == invalid { - return nil - } - return x.typ - } - - // If the lhs is an identifier denoting a variable v, this assignment - // is not a 'use' of v. Remember current value of v.used and restore - // after evaluating the lhs via check.expr. - var v *Var - var v_used bool - if ident != nil { - if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil { - // It's ok to mark non-local variables, but ignore variables - // from other packages to avoid potential race conditions with - // dot-imported variables. - if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg { - v = w - v_used = v.used - } - } - } - - var z operand - check.expr(&z, lhs) - if v != nil { - v.used = v_used // restore v.used - } - - if z.mode == invalid || z.typ == Typ[Invalid] { - return nil - } - - // spec: "Each left-hand side operand must be addressable, a map index - // expression, or the blank identifier. Operands may be parenthesized." - switch z.mode { - case invalid: - return nil - case variable, mapindex: - // ok - default: - if sel, ok := z.expr.(*ast.SelectorExpr); ok { - var op operand - check.expr(&op, sel.X) - if op.mode == mapindex { - check.errorf(z.pos(), "cannot assign to struct field %s in map", ExprString(z.expr)) - return nil - } - } - check.errorf(z.pos(), "cannot assign to %s", &z) - return nil - } - - check.assignment(x, z.typ, "assignment") - if x.mode == invalid { - return nil - } - - return x.typ -} - -// If returnPos is valid, initVars is called to type-check the assignment of -// return expressions, and returnPos is the position of the return statement. -func (check *Checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos) { - l := len(lhs) - get, r, commaOk := unpack(func(x *operand, i int) { check.multiExpr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid()) - if get == nil || l != r { - // invalidate lhs and use rhs - for _, obj := range lhs { - if obj.typ == nil { - obj.typ = Typ[Invalid] - } - } - if get == nil { - return // error reported by unpack - } - check.useGetter(get, r) - if returnPos.IsValid() { - check.errorf(returnPos, "wrong number of return values (want %d, got %d)", l, r) - return - } - check.errorf(rhs[0].Pos(), "cannot initialize %d variables with %d values", l, r) - return - } - - context := "assignment" - if returnPos.IsValid() { - context = "return statement" - } - - var x operand - if commaOk { - var a [2]Type - for i := range a { - get(&x, i) - a[i] = check.initVar(lhs[i], &x, context) - } - check.recordCommaOkTypes(rhs[0], a) - return - } - - for i, lhs := range lhs { - get(&x, i) - check.initVar(lhs, &x, context) - } -} - -func (check *Checker) assignVars(lhs, rhs []ast.Expr) { - l := len(lhs) - get, r, commaOk := unpack(func(x *operand, i int) { check.multiExpr(x, rhs[i]) }, len(rhs), l == 2) - if get == nil { - check.useLHS(lhs...) - return // error reported by unpack - } - if l != r { - check.useGetter(get, r) - check.errorf(rhs[0].Pos(), "cannot assign %d values to %d variables", r, l) - return - } - - var x operand - if commaOk { - var a [2]Type - for i := range a { - get(&x, i) - a[i] = check.assignVar(lhs[i], &x) - } - check.recordCommaOkTypes(rhs[0], a) - return - } - - for i, lhs := range lhs { - get(&x, i) - check.assignVar(lhs, &x) - } -} - -func (check *Checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) { - scope := check.scope - - // collect lhs variables - var newVars []*Var - var lhsVars = make([]*Var, len(lhs)) - for i, lhs := range lhs { - var obj *Var - if ident, _ := lhs.(*ast.Ident); ident != nil { - // Use the correct obj if the ident is redeclared. The - // variable's scope starts after the declaration; so we - // must use Scope.Lookup here and call Scope.Insert - // (via check.declare) later. - name := ident.Name - if alt := scope.Lookup(name); alt != nil { - // redeclared object must be a variable - if alt, _ := alt.(*Var); alt != nil { - obj = alt - } else { - check.errorf(lhs.Pos(), "cannot assign to %s", lhs) - } - check.recordUse(ident, alt) - } else { - // declare new variable, possibly a blank (_) variable - obj = NewVar(ident.Pos(), check.pkg, name, nil) - if name != "_" { - newVars = append(newVars, obj) - } - check.recordDef(ident, obj) - } - } else { - check.errorf(lhs.Pos(), "cannot declare %s", lhs) - } - if obj == nil { - obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable - } - lhsVars[i] = obj - } - - check.initVars(lhsVars, rhs, token.NoPos) - - // declare new variables - if len(newVars) > 0 { - // spec: "The scope of a constant or variable identifier declared inside - // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl - // for short variable declarations) and ends at the end of the innermost - // containing block." - scopePos := rhs[len(rhs)-1].End() - for _, obj := range newVars { - check.declare(scope, nil, obj, scopePos) // recordObject already called - } - } else { - check.softErrorf(pos, "no new variables on left side of :=") - } -} diff --git a/third_party/forked/golang/go/types/builtins.go b/third_party/forked/golang/go/types/builtins.go deleted file mode 100644 index 87f80630ac1..00000000000 --- a/third_party/forked/golang/go/types/builtins.go +++ /dev/null @@ -1,670 +0,0 @@ -// Copyright 2012 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. - -// This file implements typechecking of builtin function calls. - -package types - -import ( - "go/ast" - "go/constant" - "go/token" -) - -// builtin type-checks a call to the built-in specified by id and -// returns true if the call is valid, with *x holding the result; -// but x.expr is not set. If the call is invalid, the result is -// false, and *x is undefined. -// -func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ bool) { - // append is the only built-in that permits the use of ... for the last argument - bin := predeclaredFuncs[id] - if call.Ellipsis.IsValid() && id != _Append { - check.invalidOp(call.Ellipsis, "invalid use of ... with built-in %s", bin.name) - check.use(call.Args...) - return - } - - // For len(x) and cap(x) we need to know if x contains any function calls or - // receive operations. Save/restore current setting and set hasCallOrRecv to - // false for the evaluation of x so that we can check it afterwards. - // Note: We must do this _before_ calling unpack because unpack evaluates the - // first argument before we even call arg(x, 0)! - if id == _Len || id == _Cap { - defer func(b bool) { - check.hasCallOrRecv = b - }(check.hasCallOrRecv) - check.hasCallOrRecv = false - } - - // determine actual arguments - var arg getter - nargs := len(call.Args) - switch id { - default: - // make argument getter - arg, nargs, _ = unpack(func(x *operand, i int) { check.multiExpr(x, call.Args[i]) }, nargs, false) - if arg == nil { - return - } - // evaluate first argument, if present - if nargs > 0 { - arg(x, 0) - if x.mode == invalid { - return - } - } - case _Make, _New, _Offsetof, _Trace: - // arguments require special handling - } - - // check argument count - { - msg := "" - if nargs < bin.nargs { - msg = "not enough" - } else if !bin.variadic && nargs > bin.nargs { - msg = "too many" - } - if msg != "" { - check.invalidOp(call.Rparen, "%s arguments for %s (expected %d, found %d)", msg, call, bin.nargs, nargs) - return - } - } - - switch id { - case _Append: - // append(s S, x ...T) S, where T is the element type of S - // spec: "The variadic function append appends zero or more values x to s of type - // S, which must be a slice type, and returns the resulting slice, also of type S. - // The values x are passed to a parameter of type ...T where T is the element type - // of S and the respective parameter passing rules apply." - S := x.typ - var T Type - if s, _ := S.Underlying().(*Slice); s != nil { - T = s.elem - } else { - check.invalidArg(x.pos(), "%s is not a slice", x) - return - } - - // remember arguments that have been evaluated already - alist := []operand{*x} - - // spec: "As a special case, append also accepts a first argument assignable - // to type []byte with a second argument of string type followed by ... . - // This form appends the bytes of the string. - if nargs == 2 && call.Ellipsis.IsValid() && x.assignableTo(check.conf, NewSlice(universeByte), nil) { - arg(x, 1) - if x.mode == invalid { - return - } - if isString(x.typ) { - if check.Types != nil { - sig := makeSig(S, S, x.typ) - sig.variadic = true - check.recordBuiltinType(call.Fun, sig) - } - x.mode = value - x.typ = S - break - } - alist = append(alist, *x) - // fallthrough - } - - // check general case by creating custom signature - sig := makeSig(S, S, NewSlice(T)) // []T required for variadic signature - sig.variadic = true - check.arguments(x, call, sig, func(x *operand, i int) { - // only evaluate arguments that have not been evaluated before - if i < len(alist) { - *x = alist[i] - return - } - arg(x, i) - }, nargs) - // ok to continue even if check.arguments reported errors - - x.mode = value - x.typ = S - if check.Types != nil { - check.recordBuiltinType(call.Fun, sig) - } - - case _Cap, _Len: - // cap(x) - // len(x) - mode := invalid - var typ Type - var val constant.Value - switch typ = implicitArrayDeref(x.typ.Underlying()); t := typ.(type) { - case *Basic: - if isString(t) && id == _Len { - if x.mode == constant_ { - mode = constant_ - val = constant.MakeInt64(int64(len(constant.StringVal(x.val)))) - } else { - mode = value - } - } - - case *Array: - mode = value - // spec: "The expressions len(s) and cap(s) are constants - // if the type of s is an array or pointer to an array and - // the expression s does not contain channel receives or - // function calls; in this case s is not evaluated." - if !check.hasCallOrRecv { - mode = constant_ - if t.len >= 0 { - val = constant.MakeInt64(t.len) - } else { - val = constant.MakeUnknown() - } - } - - case *Slice, *Chan: - mode = value - - case *Map: - if id == _Len { - mode = value - } - } - - if mode == invalid { - check.invalidArg(x.pos(), "%s for %s", x, bin.name) - return - } - - x.mode = mode - x.typ = Typ[Int] - x.val = val - if check.Types != nil && mode != constant_ { - check.recordBuiltinType(call.Fun, makeSig(x.typ, typ)) - } - - case _Close: - // close(c) - c, _ := x.typ.Underlying().(*Chan) - if c == nil { - check.invalidArg(x.pos(), "%s is not a channel", x) - return - } - if c.dir == RecvOnly { - check.invalidArg(x.pos(), "%s must not be a receive-only channel", x) - return - } - - x.mode = novalue - if check.Types != nil { - check.recordBuiltinType(call.Fun, makeSig(nil, c)) - } - - case _Complex: - // complex(x, y floatT) complexT - var y operand - arg(&y, 1) - if y.mode == invalid { - return - } - - // convert or check untyped arguments - d := 0 - if isUntyped(x.typ) { - d |= 1 - } - if isUntyped(y.typ) { - d |= 2 - } - switch d { - case 0: - // x and y are typed => nothing to do - case 1: - // only x is untyped => convert to type of y - check.convertUntyped(x, y.typ) - case 2: - // only y is untyped => convert to type of x - check.convertUntyped(&y, x.typ) - case 3: - // x and y are untyped => - // 1) if both are constants, convert them to untyped - // floating-point numbers if possible, - // 2) if one of them is not constant (possible because - // it contains a shift that is yet untyped), convert - // both of them to float64 since they must have the - // same type to succeed (this will result in an error - // because shifts of floats are not permitted) - if x.mode == constant_ && y.mode == constant_ { - toFloat := func(x *operand) { - if isNumeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 { - x.typ = Typ[UntypedFloat] - } - } - toFloat(x) - toFloat(&y) - } else { - check.convertUntyped(x, Typ[Float64]) - check.convertUntyped(&y, Typ[Float64]) - // x and y should be invalid now, but be conservative - // and check below - } - } - if x.mode == invalid || y.mode == invalid { - return - } - - // both argument types must be identical - if !Identical(x.typ, y.typ) { - check.invalidArg(x.pos(), "mismatched types %s and %s", x.typ, y.typ) - return - } - - // the argument types must be of floating-point type - if !isFloat(x.typ) { - check.invalidArg(x.pos(), "arguments have type %s, expected floating-point", x.typ) - return - } - - // if both arguments are constants, the result is a constant - if x.mode == constant_ && y.mode == constant_ { - x.val = constant.BinaryOp(constant.ToFloat(x.val), token.ADD, constant.MakeImag(constant.ToFloat(y.val))) - } else { - x.mode = value - } - - // determine result type - var res BasicKind - switch x.typ.Underlying().(*Basic).kind { - case Float32: - res = Complex64 - case Float64: - res = Complex128 - case UntypedFloat: - res = UntypedComplex - default: - unreachable() - } - resTyp := Typ[res] - - if check.Types != nil && x.mode != constant_ { - check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ, x.typ)) - } - - x.typ = resTyp - - case _Copy: - // copy(x, y []T) int - var dst Type - if t, _ := x.typ.Underlying().(*Slice); t != nil { - dst = t.elem - } - - var y operand - arg(&y, 1) - if y.mode == invalid { - return - } - var src Type - switch t := y.typ.Underlying().(type) { - case *Basic: - if isString(y.typ) { - src = universeByte - } - case *Slice: - src = t.elem - } - - if dst == nil || src == nil { - check.invalidArg(x.pos(), "copy expects slice arguments; found %s and %s", x, &y) - return - } - - if !Identical(dst, src) { - check.invalidArg(x.pos(), "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src) - return - } - - if check.Types != nil { - check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ, y.typ)) - } - x.mode = value - x.typ = Typ[Int] - - case _Delete: - // delete(m, k) - m, _ := x.typ.Underlying().(*Map) - if m == nil { - check.invalidArg(x.pos(), "%s is not a map", x) - return - } - arg(x, 1) // k - if x.mode == invalid { - return - } - - if !x.assignableTo(check.conf, m.key, nil) { - check.invalidArg(x.pos(), "%s is not assignable to %s", x, m.key) - return - } - - x.mode = novalue - if check.Types != nil { - check.recordBuiltinType(call.Fun, makeSig(nil, m, m.key)) - } - - case _Imag, _Real: - // imag(complexT) floatT - // real(complexT) floatT - - // convert or check untyped argument - if isUntyped(x.typ) { - if x.mode == constant_ { - // an untyped constant number can alway be considered - // as a complex constant - if isNumeric(x.typ) { - x.typ = Typ[UntypedComplex] - } - } else { - // an untyped non-constant argument may appear if - // it contains a (yet untyped non-constant) shift - // expression: convert it to complex128 which will - // result in an error (shift of complex value) - check.convertUntyped(x, Typ[Complex128]) - // x should be invalid now, but be conservative and check - if x.mode == invalid { - return - } - } - } - - // the argument must be of complex type - if !isComplex(x.typ) { - check.invalidArg(x.pos(), "argument has type %s, expected complex type", x.typ) - return - } - - // if the argument is a constant, the result is a constant - if x.mode == constant_ { - if id == _Real { - x.val = constant.Real(x.val) - } else { - x.val = constant.Imag(x.val) - } - } else { - x.mode = value - } - - // determine result type - var res BasicKind - switch x.typ.Underlying().(*Basic).kind { - case Complex64: - res = Float32 - case Complex128: - res = Float64 - case UntypedComplex: - res = UntypedFloat - default: - unreachable() - } - resTyp := Typ[res] - - if check.Types != nil && x.mode != constant_ { - check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ)) - } - - x.typ = resTyp - - case _Make: - // make(T, n) - // make(T, n, m) - // (no argument evaluated yet) - arg0 := call.Args[0] - T := check.typ(arg0) - if T == Typ[Invalid] { - return - } - - var min int // minimum number of arguments - switch T.Underlying().(type) { - case *Slice: - min = 2 - case *Map, *Chan: - min = 1 - default: - check.invalidArg(arg0.Pos(), "cannot make %s; type must be slice, map, or channel", arg0) - return - } - if nargs < min || min+1 < nargs { - check.errorf(call.Pos(), "%v expects %d or %d arguments; found %d", call, min, min+1, nargs) - return - } - var sizes []int64 // constant integer arguments, if any - for _, arg := range call.Args[1:] { - if s, ok := check.index(arg, -1); ok && s >= 0 { - sizes = append(sizes, s) - } - } - if len(sizes) == 2 && sizes[0] > sizes[1] { - check.invalidArg(call.Args[1].Pos(), "length and capacity swapped") - // safe to continue - } - x.mode = value - x.typ = T - if check.Types != nil { - params := [...]Type{T, Typ[Int], Typ[Int]} - check.recordBuiltinType(call.Fun, makeSig(x.typ, params[:1+len(sizes)]...)) - } - - case _New: - // new(T) - // (no argument evaluated yet) - T := check.typ(call.Args[0]) - if T == Typ[Invalid] { - return - } - - x.mode = value - x.typ = &Pointer{base: T} - if check.Types != nil { - check.recordBuiltinType(call.Fun, makeSig(x.typ, T)) - } - - case _Panic: - // panic(x) - check.assignment(x, &emptyInterface, "argument to panic") - if x.mode == invalid { - return - } - - x.mode = novalue - if check.Types != nil { - check.recordBuiltinType(call.Fun, makeSig(nil, &emptyInterface)) - } - - case _Print, _Println: - // print(x, y, ...) - // println(x, y, ...) - var params []Type - if nargs > 0 { - params = make([]Type, nargs) - for i := 0; i < nargs; i++ { - if i > 0 { - arg(x, i) // first argument already evaluated - } - check.assignment(x, nil, "argument to "+predeclaredFuncs[id].name) - if x.mode == invalid { - // TODO(gri) "use" all arguments? - return - } - params[i] = x.typ - } - } - - x.mode = novalue - if check.Types != nil { - check.recordBuiltinType(call.Fun, makeSig(nil, params...)) - } - - case _Recover: - // recover() interface{} - x.mode = value - x.typ = &emptyInterface - if check.Types != nil { - check.recordBuiltinType(call.Fun, makeSig(x.typ)) - } - - case _Alignof: - // unsafe.Alignof(x T) uintptr - check.assignment(x, nil, "argument to unsafe.Alignof") - if x.mode == invalid { - return - } - - x.mode = constant_ - x.val = constant.MakeInt64(check.conf.alignof(x.typ)) - x.typ = Typ[Uintptr] - // result is constant - no need to record signature - - case _Offsetof: - // unsafe.Offsetof(x T) uintptr, where x must be a selector - // (no argument evaluated yet) - arg0 := call.Args[0] - selx, _ := unparen(arg0).(*ast.SelectorExpr) - if selx == nil { - check.invalidArg(arg0.Pos(), "%s is not a selector expression", arg0) - check.use(arg0) - return - } - - check.expr(x, selx.X) - if x.mode == invalid { - return - } - - base := derefStructPtr(x.typ) - sel := selx.Sel.Name - obj, index, indirect := LookupFieldOrMethod(base, false, check.pkg, sel) - switch obj.(type) { - case nil: - check.invalidArg(x.pos(), "%s has no single field %s", base, sel) - return - case *Func: - // TODO(gri) Using derefStructPtr may result in methods being found - // that don't actually exist. An error either way, but the error - // message is confusing. See: https://play.golang.org/p/al75v23kUy , - // but go/types reports: "invalid argument: x.m is a method value". - check.invalidArg(arg0.Pos(), "%s is a method value", arg0) - return - } - if indirect { - check.invalidArg(x.pos(), "field %s is embedded via a pointer in %s", sel, base) - return - } - - // TODO(gri) Should we pass x.typ instead of base (and indirect report if derefStructPtr indirected)? - check.recordSelection(selx, FieldVal, base, obj, index, false) - - offs := check.conf.offsetof(base, index) - x.mode = constant_ - x.val = constant.MakeInt64(offs) - x.typ = Typ[Uintptr] - // result is constant - no need to record signature - - case _Sizeof: - // unsafe.Sizeof(x T) uintptr - check.assignment(x, nil, "argument to unsafe.Sizeof") - if x.mode == invalid { - return - } - - x.mode = constant_ - x.val = constant.MakeInt64(check.conf.sizeof(x.typ)) - x.typ = Typ[Uintptr] - // result is constant - no need to record signature - - case _Assert: - // assert(pred) causes a typechecker error if pred is false. - // The result of assert is the value of pred if there is no error. - // Note: assert is only available in self-test mode. - if x.mode != constant_ || !isBoolean(x.typ) { - check.invalidArg(x.pos(), "%s is not a boolean constant", x) - return - } - if x.val.Kind() != constant.Bool { - check.errorf(x.pos(), "internal error: value of %s should be a boolean constant", x) - return - } - if !constant.BoolVal(x.val) { - check.errorf(call.Pos(), "%v failed", call) - // compile-time assertion failure - safe to continue - } - // result is constant - no need to record signature - - case _Trace: - // trace(x, y, z, ...) dumps the positions, expressions, and - // values of its arguments. The result of trace is the value - // of the first argument. - // Note: trace is only available in self-test mode. - // (no argument evaluated yet) - if nargs == 0 { - check.dump("%s: trace() without arguments", call.Pos()) - x.mode = novalue - break - } - var t operand - x1 := x - for _, arg := range call.Args { - check.rawExpr(x1, arg, nil) // permit trace for types, e.g.: new(trace(T)) - check.dump("%s: %s", x1.pos(), x1) - x1 = &t // use incoming x only for first argument - } - // trace is only available in test mode - no need to record signature - - default: - unreachable() - } - - return true -} - -// makeSig makes a signature for the given argument and result types. -// Default types are used for untyped arguments, and res may be nil. -func makeSig(res Type, args ...Type) *Signature { - list := make([]*Var, len(args)) - for i, param := range args { - list[i] = NewVar(token.NoPos, nil, "", Default(param)) - } - params := NewTuple(list...) - var result *Tuple - if res != nil { - assert(!isUntyped(res)) - result = NewTuple(NewVar(token.NoPos, nil, "", res)) - } - return &Signature{params: params, results: result} -} - -// implicitArrayDeref returns A if typ is of the form *A and A is an array; -// otherwise it returns typ. -// -func implicitArrayDeref(typ Type) Type { - if p, ok := typ.(*Pointer); ok { - if a, ok := p.base.Underlying().(*Array); ok { - return a - } - } - return typ -} - -// unparen returns e with any enclosing parentheses stripped. -func unparen(e ast.Expr) ast.Expr { - for { - p, ok := e.(*ast.ParenExpr) - if !ok { - return e - } - e = p.X - } -} diff --git a/third_party/forked/golang/go/types/call.go b/third_party/forked/golang/go/types/call.go deleted file mode 100644 index 8fe65e41d5f..00000000000 --- a/third_party/forked/golang/go/types/call.go +++ /dev/null @@ -1,478 +0,0 @@ -// Copyright 2013 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. - -// This file implements typechecking of call and selector expressions. - -package types - -import ( - "go/ast" - "go/token" -) - -func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind { - check.exprOrType(x, e.Fun) - - switch x.mode { - case invalid: - check.use(e.Args...) - x.mode = invalid - x.expr = e - return statement - - case typexpr: - // conversion - T := x.typ - x.mode = invalid - switch n := len(e.Args); n { - case 0: - check.errorf(e.Rparen, "missing argument in conversion to %s", T) - case 1: - check.expr(x, e.Args[0]) - if x.mode != invalid { - check.conversion(x, T) - } - default: - check.errorf(e.Args[n-1].Pos(), "too many arguments in conversion to %s", T) - } - x.expr = e - return conversion - - case builtin: - id := x.id - if !check.builtin(x, e, id) { - x.mode = invalid - } - x.expr = e - // a non-constant result implies a function call - if x.mode != invalid && x.mode != constant_ { - check.hasCallOrRecv = true - } - return predeclaredFuncs[id].kind - - default: - // function/method call - sig, _ := x.typ.Underlying().(*Signature) - if sig == nil { - check.invalidOp(x.pos(), "cannot call non-function %s", x) - x.mode = invalid - x.expr = e - return statement - } - - arg, n, _ := unpack(func(x *operand, i int) { check.multiExpr(x, e.Args[i]) }, len(e.Args), false) - if arg != nil { - check.arguments(x, e, sig, arg, n) - } else { - x.mode = invalid - } - - // determine result - switch sig.results.Len() { - case 0: - x.mode = novalue - case 1: - x.mode = value - x.typ = sig.results.vars[0].typ // unpack tuple - default: - x.mode = value - x.typ = sig.results - } - - x.expr = e - check.hasCallOrRecv = true - - return statement - } -} - -// use type-checks each argument. -// Useful to make sure expressions are evaluated -// (and variables are "used") in the presence of other errors. -// The arguments may be nil. -func (check *Checker) use(arg ...ast.Expr) { - var x operand - for _, e := range arg { - // The nil check below is necessary since certain AST fields - // may legally be nil (e.g., the ast.SliceExpr.High field). - if e != nil { - check.rawExpr(&x, e, nil) - } - } -} - -// useLHS is like use, but doesn't "use" top-level identifiers. -// It should be called instead of use if the arguments are -// expressions on the lhs of an assignment. -// The arguments must not be nil. -func (check *Checker) useLHS(arg ...ast.Expr) { - var x operand - for _, e := range arg { - // If the lhs is an identifier denoting a variable v, this assignment - // is not a 'use' of v. Remember current value of v.used and restore - // after evaluating the lhs via check.rawExpr. - var v *Var - var v_used bool - if ident, _ := unparen(e).(*ast.Ident); ident != nil { - // never type-check the blank name on the lhs - if ident.Name == "_" { - continue - } - if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil { - // It's ok to mark non-local variables, but ignore variables - // from other packages to avoid potential race conditions with - // dot-imported variables. - if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg { - v = w - v_used = v.used - } - } - } - check.rawExpr(&x, e, nil) - if v != nil { - v.used = v_used // restore v.used - } - } -} - -// useGetter is like use, but takes a getter instead of a list of expressions. -// It should be called instead of use if a getter is present to avoid repeated -// evaluation of the first argument (since the getter was likely obtained via -// unpack, which may have evaluated the first argument already). -func (check *Checker) useGetter(get getter, n int) { - var x operand - for i := 0; i < n; i++ { - get(&x, i) - } -} - -// A getter sets x as the i'th operand, where 0 <= i < n and n is the total -// number of operands (context-specific, and maintained elsewhere). A getter -// type-checks the i'th operand; the details of the actual check are getter- -// specific. -type getter func(x *operand, i int) - -// unpack takes a getter get and a number of operands n. If n == 1, unpack -// calls the incoming getter for the first operand. If that operand is -// invalid, unpack returns (nil, 0, false). Otherwise, if that operand is a -// function call, or a comma-ok expression and allowCommaOk is set, the result -// is a new getter and operand count providing access to the function results, -// or comma-ok values, respectively. The third result value reports if it -// is indeed the comma-ok case. In all other cases, the incoming getter and -// operand count are returned unchanged, and the third result value is false. -// -// In other words, if there's exactly one operand that - after type-checking -// by calling get - stands for multiple operands, the resulting getter provides -// access to those operands instead. -// -// If the returned getter is called at most once for a given operand index i -// (including i == 0), that operand is guaranteed to cause only one call of -// the incoming getter with that i. -// -func unpack(get getter, n int, allowCommaOk bool) (getter, int, bool) { - if n != 1 { - // zero or multiple values - return get, n, false - } - // possibly result of an n-valued function call or comma,ok value - var x0 operand - get(&x0, 0) - if x0.mode == invalid { - return nil, 0, false - } - - if t, ok := x0.typ.(*Tuple); ok { - // result of an n-valued function call - return func(x *operand, i int) { - x.mode = value - x.expr = x0.expr - x.typ = t.At(i).typ - }, t.Len(), false - } - - if x0.mode == mapindex || x0.mode == commaok { - // comma-ok value - if allowCommaOk { - a := [2]Type{x0.typ, Typ[UntypedBool]} - return func(x *operand, i int) { - x.mode = value - x.expr = x0.expr - x.typ = a[i] - }, 2, true - } - x0.mode = value - } - - // single value - return func(x *operand, i int) { - if i != 0 { - unreachable() - } - *x = x0 - }, 1, false -} - -// arguments checks argument passing for the call with the given signature. -// The arg function provides the operand for the i'th argument. -func (check *Checker) arguments(x *operand, call *ast.CallExpr, sig *Signature, arg getter, n int) { - if call.Ellipsis.IsValid() { - // last argument is of the form x... - if !sig.variadic { - check.errorf(call.Ellipsis, "cannot use ... in call to non-variadic %s", call.Fun) - check.useGetter(arg, n) - return - } - if len(call.Args) == 1 && n > 1 { - // f()... is not permitted if f() is multi-valued - check.errorf(call.Ellipsis, "cannot use ... with %d-valued %s", n, call.Args[0]) - check.useGetter(arg, n) - return - } - } - - // evaluate arguments - for i := 0; i < n; i++ { - arg(x, i) - if x.mode != invalid { - var ellipsis token.Pos - if i == n-1 && call.Ellipsis.IsValid() { - ellipsis = call.Ellipsis - } - check.argument(call.Fun, sig, i, x, ellipsis) - } - } - - // check argument count - if sig.variadic { - // a variadic function accepts an "empty" - // last argument: count one extra - n++ - } - if n < sig.params.Len() { - check.errorf(call.Rparen, "too few arguments in call to %s", call.Fun) - // ok to continue - } -} - -// argument checks passing of argument x to the i'th parameter of the given signature. -// If ellipsis is valid, the argument is followed by ... at that position in the call. -func (check *Checker) argument(fun ast.Expr, sig *Signature, i int, x *operand, ellipsis token.Pos) { - check.singleValue(x) - if x.mode == invalid { - return - } - - n := sig.params.Len() - - // determine parameter type - var typ Type - switch { - case i < n: - typ = sig.params.vars[i].typ - case sig.variadic: - typ = sig.params.vars[n-1].typ - if debug { - if _, ok := typ.(*Slice); !ok { - check.dump("%s: expected unnamed slice type, got %s", sig.params.vars[n-1].Pos(), typ) - } - } - default: - check.errorf(x.pos(), "too many arguments") - return - } - - if ellipsis.IsValid() { - // argument is of the form x... and x is single-valued - if i != n-1 { - check.errorf(ellipsis, "can only use ... with matching parameter") - return - } - if _, ok := x.typ.Underlying().(*Slice); !ok && x.typ != Typ[UntypedNil] { // see issue #18268 - check.errorf(x.pos(), "cannot use %s as parameter of type %s", x, typ) - return - } - } else if sig.variadic && i >= n-1 { - // use the variadic parameter slice's element type - typ = typ.(*Slice).elem - } - - check.assignment(x, typ, check.sprintf("argument to %s", fun)) -} - -func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { - // these must be declared before the "goto Error" statements - var ( - obj Object - index []int - indirect bool - ) - - sel := e.Sel.Name - // If the identifier refers to a package, handle everything here - // so we don't need a "package" mode for operands: package names - // can only appear in qualified identifiers which are mapped to - // selector expressions. - if ident, ok := e.X.(*ast.Ident); ok { - _, obj := check.scope.LookupParent(ident.Name, check.pos) - if pname, _ := obj.(*PkgName); pname != nil { - assert(pname.pkg == check.pkg) - check.recordUse(ident, pname) - pname.used = true - pkg := pname.imported - exp := pkg.scope.Lookup(sel) - if exp == nil { - if !pkg.fake { - check.errorf(e.Pos(), "%s not declared by package %s", sel, pkg.name) - } - goto Error - } - if !exp.Exported() { - check.errorf(e.Pos(), "%s not exported by package %s", sel, pkg.name) - // ok to continue - } - check.recordUse(e.Sel, exp) - - // Simplified version of the code for *ast.Idents: - // - imported objects are always fully initialized - switch exp := exp.(type) { - case *Const: - assert(exp.Val() != nil) - x.mode = constant_ - x.typ = exp.typ - x.val = exp.val - case *TypeName: - x.mode = typexpr - x.typ = exp.typ - case *Var: - x.mode = variable - x.typ = exp.typ - case *Func: - x.mode = value - x.typ = exp.typ - case *Builtin: - x.mode = builtin - x.typ = exp.typ - x.id = exp.id - default: - check.dump("unexpected object %v", exp) - unreachable() - } - x.expr = e - return - } - } - - check.exprOrType(x, e.X) - if x.mode == invalid { - goto Error - } - - obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel) - if obj == nil { - switch { - case index != nil: - // TODO(gri) should provide actual type where the conflict happens - check.invalidOp(e.Pos(), "ambiguous selector %s", sel) - case indirect: - check.invalidOp(e.Pos(), "%s is not in method set of %s", sel, x.typ) - default: - check.invalidOp(e.Pos(), "%s has no field or method %s", x, sel) - } - goto Error - } - - if x.mode == typexpr { - // method expression - m, _ := obj.(*Func) - if m == nil { - check.invalidOp(e.Pos(), "%s has no method %s", x, sel) - goto Error - } - - check.recordSelection(e, MethodExpr, x.typ, m, index, indirect) - - // the receiver type becomes the type of the first function - // argument of the method expression's function type - var params []*Var - sig := m.typ.(*Signature) - if sig.params != nil { - params = sig.params.vars - } - x.mode = value - x.typ = &Signature{ - params: NewTuple(append([]*Var{NewVar(token.NoPos, check.pkg, "", x.typ)}, params...)...), - results: sig.results, - variadic: sig.variadic, - } - - check.addDeclDep(m) - - } else { - // regular selector - switch obj := obj.(type) { - case *Var: - check.recordSelection(e, FieldVal, x.typ, obj, index, indirect) - if x.mode == variable || indirect { - x.mode = variable - } else { - x.mode = value - } - x.typ = obj.typ - - case *Func: - // TODO(gri) If we needed to take into account the receiver's - // addressability, should we report the type &(x.typ) instead? - check.recordSelection(e, MethodVal, x.typ, obj, index, indirect) - - if debug { - // Verify that LookupFieldOrMethod and MethodSet.Lookup agree. - typ := x.typ - if x.mode == variable { - // If typ is not an (unnamed) pointer or an interface, - // use *typ instead, because the method set of *typ - // includes the methods of typ. - // Variables are addressable, so we can always take their - // address. - if _, ok := typ.(*Pointer); !ok && !IsInterface(typ) { - typ = &Pointer{base: typ} - } - } - // If we created a synthetic pointer type above, we will throw - // away the method set computed here after use. - // TODO(gri) Method set computation should probably always compute - // both, the value and the pointer receiver method set and represent - // them in a single structure. - // TODO(gri) Consider also using a method set cache for the lifetime - // of checker once we rely on MethodSet lookup instead of individual - // lookup. - mset := NewMethodSet(typ) - if m := mset.Lookup(check.pkg, sel); m == nil || m.obj != obj { - check.dump("%s: (%s).%v -> %s", e.Pos(), typ, obj.name, m) - check.dump("%s\n", mset) - panic("method sets and lookup don't agree") - } - } - - x.mode = value - - // remove receiver - sig := *obj.typ.(*Signature) - sig.recv = nil - x.typ = &sig - - check.addDeclDep(obj) - - default: - unreachable() - } - } - - // everything went well - x.expr = e - return - -Error: - x.mode = invalid - x.expr = e -} diff --git a/third_party/forked/golang/go/types/check.go b/third_party/forked/golang/go/types/check.go deleted file mode 100644 index 26db5769b98..00000000000 --- a/third_party/forked/golang/go/types/check.go +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright 2011 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. - -// This file implements the Check function, which drives type-checking. - -package types - -import ( - "go/ast" - "go/constant" - "go/token" -) - -// debugging/development support -const ( - debug = false // leave on during development - trace = false // turn on for detailed type resolution traces -) - -// If Strict is set, the type-checker enforces additional -// rules not specified by the Go 1 spec, but which will -// catch guaranteed run-time errors if the respective -// code is executed. In other words, programs passing in -// Strict mode are Go 1 compliant, but not all Go 1 programs -// will pass in Strict mode. The additional rules are: -// -// - A type assertion x.(T) where T is an interface type -// is invalid if any (statically known) method that exists -// for both x and T have different signatures. -// -const strict = false - -// exprInfo stores information about an untyped expression. -type exprInfo struct { - isLhs bool // expression is lhs operand of a shift with delayed type-check - mode operandMode - typ *Basic - val constant.Value // constant value; or nil (if not a constant) -} - -// funcInfo stores the information required for type-checking a function. -type funcInfo struct { - name string // for debugging/tracing only - decl *declInfo // for cycle detection - sig *Signature - body *ast.BlockStmt -} - -// A context represents the context within which an object is type-checked. -type context struct { - decl *declInfo // package-level declaration whose init expression/function body is checked - scope *Scope // top-most scope for lookups - iota constant.Value // value of iota in a constant declaration; nil otherwise - sig *Signature // function signature if inside a function; nil otherwise - hasLabel bool // set if a function makes use of labels (only ~1% of functions); unused outside functions - hasCallOrRecv bool // set if an expression contains a function call or channel receive operation -} - -// An importKey identifies an imported package by import path and source directory -// (directory containing the file containing the import). In practice, the directory -// may always be the same, or may not matter. Given an (import path, directory), an -// importer must always return the same package (but given two different import paths, -// an importer may still return the same package by mapping them to the same package -// paths). -type importKey struct { - path, dir string -} - -// A Checker maintains the state of the type checker. -// It must be created with NewChecker. -type Checker struct { - // package information - // (initialized by NewChecker, valid for the life-time of checker) - conf *Config - fset *token.FileSet - pkg *Package - *Info - objMap map[Object]*declInfo // maps package-level object to declaration info - impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package - - // information collected during type-checking of a set of package files - // (initialized by Files, valid only for the duration of check.Files; - // maps and lists are allocated on demand) - files []*ast.File // package files - unusedDotImports map[*Scope]map[*Package]token.Pos // positions of unused dot-imported packages for each file scope - - firstErr error // first error encountered - methods map[string][]*Func // maps type names to associated methods - untyped map[ast.Expr]exprInfo // map of expressions without final type - funcs []funcInfo // list of functions to type-check - delayed []func() // delayed checks requiring fully setup types - - // context within which the current object is type-checked - // (valid only for the duration of type-checking a specific object) - context - pos token.Pos // if valid, identifiers are looked up as if at position pos (used by Eval) - - // debugging - indent int // indentation for tracing -} - -// addUnusedImport adds the position of a dot-imported package -// pkg to the map of dot imports for the given file scope. -func (check *Checker) addUnusedDotImport(scope *Scope, pkg *Package, pos token.Pos) { - mm := check.unusedDotImports - if mm == nil { - mm = make(map[*Scope]map[*Package]token.Pos) - check.unusedDotImports = mm - } - m := mm[scope] - if m == nil { - m = make(map[*Package]token.Pos) - mm[scope] = m - } - m[pkg] = pos -} - -// addDeclDep adds the dependency edge (check.decl -> to) if check.decl exists -func (check *Checker) addDeclDep(to Object) { - from := check.decl - if from == nil { - return // not in a package-level init expression - } - if _, found := check.objMap[to]; !found { - return // to is not a package-level object - } - from.addDep(to) -} - -func (check *Checker) assocMethod(tname string, meth *Func) { - m := check.methods - if m == nil { - m = make(map[string][]*Func) - check.methods = m - } - m[tname] = append(m[tname], meth) -} - -func (check *Checker) rememberUntyped(e ast.Expr, lhs bool, mode operandMode, typ *Basic, val constant.Value) { - m := check.untyped - if m == nil { - m = make(map[ast.Expr]exprInfo) - check.untyped = m - } - m[e] = exprInfo{lhs, mode, typ, val} -} - -func (check *Checker) later(name string, decl *declInfo, sig *Signature, body *ast.BlockStmt) { - check.funcs = append(check.funcs, funcInfo{name, decl, sig, body}) -} - -func (check *Checker) delay(f func()) { - check.delayed = append(check.delayed, f) -} - -// NewChecker returns a new Checker instance for a given package. -// Package files may be added incrementally via checker.Files. -func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Checker { - // make sure we have a configuration - if conf == nil { - conf = new(Config) - } - - // make sure we have an info struct - if info == nil { - info = new(Info) - } - - return &Checker{ - conf: conf, - fset: fset, - pkg: pkg, - Info: info, - objMap: make(map[Object]*declInfo), - impMap: make(map[importKey]*Package), - } -} - -// initFiles initializes the files-specific portion of checker. -// The provided files must all belong to the same package. -func (check *Checker) initFiles(files []*ast.File) { - // start with a clean slate (check.Files may be called multiple times) - check.files = nil - check.unusedDotImports = nil - - check.firstErr = nil - check.methods = nil - check.untyped = nil - check.funcs = nil - check.delayed = nil - - // determine package name and collect valid files - pkg := check.pkg - for _, file := range files { - switch name := file.Name.Name; pkg.name { - case "": - if name != "_" { - pkg.name = name - } else { - check.errorf(file.Name.Pos(), "invalid package name _") - } - fallthrough - - case name: - check.files = append(check.files, file) - - default: - check.errorf(file.Package, "package %s; expected %s", name, pkg.name) - // ignore this file - } - } -} - -// A bailout panic is used for early termination. -type bailout struct{} - -func (check *Checker) handleBailout(err *error) { - switch p := recover().(type) { - case nil, bailout: - // normal return or early exit - *err = check.firstErr - default: - // re-panic - panic(p) - } -} - -// Files checks the provided files as part of the checker's package. -func (check *Checker) Files(files []*ast.File) error { return check.checkFiles(files) } - -func (check *Checker) checkFiles(files []*ast.File) (err error) { - defer check.handleBailout(&err) - - check.initFiles(files) - - check.collectObjects() - - check.packageObjects(check.resolveOrder()) - - check.functionBodies() - - check.initOrder() - - if !check.conf.DisableUnusedImportCheck { - check.unusedImports() - } - - // perform delayed checks - for _, f := range check.delayed { - f() - } - - check.recordUntyped() - - check.pkg.complete = true - return -} - -func (check *Checker) recordUntyped() { - if !debug && check.Types == nil { - return // nothing to do - } - - for x, info := range check.untyped { - if debug && isTyped(info.typ) { - check.dump("%s: %s (type %s) is typed", x.Pos(), x, info.typ) - unreachable() - } - check.recordTypeAndValue(x, info.mode, info.typ, info.val) - } -} - -func (check *Checker) recordTypeAndValue(x ast.Expr, mode operandMode, typ Type, val constant.Value) { - assert(x != nil) - assert(typ != nil) - if mode == invalid { - return // omit - } - assert(typ != nil) - if mode == constant_ { - assert(val != nil) - assert(typ == Typ[Invalid] || isConstType(typ)) - } - if m := check.Types; m != nil { - m[x] = TypeAndValue{mode, typ, val} - } -} - -func (check *Checker) recordBuiltinType(f ast.Expr, sig *Signature) { - // f must be a (possibly parenthesized) identifier denoting a built-in - // (built-ins in package unsafe always produce a constant result and - // we don't record their signatures, so we don't see qualified idents - // here): record the signature for f and possible children. - for { - check.recordTypeAndValue(f, builtin, sig, nil) - switch p := f.(type) { - case *ast.Ident: - return // we're done - case *ast.ParenExpr: - f = p.X - default: - unreachable() - } - } -} - -func (check *Checker) recordCommaOkTypes(x ast.Expr, a [2]Type) { - assert(x != nil) - if a[0] == nil || a[1] == nil { - return - } - assert(isTyped(a[0]) && isTyped(a[1]) && isBoolean(a[1])) - if m := check.Types; m != nil { - for { - tv := m[x] - assert(tv.Type != nil) // should have been recorded already - pos := x.Pos() - tv.Type = NewTuple( - NewVar(pos, check.pkg, "", a[0]), - NewVar(pos, check.pkg, "", a[1]), - ) - m[x] = tv - // if x is a parenthesized expression (p.X), update p.X - p, _ := x.(*ast.ParenExpr) - if p == nil { - break - } - x = p.X - } - } -} - -func (check *Checker) recordDef(id *ast.Ident, obj Object) { - assert(id != nil) - if m := check.Defs; m != nil { - m[id] = obj - } -} - -func (check *Checker) recordUse(id *ast.Ident, obj Object) { - assert(id != nil) - assert(obj != nil) - if m := check.Uses; m != nil { - m[id] = obj - } -} - -func (check *Checker) recordImplicit(node ast.Node, obj Object) { - assert(node != nil) - assert(obj != nil) - if m := check.Implicits; m != nil { - m[node] = obj - } -} - -func (check *Checker) recordSelection(x *ast.SelectorExpr, kind SelectionKind, recv Type, obj Object, index []int, indirect bool) { - assert(obj != nil && (recv == nil || len(index) > 0)) - check.recordUse(x.Sel, obj) - if m := check.Selections; m != nil { - m[x] = &Selection{kind, recv, obj, index, indirect} - } -} - -func (check *Checker) recordScope(node ast.Node, scope *Scope) { - assert(node != nil) - assert(scope != nil) - if m := check.Scopes; m != nil { - m[node] = scope - } -} diff --git a/third_party/forked/golang/go/types/conversions.go b/third_party/forked/golang/go/types/conversions.go deleted file mode 100644 index 81a65838fe0..00000000000 --- a/third_party/forked/golang/go/types/conversions.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2012 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. - -// This file implements typechecking of conversions. - -package types - -import "go/constant" - -// Conversion type-checks the conversion T(x). -// The result is in x. -func (check *Checker) conversion(x *operand, T Type) { - constArg := x.mode == constant_ - - var ok bool - switch { - case constArg && isConstType(T): - // constant conversion - switch t := T.Underlying().(*Basic); { - case representableConst(x.val, check.conf, t, &x.val): - ok = true - case isInteger(x.typ) && isString(t): - codepoint := int64(-1) - if i, ok := constant.Int64Val(x.val); ok { - codepoint = i - } - // If codepoint < 0 the absolute value is too large (or unknown) for - // conversion. This is the same as converting any other out-of-range - // value - let string(codepoint) do the work. - x.val = constant.MakeString(string(codepoint)) - ok = true - } - case x.convertibleTo(check.conf, T): - // non-constant conversion - x.mode = value - ok = true - } - - if !ok { - check.errorf(x.pos(), "cannot convert %s to %s", x, T) - x.mode = invalid - return - } - - // The conversion argument types are final. For untyped values the - // conversion provides the type, per the spec: "A constant may be - // given a type explicitly by a constant declaration or conversion,...". - if isUntyped(x.typ) { - final := T - // - For conversions to interfaces, use the argument's default type. - // - For conversions of untyped constants to non-constant types, also - // use the default type (e.g., []byte("foo") should report string - // not []byte as type for the constant "foo"). - // - Keep untyped nil for untyped nil arguments. - // - For integer to string conversions, keep the argument type. - // (See also the TODO below.) - if IsInterface(T) || constArg && !isConstType(T) { - final = Default(x.typ) - } else if isInteger(x.typ) && isString(T) { - final = x.typ - } - check.updateExprType(x.expr, final, true) - } - - x.typ = T -} - -// TODO(gri) convertibleTo checks if T(x) is valid. It assumes that the type -// of x is fully known, but that's not the case for say string(1< %s", obj) - }() - } - - d := check.objMap[obj] - if d == nil { - check.dump("%s: %s should have been declared", obj.Pos(), obj.Name()) - unreachable() - } - - // save/restore current context and setup object context - defer func(ctxt context) { - check.context = ctxt - }(check.context) - check.context = context{ - scope: d.file, - } - - // Const and var declarations must not have initialization - // cycles. We track them by remembering the current declaration - // in check.decl. Initialization expressions depending on other - // consts, vars, or functions, add dependencies to the current - // check.decl. - switch obj := obj.(type) { - case *Const: - check.decl = d // new package-level const decl - check.constDecl(obj, d.typ, d.init) - case *Var: - check.decl = d // new package-level var decl - check.varDecl(obj, d.lhs, d.typ, d.init) - case *TypeName: - // invalid recursive types are detected via path - check.typeDecl(obj, d.typ, def, path, d.alias) - case *Func: - // functions may be recursive - no need to track dependencies - check.funcDecl(obj, d) - default: - unreachable() - } -} - -func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) { - assert(obj.typ == nil) - - if obj.visited { - obj.typ = Typ[Invalid] - return - } - obj.visited = true - - // use the correct value of iota - assert(check.iota == nil) - check.iota = obj.val - defer func() { check.iota = nil }() - - // provide valid constant value under all circumstances - obj.val = constant.MakeUnknown() - - // determine type, if any - if typ != nil { - t := check.typ(typ) - if !isConstType(t) { - // don't report an error if the type is an invalid C (defined) type - // (issue #22090) - if t.Underlying() != Typ[Invalid] { - check.errorf(typ.Pos(), "invalid constant type %s", t) - } - obj.typ = Typ[Invalid] - return - } - obj.typ = t - } - - // check initialization - var x operand - if init != nil { - check.expr(&x, init) - } - check.initConst(obj, &x) -} - -func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) { - assert(obj.typ == nil) - - if obj.visited { - obj.typ = Typ[Invalid] - return - } - obj.visited = true - - // var declarations cannot use iota - assert(check.iota == nil) - - // determine type, if any - if typ != nil { - obj.typ = check.typ(typ) - // We cannot spread the type to all lhs variables if there - // are more than one since that would mark them as checked - // (see Checker.objDecl) and the assignment of init exprs, - // if any, would not be checked. - // - // TODO(gri) If we have no init expr, we should distribute - // a given type otherwise we need to re-evalate the type - // expr for each lhs variable, leading to duplicate work. - } - - // check initialization - if init == nil { - if typ == nil { - // error reported before by arityMatch - obj.typ = Typ[Invalid] - } - return - } - - if lhs == nil || len(lhs) == 1 { - assert(lhs == nil || lhs[0] == obj) - var x operand - check.expr(&x, init) - check.initVar(obj, &x, "variable declaration") - return - } - - if debug { - // obj must be one of lhs - found := false - for _, lhs := range lhs { - if obj == lhs { - found = true - break - } - } - if !found { - panic("inconsistent lhs") - } - } - - // We have multiple variables on the lhs and one init expr. - // Make sure all variables have been given the same type if - // one was specified, otherwise they assume the type of the - // init expression values (was issue #15755). - if typ != nil { - for _, lhs := range lhs { - lhs.typ = obj.typ - } - } - - check.initVars(lhs, []ast.Expr{init}, token.NoPos) -} - -// underlying returns the underlying type of typ; possibly by following -// forward chains of named types. Such chains only exist while named types -// are incomplete. -func underlying(typ Type) Type { - for { - n, _ := typ.(*Named) - if n == nil { - break - } - typ = n.underlying - } - return typ -} - -func (n *Named) setUnderlying(typ Type) { - if n != nil { - n.underlying = typ - } -} - -func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, path []*TypeName, alias bool) { - assert(obj.typ == nil) - - // type declarations cannot use iota - assert(check.iota == nil) - - if alias { - - obj.typ = Typ[Invalid] - obj.typ = check.typExpr(typ, nil, append(path, obj)) - - } else { - - named := &Named{obj: obj} - def.setUnderlying(named) - obj.typ = named // make sure recursive type declarations terminate - - // determine underlying type of named - check.typExpr(typ, named, append(path, obj)) - - // The underlying type of named may be itself a named type that is - // incomplete: - // - // type ( - // A B - // B *C - // C A - // ) - // - // The type of C is the (named) type of A which is incomplete, - // and which has as its underlying type the named type B. - // Determine the (final, unnamed) underlying type by resolving - // any forward chain (they always end in an unnamed type). - named.underlying = underlying(named.underlying) - - } - - // check and add associated methods - // TODO(gri) It's easy to create pathological cases where the - // current approach is incorrect: In general we need to know - // and add all methods _before_ type-checking the type. - // See https://play.golang.org/p/WMpE0q2wK8 - check.addMethodDecls(obj) -} - -func (check *Checker) addMethodDecls(obj *TypeName) { - // get associated methods - methods := check.methods[obj.name] - if len(methods) == 0 { - return // no methods - } - delete(check.methods, obj.name) - - // use an objset to check for name conflicts - var mset objset - - // spec: "If the base type is a struct type, the non-blank method - // and field names must be distinct." - base, _ := obj.typ.(*Named) // nil if receiver base type is type alias - if base != nil { - if t, _ := base.underlying.(*Struct); t != nil { - for _, fld := range t.fields { - if fld.name != "_" { - assert(mset.insert(fld) == nil) - } - } - } - - // Checker.Files may be called multiple times; additional package files - // may add methods to already type-checked types. Add pre-existing methods - // so that we can detect redeclarations. - for _, m := range base.methods { - assert(m.name != "_") - assert(mset.insert(m) == nil) - } - } - - // type-check methods - for _, m := range methods { - // spec: "For a base type, the non-blank names of methods bound - // to it must be unique." - if m.name != "_" { - if alt := mset.insert(m); alt != nil { - switch alt.(type) { - case *Var: - check.errorf(m.pos, "field and method with the same name %s", m.name) - case *Func: - check.errorf(m.pos, "method %s already declared for %s", m.name, obj) - default: - unreachable() - } - check.reportAltDecl(alt) - continue - } - } - - // type-check - check.objDecl(m, nil, nil) - - // methods with blank _ names cannot be found - don't keep them - if base != nil && m.name != "_" { - base.methods = append(base.methods, m) - } - } -} - -func (check *Checker) funcDecl(obj *Func, decl *declInfo) { - assert(obj.typ == nil) - - // func declarations cannot use iota - assert(check.iota == nil) - - sig := new(Signature) - obj.typ = sig // guard against cycles - fdecl := decl.fdecl - check.funcType(sig, fdecl.Recv, fdecl.Type) - if sig.recv == nil && obj.name == "init" && (sig.params.Len() > 0 || sig.results.Len() > 0) { - check.errorf(fdecl.Pos(), "func init must have no arguments and no return values") - // ok to continue - } - - // function body must be type-checked after global declarations - // (functions implemented elsewhere have no body) - if !check.conf.IgnoreFuncBodies && fdecl.Body != nil { - check.later(obj.name, decl, sig, fdecl.Body) - } -} - -func (check *Checker) declStmt(decl ast.Decl) { - pkg := check.pkg - - switch d := decl.(type) { - case *ast.BadDecl: - // ignore - - case *ast.GenDecl: - var last *ast.ValueSpec // last ValueSpec with type or init exprs seen - for iota, spec := range d.Specs { - switch s := spec.(type) { - case *ast.ValueSpec: - switch d.Tok { - case token.CONST: - // determine which init exprs to use - switch { - case s.Type != nil || len(s.Values) > 0: - last = s - case last == nil: - last = new(ast.ValueSpec) // make sure last exists - } - - // declare all constants - lhs := make([]*Const, len(s.Names)) - for i, name := range s.Names { - obj := NewConst(name.Pos(), pkg, name.Name, nil, constant.MakeInt64(int64(iota))) - lhs[i] = obj - - var init ast.Expr - if i < len(last.Values) { - init = last.Values[i] - } - - check.constDecl(obj, last.Type, init) - } - - check.arityMatch(s, last) - - // spec: "The scope of a constant or variable identifier declared - // inside a function begins at the end of the ConstSpec or VarSpec - // (ShortVarDecl for short variable declarations) and ends at the - // end of the innermost containing block." - scopePos := s.End() - for i, name := range s.Names { - check.declare(check.scope, name, lhs[i], scopePos) - } - - case token.VAR: - lhs0 := make([]*Var, len(s.Names)) - for i, name := range s.Names { - lhs0[i] = NewVar(name.Pos(), pkg, name.Name, nil) - } - - // initialize all variables - for i, obj := range lhs0 { - var lhs []*Var - var init ast.Expr - switch len(s.Values) { - case len(s.Names): - // lhs and rhs match - init = s.Values[i] - case 1: - // rhs is expected to be a multi-valued expression - lhs = lhs0 - init = s.Values[0] - default: - if i < len(s.Values) { - init = s.Values[i] - } - } - check.varDecl(obj, lhs, s.Type, init) - if len(s.Values) == 1 { - // If we have a single lhs variable we are done either way. - // If we have a single rhs expression, it must be a multi- - // valued expression, in which case handling the first lhs - // variable will cause all lhs variables to have a type - // assigned, and we are done as well. - if debug { - for _, obj := range lhs0 { - assert(obj.typ != nil) - } - } - break - } - } - - check.arityMatch(s, nil) - - // declare all variables - // (only at this point are the variable scopes (parents) set) - scopePos := s.End() // see constant declarations - for i, name := range s.Names { - // see constant declarations - check.declare(check.scope, name, lhs0[i], scopePos) - } - - default: - check.invalidAST(s.Pos(), "invalid token %s", d.Tok) - } - - case *ast.TypeSpec: - obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Name, nil) - // spec: "The scope of a type identifier declared inside a function - // begins at the identifier in the TypeSpec and ends at the end of - // the innermost containing block." - scopePos := s.Name.Pos() - check.declare(check.scope, s.Name, obj, scopePos) - check.typeDecl(obj, s.Type, nil, nil, s.Assign.IsValid()) - - default: - check.invalidAST(s.Pos(), "const, type, or var declaration expected") - } - } - - default: - check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d) - } -} diff --git a/third_party/forked/golang/go/types/errors.go b/third_party/forked/golang/go/types/errors.go deleted file mode 100644 index 0c0049b1f3e..00000000000 --- a/third_party/forked/golang/go/types/errors.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2012 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. - -// This file implements various error reporters. - -package types - -import ( - "fmt" - "go/ast" - "go/token" - "strings" -) - -func assert(p bool) { - if !p { - panic("assertion failed") - } -} - -func unreachable() { - panic("unreachable") -} - -func (check *Checker) qualifier(pkg *Package) string { - if pkg != check.pkg { - return pkg.path - } - return "" -} - -func (check *Checker) sprintf(format string, args ...interface{}) string { - for i, arg := range args { - switch a := arg.(type) { - case nil: - arg = "" - case operand: - panic("internal error: should always pass *operand") - case *operand: - arg = operandString(a, check.qualifier) - case token.Pos: - arg = check.fset.Position(a).String() - case ast.Expr: - arg = ExprString(a) - case Object: - arg = ObjectString(a, check.qualifier) - case Type: - arg = TypeString(a, check.qualifier) - } - args[i] = arg - } - return fmt.Sprintf(format, args...) -} - -func (check *Checker) trace(pos token.Pos, format string, args ...interface{}) { - fmt.Printf("%s:\t%s%s\n", - check.fset.Position(pos), - strings.Repeat(". ", check.indent), - check.sprintf(format, args...), - ) -} - -// dump is only needed for debugging -func (check *Checker) dump(format string, args ...interface{}) { - fmt.Println(check.sprintf(format, args...)) -} - -func (check *Checker) err(pos token.Pos, msg string, soft bool) { - err := Error{check.fset, pos, msg, soft} - if check.firstErr == nil { - check.firstErr = err - } - f := check.conf.Error - if f == nil { - panic(bailout{}) // report only first error - } - f(err) -} - -func (check *Checker) error(pos token.Pos, msg string) { - check.err(pos, msg, false) -} - -func (check *Checker) errorf(pos token.Pos, format string, args ...interface{}) { - check.err(pos, check.sprintf(format, args...), false) -} - -func (check *Checker) softErrorf(pos token.Pos, format string, args ...interface{}) { - check.err(pos, check.sprintf(format, args...), true) -} - -func (check *Checker) invalidAST(pos token.Pos, format string, args ...interface{}) { - check.errorf(pos, "invalid AST: "+format, args...) -} - -func (check *Checker) invalidArg(pos token.Pos, format string, args ...interface{}) { - check.errorf(pos, "invalid argument: "+format, args...) -} - -func (check *Checker) invalidOp(pos token.Pos, format string, args ...interface{}) { - check.errorf(pos, "invalid operation: "+format, args...) -} diff --git a/third_party/forked/golang/go/types/eval.go b/third_party/forked/golang/go/types/eval.go deleted file mode 100644 index 831d771d807..00000000000 --- a/third_party/forked/golang/go/types/eval.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2013 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 types - -import ( - "fmt" - "go/parser" - "go/token" -) - -// Eval returns the type and, if constant, the value for the -// expression expr, evaluated at position pos of package pkg, -// which must have been derived from type-checking an AST with -// complete position information relative to the provided file -// set. -// -// If the expression contains function literals, their bodies -// are ignored (i.e., the bodies are not type-checked). -// -// If pkg == nil, the Universe scope is used and the provided -// position pos is ignored. If pkg != nil, and pos is invalid, -// the package scope is used. Otherwise, pos must belong to the -// package. -// -// An error is returned if pos is not within the package or -// if the node cannot be evaluated. -// -// Note: Eval should not be used instead of running Check to compute -// types and values, but in addition to Check. Eval will re-evaluate -// its argument each time, and it also does not know about the context -// in which an expression is used (e.g., an assignment). Thus, top- -// level untyped constants will return an untyped type rather then the -// respective context-specific type. -// -func Eval(fset *token.FileSet, pkg *Package, pos token.Pos, expr string) (TypeAndValue, error) { - // determine scope - var scope *Scope - if pkg == nil { - scope = Universe - pos = token.NoPos - } else if !pos.IsValid() { - scope = pkg.scope - } else { - // The package scope extent (position information) may be - // incorrect (files spread across a wide range of fset - // positions) - ignore it and just consider its children - // (file scopes). - for _, fscope := range pkg.scope.children { - if scope = fscope.Innermost(pos); scope != nil { - break - } - } - if scope == nil || debug { - s := scope - for s != nil && s != pkg.scope { - s = s.parent - } - // s == nil || s == pkg.scope - if s == nil { - return TypeAndValue{}, fmt.Errorf("no position %s found in package %s", fset.Position(pos), pkg.name) - } - } - } - - // parse expressions - node, err := parser.ParseExprFrom(fset, "eval", expr, 0) - if err != nil { - return TypeAndValue{}, err - } - - // initialize checker - check := NewChecker(nil, fset, pkg, nil) - check.scope = scope - check.pos = pos - defer check.handleBailout(&err) - - // evaluate node - var x operand - check.rawExpr(&x, node, nil) - return TypeAndValue{x.mode, x.typ, x.val}, err -} diff --git a/third_party/forked/golang/go/types/expr.go b/third_party/forked/golang/go/types/expr.go deleted file mode 100644 index 59534c75708..00000000000 --- a/third_party/forked/golang/go/types/expr.go +++ /dev/null @@ -1,1623 +0,0 @@ -// Copyright 2012 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. - -// This file implements typechecking of expressions. - -package types - -import ( - "fmt" - "go/ast" - "go/constant" - "go/token" - "math" -) - -/* -Basic algorithm: - -Expressions are checked recursively, top down. Expression checker functions -are generally of the form: - - func f(x *operand, e *ast.Expr, ...) - -where e is the expression to be checked, and x is the result of the check. -The check performed by f may fail in which case x.mode == invalid, and -related error messages will have been issued by f. - -If a hint argument is present, it is the composite literal element type -of an outer composite literal; it is used to type-check composite literal -elements that have no explicit type specification in the source -(e.g.: []T{{...}, {...}}, the hint is the type T in this case). - -All expressions are checked via rawExpr, which dispatches according -to expression kind. Upon returning, rawExpr is recording the types and -constant values for all expressions that have an untyped type (those types -may change on the way up in the expression tree). Usually these are constants, -but the results of comparisons or non-constant shifts of untyped constants -may also be untyped, but not constant. - -Untyped expressions may eventually become fully typed (i.e., not untyped), -typically when the value is assigned to a variable, or is used otherwise. -The updateExprType method is used to record this final type and update -the recorded types: the type-checked expression tree is again traversed down, -and the new type is propagated as needed. Untyped constant expression values -that become fully typed must now be representable by the full type (constant -sub-expression trees are left alone except for their roots). This mechanism -ensures that a client sees the actual (run-time) type an untyped value would -have. It also permits type-checking of lhs shift operands "as if the shift -were not present": when updateExprType visits an untyped lhs shift operand -and assigns it it's final type, that type must be an integer type, and a -constant lhs must be representable as an integer. - -When an expression gets its final type, either on the way out from rawExpr, -on the way down in updateExprType, or at the end of the type checker run, -the type (and constant value, if any) is recorded via Info.Types, if present. -*/ - -type opPredicates map[token.Token]func(Type) bool - -var unaryOpPredicates = opPredicates{ - token.ADD: isNumeric, - token.SUB: isNumeric, - token.XOR: isInteger, - token.NOT: isBoolean, -} - -func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool { - if pred := m[op]; pred != nil { - if !pred(x.typ) { - check.invalidOp(x.pos(), "operator %s not defined for %s", op, x) - return false - } - } else { - check.invalidAST(x.pos(), "unknown operator %s", op) - return false - } - return true -} - -// The unary expression e may be nil. It's passed in for better error messages only. -func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) { - switch op { - case token.AND: - // spec: "As an exception to the addressability - // requirement x may also be a composite literal." - if _, ok := unparen(x.expr).(*ast.CompositeLit); !ok && x.mode != variable { - check.invalidOp(x.pos(), "cannot take address of %s", x) - x.mode = invalid - return - } - x.mode = value - x.typ = &Pointer{base: x.typ} - return - - case token.ARROW: - typ, ok := x.typ.Underlying().(*Chan) - if !ok { - check.invalidOp(x.pos(), "cannot receive from non-channel %s", x) - x.mode = invalid - return - } - if typ.dir == SendOnly { - check.invalidOp(x.pos(), "cannot receive from send-only channel %s", x) - x.mode = invalid - return - } - x.mode = commaok - x.typ = typ.elem - check.hasCallOrRecv = true - return - } - - if !check.op(unaryOpPredicates, x, op) { - x.mode = invalid - return - } - - if x.mode == constant_ { - typ := x.typ.Underlying().(*Basic) - var prec uint - if isUnsigned(typ) { - prec = uint(check.conf.sizeof(typ) * 8) - } - x.val = constant.UnaryOp(op, x.val, prec) - // Typed constants must be representable in - // their type after each constant operation. - if isTyped(typ) { - if e != nil { - x.expr = e // for better error message - } - check.representable(x, typ) - } - return - } - - x.mode = value - // x.typ remains unchanged -} - -func isShift(op token.Token) bool { - return op == token.SHL || op == token.SHR -} - -func isComparison(op token.Token) bool { - // Note: tokens are not ordered well to make this much easier - switch op { - case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ: - return true - } - return false -} - -func fitsFloat32(x constant.Value) bool { - f32, _ := constant.Float32Val(x) - f := float64(f32) - return !math.IsInf(f, 0) -} - -func roundFloat32(x constant.Value) constant.Value { - f32, _ := constant.Float32Val(x) - f := float64(f32) - if !math.IsInf(f, 0) { - return constant.MakeFloat64(f) - } - return nil -} - -func fitsFloat64(x constant.Value) bool { - f, _ := constant.Float64Val(x) - return !math.IsInf(f, 0) -} - -func roundFloat64(x constant.Value) constant.Value { - f, _ := constant.Float64Val(x) - if !math.IsInf(f, 0) { - return constant.MakeFloat64(f) - } - return nil -} - -// representableConst reports whether x can be represented as -// value of the given basic type and for the configuration -// provided (only needed for int/uint sizes). -// -// If rounded != nil, *rounded is set to the rounded value of x for -// representable floating-point and complex values, and to an Int -// value for integer values; it is left alone otherwise. -// It is ok to provide the addressof the first argument for rounded. -func representableConst(x constant.Value, conf *Config, typ *Basic, rounded *constant.Value) bool { - if x.Kind() == constant.Unknown { - return true // avoid follow-up errors - } - - switch { - case isInteger(typ): - x := constant.ToInt(x) - if x.Kind() != constant.Int { - return false - } - if rounded != nil { - *rounded = x - } - if x, ok := constant.Int64Val(x); ok { - switch typ.kind { - case Int: - var s = uint(conf.sizeof(typ)) * 8 - return int64(-1)<<(s-1) <= x && x <= int64(1)<<(s-1)-1 - case Int8: - const s = 8 - return -1<<(s-1) <= x && x <= 1<<(s-1)-1 - case Int16: - const s = 16 - return -1<<(s-1) <= x && x <= 1<<(s-1)-1 - case Int32: - const s = 32 - return -1<<(s-1) <= x && x <= 1<<(s-1)-1 - case Int64, UntypedInt: - return true - case Uint, Uintptr: - if s := uint(conf.sizeof(typ)) * 8; s < 64 { - return 0 <= x && x <= int64(1)<= 0 && n <= int(s) - case Uint64: - return constant.Sign(x) >= 0 && n <= 64 - case UntypedInt: - return true - } - - case isFloat(typ): - x := constant.ToFloat(x) - if x.Kind() != constant.Float { - return false - } - switch typ.kind { - case Float32: - if rounded == nil { - return fitsFloat32(x) - } - r := roundFloat32(x) - if r != nil { - *rounded = r - return true - } - case Float64: - if rounded == nil { - return fitsFloat64(x) - } - r := roundFloat64(x) - if r != nil { - *rounded = r - return true - } - case UntypedFloat: - return true - default: - unreachable() - } - - case isComplex(typ): - x := constant.ToComplex(x) - if x.Kind() != constant.Complex { - return false - } - switch typ.kind { - case Complex64: - if rounded == nil { - return fitsFloat32(constant.Real(x)) && fitsFloat32(constant.Imag(x)) - } - re := roundFloat32(constant.Real(x)) - im := roundFloat32(constant.Imag(x)) - if re != nil && im != nil { - *rounded = constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) - return true - } - case Complex128: - if rounded == nil { - return fitsFloat64(constant.Real(x)) && fitsFloat64(constant.Imag(x)) - } - re := roundFloat64(constant.Real(x)) - im := roundFloat64(constant.Imag(x)) - if re != nil && im != nil { - *rounded = constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) - return true - } - case UntypedComplex: - return true - default: - unreachable() - } - - case isString(typ): - return x.Kind() == constant.String - - case isBoolean(typ): - return x.Kind() == constant.Bool - } - - return false -} - -// representable checks that a constant operand is representable in the given basic type. -func (check *Checker) representable(x *operand, typ *Basic) { - assert(x.mode == constant_) - if !representableConst(x.val, check.conf, typ, &x.val) { - var msg string - if isNumeric(x.typ) && isNumeric(typ) { - // numeric conversion : error msg - // - // integer -> integer : overflows - // integer -> float : overflows (actually not possible) - // float -> integer : truncated - // float -> float : overflows - // - if !isInteger(x.typ) && isInteger(typ) { - msg = "%s truncated to %s" - } else { - msg = "%s overflows %s" - } - } else { - msg = "cannot convert %s to %s" - } - check.errorf(x.pos(), msg, x, typ) - x.mode = invalid - } -} - -// updateExprType updates the type of x to typ and invokes itself -// recursively for the operands of x, depending on expression kind. -// If typ is still an untyped and not the final type, updateExprType -// only updates the recorded untyped type for x and possibly its -// operands. Otherwise (i.e., typ is not an untyped type anymore, -// or it is the final type for x), the type and value are recorded. -// Also, if x is a constant, it must be representable as a value of typ, -// and if x is the (formerly untyped) lhs operand of a non-constant -// shift, it must be an integer value. -// -func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) { - old, found := check.untyped[x] - if !found { - return // nothing to do - } - - // update operands of x if necessary - switch x := x.(type) { - case *ast.BadExpr, - *ast.FuncLit, - *ast.CompositeLit, - *ast.IndexExpr, - *ast.SliceExpr, - *ast.TypeAssertExpr, - *ast.StarExpr, - *ast.KeyValueExpr, - *ast.ArrayType, - *ast.StructType, - *ast.FuncType, - *ast.InterfaceType, - *ast.MapType, - *ast.ChanType: - // These expression are never untyped - nothing to do. - // The respective sub-expressions got their final types - // upon assignment or use. - if debug { - check.dump("%s: found old type(%s): %s (new: %s)", x.Pos(), x, old.typ, typ) - unreachable() - } - return - - case *ast.CallExpr: - // Resulting in an untyped constant (e.g., built-in complex). - // The respective calls take care of calling updateExprType - // for the arguments if necessary. - - case *ast.Ident, *ast.BasicLit, *ast.SelectorExpr: - // An identifier denoting a constant, a constant literal, - // or a qualified identifier (imported untyped constant). - // No operands to take care of. - - case *ast.ParenExpr: - check.updateExprType(x.X, typ, final) - - case *ast.UnaryExpr: - // If x is a constant, the operands were constants. - // The operands don't need to be updated since they - // never get "materialized" into a typed value. If - // left in the untyped map, they will be processed - // at the end of the type check. - if old.val != nil { - break - } - check.updateExprType(x.X, typ, final) - - case *ast.BinaryExpr: - if old.val != nil { - break // see comment for unary expressions - } - if isComparison(x.Op) { - // The result type is independent of operand types - // and the operand types must have final types. - } else if isShift(x.Op) { - // The result type depends only on lhs operand. - // The rhs type was updated when checking the shift. - check.updateExprType(x.X, typ, final) - } else { - // The operand types match the result type. - check.updateExprType(x.X, typ, final) - check.updateExprType(x.Y, typ, final) - } - - default: - unreachable() - } - - // If the new type is not final and still untyped, just - // update the recorded type. - if !final && isUntyped(typ) { - old.typ = typ.Underlying().(*Basic) - check.untyped[x] = old - return - } - - // Otherwise we have the final (typed or untyped type). - // Remove it from the map of yet untyped expressions. - delete(check.untyped, x) - - if old.isLhs { - // If x is the lhs of a shift, its final type must be integer. - // We already know from the shift check that it is representable - // as an integer if it is a constant. - if !isInteger(typ) { - check.invalidOp(x.Pos(), "shifted operand %s (type %s) must be integer", x, typ) - return - } - } else if old.val != nil { - // If x is a constant, it must be representable as a value of typ. - c := operand{old.mode, x, old.typ, old.val, 0} - check.convertUntyped(&c, typ) - if c.mode == invalid { - return - } - } - - // Everything's fine, record final type and value for x. - check.recordTypeAndValue(x, old.mode, typ, old.val) -} - -// updateExprVal updates the value of x to val. -func (check *Checker) updateExprVal(x ast.Expr, val constant.Value) { - if info, ok := check.untyped[x]; ok { - info.val = val - check.untyped[x] = info - } -} - -// convertUntyped attempts to set the type of an untyped value to the target type. -func (check *Checker) convertUntyped(x *operand, target Type) { - if x.mode == invalid || isTyped(x.typ) || target == Typ[Invalid] { - return - } - - // TODO(gri) Sloppy code - clean up. This function is central - // to assignment and expression checking. - - if isUntyped(target) { - // both x and target are untyped - xkind := x.typ.(*Basic).kind - tkind := target.(*Basic).kind - if isNumeric(x.typ) && isNumeric(target) { - if xkind < tkind { - x.typ = target - check.updateExprType(x.expr, target, false) - } - } else if xkind != tkind { - goto Error - } - return - } - - // typed target - switch t := target.Underlying().(type) { - case *Basic: - if x.mode == constant_ { - check.representable(x, t) - if x.mode == invalid { - return - } - // expression value may have been rounded - update if needed - check.updateExprVal(x.expr, x.val) - } else { - // Non-constant untyped values may appear as the - // result of comparisons (untyped bool), intermediate - // (delayed-checked) rhs operands of shifts, and as - // the value nil. - switch x.typ.(*Basic).kind { - case UntypedBool: - if !isBoolean(target) { - goto Error - } - case UntypedInt, UntypedRune, UntypedFloat, UntypedComplex: - if !isNumeric(target) { - goto Error - } - case UntypedString: - // Non-constant untyped string values are not - // permitted by the spec and should not occur. - unreachable() - case UntypedNil: - // Unsafe.Pointer is a basic type that includes nil. - if !hasNil(target) { - goto Error - } - default: - goto Error - } - } - case *Interface: - if !x.isNil() && !t.Empty() /* empty interfaces are ok */ { - goto Error - } - // Update operand types to the default type rather then - // the target (interface) type: values must have concrete - // dynamic types. If the value is nil, keep it untyped - // (this is important for tools such as go vet which need - // the dynamic type for argument checking of say, print - // functions) - if x.isNil() { - target = Typ[UntypedNil] - } else { - // cannot assign untyped values to non-empty interfaces - if !t.Empty() { - goto Error - } - target = Default(x.typ) - } - case *Pointer, *Signature, *Slice, *Map, *Chan: - if !x.isNil() { - goto Error - } - // keep nil untyped - see comment for interfaces, above - target = Typ[UntypedNil] - default: - goto Error - } - - x.typ = target - check.updateExprType(x.expr, target, true) // UntypedNils are final - return - -Error: - check.errorf(x.pos(), "cannot convert %s to %s", x, target) - x.mode = invalid -} - -func (check *Checker) comparison(x, y *operand, op token.Token) { - // spec: "In any comparison, the first operand must be assignable - // to the type of the second operand, or vice versa." - err := "" - if x.assignableTo(check.conf, y.typ, nil) || y.assignableTo(check.conf, x.typ, nil) { - defined := false - switch op { - case token.EQL, token.NEQ: - // spec: "The equality operators == and != apply to operands that are comparable." - defined = Comparable(x.typ) || x.isNil() && hasNil(y.typ) || y.isNil() && hasNil(x.typ) - case token.LSS, token.LEQ, token.GTR, token.GEQ: - // spec: The ordering operators <, <=, >, and >= apply to operands that are ordered." - defined = isOrdered(x.typ) - default: - unreachable() - } - if !defined { - typ := x.typ - if x.isNil() { - typ = y.typ - } - err = check.sprintf("operator %s not defined for %s", op, typ) - } - } else { - err = check.sprintf("mismatched types %s and %s", x.typ, y.typ) - } - - if err != "" { - check.errorf(x.pos(), "cannot compare %s %s %s (%s)", x.expr, op, y.expr, err) - x.mode = invalid - return - } - - if x.mode == constant_ && y.mode == constant_ { - x.val = constant.MakeBool(constant.Compare(x.val, op, y.val)) - // The operands are never materialized; no need to update - // their types. - } else { - x.mode = value - // The operands have now their final types, which at run- - // time will be materialized. Update the expression trees. - // If the current types are untyped, the materialized type - // is the respective default type. - check.updateExprType(x.expr, Default(x.typ), true) - check.updateExprType(y.expr, Default(y.typ), true) - } - - // spec: "Comparison operators compare two operands and yield - // an untyped boolean value." - x.typ = Typ[UntypedBool] -} - -func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) { - untypedx := isUntyped(x.typ) - - var xval constant.Value - if x.mode == constant_ { - xval = constant.ToInt(x.val) - } - - if isInteger(x.typ) || untypedx && xval != nil && xval.Kind() == constant.Int { - // The lhs is of integer type or an untyped constant representable - // as an integer. Nothing to do. - } else { - // shift has no chance - check.invalidOp(x.pos(), "shifted operand %s must be integer", x) - x.mode = invalid - return - } - - // spec: "The right operand in a shift expression must have unsigned - // integer type or be an untyped constant representable by a value of - // type uint." - switch { - case isUnsigned(y.typ): - // nothing to do - case isUntyped(y.typ): - check.convertUntyped(y, Typ[Uint]) - if y.mode == invalid { - x.mode = invalid - return - } - default: - check.invalidOp(y.pos(), "shift count %s must be unsigned integer", y) - x.mode = invalid - return - } - - if x.mode == constant_ { - if y.mode == constant_ { - // rhs must be an integer value - yval := constant.ToInt(y.val) - if yval.Kind() != constant.Int { - check.invalidOp(y.pos(), "shift count %s must be unsigned integer", y) - x.mode = invalid - return - } - // rhs must be within reasonable bounds - const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64 - s, ok := constant.Uint64Val(yval) - if !ok || s > shiftBound { - check.invalidOp(y.pos(), "invalid shift count %s", y) - x.mode = invalid - return - } - // The lhs is representable as an integer but may not be an integer - // (e.g., 2.0, an untyped float) - this can only happen for untyped - // non-integer numeric constants. Correct the type so that the shift - // result is of integer type. - if !isInteger(x.typ) { - x.typ = Typ[UntypedInt] - } - // x is a constant so xval != nil and it must be of Int kind. - x.val = constant.Shift(xval, op, uint(s)) - // Typed constants must be representable in - // their type after each constant operation. - if isTyped(x.typ) { - if e != nil { - x.expr = e // for better error message - } - check.representable(x, x.typ.Underlying().(*Basic)) - } - return - } - - // non-constant shift with constant lhs - if untypedx { - // spec: "If the left operand of a non-constant shift - // expression is an untyped constant, the type of the - // constant is what it would be if the shift expression - // were replaced by its left operand alone.". - // - // Delay operand checking until we know the final type - // by marking the lhs expression as lhs shift operand. - // - // Usually (in correct programs), the lhs expression - // is in the untyped map. However, it is possible to - // create incorrect programs where the same expression - // is evaluated twice (via a declaration cycle) such - // that the lhs expression type is determined in the - // first round and thus deleted from the map, and then - // not found in the second round (double insertion of - // the same expr node still just leads to one entry for - // that node, and it can only be deleted once). - // Be cautious and check for presence of entry. - // Example: var e, f = int(1<<""[f]) // issue 11347 - if info, found := check.untyped[x.expr]; found { - info.isLhs = true - check.untyped[x.expr] = info - } - // keep x's type - x.mode = value - return - } - } - - // constant rhs must be >= 0 - if y.mode == constant_ && constant.Sign(y.val) < 0 { - check.invalidOp(y.pos(), "shift count %s must not be negative", y) - } - - // non-constant shift - lhs must be an integer - if !isInteger(x.typ) { - check.invalidOp(x.pos(), "shifted operand %s must be integer", x) - x.mode = invalid - return - } - - x.mode = value -} - -var binaryOpPredicates = opPredicates{ - token.ADD: func(typ Type) bool { return isNumeric(typ) || isString(typ) }, - token.SUB: isNumeric, - token.MUL: isNumeric, - token.QUO: isNumeric, - token.REM: isInteger, - - token.AND: isInteger, - token.OR: isInteger, - token.XOR: isInteger, - token.AND_NOT: isInteger, - - token.LAND: isBoolean, - token.LOR: isBoolean, -} - -// The binary expression e may be nil. It's passed in for better error messages only. -func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, op token.Token) { - var y operand - - check.expr(x, lhs) - check.expr(&y, rhs) - - if x.mode == invalid { - return - } - if y.mode == invalid { - x.mode = invalid - x.expr = y.expr - return - } - - if isShift(op) { - check.shift(x, &y, e, op) - return - } - - check.convertUntyped(x, y.typ) - if x.mode == invalid { - return - } - check.convertUntyped(&y, x.typ) - if y.mode == invalid { - x.mode = invalid - return - } - - if isComparison(op) { - check.comparison(x, &y, op) - return - } - - if !Identical(x.typ, y.typ) { - // only report an error if we have valid types - // (otherwise we had an error reported elsewhere already) - if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] { - check.invalidOp(x.pos(), "mismatched types %s and %s", x.typ, y.typ) - } - x.mode = invalid - return - } - - if !check.op(binaryOpPredicates, x, op) { - x.mode = invalid - return - } - - if op == token.QUO || op == token.REM { - // check for zero divisor - if (x.mode == constant_ || isInteger(x.typ)) && y.mode == constant_ && constant.Sign(y.val) == 0 { - check.invalidOp(y.pos(), "division by zero") - x.mode = invalid - return - } - - // check for divisor underflow in complex division (see issue 20227) - if x.mode == constant_ && y.mode == constant_ && isComplex(x.typ) { - re, im := constant.Real(y.val), constant.Imag(y.val) - re2, im2 := constant.BinaryOp(re, token.MUL, re), constant.BinaryOp(im, token.MUL, im) - if constant.Sign(re2) == 0 && constant.Sign(im2) == 0 { - check.invalidOp(y.pos(), "division by zero") - x.mode = invalid - return - } - } - } - - if x.mode == constant_ && y.mode == constant_ { - xval := x.val - yval := y.val - typ := x.typ.Underlying().(*Basic) - // force integer division of integer operands - if op == token.QUO && isInteger(typ) { - op = token.QUO_ASSIGN - } - x.val = constant.BinaryOp(xval, op, yval) - // Typed constants must be representable in - // their type after each constant operation. - if isTyped(typ) { - if e != nil { - x.expr = e // for better error message - } - check.representable(x, typ) - } - return - } - - x.mode = value - // x.typ is unchanged -} - -// index checks an index expression for validity. -// If max >= 0, it is the upper bound for index. -// If index is valid and the result i >= 0, then i is the constant value of index. -func (check *Checker) index(index ast.Expr, max int64) (i int64, valid bool) { - var x operand - check.expr(&x, index) - if x.mode == invalid { - return - } - - // an untyped constant must be representable as Int - check.convertUntyped(&x, Typ[Int]) - if x.mode == invalid { - return - } - - // the index must be of integer type - if !isInteger(x.typ) { - check.invalidArg(x.pos(), "index %s must be integer", &x) - return - } - - // a constant index i must be in bounds - if x.mode == constant_ { - if constant.Sign(x.val) < 0 { - check.invalidArg(x.pos(), "index %s must not be negative", &x) - return - } - i, valid = constant.Int64Val(constant.ToInt(x.val)) - if !valid || max >= 0 && i >= max { - check.errorf(x.pos(), "index %s is out of bounds", &x) - return i, false - } - // 0 <= i [ && i < max ] - return i, true - } - - return -1, true -} - -// indexElts checks the elements (elts) of an array or slice composite literal -// against the literal's element type (typ), and the element indices against -// the literal length if known (length >= 0). It returns the length of the -// literal (maximum index value + 1). -// -func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64 { - visited := make(map[int64]bool, len(elts)) - var index, max int64 - for _, e := range elts { - // determine and check index - validIndex := false - eval := e - if kv, _ := e.(*ast.KeyValueExpr); kv != nil { - if i, ok := check.index(kv.Key, length); ok { - if i >= 0 { - index = i - validIndex = true - } else { - check.errorf(e.Pos(), "index %s must be integer constant", kv.Key) - } - } - eval = kv.Value - } else if length >= 0 && index >= length { - check.errorf(e.Pos(), "index %d is out of bounds (>= %d)", index, length) - } else { - validIndex = true - } - - // if we have a valid index, check for duplicate entries - if validIndex { - if visited[index] { - check.errorf(e.Pos(), "duplicate index %d in array or slice literal", index) - } - visited[index] = true - } - index++ - if index > max { - max = index - } - - // check element against composite literal element type - var x operand - check.exprWithHint(&x, eval, typ) - check.assignment(&x, typ, "array or slice literal") - } - return max -} - -// exprKind describes the kind of an expression; the kind -// determines if an expression is valid in 'statement context'. -type exprKind int - -const ( - conversion exprKind = iota - expression - statement -) - -// rawExpr typechecks expression e and initializes x with the expression -// value or type. If an error occurred, x.mode is set to invalid. -// If hint != nil, it is the type of a composite literal element. -// -func (check *Checker) rawExpr(x *operand, e ast.Expr, hint Type) exprKind { - if trace { - check.trace(e.Pos(), "%s", e) - check.indent++ - defer func() { - check.indent-- - check.trace(e.Pos(), "=> %s", x) - }() - } - - kind := check.exprInternal(x, e, hint) - - // convert x into a user-friendly set of values - // TODO(gri) this code can be simplified - var typ Type - var val constant.Value - switch x.mode { - case invalid: - typ = Typ[Invalid] - case novalue: - typ = (*Tuple)(nil) - case constant_: - typ = x.typ - val = x.val - default: - typ = x.typ - } - assert(x.expr != nil && typ != nil) - - if isUntyped(typ) { - // delay type and value recording until we know the type - // or until the end of type checking - check.rememberUntyped(x.expr, false, x.mode, typ.(*Basic), val) - } else { - check.recordTypeAndValue(e, x.mode, typ, val) - } - - return kind -} - -// exprInternal contains the core of type checking of expressions. -// Must only be called by rawExpr. -// -func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { - // make sure x has a valid state in case of bailout - // (was issue 5770) - x.mode = invalid - x.typ = Typ[Invalid] - - switch e := e.(type) { - case *ast.BadExpr: - goto Error // error was reported before - - case *ast.Ident: - check.ident(x, e, nil, nil) - - case *ast.Ellipsis: - // ellipses are handled explicitly where they are legal - // (array composite literals and parameter lists) - check.error(e.Pos(), "invalid use of '...'") - goto Error - - case *ast.BasicLit: - x.setConst(e.Kind, e.Value) - if x.mode == invalid { - check.invalidAST(e.Pos(), "invalid literal %v", e.Value) - goto Error - } - - case *ast.FuncLit: - if sig, ok := check.typ(e.Type).(*Signature); ok { - // Anonymous functions are considered part of the - // init expression/func declaration which contains - // them: use existing package-level declaration info. - // - // TODO(gri) We delay type-checking of regular (top-level) - // function bodies until later. Why don't we do - // it for closures of top-level expressions? - // (We can't easily do it for local closures - // because the surrounding scopes must reflect - // the exact position where the closure appears - // in the source; e.g., variables declared below - // must not be visible). - check.funcBody(check.decl, "", sig, e.Body) - x.mode = value - x.typ = sig - } else { - check.invalidAST(e.Pos(), "invalid function literal %s", e) - goto Error - } - - case *ast.CompositeLit: - var typ, base Type - - switch { - case e.Type != nil: - // composite literal type present - use it - // [...]T array types may only appear with composite literals. - // Check for them here so we don't have to handle ... in general. - if atyp, _ := e.Type.(*ast.ArrayType); atyp != nil && atyp.Len != nil { - if ellip, _ := atyp.Len.(*ast.Ellipsis); ellip != nil && ellip.Elt == nil { - // We have an "open" [...]T array type. - // Create a new ArrayType with unknown length (-1) - // and finish setting it up after analyzing the literal. - typ = &Array{len: -1, elem: check.typ(atyp.Elt)} - base = typ - break - } - } - typ = check.typ(e.Type) - base = typ - - case hint != nil: - // no composite literal type present - use hint (element type of enclosing type) - typ = hint - base, _ = deref(typ.Underlying()) // *T implies &T{} - - default: - // TODO(gri) provide better error messages depending on context - check.error(e.Pos(), "missing type in composite literal") - goto Error - } - - switch utyp := base.Underlying().(type) { - case *Struct: - if len(e.Elts) == 0 { - break - } - fields := utyp.fields - if _, ok := e.Elts[0].(*ast.KeyValueExpr); ok { - // all elements must have keys - visited := make([]bool, len(fields)) - for _, e := range e.Elts { - kv, _ := e.(*ast.KeyValueExpr) - if kv == nil { - check.error(e.Pos(), "mixture of field:value and value elements in struct literal") - continue - } - key, _ := kv.Key.(*ast.Ident) - if key == nil { - check.errorf(kv.Pos(), "invalid field name %s in struct literal", kv.Key) - continue - } - i := fieldIndex(utyp.fields, check.pkg, key.Name) - if i < 0 { - check.errorf(kv.Pos(), "unknown field %s in struct literal", key.Name) - continue - } - fld := fields[i] - check.recordUse(key, fld) - // 0 <= i < len(fields) - if visited[i] { - check.errorf(kv.Pos(), "duplicate field name %s in struct literal", key.Name) - continue - } - visited[i] = true - check.expr(x, kv.Value) - etyp := fld.typ - check.assignment(x, etyp, "struct literal") - } - } else { - // no element must have a key - for i, e := range e.Elts { - if kv, _ := e.(*ast.KeyValueExpr); kv != nil { - check.error(kv.Pos(), "mixture of field:value and value elements in struct literal") - continue - } - check.expr(x, e) - if i >= len(fields) { - check.error(x.pos(), "too many values in struct literal") - break // cannot continue - } - // i < len(fields) - fld := fields[i] - if !fld.Exported() && fld.pkg != check.pkg { - check.errorf(x.pos(), "implicit assignment to unexported field %s in %s literal", fld.name, typ) - continue - } - etyp := fld.typ - check.assignment(x, etyp, "struct literal") - } - if len(e.Elts) < len(fields) { - check.error(e.Rbrace, "too few values in struct literal") - // ok to continue - } - } - - case *Array: - // Prevent crash if the array referred to is not yet set up. - // This is a stop-gap solution; a better approach would use the mechanism of - // Checker.ident (typexpr.go) using a path of types. But that would require - // passing the path everywhere (all expression-checking methods, not just - // type expression checking), and we're not set up for that (quite possibly - // an indication that cycle detection needs to be rethought). Was issue #18643. - if utyp.elem == nil { - check.error(e.Pos(), "illegal cycle in type declaration") - goto Error - } - n := check.indexedElts(e.Elts, utyp.elem, utyp.len) - // If we have an "open" [...]T array, set the length now that we know it - // and record the type for [...] (usually done by check.typExpr which is - // not called for [...]). - if utyp.len < 0 { - utyp.len = n - check.recordTypeAndValue(e.Type, typexpr, utyp, nil) - } - - case *Slice: - // Prevent crash if the slice referred to is not yet set up. - // See analogous comment for *Array. - if utyp.elem == nil { - check.error(e.Pos(), "illegal cycle in type declaration") - goto Error - } - check.indexedElts(e.Elts, utyp.elem, -1) - - case *Map: - // Prevent crash if the map referred to is not yet set up. - // See analogous comment for *Array. - if utyp.key == nil || utyp.elem == nil { - check.error(e.Pos(), "illegal cycle in type declaration") - goto Error - } - visited := make(map[interface{}][]Type, len(e.Elts)) - for _, e := range e.Elts { - kv, _ := e.(*ast.KeyValueExpr) - if kv == nil { - check.error(e.Pos(), "missing key in map literal") - continue - } - check.exprWithHint(x, kv.Key, utyp.key) - check.assignment(x, utyp.key, "map literal") - if x.mode == invalid { - continue - } - if x.mode == constant_ { - duplicate := false - // if the key is of interface type, the type is also significant when checking for duplicates - xkey := keyVal(x.val) - if _, ok := utyp.key.Underlying().(*Interface); ok { - for _, vtyp := range visited[xkey] { - if Identical(vtyp, x.typ) { - duplicate = true - break - } - } - visited[xkey] = append(visited[xkey], x.typ) - } else { - _, duplicate = visited[xkey] - visited[xkey] = nil - } - if duplicate { - check.errorf(x.pos(), "duplicate key %s in map literal", x.val) - continue - } - } - check.exprWithHint(x, kv.Value, utyp.elem) - check.assignment(x, utyp.elem, "map literal") - } - - default: - // when "using" all elements unpack KeyValueExpr - // explicitly because check.use doesn't accept them - for _, e := range e.Elts { - if kv, _ := e.(*ast.KeyValueExpr); kv != nil { - // Ideally, we should also "use" kv.Key but we can't know - // if it's an externally defined struct key or not. Going - // forward anyway can lead to other errors. Give up instead. - e = kv.Value - } - check.use(e) - } - // if utyp is invalid, an error was reported before - if utyp != Typ[Invalid] { - check.errorf(e.Pos(), "invalid composite literal type %s", typ) - goto Error - } - } - - x.mode = value - x.typ = typ - - case *ast.ParenExpr: - kind := check.rawExpr(x, e.X, nil) - x.expr = e - return kind - - case *ast.SelectorExpr: - check.selector(x, e) - - case *ast.IndexExpr: - check.expr(x, e.X) - if x.mode == invalid { - check.use(e.Index) - goto Error - } - - valid := false - length := int64(-1) // valid if >= 0 - switch typ := x.typ.Underlying().(type) { - case *Basic: - if isString(typ) { - valid = true - if x.mode == constant_ { - length = int64(len(constant.StringVal(x.val))) - } - // an indexed string always yields a byte value - // (not a constant) even if the string and the - // index are constant - x.mode = value - x.typ = universeByte // use 'byte' name - } - - case *Array: - valid = true - length = typ.len - if x.mode != variable { - x.mode = value - } - x.typ = typ.elem - - case *Pointer: - if typ, _ := typ.base.Underlying().(*Array); typ != nil { - valid = true - length = typ.len - x.mode = variable - x.typ = typ.elem - } - - case *Slice: - valid = true - x.mode = variable - x.typ = typ.elem - - case *Map: - var key operand - check.expr(&key, e.Index) - check.assignment(&key, typ.key, "map index") - if x.mode == invalid { - goto Error - } - x.mode = mapindex - x.typ = typ.elem - x.expr = e - return expression - } - - if !valid { - check.invalidOp(x.pos(), "cannot index %s", x) - goto Error - } - - if e.Index == nil { - check.invalidAST(e.Pos(), "missing index for %s", x) - goto Error - } - - check.index(e.Index, length) - // ok to continue - - case *ast.SliceExpr: - check.expr(x, e.X) - if x.mode == invalid { - check.use(e.Low, e.High, e.Max) - goto Error - } - - valid := false - length := int64(-1) // valid if >= 0 - switch typ := x.typ.Underlying().(type) { - case *Basic: - if isString(typ) { - if e.Slice3 { - check.invalidOp(x.pos(), "3-index slice of string") - goto Error - } - valid = true - if x.mode == constant_ { - length = int64(len(constant.StringVal(x.val))) - } - // spec: "For untyped string operands the result - // is a non-constant value of type string." - if typ.kind == UntypedString { - x.typ = Typ[String] - } - } - - case *Array: - valid = true - length = typ.len - if x.mode != variable { - check.invalidOp(x.pos(), "cannot slice %s (value not addressable)", x) - goto Error - } - x.typ = &Slice{elem: typ.elem} - - case *Pointer: - if typ, _ := typ.base.Underlying().(*Array); typ != nil { - valid = true - length = typ.len - x.typ = &Slice{elem: typ.elem} - } - - case *Slice: - valid = true - // x.typ doesn't change - } - - if !valid { - check.invalidOp(x.pos(), "cannot slice %s", x) - goto Error - } - - x.mode = value - - // spec: "Only the first index may be omitted; it defaults to 0." - if e.Slice3 && (e.High == nil || e.Max == nil) { - check.error(e.Rbrack, "2nd and 3rd index required in 3-index slice") - goto Error - } - - // check indices - var ind [3]int64 - for i, expr := range []ast.Expr{e.Low, e.High, e.Max} { - x := int64(-1) - switch { - case expr != nil: - // The "capacity" is only known statically for strings, arrays, - // and pointers to arrays, and it is the same as the length for - // those types. - max := int64(-1) - if length >= 0 { - max = length + 1 - } - if t, ok := check.index(expr, max); ok && t >= 0 { - x = t - } - case i == 0: - // default is 0 for the first index - x = 0 - case length >= 0: - // default is length (== capacity) otherwise - x = length - } - ind[i] = x - } - - // constant indices must be in range - // (check.index already checks that existing indices >= 0) - L: - for i, x := range ind[:len(ind)-1] { - if x > 0 { - for _, y := range ind[i+1:] { - if y >= 0 && x > y { - check.errorf(e.Rbrack, "invalid slice indices: %d > %d", x, y) - break L // only report one error, ok to continue - } - } - } - } - - case *ast.TypeAssertExpr: - check.expr(x, e.X) - if x.mode == invalid { - goto Error - } - xtyp, _ := x.typ.Underlying().(*Interface) - if xtyp == nil { - check.invalidOp(x.pos(), "%s is not an interface", x) - goto Error - } - // x.(type) expressions are handled explicitly in type switches - if e.Type == nil { - check.invalidAST(e.Pos(), "use of .(type) outside type switch") - goto Error - } - T := check.typ(e.Type) - if T == Typ[Invalid] { - goto Error - } - check.typeAssertion(x.pos(), x, xtyp, T) - x.mode = commaok - x.typ = T - - case *ast.CallExpr: - return check.call(x, e) - - case *ast.StarExpr: - check.exprOrType(x, e.X) - switch x.mode { - case invalid: - goto Error - case typexpr: - x.typ = &Pointer{base: x.typ} - default: - if typ, ok := x.typ.Underlying().(*Pointer); ok { - x.mode = variable - x.typ = typ.base - } else { - check.invalidOp(x.pos(), "cannot indirect %s", x) - goto Error - } - } - - case *ast.UnaryExpr: - check.expr(x, e.X) - if x.mode == invalid { - goto Error - } - check.unary(x, e, e.Op) - if x.mode == invalid { - goto Error - } - if e.Op == token.ARROW { - x.expr = e - return statement // receive operations may appear in statement context - } - - case *ast.BinaryExpr: - check.binary(x, e, e.X, e.Y, e.Op) - if x.mode == invalid { - goto Error - } - - case *ast.KeyValueExpr: - // key:value expressions are handled in composite literals - check.invalidAST(e.Pos(), "no key:value expected") - goto Error - - case *ast.ArrayType, *ast.StructType, *ast.FuncType, - *ast.InterfaceType, *ast.MapType, *ast.ChanType: - x.mode = typexpr - x.typ = check.typ(e) - // Note: rawExpr (caller of exprInternal) will call check.recordTypeAndValue - // even though check.typ has already called it. This is fine as both - // times the same expression and type are recorded. It is also not a - // performance issue because we only reach here for composite literal - // types, which are comparatively rare. - - default: - panic(fmt.Sprintf("%s: unknown expression type %T", check.fset.Position(e.Pos()), e)) - } - - // everything went well - x.expr = e - return expression - -Error: - x.mode = invalid - x.expr = e - return statement // avoid follow-up errors -} - -func keyVal(x constant.Value) interface{} { - switch x.Kind() { - case constant.Bool: - return constant.BoolVal(x) - case constant.String: - return constant.StringVal(x) - case constant.Int: - if v, ok := constant.Int64Val(x); ok { - return v - } - if v, ok := constant.Uint64Val(x); ok { - return v - } - case constant.Float: - v, _ := constant.Float64Val(x) - return v - case constant.Complex: - r, _ := constant.Float64Val(constant.Real(x)) - i, _ := constant.Float64Val(constant.Imag(x)) - return complex(r, i) - } - return x -} - -// typeAssertion checks that x.(T) is legal; xtyp must be the type of x. -func (check *Checker) typeAssertion(pos token.Pos, x *operand, xtyp *Interface, T Type) { - method, wrongType := assertableTo(xtyp, T) - if method == nil { - return - } - - var msg string - if wrongType { - msg = "wrong type for method" - } else { - msg = "missing method" - } - check.errorf(pos, "%s cannot have dynamic type %s (%s %s)", x, T, msg, method.name) -} - -func (check *Checker) singleValue(x *operand) { - if x.mode == value { - // tuple types are never named - no need for underlying type below - if t, ok := x.typ.(*Tuple); ok { - assert(t.Len() != 1) - check.errorf(x.pos(), "%d-valued %s where single value is expected", t.Len(), x) - x.mode = invalid - } - } -} - -// expr typechecks expression e and initializes x with the expression value. -// The result must be a single value. -// If an error occurred, x.mode is set to invalid. -// -func (check *Checker) expr(x *operand, e ast.Expr) { - check.multiExpr(x, e) - check.singleValue(x) -} - -// multiExpr is like expr but the result may be a multi-value. -func (check *Checker) multiExpr(x *operand, e ast.Expr) { - check.rawExpr(x, e, nil) - var msg string - switch x.mode { - default: - return - case novalue: - msg = "%s used as value" - case builtin: - msg = "%s must be called" - case typexpr: - msg = "%s is not an expression" - } - check.errorf(x.pos(), msg, x) - x.mode = invalid -} - -// exprWithHint typechecks expression e and initializes x with the expression value; -// hint is the type of a composite literal element. -// If an error occurred, x.mode is set to invalid. -// -func (check *Checker) exprWithHint(x *operand, e ast.Expr, hint Type) { - assert(hint != nil) - check.rawExpr(x, e, hint) - check.singleValue(x) - var msg string - switch x.mode { - default: - return - case novalue: - msg = "%s used as value" - case builtin: - msg = "%s must be called" - case typexpr: - msg = "%s is not an expression" - } - check.errorf(x.pos(), msg, x) - x.mode = invalid -} - -// exprOrType typechecks expression or type e and initializes x with the expression value or type. -// If an error occurred, x.mode is set to invalid. -// -func (check *Checker) exprOrType(x *operand, e ast.Expr) { - check.rawExpr(x, e, nil) - check.singleValue(x) - if x.mode == novalue { - check.errorf(x.pos(), "%s used as value or type", x) - x.mode = invalid - } -} diff --git a/third_party/forked/golang/go/types/exprstring.go b/third_party/forked/golang/go/types/exprstring.go deleted file mode 100644 index 28d605f5ee8..00000000000 --- a/third_party/forked/golang/go/types/exprstring.go +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright 2013 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. - -// This file implements printing of expressions. - -package types - -import ( - "bytes" - "go/ast" -) - -// ExprString returns the (possibly shortened) string representation for x. -// Shortened representations are suitable for user interfaces but may not -// necessarily follow Go syntax. -func ExprString(x ast.Expr) string { - var buf bytes.Buffer - WriteExpr(&buf, x) - return buf.String() -} - -// WriteExpr writes the (possibly shortened) string representation for x to buf. -// Shortened representations are suitable for user interfaces but may not -// necessarily follow Go syntax. -func WriteExpr(buf *bytes.Buffer, x ast.Expr) { - // The AST preserves source-level parentheses so there is - // no need to introduce them here to correct for different - // operator precedences. (This assumes that the AST was - // generated by a Go parser.) - - switch x := x.(type) { - default: - buf.WriteString("(bad expr)") // nil, ast.BadExpr, ast.KeyValueExpr - - case *ast.Ident: - buf.WriteString(x.Name) - - case *ast.Ellipsis: - buf.WriteString("...") - if x.Elt != nil { - WriteExpr(buf, x.Elt) - } - - case *ast.BasicLit: - buf.WriteString(x.Value) - - case *ast.FuncLit: - buf.WriteByte('(') - WriteExpr(buf, x.Type) - buf.WriteString(" literal)") // shortened - - case *ast.CompositeLit: - buf.WriteByte('(') - WriteExpr(buf, x.Type) - buf.WriteString(" literal)") // shortened - - case *ast.ParenExpr: - buf.WriteByte('(') - WriteExpr(buf, x.X) - buf.WriteByte(')') - - case *ast.SelectorExpr: - WriteExpr(buf, x.X) - buf.WriteByte('.') - buf.WriteString(x.Sel.Name) - - case *ast.IndexExpr: - WriteExpr(buf, x.X) - buf.WriteByte('[') - WriteExpr(buf, x.Index) - buf.WriteByte(']') - - case *ast.SliceExpr: - WriteExpr(buf, x.X) - buf.WriteByte('[') - if x.Low != nil { - WriteExpr(buf, x.Low) - } - buf.WriteByte(':') - if x.High != nil { - WriteExpr(buf, x.High) - } - if x.Slice3 { - buf.WriteByte(':') - if x.Max != nil { - WriteExpr(buf, x.Max) - } - } - buf.WriteByte(']') - - case *ast.TypeAssertExpr: - WriteExpr(buf, x.X) - buf.WriteString(".(") - WriteExpr(buf, x.Type) - buf.WriteByte(')') - - case *ast.CallExpr: - WriteExpr(buf, x.Fun) - buf.WriteByte('(') - for i, arg := range x.Args { - if i > 0 { - buf.WriteString(", ") - } - WriteExpr(buf, arg) - } - if x.Ellipsis.IsValid() { - buf.WriteString("...") - } - buf.WriteByte(')') - - case *ast.StarExpr: - buf.WriteByte('*') - WriteExpr(buf, x.X) - - case *ast.UnaryExpr: - buf.WriteString(x.Op.String()) - WriteExpr(buf, x.X) - - case *ast.BinaryExpr: - WriteExpr(buf, x.X) - buf.WriteByte(' ') - buf.WriteString(x.Op.String()) - buf.WriteByte(' ') - WriteExpr(buf, x.Y) - - case *ast.ArrayType: - buf.WriteByte('[') - if x.Len != nil { - WriteExpr(buf, x.Len) - } - buf.WriteByte(']') - WriteExpr(buf, x.Elt) - - case *ast.StructType: - buf.WriteString("struct{") - writeFieldList(buf, x.Fields, "; ", false) - buf.WriteByte('}') - - case *ast.FuncType: - buf.WriteString("func") - writeSigExpr(buf, x) - - case *ast.InterfaceType: - buf.WriteString("interface{") - writeFieldList(buf, x.Methods, "; ", true) - buf.WriteByte('}') - - case *ast.MapType: - buf.WriteString("map[") - WriteExpr(buf, x.Key) - buf.WriteByte(']') - WriteExpr(buf, x.Value) - - case *ast.ChanType: - var s string - switch x.Dir { - case ast.SEND: - s = "chan<- " - case ast.RECV: - s = "<-chan " - default: - s = "chan " - } - buf.WriteString(s) - WriteExpr(buf, x.Value) - } -} - -func writeSigExpr(buf *bytes.Buffer, sig *ast.FuncType) { - buf.WriteByte('(') - writeFieldList(buf, sig.Params, ", ", false) - buf.WriteByte(')') - - res := sig.Results - n := res.NumFields() - if n == 0 { - // no result - return - } - - buf.WriteByte(' ') - if n == 1 && len(res.List[0].Names) == 0 { - // single unnamed result - WriteExpr(buf, res.List[0].Type) - return - } - - // multiple or named result(s) - buf.WriteByte('(') - writeFieldList(buf, res, ", ", false) - buf.WriteByte(')') -} - -func writeFieldList(buf *bytes.Buffer, fields *ast.FieldList, sep string, iface bool) { - for i, f := range fields.List { - if i > 0 { - buf.WriteString(sep) - } - - // field list names - for i, name := range f.Names { - if i > 0 { - buf.WriteString(", ") - } - buf.WriteString(name.Name) - } - - // types of interface methods consist of signatures only - if sig, _ := f.Type.(*ast.FuncType); sig != nil && iface { - writeSigExpr(buf, sig) - continue - } - - // named fields are separated with a blank from the field type - if len(f.Names) > 0 { - buf.WriteByte(' ') - } - - WriteExpr(buf, f.Type) - - // ignore tag - } -} diff --git a/third_party/forked/golang/go/types/gotype.go b/third_party/forked/golang/go/types/gotype.go deleted file mode 100644 index 196fc9bbd60..00000000000 --- a/third_party/forked/golang/go/types/gotype.go +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright 2011 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. - -// +build ignore - -// Build this command explicitly: go build gotype.go - -/* -The gotype command, like the front-end of a Go compiler, parses and -type-checks a single Go package. Errors are reported if the analysis -fails; otherwise gotype is quiet (unless -v is set). - -Without a list of paths, gotype reads from standard input, which -must provide a single Go source file defining a complete package. - -With a single directory argument, gotype checks the Go files in -that directory, comprising a single package. Use -t to include the -(in-package) _test.go files. Use -x to type check only external -test files. - -Otherwise, each path must be the filename of a Go file belonging -to the same package. - -Imports are processed by importing directly from the source of -imported packages (default), or by importing from compiled and -installed packages (by setting -c to the respective compiler). - -The -c flag must be set to a compiler ("gc", "gccgo") when type- -checking packages containing imports with relative import paths -(import "./mypkg") because the source importer cannot know which -files to include for such packages. - -Usage: - gotype [flags] [path...] - -The flags are: - -t - include local test files in a directory (ignored if -x is provided) - -x - consider only external test files in a directory - -e - report all errors (not just the first 10) - -v - verbose mode - -c - compiler used for installed packages (gc, gccgo, or source); default: source - -Flags controlling additional output: - -ast - print AST (forces -seq) - -trace - print parse trace (forces -seq) - -comments - parse comments (ignored unless -ast or -trace is provided) - -Examples: - -To check the files a.go, b.go, and c.go: - - gotype a.go b.go c.go - -To check an entire package including (in-package) tests in the directory dir and print the processed files: - - gotype -t -v dir - -To check the external test package (if any) in the current directory, based on installed packages compiled with -cmd/compile: - - gotype -c=gc -x . - -To verify the output of a pipe: - - echo "package foo" | gotype - -*/ -package main - -import ( - "flag" - "fmt" - "go/ast" - "go/build" - "go/importer" - "go/parser" - "go/scanner" - "go/token" - "go/types" - "io/ioutil" - "os" - "path/filepath" - "sync" - "time" -) - -var ( - // main operation modes - testFiles = flag.Bool("t", false, "include in-package test files in a directory") - xtestFiles = flag.Bool("x", false, "consider only external test files in a directory") - allErrors = flag.Bool("e", false, "report all errors, not just the first 10") - verbose = flag.Bool("v", false, "verbose mode") - compiler = flag.String("c", "source", "compiler used for installed packages (gc, gccgo, or source)") - - // additional output control - printAST = flag.Bool("ast", false, "print AST (forces -seq)") - printTrace = flag.Bool("trace", false, "print parse trace (forces -seq)") - parseComments = flag.Bool("comments", false, "parse comments (ignored unless -ast or -trace is provided)") -) - -var ( - fset = token.NewFileSet() - errorCount = 0 - sequential = false - parserMode parser.Mode -) - -func initParserMode() { - if *allErrors { - parserMode |= parser.AllErrors - } - if *printAST { - sequential = true - } - if *printTrace { - parserMode |= parser.Trace - sequential = true - } - if *parseComments && (*printAST || *printTrace) { - parserMode |= parser.ParseComments - } -} - -const usageString = `usage: gotype [flags] [path ...] - -The gotype command, like the front-end of a Go compiler, parses and -type-checks a single Go package. Errors are reported if the analysis -fails; otherwise gotype is quiet (unless -v is set). - -Without a list of paths, gotype reads from standard input, which -must provide a single Go source file defining a complete package. - -With a single directory argument, gotype checks the Go files in -that directory, comprising a single package. Use -t to include the -(in-package) _test.go files. Use -x to type check only external -test files. - -Otherwise, each path must be the filename of a Go file belonging -to the same package. - -Imports are processed by importing directly from the source of -imported packages (default), or by importing from compiled and -installed packages (by setting -c to the respective compiler). - -The -c flag must be set to a compiler ("gc", "gccgo") when type- -checking packages containing imports with relative import paths -(import "./mypkg") because the source importer cannot know which -files to include for such packages. -` - -func usage() { - fmt.Fprintln(os.Stderr, usageString) - flag.PrintDefaults() - os.Exit(2) -} - -func report(err error) { - scanner.PrintError(os.Stderr, err) - if list, ok := err.(scanner.ErrorList); ok { - errorCount += len(list) - return - } - errorCount++ -} - -// parse may be called concurrently -func parse(filename string, src interface{}) (*ast.File, error) { - if *verbose { - fmt.Println(filename) - } - file, err := parser.ParseFile(fset, filename, src, parserMode) // ok to access fset concurrently - if *printAST { - ast.Print(fset, file) - } - return file, err -} - -func parseStdin() (*ast.File, error) { - src, err := ioutil.ReadAll(os.Stdin) - if err != nil { - return nil, err - } - return parse("", src) -} - -func parseFiles(dir string, filenames []string) ([]*ast.File, error) { - files := make([]*ast.File, len(filenames)) - errors := make([]error, len(filenames)) - - var wg sync.WaitGroup - for i, filename := range filenames { - wg.Add(1) - go func(i int, filepath string) { - defer wg.Done() - files[i], errors[i] = parse(filepath, nil) - }(i, filepath.Join(dir, filename)) - if sequential { - wg.Wait() - } - } - wg.Wait() - - // if there are errors, return the first one for deterministic results - for _, err := range errors { - if err != nil { - return nil, err - } - } - - return files, nil -} - -func parseDir(dir string) ([]*ast.File, error) { - ctxt := build.Default - pkginfo, err := ctxt.ImportDir(dir, 0) - if _, nogo := err.(*build.NoGoError); err != nil && !nogo { - return nil, err - } - - if *xtestFiles { - return parseFiles(dir, pkginfo.XTestGoFiles) - } - - filenames := append(pkginfo.GoFiles, pkginfo.CgoFiles...) - if *testFiles { - filenames = append(filenames, pkginfo.TestGoFiles...) - } - return parseFiles(dir, filenames) -} - -func getPkgFiles(args []string) ([]*ast.File, error) { - if len(args) == 0 { - // stdin - file, err := parseStdin() - if err != nil { - return nil, err - } - return []*ast.File{file}, nil - } - - if len(args) == 1 { - // possibly a directory - path := args[0] - info, err := os.Stat(path) - if err != nil { - return nil, err - } - if info.IsDir() { - return parseDir(path) - } - } - - // list of files - return parseFiles("", args) -} - -func checkPkgFiles(files []*ast.File) { - type bailout struct{} - - // if checkPkgFiles is called multiple times, set up conf only once - conf := types.Config{ - FakeImportC: true, - Error: func(err error) { - if !*allErrors && errorCount >= 10 { - panic(bailout{}) - } - report(err) - }, - Importer: importer.For(*compiler, nil), - Sizes: types.SizesFor(build.Default.Compiler, build.Default.GOARCH), - } - - defer func() { - switch p := recover().(type) { - case nil, bailout: - // normal return or early exit - default: - // re-panic - panic(p) - } - }() - - const path = "pkg" // any non-empty string will do for now - conf.Check(path, fset, files, nil) -} - -func printStats(d time.Duration) { - fileCount := 0 - lineCount := 0 - fset.Iterate(func(f *token.File) bool { - fileCount++ - lineCount += f.LineCount() - return true - }) - - fmt.Printf( - "%s (%d files, %d lines, %d lines/s)\n", - d, fileCount, lineCount, int64(float64(lineCount)/d.Seconds()), - ) -} - -func main() { - flag.Usage = usage - flag.Parse() - initParserMode() - - start := time.Now() - - files, err := getPkgFiles(flag.Args()) - if err != nil { - report(err) - os.Exit(2) - } - - checkPkgFiles(files) - if errorCount > 0 { - os.Exit(2) - } - - if *verbose { - printStats(time.Since(start)) - } -} diff --git a/third_party/forked/golang/go/types/initorder.go b/third_party/forked/golang/go/types/initorder.go deleted file mode 100644 index 966dccb8289..00000000000 --- a/third_party/forked/golang/go/types/initorder.go +++ /dev/null @@ -1,297 +0,0 @@ -// Copyright 2014 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 types - -import ( - "container/heap" - "fmt" -) - -// initOrder computes the Info.InitOrder for package variables. -func (check *Checker) initOrder() { - // An InitOrder may already have been computed if a package is - // built from several calls to (*Checker).Files. Clear it. - check.Info.InitOrder = check.Info.InitOrder[:0] - - // Compute the object dependency graph and initialize - // a priority queue with the list of graph nodes. - pq := nodeQueue(dependencyGraph(check.objMap)) - heap.Init(&pq) - - const debug = false - if debug { - fmt.Printf("Computing initialization order for %s\n\n", check.pkg) - fmt.Println("Object dependency graph:") - for obj, d := range check.objMap { - // only print objects that may appear in the dependency graph - if obj, _ := obj.(dependency); obj != nil { - if len(d.deps) > 0 { - fmt.Printf("\t%s depends on\n", obj.Name()) - for dep := range d.deps { - fmt.Printf("\t\t%s\n", dep.Name()) - } - } else { - fmt.Printf("\t%s has no dependencies\n", obj.Name()) - } - } - } - fmt.Println() - - fmt.Println("Transposed object dependency graph (functions eliminated):") - for _, n := range pq { - fmt.Printf("\t%s depends on %d nodes\n", n.obj.Name(), n.ndeps) - for p := range n.pred { - fmt.Printf("\t\t%s is dependent\n", p.obj.Name()) - } - } - fmt.Println() - - fmt.Println("Processing nodes:") - } - - // Determine initialization order by removing the highest priority node - // (the one with the fewest dependencies) and its edges from the graph, - // repeatedly, until there are no nodes left. - // In a valid Go program, those nodes always have zero dependencies (after - // removing all incoming dependencies), otherwise there are initialization - // cycles. - emitted := make(map[*declInfo]bool) - for len(pq) > 0 { - // get the next node - n := heap.Pop(&pq).(*graphNode) - - if debug { - fmt.Printf("\t%s (src pos %d) depends on %d nodes now\n", - n.obj.Name(), n.obj.order(), n.ndeps) - } - - // if n still depends on other nodes, we have a cycle - if n.ndeps > 0 { - cycle := findPath(check.objMap, n.obj, n.obj, make(objSet)) - // If n.obj is not part of the cycle (e.g., n.obj->b->c->d->c), - // cycle will be nil. Don't report anything in that case since - // the cycle is reported when the algorithm gets to an object - // in the cycle. - // Furthermore, once an object in the cycle is encountered, - // the cycle will be broken (dependency count will be reduced - // below), and so the remaining nodes in the cycle don't trigger - // another error (unless they are part of multiple cycles). - if cycle != nil { - check.reportCycle(cycle) - } - // Ok to continue, but the variable initialization order - // will be incorrect at this point since it assumes no - // cycle errors. - } - - // reduce dependency count of all dependent nodes - // and update priority queue - for p := range n.pred { - p.ndeps-- - heap.Fix(&pq, p.index) - } - - // record the init order for variables with initializers only - v, _ := n.obj.(*Var) - info := check.objMap[v] - if v == nil || !info.hasInitializer() { - continue - } - - // n:1 variable declarations such as: a, b = f() - // introduce a node for each lhs variable (here: a, b); - // but they all have the same initializer - emit only - // one, for the first variable seen - if emitted[info] { - continue // initializer already emitted, if any - } - emitted[info] = true - - infoLhs := info.lhs // possibly nil (see declInfo.lhs field comment) - if infoLhs == nil { - infoLhs = []*Var{v} - } - init := &Initializer{infoLhs, info.init} - check.Info.InitOrder = append(check.Info.InitOrder, init) - } - - if debug { - fmt.Println() - fmt.Println("Initialization order:") - for _, init := range check.Info.InitOrder { - fmt.Printf("\t%s\n", init) - } - fmt.Println() - } -} - -// findPath returns the (reversed) list of objects []Object{to, ... from} -// such that there is a path of object dependencies from 'from' to 'to'. -// If there is no such path, the result is nil. -func findPath(objMap map[Object]*declInfo, from, to Object, visited objSet) []Object { - if visited[from] { - return nil // node already seen - } - visited[from] = true - - for d := range objMap[from].deps { - if d == to { - return []Object{d} - } - if P := findPath(objMap, d, to, visited); P != nil { - return append(P, d) - } - } - - return nil -} - -// reportCycle reports an error for the given cycle. -func (check *Checker) reportCycle(cycle []Object) { - obj := cycle[0] - check.errorf(obj.Pos(), "initialization cycle for %s", obj.Name()) - // subtle loop: print cycle[i] for i = 0, n-1, n-2, ... 1 for len(cycle) = n - for i := len(cycle) - 1; i >= 0; i-- { - check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented - obj = cycle[i] - } - // print cycle[0] again to close the cycle - check.errorf(obj.Pos(), "\t%s", obj.Name()) -} - -// ---------------------------------------------------------------------------- -// Object dependency graph - -// A dependency is an object that may be a dependency in an initialization -// expression. Only constants, variables, and functions can be dependencies. -// Constants are here because constant expression cycles are reported during -// initialization order computation. -type dependency interface { - Object - isDependency() -} - -// A graphNode represents a node in the object dependency graph. -// Each node p in n.pred represents an edge p->n, and each node -// s in n.succ represents an edge n->s; with a->b indicating that -// a depends on b. -type graphNode struct { - obj dependency // object represented by this node - pred, succ nodeSet // consumers and dependencies of this node (lazily initialized) - index int // node index in graph slice/priority queue - ndeps int // number of outstanding dependencies before this object can be initialized -} - -type nodeSet map[*graphNode]bool - -func (s *nodeSet) add(p *graphNode) { - if *s == nil { - *s = make(nodeSet) - } - (*s)[p] = true -} - -// dependencyGraph computes the object dependency graph from the given objMap, -// with any function nodes removed. The resulting graph contains only constants -// and variables. -func dependencyGraph(objMap map[Object]*declInfo) []*graphNode { - // M is the dependency (Object) -> graphNode mapping - M := make(map[dependency]*graphNode) - for obj := range objMap { - // only consider nodes that may be an initialization dependency - if obj, _ := obj.(dependency); obj != nil { - M[obj] = &graphNode{obj: obj} - } - } - - // compute edges for graph M - // (We need to include all nodes, even isolated ones, because they still need - // to be scheduled for initialization in correct order relative to other nodes.) - for obj, n := range M { - // for each dependency obj -> d (= deps[i]), create graph edges n->s and s->n - for d := range objMap[obj].deps { - // only consider nodes that may be an initialization dependency - if d, _ := d.(dependency); d != nil { - d := M[d] - n.succ.add(d) - d.pred.add(n) - } - } - } - - // remove function nodes and collect remaining graph nodes in G - // (Mutually recursive functions may introduce cycles among themselves - // which are permitted. Yet such cycles may incorrectly inflate the dependency - // count for variables which in turn may not get scheduled for initialization - // in correct order.) - var G []*graphNode - for obj, n := range M { - if _, ok := obj.(*Func); ok { - // connect each predecessor p of n with each successor s - // and drop the function node (don't collect it in G) - for p := range n.pred { - // ignore self-cycles - if p != n { - // Each successor s of n becomes a successor of p, and - // each predecessor p of n becomes a predecessor of s. - for s := range n.succ { - // ignore self-cycles - if s != n { - p.succ.add(s) - s.pred.add(p) - delete(s.pred, n) // remove edge to n - } - } - delete(p.succ, n) // remove edge to n - } - } - } else { - // collect non-function nodes - G = append(G, n) - } - } - - // fill in index and ndeps fields - for i, n := range G { - n.index = i - n.ndeps = len(n.succ) - } - - return G -} - -// ---------------------------------------------------------------------------- -// Priority queue - -// nodeQueue implements the container/heap interface; -// a nodeQueue may be used as a priority queue. -type nodeQueue []*graphNode - -func (a nodeQueue) Len() int { return len(a) } - -func (a nodeQueue) Swap(i, j int) { - x, y := a[i], a[j] - a[i], a[j] = y, x - x.index, y.index = j, i -} - -func (a nodeQueue) Less(i, j int) bool { - x, y := a[i], a[j] - // nodes are prioritized by number of incoming dependencies (1st key) - // and source order (2nd key) - return x.ndeps < y.ndeps || x.ndeps == y.ndeps && x.obj.order() < y.obj.order() -} - -func (a *nodeQueue) Push(x interface{}) { - panic("unreachable") -} - -func (a *nodeQueue) Pop() interface{} { - n := len(*a) - x := (*a)[n-1] - x.index = -1 // for safety - *a = (*a)[:n-1] - return x -} diff --git a/third_party/forked/golang/go/types/labels.go b/third_party/forked/golang/go/types/labels.go deleted file mode 100644 index 3b43b4ba05c..00000000000 --- a/third_party/forked/golang/go/types/labels.go +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright 2013 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 types - -import ( - "go/ast" - "go/token" -) - -// labels checks correct label use in body. -func (check *Checker) labels(body *ast.BlockStmt) { - // set of all labels in this body - all := NewScope(nil, body.Pos(), body.End(), "label") - - fwdJumps := check.blockBranches(all, nil, nil, body.List) - - // If there are any forward jumps left, no label was found for - // the corresponding goto statements. Either those labels were - // never defined, or they are inside blocks and not reachable - // for the respective gotos. - for _, jmp := range fwdJumps { - var msg string - name := jmp.Label.Name - if alt := all.Lookup(name); alt != nil { - msg = "goto %s jumps into block" - alt.(*Label).used = true // avoid another error - } else { - msg = "label %s not declared" - } - check.errorf(jmp.Label.Pos(), msg, name) - } - - // spec: "It is illegal to define a label that is never used." - for _, obj := range all.elems { - if lbl := obj.(*Label); !lbl.used { - check.softErrorf(lbl.pos, "label %s declared but not used", lbl.name) - } - } -} - -// A block tracks label declarations in a block and its enclosing blocks. -type block struct { - parent *block // enclosing block - lstmt *ast.LabeledStmt // labeled statement to which this block belongs, or nil - labels map[string]*ast.LabeledStmt // allocated lazily -} - -// insert records a new label declaration for the current block. -// The label must not have been declared before in any block. -func (b *block) insert(s *ast.LabeledStmt) { - name := s.Label.Name - if debug { - assert(b.gotoTarget(name) == nil) - } - labels := b.labels - if labels == nil { - labels = make(map[string]*ast.LabeledStmt) - b.labels = labels - } - labels[name] = s -} - -// gotoTarget returns the labeled statement in the current -// or an enclosing block with the given label name, or nil. -func (b *block) gotoTarget(name string) *ast.LabeledStmt { - for s := b; s != nil; s = s.parent { - if t := s.labels[name]; t != nil { - return t - } - } - return nil -} - -// enclosingTarget returns the innermost enclosing labeled -// statement with the given label name, or nil. -func (b *block) enclosingTarget(name string) *ast.LabeledStmt { - for s := b; s != nil; s = s.parent { - if t := s.lstmt; t != nil && t.Label.Name == name { - return t - } - } - return nil -} - -// blockBranches processes a block's statement list and returns the set of outgoing forward jumps. -// all is the scope of all declared labels, parent the set of labels declared in the immediately -// enclosing block, and lstmt is the labeled statement this block is associated with (or nil). -func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.LabeledStmt, list []ast.Stmt) []*ast.BranchStmt { - b := &block{parent: parent, lstmt: lstmt} - - var ( - varDeclPos token.Pos - fwdJumps, badJumps []*ast.BranchStmt - ) - - // All forward jumps jumping over a variable declaration are possibly - // invalid (they may still jump out of the block and be ok). - // recordVarDecl records them for the given position. - recordVarDecl := func(pos token.Pos) { - varDeclPos = pos - badJumps = append(badJumps[:0], fwdJumps...) // copy fwdJumps to badJumps - } - - jumpsOverVarDecl := func(jmp *ast.BranchStmt) bool { - if varDeclPos.IsValid() { - for _, bad := range badJumps { - if jmp == bad { - return true - } - } - } - return false - } - - blockBranches := func(lstmt *ast.LabeledStmt, list []ast.Stmt) { - // Unresolved forward jumps inside the nested block - // become forward jumps in the current block. - fwdJumps = append(fwdJumps, check.blockBranches(all, b, lstmt, list)...) - } - - var stmtBranches func(ast.Stmt) - stmtBranches = func(s ast.Stmt) { - switch s := s.(type) { - case *ast.DeclStmt: - if d, _ := s.Decl.(*ast.GenDecl); d != nil && d.Tok == token.VAR { - recordVarDecl(d.Pos()) - } - - case *ast.LabeledStmt: - // declare non-blank label - if name := s.Label.Name; name != "_" { - lbl := NewLabel(s.Label.Pos(), check.pkg, name) - if alt := all.Insert(lbl); alt != nil { - check.softErrorf(lbl.pos, "label %s already declared", name) - check.reportAltDecl(alt) - // ok to continue - } else { - b.insert(s) - check.recordDef(s.Label, lbl) - } - // resolve matching forward jumps and remove them from fwdJumps - i := 0 - for _, jmp := range fwdJumps { - if jmp.Label.Name == name { - // match - lbl.used = true - check.recordUse(jmp.Label, lbl) - if jumpsOverVarDecl(jmp) { - check.softErrorf( - jmp.Label.Pos(), - "goto %s jumps over variable declaration at line %d", - name, - check.fset.Position(varDeclPos).Line, - ) - // ok to continue - } - } else { - // no match - record new forward jump - fwdJumps[i] = jmp - i++ - } - } - fwdJumps = fwdJumps[:i] - lstmt = s - } - stmtBranches(s.Stmt) - - case *ast.BranchStmt: - if s.Label == nil { - return // checked in 1st pass (check.stmt) - } - - // determine and validate target - name := s.Label.Name - switch s.Tok { - case token.BREAK: - // spec: "If there is a label, it must be that of an enclosing - // "for", "switch", or "select" statement, and that is the one - // whose execution terminates." - valid := false - if t := b.enclosingTarget(name); t != nil { - switch t.Stmt.(type) { - case *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt, *ast.ForStmt, *ast.RangeStmt: - valid = true - } - } - if !valid { - check.errorf(s.Label.Pos(), "invalid break label %s", name) - return - } - - case token.CONTINUE: - // spec: "If there is a label, it must be that of an enclosing - // "for" statement, and that is the one whose execution advances." - valid := false - if t := b.enclosingTarget(name); t != nil { - switch t.Stmt.(type) { - case *ast.ForStmt, *ast.RangeStmt: - valid = true - } - } - if !valid { - check.errorf(s.Label.Pos(), "invalid continue label %s", name) - return - } - - case token.GOTO: - if b.gotoTarget(name) == nil { - // label may be declared later - add branch to forward jumps - fwdJumps = append(fwdJumps, s) - return - } - - default: - check.invalidAST(s.Pos(), "branch statement: %s %s", s.Tok, name) - return - } - - // record label use - obj := all.Lookup(name) - obj.(*Label).used = true - check.recordUse(s.Label, obj) - - case *ast.AssignStmt: - if s.Tok == token.DEFINE { - recordVarDecl(s.Pos()) - } - - case *ast.BlockStmt: - blockBranches(lstmt, s.List) - - case *ast.IfStmt: - stmtBranches(s.Body) - if s.Else != nil { - stmtBranches(s.Else) - } - - case *ast.CaseClause: - blockBranches(nil, s.Body) - - case *ast.SwitchStmt: - stmtBranches(s.Body) - - case *ast.TypeSwitchStmt: - stmtBranches(s.Body) - - case *ast.CommClause: - blockBranches(nil, s.Body) - - case *ast.SelectStmt: - stmtBranches(s.Body) - - case *ast.ForStmt: - stmtBranches(s.Body) - - case *ast.RangeStmt: - stmtBranches(s.Body) - } - } - - for _, s := range list { - stmtBranches(s) - } - - return fwdJumps -} diff --git a/third_party/forked/golang/go/types/lookup.go b/third_party/forked/golang/go/types/lookup.go deleted file mode 100644 index ee8202d9e42..00000000000 --- a/third_party/forked/golang/go/types/lookup.go +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright 2013 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. - -// This file implements various field and method lookup functions. - -package types - -// LookupFieldOrMethod looks up a field or method with given package and name -// in T and returns the corresponding *Var or *Func, an index sequence, and a -// bool indicating if there were any pointer indirections on the path to the -// field or method. If addressable is set, T is the type of an addressable -// variable (only matters for method lookups). -// -// The last index entry is the field or method index in the (possibly embedded) -// type where the entry was found, either: -// -// 1) the list of declared methods of a named type; or -// 2) the list of all methods (method set) of an interface type; or -// 3) the list of fields of a struct type. -// -// The earlier index entries are the indices of the anonymous struct fields -// traversed to get to the found entry, starting at depth 0. -// -// If no entry is found, a nil object is returned. In this case, the returned -// index and indirect values have the following meaning: -// -// - If index != nil, the index sequence points to an ambiguous entry -// (the same name appeared more than once at the same embedding level). -// -// - If indirect is set, a method with a pointer receiver type was found -// but there was no pointer on the path from the actual receiver type to -// the method's formal receiver base type, nor was the receiver addressable. -// -func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) { - // Methods cannot be associated to a named pointer type - // (spec: "The type denoted by T is called the receiver base type; - // it must not be a pointer or interface type and it must be declared - // in the same package as the method."). - // Thus, if we have a named pointer type, proceed with the underlying - // pointer type but discard the result if it is a method since we would - // not have found it for T (see also issue 8590). - if t, _ := T.(*Named); t != nil { - if p, _ := t.underlying.(*Pointer); p != nil { - obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name) - if _, ok := obj.(*Func); ok { - return nil, nil, false - } - return - } - } - - return lookupFieldOrMethod(T, addressable, pkg, name) -} - -// TODO(gri) The named type consolidation and seen maps below must be -// indexed by unique keys for a given type. Verify that named -// types always have only one representation (even when imported -// indirectly via different packages.) - -func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) { - // WARNING: The code in this function is extremely subtle - do not modify casually! - // This function and NewMethodSet should be kept in sync. - - if name == "_" { - return // blank fields/methods are never found - } - - typ, isPtr := deref(T) - - // *typ where typ is an interface has no methods. - if isPtr && IsInterface(typ) { - return - } - - // Start with typ as single entry at shallowest depth. - current := []embeddedType{{typ, nil, isPtr, false}} - - // Named types that we have seen already, allocated lazily. - // Used to avoid endless searches in case of recursive types. - // Since only Named types can be used for recursive types, we - // only need to track those. - // (If we ever allow type aliases to construct recursive types, - // we must use type identity rather than pointer equality for - // the map key comparison, as we do in consolidateMultiples.) - var seen map[*Named]bool - - // search current depth - for len(current) > 0 { - var next []embeddedType // embedded types found at current depth - - // look for (pkg, name) in all types at current depth - for _, e := range current { - typ := e.typ - - // If we have a named type, we may have associated methods. - // Look for those first. - if named, _ := typ.(*Named); named != nil { - if seen[named] { - // We have seen this type before, at a more shallow depth - // (note that multiples of this type at the current depth - // were consolidated before). The type at that depth shadows - // this same type at the current depth, so we can ignore - // this one. - continue - } - if seen == nil { - seen = make(map[*Named]bool) - } - seen[named] = true - - // look for a matching attached method - if i, m := lookupMethod(named.methods, pkg, name); m != nil { - // potential match - assert(m.typ != nil) - index = concat(e.index, i) - if obj != nil || e.multiples { - return nil, index, false // collision - } - obj = m - indirect = e.indirect - continue // we can't have a matching field or interface method - } - - // continue with underlying type - typ = named.underlying - } - - switch t := typ.(type) { - case *Struct: - // look for a matching field and collect embedded types - for i, f := range t.fields { - if f.sameId(pkg, name) { - assert(f.typ != nil) - index = concat(e.index, i) - if obj != nil || e.multiples { - return nil, index, false // collision - } - obj = f - indirect = e.indirect - continue // we can't have a matching interface method - } - // Collect embedded struct fields for searching the next - // lower depth, but only if we have not seen a match yet - // (if we have a match it is either the desired field or - // we have a name collision on the same depth; in either - // case we don't need to look further). - // Embedded fields are always of the form T or *T where - // T is a type name. If e.typ appeared multiple times at - // this depth, f.typ appears multiple times at the next - // depth. - if obj == nil && f.anonymous { - typ, isPtr := deref(f.typ) - // TODO(gri) optimization: ignore types that can't - // have fields or methods (only Named, Struct, and - // Interface types need to be considered). - next = append(next, embeddedType{typ, concat(e.index, i), e.indirect || isPtr, e.multiples}) - } - } - - case *Interface: - // look for a matching method - // TODO(gri) t.allMethods is sorted - use binary search - if i, m := lookupMethod(t.allMethods, pkg, name); m != nil { - assert(m.typ != nil) - index = concat(e.index, i) - if obj != nil || e.multiples { - return nil, index, false // collision - } - obj = m - indirect = e.indirect - } - } - } - - if obj != nil { - // found a potential match - // spec: "A method call x.m() is valid if the method set of (the type of) x - // contains m and the argument list can be assigned to the parameter - // list of m. If x is addressable and &x's method set contains m, x.m() - // is shorthand for (&x).m()". - if f, _ := obj.(*Func); f != nil && ptrRecv(f) && !indirect && !addressable { - return nil, nil, true // pointer/addressable receiver required - } - return - } - - current = consolidateMultiples(next) - } - - return nil, nil, false // not found -} - -// embeddedType represents an embedded type -type embeddedType struct { - typ Type - index []int // embedded field indices, starting with index at depth 0 - indirect bool // if set, there was a pointer indirection on the path to this field - multiples bool // if set, typ appears multiple times at this depth -} - -// consolidateMultiples collects multiple list entries with the same type -// into a single entry marked as containing multiples. The result is the -// consolidated list. -func consolidateMultiples(list []embeddedType) []embeddedType { - if len(list) <= 1 { - return list // at most one entry - nothing to do - } - - n := 0 // number of entries w/ unique type - prev := make(map[Type]int) // index at which type was previously seen - for _, e := range list { - if i, found := lookupType(prev, e.typ); found { - list[i].multiples = true - // ignore this entry - } else { - prev[e.typ] = n - list[n] = e - n++ - } - } - return list[:n] -} - -func lookupType(m map[Type]int, typ Type) (int, bool) { - // fast path: maybe the types are equal - if i, found := m[typ]; found { - return i, true - } - - for t, i := range m { - if Identical(t, typ) { - return i, true - } - } - - return 0, false -} - -// MissingMethod returns (nil, false) if V implements T, otherwise it -// returns a missing method required by T and whether it is missing or -// just has the wrong type. -// -// For non-interface types V, or if static is set, V implements T if all -// methods of T are present in V. Otherwise (V is an interface and static -// is not set), MissingMethod only checks that methods of T which are also -// present in V have matching types (e.g., for a type assertion x.(T) where -// x is of interface type V). -// -func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType bool) { - // fast path for common case - if T.Empty() { - return - } - - // TODO(gri) Consider using method sets here. Might be more efficient. - - if ityp, _ := V.Underlying().(*Interface); ityp != nil { - // TODO(gri) allMethods is sorted - can do this more efficiently - for _, m := range T.allMethods { - _, obj := lookupMethod(ityp.allMethods, m.pkg, m.name) - switch { - case obj == nil: - if static { - return m, false - } - case !Identical(obj.Type(), m.typ): - return m, true - } - } - return - } - - // A concrete type implements T if it implements all methods of T. - for _, m := range T.allMethods { - obj, _, _ := lookupFieldOrMethod(V, false, m.pkg, m.name) - - f, _ := obj.(*Func) - if f == nil { - return m, false - } - - if !Identical(f.typ, m.typ) { - return m, true - } - } - - return -} - -// assertableTo reports whether a value of type V can be asserted to have type T. -// It returns (nil, false) as affirmative answer. Otherwise it returns a missing -// method required by V and whether it is missing or just has the wrong type. -func assertableTo(V *Interface, T Type) (method *Func, wrongType bool) { - // no static check is required if T is an interface - // spec: "If T is an interface type, x.(T) asserts that the - // dynamic type of x implements the interface T." - if _, ok := T.Underlying().(*Interface); ok && !strict { - return - } - return MissingMethod(T, V, false) -} - -// deref dereferences typ if it is a *Pointer and returns its base and true. -// Otherwise it returns (typ, false). -func deref(typ Type) (Type, bool) { - if p, _ := typ.(*Pointer); p != nil { - return p.base, true - } - return typ, false -} - -// derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a -// (named or unnamed) struct and returns its base. Otherwise it returns typ. -func derefStructPtr(typ Type) Type { - if p, _ := typ.Underlying().(*Pointer); p != nil { - if _, ok := p.base.Underlying().(*Struct); ok { - return p.base - } - } - return typ -} - -// concat returns the result of concatenating list and i. -// The result does not share its underlying array with list. -func concat(list []int, i int) []int { - var t []int - t = append(t, list...) - return append(t, i) -} - -// fieldIndex returns the index for the field with matching package and name, or a value < 0. -func fieldIndex(fields []*Var, pkg *Package, name string) int { - if name != "_" { - for i, f := range fields { - if f.sameId(pkg, name) { - return i - } - } - } - return -1 -} - -// lookupMethod returns the index of and method with matching package and name, or (-1, nil). -func lookupMethod(methods []*Func, pkg *Package, name string) (int, *Func) { - if name != "_" { - for i, m := range methods { - if m.sameId(pkg, name) { - return i, m - } - } - } - return -1, nil -} diff --git a/third_party/forked/golang/go/types/methodset.go b/third_party/forked/golang/go/types/methodset.go deleted file mode 100644 index 2a8b1c24f7a..00000000000 --- a/third_party/forked/golang/go/types/methodset.go +++ /dev/null @@ -1,262 +0,0 @@ -// Copyright 2013 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. - -// This file implements method sets. - -package types - -import ( - "bytes" - "fmt" - "sort" -) - -// A MethodSet is an ordered set of concrete or abstract (interface) methods; -// a method is a MethodVal selection, and they are ordered by ascending m.Obj().Id(). -// The zero value for a MethodSet is a ready-to-use empty method set. -type MethodSet struct { - list []*Selection -} - -func (s *MethodSet) String() string { - if s.Len() == 0 { - return "MethodSet {}" - } - - var buf bytes.Buffer - fmt.Fprintln(&buf, "MethodSet {") - for _, f := range s.list { - fmt.Fprintf(&buf, "\t%s\n", f) - } - fmt.Fprintln(&buf, "}") - return buf.String() -} - -// Len returns the number of methods in s. -func (s *MethodSet) Len() int { return len(s.list) } - -// At returns the i'th method in s for 0 <= i < s.Len(). -func (s *MethodSet) At(i int) *Selection { return s.list[i] } - -// Lookup returns the method with matching package and name, or nil if not found. -func (s *MethodSet) Lookup(pkg *Package, name string) *Selection { - if s.Len() == 0 { - return nil - } - - key := Id(pkg, name) - i := sort.Search(len(s.list), func(i int) bool { - m := s.list[i] - return m.obj.Id() >= key - }) - if i < len(s.list) { - m := s.list[i] - if m.obj.Id() == key { - return m - } - } - return nil -} - -// Shared empty method set. -var emptyMethodSet MethodSet - -// NewMethodSet returns the method set for the given type T. -// It always returns a non-nil method set, even if it is empty. -func NewMethodSet(T Type) *MethodSet { - // WARNING: The code in this function is extremely subtle - do not modify casually! - // This function and lookupFieldOrMethod should be kept in sync. - - // method set up to the current depth, allocated lazily - var base methodSet - - typ, isPtr := deref(T) - - // *typ where typ is an interface has no methods. - if isPtr && IsInterface(typ) { - return &emptyMethodSet - } - - // Start with typ as single entry at shallowest depth. - current := []embeddedType{{typ, nil, isPtr, false}} - - // Named types that we have seen already, allocated lazily. - // Used to avoid endless searches in case of recursive types. - // Since only Named types can be used for recursive types, we - // only need to track those. - // (If we ever allow type aliases to construct recursive types, - // we must use type identity rather than pointer equality for - // the map key comparison, as we do in consolidateMultiples.) - var seen map[*Named]bool - - // collect methods at current depth - for len(current) > 0 { - var next []embeddedType // embedded types found at current depth - - // field and method sets at current depth, allocated lazily - var fset fieldSet - var mset methodSet - - for _, e := range current { - typ := e.typ - - // If we have a named type, we may have associated methods. - // Look for those first. - if named, _ := typ.(*Named); named != nil { - if seen[named] { - // We have seen this type before, at a more shallow depth - // (note that multiples of this type at the current depth - // were consolidated before). The type at that depth shadows - // this same type at the current depth, so we can ignore - // this one. - continue - } - if seen == nil { - seen = make(map[*Named]bool) - } - seen[named] = true - - mset = mset.add(named.methods, e.index, e.indirect, e.multiples) - - // continue with underlying type - typ = named.underlying - } - - switch t := typ.(type) { - case *Struct: - for i, f := range t.fields { - fset = fset.add(f, e.multiples) - - // Embedded fields are always of the form T or *T where - // T is a type name. If typ appeared multiple times at - // this depth, f.Type appears multiple times at the next - // depth. - if f.anonymous { - typ, isPtr := deref(f.typ) - // TODO(gri) optimization: ignore types that can't - // have fields or methods (only Named, Struct, and - // Interface types need to be considered). - next = append(next, embeddedType{typ, concat(e.index, i), e.indirect || isPtr, e.multiples}) - } - } - - case *Interface: - mset = mset.add(t.allMethods, e.index, true, e.multiples) - } - } - - // Add methods and collisions at this depth to base if no entries with matching - // names exist already. - for k, m := range mset { - if _, found := base[k]; !found { - // Fields collide with methods of the same name at this depth. - if _, found := fset[k]; found { - m = nil // collision - } - if base == nil { - base = make(methodSet) - } - base[k] = m - } - } - - // Multiple fields with matching names collide at this depth and shadow all - // entries further down; add them as collisions to base if no entries with - // matching names exist already. - for k, f := range fset { - if f == nil { - if _, found := base[k]; !found { - if base == nil { - base = make(methodSet) - } - base[k] = nil // collision - } - } - } - - current = consolidateMultiples(next) - } - - if len(base) == 0 { - return &emptyMethodSet - } - - // collect methods - var list []*Selection - for _, m := range base { - if m != nil { - m.recv = T - list = append(list, m) - } - } - // sort by unique name - sort.Slice(list, func(i, j int) bool { - return list[i].obj.Id() < list[j].obj.Id() - }) - return &MethodSet{list} -} - -// A fieldSet is a set of fields and name collisions. -// A collision indicates that multiple fields with the -// same unique id appeared. -type fieldSet map[string]*Var // a nil entry indicates a name collision - -// Add adds field f to the field set s. -// If multiples is set, f appears multiple times -// and is treated as a collision. -func (s fieldSet) add(f *Var, multiples bool) fieldSet { - if s == nil { - s = make(fieldSet) - } - key := f.Id() - // if f is not in the set, add it - if !multiples { - if _, found := s[key]; !found { - s[key] = f - return s - } - } - s[key] = nil // collision - return s -} - -// A methodSet is a set of methods and name collisions. -// A collision indicates that multiple methods with the -// same unique id appeared. -type methodSet map[string]*Selection // a nil entry indicates a name collision - -// Add adds all functions in list to the method set s. -// If multiples is set, every function in list appears multiple times -// and is treated as a collision. -func (s methodSet) add(list []*Func, index []int, indirect bool, multiples bool) methodSet { - if len(list) == 0 { - return s - } - if s == nil { - s = make(methodSet) - } - for i, f := range list { - key := f.Id() - // if f is not in the set, add it - if !multiples { - // TODO(gri) A found method may not be added because it's not in the method set - // (!indirect && ptrRecv(f)). A 2nd method on the same level may be in the method - // set and may not collide with the first one, thus leading to a false positive. - // Is that possible? Investigate. - if _, found := s[key]; !found && (indirect || !ptrRecv(f)) { - s[key] = &Selection{MethodVal, nil, f, concat(index, i), indirect} - continue - } - } - s[key] = nil // collision - } - return s -} - -// ptrRecv reports whether the receiver is of the form *T. -// The receiver must exist. -func ptrRecv(f *Func) bool { - _, isPtr := deref(f.typ.(*Signature).recv.typ) - return isPtr -} diff --git a/third_party/forked/golang/go/types/object.go b/third_party/forked/golang/go/types/object.go deleted file mode 100644 index 633d32712ae..00000000000 --- a/third_party/forked/golang/go/types/object.go +++ /dev/null @@ -1,424 +0,0 @@ -// Copyright 2013 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 types - -import ( - "bytes" - "fmt" - "go/ast" - "go/constant" - "go/token" -) - -// An Object describes a named language entity such as a package, -// constant, type, variable, function (incl. methods), or label. -// All objects implement the Object interface. -// -type Object interface { - Parent() *Scope // scope in which this object is declared; nil for methods and struct fields - Pos() token.Pos // position of object identifier in declaration - Pkg() *Package // package to which this object belongs; nil for labels and objects in the Universe scope - Name() string // package local object name - Type() Type // object type - Exported() bool // reports whether the name starts with a capital letter - Id() string // object name if exported, qualified name if not exported (see func Id) - - // String returns a human-readable string of the object. - String() string - - // order reflects a package-level object's source order: if object - // a is before object b in the source, then a.order() < b.order(). - // order returns a value > 0 for package-level objects; it returns - // 0 for all other objects (including objects in file scopes). - order() uint32 - - // setOrder sets the order number of the object. It must be > 0. - setOrder(uint32) - - // setParent sets the parent scope of the object. - setParent(*Scope) - - // sameId reports whether obj.Id() and Id(pkg, name) are the same. - sameId(pkg *Package, name string) bool - - // scopePos returns the start position of the scope of this Object - scopePos() token.Pos - - // setScopePos sets the start position of the scope for this Object. - setScopePos(pos token.Pos) -} - -// Id returns name if it is exported, otherwise it -// returns the name qualified with the package path. -func Id(pkg *Package, name string) string { - if ast.IsExported(name) { - return name - } - // unexported names need the package path for differentiation - // (if there's no package, make sure we don't start with '.' - // as that may change the order of methods between a setup - // inside a package and outside a package - which breaks some - // tests) - path := "_" - // pkg is nil for objects in Universe scope and possibly types - // introduced via Eval (see also comment in object.sameId) - if pkg != nil && pkg.path != "" { - path = pkg.path - } - return path + "." + name -} - -// An object implements the common parts of an Object. -type object struct { - parent *Scope - pos token.Pos - pkg *Package - name string - typ Type - order_ uint32 - scopePos_ token.Pos -} - -func (obj *object) Parent() *Scope { return obj.parent } -func (obj *object) Pos() token.Pos { return obj.pos } -func (obj *object) Pkg() *Package { return obj.pkg } -func (obj *object) Name() string { return obj.name } -func (obj *object) Type() Type { return obj.typ } -func (obj *object) Exported() bool { return ast.IsExported(obj.name) } -func (obj *object) Id() string { return Id(obj.pkg, obj.name) } -func (obj *object) String() string { panic("abstract") } -func (obj *object) order() uint32 { return obj.order_ } -func (obj *object) scopePos() token.Pos { return obj.scopePos_ } - -func (obj *object) setParent(parent *Scope) { obj.parent = parent } -func (obj *object) setOrder(order uint32) { assert(order > 0); obj.order_ = order } -func (obj *object) setScopePos(pos token.Pos) { obj.scopePos_ = pos } - -func (obj *object) sameId(pkg *Package, name string) bool { - // spec: - // "Two identifiers are different if they are spelled differently, - // or if they appear in different packages and are not exported. - // Otherwise, they are the same." - if name != obj.name { - return false - } - // obj.Name == name - if obj.Exported() { - return true - } - // not exported, so packages must be the same (pkg == nil for - // fields in Universe scope; this can only happen for types - // introduced via Eval) - if pkg == nil || obj.pkg == nil { - return pkg == obj.pkg - } - // pkg != nil && obj.pkg != nil - return pkg.path == obj.pkg.path -} - -// A PkgName represents an imported Go package. -// PkgNames don't have a type. -type PkgName struct { - object - imported *Package - used bool // set if the package was used -} - -// NewPkgName returns a new PkgName object representing an imported package. -// The remaining arguments set the attributes found with all Objects. -func NewPkgName(pos token.Pos, pkg *Package, name string, imported *Package) *PkgName { - return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, token.NoPos}, imported, false} -} - -// Imported returns the package that was imported. -// It is distinct from Pkg(), which is the package containing the import statement. -func (obj *PkgName) Imported() *Package { return obj.imported } - -// A Const represents a declared constant. -type Const struct { - object - val constant.Value - visited bool // for initialization cycle detection -} - -// NewConst returns a new constant with value val. -// The remaining arguments set the attributes found with all Objects. -func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val constant.Value) *Const { - return &Const{object{nil, pos, pkg, name, typ, 0, token.NoPos}, val, false} -} - -func (obj *Const) Val() constant.Value { return obj.val } -func (*Const) isDependency() {} // a constant may be a dependency of an initialization expression - -// A TypeName represents a name for a (named or alias) type. -type TypeName struct { - object -} - -// NewTypeName returns a new type name denoting the given typ. -// The remaining arguments set the attributes found with all Objects. -// -// The typ argument may be a defined (Named) type or an alias type. -// It may also be nil such that the returned TypeName can be used as -// argument for NewNamed, which will set the TypeName's type as a side- -// effect. -func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName { - return &TypeName{object{nil, pos, pkg, name, typ, 0, token.NoPos}} -} - -// IsAlias reports whether obj is an alias name for a type. -func (obj *TypeName) IsAlias() bool { - switch t := obj.typ.(type) { - case nil: - return false - case *Basic: - // unsafe.Pointer is not an alias. - if obj.pkg == Unsafe { - return false - } - // Any user-defined type name for a basic type is an alias for a - // basic type (because basic types are pre-declared in the Universe - // scope, outside any package scope), and so is any type name with - // a different name than the name of the basic type it refers to. - // Additionally, we need to look for "byte" and "rune" because they - // are aliases but have the same names (for better error messages). - return obj.pkg != nil || t.name != obj.name || t == universeByte || t == universeRune - case *Named: - return obj != t.obj - default: - return true - } -} - -// A Variable represents a declared variable (including function parameters and results, and struct fields). -type Var struct { - object - anonymous bool // if set, the variable is an anonymous struct field, and name is the type name - visited bool // for initialization cycle detection - isField bool // var is struct field - used bool // set if the variable was used -} - -// NewVar returns a new variable. -// The arguments set the attributes found with all Objects. -func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var { - return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}} -} - -// NewParam returns a new variable representing a function parameter. -func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var { - return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}, used: true} // parameters are always 'used' -} - -// NewField returns a new variable representing a struct field. -// For anonymous (embedded) fields, the name is the unqualified -// type name under which the field is accessible. -func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool) *Var { - return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}, anonymous: anonymous, isField: true} -} - -// Anonymous reports whether the variable is an anonymous field. -func (obj *Var) Anonymous() bool { return obj.anonymous } - -// IsField reports whether the variable is a struct field. -func (obj *Var) IsField() bool { return obj.isField } - -func (*Var) isDependency() {} // a variable may be a dependency of an initialization expression - -// A Func represents a declared function, concrete method, or abstract -// (interface) method. Its Type() is always a *Signature. -// An abstract method may belong to many interfaces due to embedding. -type Func struct { - object -} - -// NewFunc returns a new function with the given signature, representing -// the function's type. -func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func { - // don't store a nil signature - var typ Type - if sig != nil { - typ = sig - } - return &Func{object{nil, pos, pkg, name, typ, 0, token.NoPos}} -} - -// FullName returns the package- or receiver-type-qualified name of -// function or method obj. -func (obj *Func) FullName() string { - var buf bytes.Buffer - writeFuncName(&buf, obj, nil) - return buf.String() -} - -// Scope returns the scope of the function's body block. -func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope } - -func (*Func) isDependency() {} // a function may be a dependency of an initialization expression - -// A Label represents a declared label. -// Labels don't have a type. -type Label struct { - object - used bool // set if the label was used -} - -// NewLabel returns a new label. -func NewLabel(pos token.Pos, pkg *Package, name string) *Label { - return &Label{object{pos: pos, pkg: pkg, name: name, typ: Typ[Invalid]}, false} -} - -// A Builtin represents a built-in function. -// Builtins don't have a valid type. -type Builtin struct { - object - id builtinId -} - -func newBuiltin(id builtinId) *Builtin { - return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid]}, id} -} - -// Nil represents the predeclared value nil. -type Nil struct { - object -} - -func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { - var tname *TypeName - typ := obj.Type() - - switch obj := obj.(type) { - case *PkgName: - fmt.Fprintf(buf, "package %s", obj.Name()) - if path := obj.imported.path; path != "" && path != obj.name { - fmt.Fprintf(buf, " (%q)", path) - } - return - - case *Const: - buf.WriteString("const") - - case *TypeName: - tname = obj - buf.WriteString("type") - - case *Var: - if obj.isField { - buf.WriteString("field") - } else { - buf.WriteString("var") - } - - case *Func: - buf.WriteString("func ") - writeFuncName(buf, obj, qf) - if typ != nil { - WriteSignature(buf, typ.(*Signature), qf) - } - return - - case *Label: - buf.WriteString("label") - typ = nil - - case *Builtin: - buf.WriteString("builtin") - typ = nil - - case *Nil: - buf.WriteString("nil") - return - - default: - panic(fmt.Sprintf("writeObject(%T)", obj)) - } - - buf.WriteByte(' ') - - // For package-level objects, qualify the name. - if obj.Pkg() != nil && obj.Pkg().scope.Lookup(obj.Name()) == obj { - writePackage(buf, obj.Pkg(), qf) - } - buf.WriteString(obj.Name()) - - if typ == nil { - return - } - - if tname != nil { - // We have a type object: Don't print anything more for - // basic types since there's no more information (names - // are the same; see also comment in TypeName.IsAlias). - if _, ok := typ.(*Basic); ok { - return - } - if tname.IsAlias() { - buf.WriteString(" =") - } else { - typ = typ.Underlying() - } - } - - buf.WriteByte(' ') - WriteType(buf, typ, qf) -} - -func writePackage(buf *bytes.Buffer, pkg *Package, qf Qualifier) { - if pkg == nil { - return - } - var s string - if qf != nil { - s = qf(pkg) - } else { - s = pkg.Path() - } - if s != "" { - buf.WriteString(s) - buf.WriteByte('.') - } -} - -// ObjectString returns the string form of obj. -// The Qualifier controls the printing of -// package-level objects, and may be nil. -func ObjectString(obj Object, qf Qualifier) string { - var buf bytes.Buffer - writeObject(&buf, obj, qf) - return buf.String() -} - -func (obj *PkgName) String() string { return ObjectString(obj, nil) } -func (obj *Const) String() string { return ObjectString(obj, nil) } -func (obj *TypeName) String() string { return ObjectString(obj, nil) } -func (obj *Var) String() string { return ObjectString(obj, nil) } -func (obj *Func) String() string { return ObjectString(obj, nil) } -func (obj *Label) String() string { return ObjectString(obj, nil) } -func (obj *Builtin) String() string { return ObjectString(obj, nil) } -func (obj *Nil) String() string { return ObjectString(obj, nil) } - -func writeFuncName(buf *bytes.Buffer, f *Func, qf Qualifier) { - if f.typ != nil { - sig := f.typ.(*Signature) - if recv := sig.Recv(); recv != nil { - buf.WriteByte('(') - if _, ok := recv.Type().(*Interface); ok { - // gcimporter creates abstract methods of - // named interfaces using the interface type - // (not the named type) as the receiver. - // Don't print it in full. - buf.WriteString("interface") - } else { - WriteType(buf, recv.Type(), qf) - } - buf.WriteByte(')') - buf.WriteByte('.') - } else if f.pkg != nil { - writePackage(buf, f.pkg, qf) - } - } - buf.WriteString(f.name) -} diff --git a/third_party/forked/golang/go/types/objset.go b/third_party/forked/golang/go/types/objset.go deleted file mode 100644 index 55eb74addba..00000000000 --- a/third_party/forked/golang/go/types/objset.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013 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. - -// This file implements objsets. -// -// An objset is similar to a Scope but objset elements -// are identified by their unique id, instead of their -// object name. - -package types - -// An objset is a set of objects identified by their unique id. -// The zero value for objset is a ready-to-use empty objset. -type objset map[string]Object // initialized lazily - -// insert attempts to insert an object obj into objset s. -// If s already contains an alternative object alt with -// the same name, insert leaves s unchanged and returns alt. -// Otherwise it inserts obj and returns nil. -func (s *objset) insert(obj Object) Object { - id := obj.Id() - if alt := (*s)[id]; alt != nil { - return alt - } - if *s == nil { - *s = make(map[string]Object) - } - (*s)[id] = obj - return nil -} diff --git a/third_party/forked/golang/go/types/operand.go b/third_party/forked/golang/go/types/operand.go deleted file mode 100644 index 07247bd6f58..00000000000 --- a/third_party/forked/golang/go/types/operand.go +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2012 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. - -// This file defines operands and associated operations. - -package types - -import ( - "bytes" - "go/ast" - "go/constant" - "go/token" -) - -// An operandMode specifies the (addressing) mode of an operand. -type operandMode byte - -const ( - invalid operandMode = iota // operand is invalid - novalue // operand represents no value (result of a function call w/o result) - builtin // operand is a built-in function - typexpr // operand is a type - constant_ // operand is a constant; the operand's typ is a Basic type - variable // operand is an addressable variable - mapindex // operand is a map index expression (acts like a variable on lhs, commaok on rhs of an assignment) - value // operand is a computed value - commaok // like value, but operand may be used in a comma,ok expression -) - -var operandModeString = [...]string{ - invalid: "invalid operand", - novalue: "no value", - builtin: "built-in", - typexpr: "type", - constant_: "constant", - variable: "variable", - mapindex: "map index expression", - value: "value", - commaok: "comma, ok expression", -} - -// An operand represents an intermediate value during type checking. -// Operands have an (addressing) mode, the expression evaluating to -// the operand, the operand's type, a value for constants, and an id -// for built-in functions. -// The zero value of operand is a ready to use invalid operand. -// -type operand struct { - mode operandMode - expr ast.Expr - typ Type - val constant.Value - id builtinId -} - -// pos returns the position of the expression corresponding to x. -// If x is invalid the position is token.NoPos. -// -func (x *operand) pos() token.Pos { - // x.expr may not be set if x is invalid - if x.expr == nil { - return token.NoPos - } - return x.expr.Pos() -} - -// Operand string formats -// (not all "untyped" cases can appear due to the type system, -// but they fall out naturally here) -// -// mode format -// -// invalid ( ) -// novalue ( ) -// builtin ( ) -// typexpr ( ) -// -// constant ( ) -// constant ( of type ) -// constant ( ) -// constant ( of type ) -// -// variable ( ) -// variable ( of type ) -// -// mapindex ( ) -// mapindex ( of type ) -// -// value ( ) -// value ( of type ) -// -// commaok ( ) -// commaok ( of type ) -// -func operandString(x *operand, qf Qualifier) string { - var buf bytes.Buffer - - var expr string - if x.expr != nil { - expr = ExprString(x.expr) - } else { - switch x.mode { - case builtin: - expr = predeclaredFuncs[x.id].name - case typexpr: - expr = TypeString(x.typ, qf) - case constant_: - expr = x.val.String() - } - } - - // ( - if expr != "" { - buf.WriteString(expr) - buf.WriteString(" (") - } - - // - hasType := false - switch x.mode { - case invalid, novalue, builtin, typexpr: - // no type - default: - // should have a type, but be cautious (don't crash during printing) - if x.typ != nil { - if isUntyped(x.typ) { - buf.WriteString(x.typ.(*Basic).name) - buf.WriteByte(' ') - break - } - hasType = true - } - } - - // - buf.WriteString(operandModeString[x.mode]) - - // - if x.mode == constant_ { - if s := x.val.String(); s != expr { - buf.WriteByte(' ') - buf.WriteString(s) - } - } - - // - if hasType { - if x.typ != Typ[Invalid] { - buf.WriteString(" of type ") - WriteType(&buf, x.typ, qf) - } else { - buf.WriteString(" with invalid type") - } - } - - // ) - if expr != "" { - buf.WriteByte(')') - } - - return buf.String() -} - -func (x *operand) String() string { - return operandString(x, nil) -} - -// setConst sets x to the untyped constant for literal lit. -func (x *operand) setConst(tok token.Token, lit string) { - var kind BasicKind - switch tok { - case token.INT: - kind = UntypedInt - case token.FLOAT: - kind = UntypedFloat - case token.IMAG: - kind = UntypedComplex - case token.CHAR: - kind = UntypedRune - case token.STRING: - kind = UntypedString - default: - unreachable() - } - - x.mode = constant_ - x.typ = Typ[kind] - x.val = constant.MakeFromLiteral(lit, tok, 0) -} - -// isNil reports whether x is the nil value. -func (x *operand) isNil() bool { - return x.mode == value && x.typ == Typ[UntypedNil] -} - -// TODO(gri) The functions operand.assignableTo, checker.convertUntyped, -// checker.representable, and checker.assignment are -// overlapping in functionality. Need to simplify and clean up. - -// assignableTo reports whether x is assignable to a variable of type T. -// If the result is false and a non-nil reason is provided, it may be set -// to a more detailed explanation of the failure (result != ""). -func (x *operand) assignableTo(conf *Config, T Type, reason *string) bool { - if x.mode == invalid || T == Typ[Invalid] { - return true // avoid spurious errors - } - - V := x.typ - - // x's type is identical to T - if Identical(V, T) { - return true - } - - Vu := V.Underlying() - Tu := T.Underlying() - - // x is an untyped value representable by a value of type T - // TODO(gri) This is borrowing from checker.convertUntyped and - // checker.representable. Need to clean up. - if isUntyped(Vu) { - switch t := Tu.(type) { - case *Basic: - if x.isNil() && t.kind == UnsafePointer { - return true - } - if x.mode == constant_ { - return representableConst(x.val, conf, t, nil) - } - // The result of a comparison is an untyped boolean, - // but may not be a constant. - if Vb, _ := Vu.(*Basic); Vb != nil { - return Vb.kind == UntypedBool && isBoolean(Tu) - } - case *Interface: - return x.isNil() || t.Empty() - case *Pointer, *Signature, *Slice, *Map, *Chan: - return x.isNil() - } - } - // Vu is typed - - // x's type V and T have identical underlying types - // and at least one of V or T is not a named type - if Identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) { - return true - } - - // T is an interface type and x implements T - if Ti, ok := Tu.(*Interface); ok { - if m, wrongType := MissingMethod(x.typ, Ti, true); m != nil /* Implements(x.typ, Ti) */ { - if reason != nil { - if wrongType { - *reason = "wrong type for method " + m.Name() - } else { - *reason = "missing method " + m.Name() - } - } - return false - } - return true - } - - // x is a bidirectional channel value, T is a channel - // type, x's type V and T have identical element types, - // and at least one of V or T is not a named type - if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv { - if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) { - return !isNamed(V) || !isNamed(T) - } - } - - return false -} diff --git a/third_party/forked/golang/go/types/ordering.go b/third_party/forked/golang/go/types/ordering.go deleted file mode 100644 index 3579abf7d7b..00000000000 --- a/third_party/forked/golang/go/types/ordering.go +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2014 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. - -// This file implements resolveOrder. - -package types - -import ( - "go/ast" - "sort" -) - -// resolveOrder computes the order in which package-level objects -// must be type-checked. -// -// Interface types appear first in the list, sorted topologically -// by dependencies on embedded interfaces that are also declared -// in this package, followed by all other objects sorted in source -// order. -// -// TODO(gri) Consider sorting all types by dependencies here, and -// in the process check _and_ report type cycles. This may simplify -// the full type-checking phase. -// -func (check *Checker) resolveOrder() []Object { - var ifaces, others []Object - - // collect interface types with their dependencies, and all other objects - for obj := range check.objMap { - if ityp := check.interfaceFor(obj); ityp != nil { - ifaces = append(ifaces, obj) - // determine dependencies on embedded interfaces - for _, f := range ityp.Methods.List { - if len(f.Names) == 0 { - // Embedded interface: The type must be a (possibly - // qualified) identifier denoting another interface. - // Imported interfaces are already fully resolved, - // so we can ignore qualified identifiers. - if ident, _ := f.Type.(*ast.Ident); ident != nil { - embedded := check.pkg.scope.Lookup(ident.Name) - if check.interfaceFor(embedded) != nil { - check.objMap[obj].addDep(embedded) - } - } - } - } - } else { - others = append(others, obj) - } - } - - // final object order - var order []Object - - // sort interface types topologically by dependencies, - // and in source order if there are no dependencies - sort.Sort(inSourceOrder(ifaces)) - visited := make(objSet) - for _, obj := range ifaces { - check.appendInPostOrder(&order, obj, visited) - } - - // sort everything else in source order - sort.Sort(inSourceOrder(others)) - - return append(order, others...) -} - -// interfaceFor returns the AST interface denoted by obj, or nil. -func (check *Checker) interfaceFor(obj Object) *ast.InterfaceType { - tname, _ := obj.(*TypeName) - if tname == nil { - return nil // not a type - } - d := check.objMap[obj] - if d == nil { - check.dump("%s: %s should have been declared", obj.Pos(), obj.Name()) - unreachable() - } - if d.typ == nil { - return nil // invalid AST - ignore (will be handled later) - } - ityp, _ := d.typ.(*ast.InterfaceType) - return ityp -} - -func (check *Checker) appendInPostOrder(order *[]Object, obj Object, visited objSet) { - if visited[obj] { - // We've already seen this object; either because it's - // already added to order, or because we have a cycle. - // In both cases we stop. Cycle errors are reported - // when type-checking types. - return - } - visited[obj] = true - - d := check.objMap[obj] - for _, obj := range orderedSetObjects(d.deps) { - check.appendInPostOrder(order, obj, visited) - } - - *order = append(*order, obj) -} - -func orderedSetObjects(set objSet) []Object { - list := make([]Object, len(set)) - i := 0 - for obj := range set { - // we don't care about the map element value - list[i] = obj - i++ - } - sort.Sort(inSourceOrder(list)) - return list -} - -// inSourceOrder implements the sort.Sort interface. -type inSourceOrder []Object - -func (a inSourceOrder) Len() int { return len(a) } -func (a inSourceOrder) Less(i, j int) bool { return a[i].order() < a[j].order() } -func (a inSourceOrder) Swap(i, j int) { a[i], a[j] = a[j], a[i] } diff --git a/third_party/forked/golang/go/types/package.go b/third_party/forked/golang/go/types/package.go deleted file mode 100644 index cd202a0ed9f..00000000000 --- a/third_party/forked/golang/go/types/package.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2013 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 types - -import ( - "fmt" - "go/token" -) - -// A Package describes a Go package. -type Package struct { - path string - name string - scope *Scope - complete bool - imports []*Package - fake bool // scope lookup errors are silently dropped if package is fake (internal use only) -} - -// NewPackage returns a new Package for the given package path and name. -// The package is not complete and contains no explicit imports. -func NewPackage(path, name string) *Package { - scope := NewScope(Universe, token.NoPos, token.NoPos, fmt.Sprintf("package %q", path)) - return &Package{path: path, name: name, scope: scope} -} - -// Path returns the package path. -func (pkg *Package) Path() string { return pkg.path } - -// Name returns the package name. -func (pkg *Package) Name() string { return pkg.name } - -// SetName sets the package name. -func (pkg *Package) SetName(name string) { pkg.name = name } - -// Scope returns the (complete or incomplete) package scope -// holding the objects declared at package level (TypeNames, -// Consts, Vars, and Funcs). -func (pkg *Package) Scope() *Scope { return pkg.scope } - -// A package is complete if its scope contains (at least) all -// exported objects; otherwise it is incomplete. -func (pkg *Package) Complete() bool { return pkg.complete } - -// MarkComplete marks a package as complete. -func (pkg *Package) MarkComplete() { pkg.complete = true } - -// Imports returns the list of packages directly imported by -// pkg; the list is in source order. -// -// If pkg was loaded from export data, Imports includes packages that -// provide package-level objects referenced by pkg. This may be more or -// less than the set of packages directly imported by pkg's source code. -func (pkg *Package) Imports() []*Package { return pkg.imports } - -// SetImports sets the list of explicitly imported packages to list. -// It is the caller's responsibility to make sure list elements are unique. -func (pkg *Package) SetImports(list []*Package) { pkg.imports = list } - -func (pkg *Package) String() string { - return fmt.Sprintf("package %s (%q)", pkg.name, pkg.path) -} diff --git a/third_party/forked/golang/go/types/predicates.go b/third_party/forked/golang/go/types/predicates.go deleted file mode 100644 index 1ca146f5904..00000000000 --- a/third_party/forked/golang/go/types/predicates.go +++ /dev/null @@ -1,320 +0,0 @@ -// Copyright 2012 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. - -// This file implements commonly used type predicates. - -package types - -import "sort" - -func isNamed(typ Type) bool { - if _, ok := typ.(*Basic); ok { - return ok - } - _, ok := typ.(*Named) - return ok -} - -func isBoolean(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsBoolean != 0 -} - -func isInteger(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsInteger != 0 -} - -func isUnsigned(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsUnsigned != 0 -} - -func isFloat(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsFloat != 0 -} - -func isComplex(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsComplex != 0 -} - -func isNumeric(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsNumeric != 0 -} - -func isString(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsString != 0 -} - -func isTyped(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return !ok || t.info&IsUntyped == 0 -} - -func isUntyped(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsUntyped != 0 -} - -func isOrdered(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsOrdered != 0 -} - -func isConstType(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsConstType != 0 -} - -// IsInterface reports whether typ is an interface type. -func IsInterface(typ Type) bool { - _, ok := typ.Underlying().(*Interface) - return ok -} - -// Comparable reports whether values of type T are comparable. -func Comparable(T Type) bool { - switch t := T.Underlying().(type) { - case *Basic: - // assume invalid types to be comparable - // to avoid follow-up errors - return t.kind != UntypedNil - case *Pointer, *Interface, *Chan: - return true - case *Struct: - for _, f := range t.fields { - if !Comparable(f.typ) { - return false - } - } - return true - case *Array: - return Comparable(t.elem) - } - return false -} - -// hasNil reports whether a type includes the nil value. -func hasNil(typ Type) bool { - switch t := typ.Underlying().(type) { - case *Basic: - return t.kind == UnsafePointer - case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan: - return true - } - return false -} - -// Identical reports whether x and y are identical types. -// Receivers of Signature types are ignored. -func Identical(x, y Type) bool { - return identical(x, y, true, nil) -} - -// IdenticalIgnoreTags reports whether x and y are identical types if tags are ignored. -// Receivers of Signature types are ignored. -func IdenticalIgnoreTags(x, y Type) bool { - return identical(x, y, false, nil) -} - -// An ifacePair is a node in a stack of interface type pairs compared for identity. -type ifacePair struct { - x, y *Interface - prev *ifacePair -} - -func (p *ifacePair) identical(q *ifacePair) bool { - return p.x == q.x && p.y == q.y || p.x == q.y && p.y == q.x -} - -func identical(x, y Type, cmpTags bool, p *ifacePair) bool { - if x == y { - return true - } - - switch x := x.(type) { - case *Basic: - // Basic types are singletons except for the rune and byte - // aliases, thus we cannot solely rely on the x == y check - // above. See also comment in TypeName.IsAlias. - if y, ok := y.(*Basic); ok { - return x.kind == y.kind - } - - case *Array: - // Two array types are identical if they have identical element types - // and the same array length. - if y, ok := y.(*Array); ok { - // If one or both array lengths are unknown (< 0) due to some error, - // assume they are the same to avoid spurious follow-on errors. - return (x.len < 0 || y.len < 0 || x.len == y.len) && identical(x.elem, y.elem, cmpTags, p) - } - - case *Slice: - // Two slice types are identical if they have identical element types. - if y, ok := y.(*Slice); ok { - return identical(x.elem, y.elem, cmpTags, p) - } - - case *Struct: - // Two struct types are identical if they have the same sequence of fields, - // and if corresponding fields have the same names, and identical types, - // and identical tags. Two anonymous fields are considered to have the same - // name. Lower-case field names from different packages are always different. - if y, ok := y.(*Struct); ok { - if x.NumFields() == y.NumFields() { - for i, f := range x.fields { - g := y.fields[i] - if f.anonymous != g.anonymous || - cmpTags && x.Tag(i) != y.Tag(i) || - !f.sameId(g.pkg, g.name) || - !identical(f.typ, g.typ, cmpTags, p) { - return false - } - } - return true - } - } - - case *Pointer: - // Two pointer types are identical if they have identical base types. - if y, ok := y.(*Pointer); ok { - return identical(x.base, y.base, cmpTags, p) - } - - case *Tuple: - // Two tuples types are identical if they have the same number of elements - // and corresponding elements have identical types. - if y, ok := y.(*Tuple); ok { - if x.Len() == y.Len() { - if x != nil { - for i, v := range x.vars { - w := y.vars[i] - if !identical(v.typ, w.typ, cmpTags, p) { - return false - } - } - } - return true - } - } - - case *Signature: - // Two function types are identical if they have the same number of parameters - // and result values, corresponding parameter and result types are identical, - // and either both functions are variadic or neither is. Parameter and result - // names are not required to match. - if y, ok := y.(*Signature); ok { - return x.variadic == y.variadic && - identical(x.params, y.params, cmpTags, p) && - identical(x.results, y.results, cmpTags, p) - } - - case *Interface: - // Two interface types are identical if they have the same set of methods with - // the same names and identical function types. Lower-case method names from - // different packages are always different. The order of the methods is irrelevant. - if y, ok := y.(*Interface); ok { - a := x.allMethods - b := y.allMethods - if len(a) == len(b) { - // Interface types are the only types where cycles can occur - // that are not "terminated" via named types; and such cycles - // can only be created via method parameter types that are - // anonymous interfaces (directly or indirectly) embedding - // the current interface. Example: - // - // type T interface { - // m() interface{T} - // } - // - // If two such (differently named) interfaces are compared, - // endless recursion occurs if the cycle is not detected. - // - // If x and y were compared before, they must be equal - // (if they were not, the recursion would have stopped); - // search the ifacePair stack for the same pair. - // - // This is a quadratic algorithm, but in practice these stacks - // are extremely short (bounded by the nesting depth of interface - // type declarations that recur via parameter types, an extremely - // rare occurrence). An alternative implementation might use a - // "visited" map, but that is probably less efficient overall. - q := &ifacePair{x, y, p} - for p != nil { - if p.identical(q) { - return true // same pair was compared before - } - p = p.prev - } - if debug { - assert(sort.IsSorted(byUniqueMethodName(a))) - assert(sort.IsSorted(byUniqueMethodName(b))) - } - for i, f := range a { - g := b[i] - if f.Id() != g.Id() || !identical(f.typ, g.typ, cmpTags, q) { - return false - } - } - return true - } - } - - case *Map: - // Two map types are identical if they have identical key and value types. - if y, ok := y.(*Map); ok { - return identical(x.key, y.key, cmpTags, p) && identical(x.elem, y.elem, cmpTags, p) - } - - case *Chan: - // Two channel types are identical if they have identical value types - // and the same direction. - if y, ok := y.(*Chan); ok { - return x.dir == y.dir && identical(x.elem, y.elem, cmpTags, p) - } - - case *Named: - // Two named types are identical if their type names originate - // in the same type declaration. - if y, ok := y.(*Named); ok { - return x.obj == y.obj - } - - case nil: - - default: - unreachable() - } - - return false -} - -// Default returns the default "typed" type for an "untyped" type; -// it returns the incoming type for all other types. The default type -// for untyped nil is untyped nil. -// -func Default(typ Type) Type { - if t, ok := typ.(*Basic); ok { - switch t.kind { - case UntypedBool: - return Typ[Bool] - case UntypedInt: - return Typ[Int] - case UntypedRune: - return universeRune // use 'rune' name - case UntypedFloat: - return Typ[Float64] - case UntypedComplex: - return Typ[Complex128] - case UntypedString: - return Typ[String] - } - } - return typ -} diff --git a/third_party/forked/golang/go/types/resolver.go b/third_party/forked/golang/go/types/resolver.go deleted file mode 100644 index d03c1799af9..00000000000 --- a/third_party/forked/golang/go/types/resolver.go +++ /dev/null @@ -1,542 +0,0 @@ -// Copyright 2013 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 types - -import ( - "fmt" - "go/ast" - "go/constant" - "go/token" - "strconv" - "strings" - "unicode" -) - -// A declInfo describes a package-level const, type, var, or func declaration. -type declInfo struct { - file *Scope // scope of file containing this declaration - lhs []*Var // lhs of n:1 variable declarations, or nil - typ ast.Expr // type, or nil - init ast.Expr // init/orig expression, or nil - fdecl *ast.FuncDecl // func declaration, or nil - alias bool // type alias declaration - - // The deps field tracks initialization expression dependencies. - // As a special (overloaded) case, it also tracks dependencies of - // interface types on embedded interfaces (see ordering.go). - deps objSet // lazily initialized -} - -// An objSet is simply a set of objects. -type objSet map[Object]bool - -// hasInitializer reports whether the declared object has an initialization -// expression or function body. -func (d *declInfo) hasInitializer() bool { - return d.init != nil || d.fdecl != nil && d.fdecl.Body != nil -} - -// addDep adds obj to the set of objects d's init expression depends on. -func (d *declInfo) addDep(obj Object) { - m := d.deps - if m == nil { - m = make(objSet) - d.deps = m - } - m[obj] = true -} - -// arityMatch checks that the lhs and rhs of a const or var decl -// have the appropriate number of names and init exprs. For const -// decls, init is the value spec providing the init exprs; for -// var decls, init is nil (the init exprs are in s in this case). -func (check *Checker) arityMatch(s, init *ast.ValueSpec) { - l := len(s.Names) - r := len(s.Values) - if init != nil { - r = len(init.Values) - } - - switch { - case init == nil && r == 0: - // var decl w/o init expr - if s.Type == nil { - check.errorf(s.Pos(), "missing type or init expr") - } - case l < r: - if l < len(s.Values) { - // init exprs from s - n := s.Values[l] - check.errorf(n.Pos(), "extra init expr %s", n) - // TODO(gri) avoid declared but not used error here - } else { - // init exprs "inherited" - check.errorf(s.Pos(), "extra init expr at %s", check.fset.Position(init.Pos())) - // TODO(gri) avoid declared but not used error here - } - case l > r && (init != nil || r != 1): - n := s.Names[r] - check.errorf(n.Pos(), "missing init expr for %s", n) - } -} - -func validatedImportPath(path string) (string, error) { - s, err := strconv.Unquote(path) - if err != nil { - return "", err - } - if s == "" { - return "", fmt.Errorf("empty string") - } - const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD" - for _, r := range s { - if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) { - return s, fmt.Errorf("invalid character %#U", r) - } - } - return s, nil -} - -// declarePkgObj declares obj in the package scope, records its ident -> obj mapping, -// and updates check.objMap. The object must not be a function or method. -func (check *Checker) declarePkgObj(ident *ast.Ident, obj Object, d *declInfo) { - assert(ident.Name == obj.Name()) - - // spec: "A package-scope or file-scope identifier with name init - // may only be declared to be a function with this (func()) signature." - if ident.Name == "init" { - check.errorf(ident.Pos(), "cannot declare init - must be func") - return - } - - // spec: "The main package must have package name main and declare - // a function main that takes no arguments and returns no value." - if ident.Name == "main" && check.pkg.name == "main" { - check.errorf(ident.Pos(), "cannot declare main - must be func") - return - } - - check.declare(check.pkg.scope, ident, obj, token.NoPos) - check.objMap[obj] = d - obj.setOrder(uint32(len(check.objMap))) -} - -// filename returns a filename suitable for debugging output. -func (check *Checker) filename(fileNo int) string { - file := check.files[fileNo] - if pos := file.Pos(); pos.IsValid() { - return check.fset.File(pos).Name() - } - return fmt.Sprintf("file[%d]", fileNo) -} - -func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package { - // If we already have a package for the given (path, dir) - // pair, use it instead of doing a full import. - // Checker.impMap only caches packages that are marked Complete - // or fake (dummy packages for failed imports). Incomplete but - // non-fake packages do require an import to complete them. - key := importKey{path, dir} - imp := check.impMap[key] - if imp != nil { - return imp - } - - // no package yet => import it - if path == "C" && check.conf.FakeImportC { - imp = NewPackage("C", "C") - imp.fake = true - } else { - // ordinary import - var err error - if importer := check.conf.Importer; importer == nil { - err = fmt.Errorf("Config.Importer not installed") - } else if importerFrom, ok := importer.(ImporterFrom); ok { - imp, err = importerFrom.ImportFrom(path, dir, 0) - if imp == nil && err == nil { - err = fmt.Errorf("Config.Importer.ImportFrom(%s, %s, 0) returned nil but no error", path, dir) - } - } else { - imp, err = importer.Import(path) - if imp == nil && err == nil { - err = fmt.Errorf("Config.Importer.Import(%s) returned nil but no error", path) - } - } - // make sure we have a valid package name - // (errors here can only happen through manipulation of packages after creation) - if err == nil && imp != nil && (imp.name == "_" || imp.name == "") { - err = fmt.Errorf("invalid package name: %q", imp.name) - imp = nil // create fake package below - } - if err != nil { - check.errorf(pos, "could not import %s (%s)", path, err) - if imp == nil { - // create a new fake package - // come up with a sensible package name (heuristic) - name := path - if i := len(name); i > 0 && name[i-1] == '/' { - name = name[:i-1] - } - if i := strings.LastIndex(name, "/"); i >= 0 { - name = name[i+1:] - } - imp = NewPackage(path, name) - } - // continue to use the package as best as we can - imp.fake = true // avoid follow-up lookup failures - } - } - - // package should be complete or marked fake, but be cautious - if imp.complete || imp.fake { - check.impMap[key] = imp - return imp - } - - // something went wrong (importer may have returned incomplete package without error) - return nil -} - -// collectObjects collects all file and package objects and inserts them -// into their respective scopes. It also performs imports and associates -// methods with receiver base type names. -func (check *Checker) collectObjects() { - pkg := check.pkg - - // pkgImports is the set of packages already imported by any package file seen - // so far. Used to avoid duplicate entries in pkg.imports. Allocate and populate - // it (pkg.imports may not be empty if we are checking test files incrementally). - // Note that pkgImports is keyed by package (and thus package path), not by an - // importKey value. Two different importKey values may map to the same package - // which is why we cannot use the check.impMap here. - var pkgImports = make(map[*Package]bool) - for _, imp := range pkg.imports { - pkgImports[imp] = true - } - - for fileNo, file := range check.files { - // The package identifier denotes the current package, - // but there is no corresponding package object. - check.recordDef(file.Name, nil) - - // Use the actual source file extent rather than *ast.File extent since the - // latter doesn't include comments which appear at the start or end of the file. - // Be conservative and use the *ast.File extent if we don't have a *token.File. - pos, end := file.Pos(), file.End() - if f := check.fset.File(file.Pos()); f != nil { - pos, end = token.Pos(f.Base()), token.Pos(f.Base()+f.Size()) - } - fileScope := NewScope(check.pkg.scope, pos, end, check.filename(fileNo)) - check.recordScope(file, fileScope) - - // determine file directory, necessary to resolve imports - // FileName may be "" (typically for tests) in which case - // we get "." as the directory which is what we would want. - fileDir := dir(check.fset.Position(file.Name.Pos()).Filename) - - for _, decl := range file.Decls { - switch d := decl.(type) { - case *ast.BadDecl: - // ignore - - case *ast.GenDecl: - var last *ast.ValueSpec // last ValueSpec with type or init exprs seen - for iota, spec := range d.Specs { - switch s := spec.(type) { - case *ast.ImportSpec: - // import package - path, err := validatedImportPath(s.Path.Value) - if err != nil { - check.errorf(s.Path.Pos(), "invalid import path (%s)", err) - continue - } - - imp := check.importPackage(s.Path.Pos(), path, fileDir) - if imp == nil { - continue - } - - // add package to list of explicit imports - // (this functionality is provided as a convenience - // for clients; it is not needed for type-checking) - if !pkgImports[imp] { - pkgImports[imp] = true - pkg.imports = append(pkg.imports, imp) - } - - // local name overrides imported package name - name := imp.name - if s.Name != nil { - name = s.Name.Name - if path == "C" { - // match cmd/compile (not prescribed by spec) - check.errorf(s.Name.Pos(), `cannot rename import "C"`) - continue - } - if name == "init" { - check.errorf(s.Name.Pos(), "cannot declare init - must be func") - continue - } - } - - obj := NewPkgName(s.Pos(), pkg, name, imp) - if s.Name != nil { - // in a dot-import, the dot represents the package - check.recordDef(s.Name, obj) - } else { - check.recordImplicit(s, obj) - } - - if path == "C" { - // match cmd/compile (not prescribed by spec) - obj.used = true - } - - // add import to file scope - if name == "." { - // merge imported scope with file scope - for _, obj := range imp.scope.elems { - // A package scope may contain non-exported objects, - // do not import them! - if obj.Exported() { - // TODO(gri) When we import a package, we create - // a new local package object. We should do the - // same for each dot-imported object. That way - // they can have correct position information. - // (We must not modify their existing position - // information because the same package - found - // via Config.Packages - may be dot-imported in - // another package!) - check.declare(fileScope, nil, obj, token.NoPos) - } - } - // add position to set of dot-import positions for this file - // (this is only needed for "imported but not used" errors) - check.addUnusedDotImport(fileScope, imp, s.Pos()) - } else { - // declare imported package object in file scope - check.declare(fileScope, nil, obj, token.NoPos) - } - - case *ast.ValueSpec: - switch d.Tok { - case token.CONST: - // determine which initialization expressions to use - switch { - case s.Type != nil || len(s.Values) > 0: - last = s - case last == nil: - last = new(ast.ValueSpec) // make sure last exists - } - - // declare all constants - for i, name := range s.Names { - obj := NewConst(name.Pos(), pkg, name.Name, nil, constant.MakeInt64(int64(iota))) - - var init ast.Expr - if i < len(last.Values) { - init = last.Values[i] - } - - d := &declInfo{file: fileScope, typ: last.Type, init: init} - check.declarePkgObj(name, obj, d) - } - - check.arityMatch(s, last) - - case token.VAR: - lhs := make([]*Var, len(s.Names)) - // If there's exactly one rhs initializer, use - // the same declInfo d1 for all lhs variables - // so that each lhs variable depends on the same - // rhs initializer (n:1 var declaration). - var d1 *declInfo - if len(s.Values) == 1 { - // The lhs elements are only set up after the for loop below, - // but that's ok because declareVar only collects the declInfo - // for a later phase. - d1 = &declInfo{file: fileScope, lhs: lhs, typ: s.Type, init: s.Values[0]} - } - - // declare all variables - for i, name := range s.Names { - obj := NewVar(name.Pos(), pkg, name.Name, nil) - lhs[i] = obj - - d := d1 - if d == nil { - // individual assignments - var init ast.Expr - if i < len(s.Values) { - init = s.Values[i] - } - d = &declInfo{file: fileScope, typ: s.Type, init: init} - } - - check.declarePkgObj(name, obj, d) - } - - check.arityMatch(s, nil) - - default: - check.invalidAST(s.Pos(), "invalid token %s", d.Tok) - } - - case *ast.TypeSpec: - obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Name, nil) - check.declarePkgObj(s.Name, obj, &declInfo{file: fileScope, typ: s.Type, alias: s.Assign.IsValid()}) - - default: - check.invalidAST(s.Pos(), "unknown ast.Spec node %T", s) - } - } - - case *ast.FuncDecl: - name := d.Name.Name - obj := NewFunc(d.Name.Pos(), pkg, name, nil) - if d.Recv == nil { - // regular function - if name == "init" { - // don't declare init functions in the package scope - they are invisible - obj.parent = pkg.scope - check.recordDef(d.Name, obj) - // init functions must have a body - if d.Body == nil { - check.softErrorf(obj.pos, "missing function body") - } - } else { - check.declare(pkg.scope, d.Name, obj, token.NoPos) - } - } else { - // method - check.recordDef(d.Name, obj) - // Associate method with receiver base type name, if possible. - // Ignore methods that have an invalid receiver, or a blank _ - // receiver name. They will be type-checked later, with regular - // functions. - if list := d.Recv.List; len(list) > 0 { - typ := unparen(list[0].Type) - if ptr, _ := typ.(*ast.StarExpr); ptr != nil { - typ = unparen(ptr.X) - } - if base, _ := typ.(*ast.Ident); base != nil && base.Name != "_" { - check.assocMethod(base.Name, obj) - } - } - } - info := &declInfo{file: fileScope, fdecl: d} - check.objMap[obj] = info - obj.setOrder(uint32(len(check.objMap))) - - default: - check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d) - } - } - } - - // verify that objects in package and file scopes have different names - for _, scope := range check.pkg.scope.children /* file scopes */ { - for _, obj := range scope.elems { - if alt := pkg.scope.Lookup(obj.Name()); alt != nil { - if pkg, ok := obj.(*PkgName); ok { - check.errorf(alt.Pos(), "%s already declared through import of %s", alt.Name(), pkg.Imported()) - check.reportAltDecl(pkg) - } else { - check.errorf(alt.Pos(), "%s already declared through dot-import of %s", alt.Name(), obj.Pkg()) - // TODO(gri) dot-imported objects don't have a position; reportAltDecl won't print anything - check.reportAltDecl(obj) - } - } - } - } -} - -// packageObjects typechecks all package objects in objList, but not function bodies. -func (check *Checker) packageObjects(objList []Object) { - // add new methods to already type-checked types (from a prior Checker.Files call) - for _, obj := range objList { - if obj, _ := obj.(*TypeName); obj != nil && obj.typ != nil { - check.addMethodDecls(obj) - } - } - - // pre-allocate space for type declaration paths so that the underlying array is reused - typePath := make([]*TypeName, 0, 8) - - for _, obj := range objList { - check.objDecl(obj, nil, typePath) - } - - // At this point we may have a non-empty check.methods map; this means that not all - // entries were deleted at the end of typeDecl because the respective receiver base - // types were not found. In that case, an error was reported when declaring those - // methods. We can now safely discard this map. - check.methods = nil -} - -// functionBodies typechecks all function bodies. -func (check *Checker) functionBodies() { - for _, f := range check.funcs { - check.funcBody(f.decl, f.name, f.sig, f.body) - } -} - -// unusedImports checks for unused imports. -func (check *Checker) unusedImports() { - // if function bodies are not checked, packages' uses are likely missing - don't check - if check.conf.IgnoreFuncBodies { - return - } - - // spec: "It is illegal (...) to directly import a package without referring to - // any of its exported identifiers. To import a package solely for its side-effects - // (initialization), use the blank identifier as explicit package name." - - // check use of regular imported packages - for _, scope := range check.pkg.scope.children /* file scopes */ { - for _, obj := range scope.elems { - if obj, ok := obj.(*PkgName); ok { - // Unused "blank imports" are automatically ignored - // since _ identifiers are not entered into scopes. - if !obj.used { - path := obj.imported.path - base := pkgName(path) - if obj.name == base { - check.softErrorf(obj.pos, "%q imported but not used", path) - } else { - check.softErrorf(obj.pos, "%q imported but not used as %s", path, obj.name) - } - } - } - } - } - - // check use of dot-imported packages - for _, unusedDotImports := range check.unusedDotImports { - for pkg, pos := range unusedDotImports { - check.softErrorf(pos, "%q imported but not used", pkg.path) - } - } -} - -// pkgName returns the package name (last element) of an import path. -func pkgName(path string) string { - if i := strings.LastIndex(path, "/"); i >= 0 { - path = path[i+1:] - } - return path -} - -// dir makes a good-faith attempt to return the directory -// portion of path. If path is empty, the result is ".". -// (Per the go/build package dependency tests, we cannot import -// path/filepath and simply use filepath.Dir.) -func dir(path string) string { - if i := strings.LastIndexAny(path, `/\`); i > 0 { - return path[:i] - } - // i <= 0 - return "." -} diff --git a/third_party/forked/golang/go/types/return.go b/third_party/forked/golang/go/types/return.go deleted file mode 100644 index 0c1447f89b3..00000000000 --- a/third_party/forked/golang/go/types/return.go +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2013 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. - -// This file implements isTerminating. - -package types - -import ( - "go/ast" - "go/token" -) - -// isTerminating reports if s is a terminating statement. -// If s is labeled, label is the label name; otherwise s -// is "". -func (check *Checker) isTerminating(s ast.Stmt, label string) bool { - switch s := s.(type) { - default: - unreachable() - - case *ast.BadStmt, *ast.DeclStmt, *ast.EmptyStmt, *ast.SendStmt, - *ast.IncDecStmt, *ast.AssignStmt, *ast.GoStmt, *ast.DeferStmt, - *ast.RangeStmt: - // no chance - - case *ast.LabeledStmt: - return check.isTerminating(s.Stmt, s.Label.Name) - - case *ast.ExprStmt: - // the predeclared (possibly parenthesized) panic() function is terminating - if call, _ := unparen(s.X).(*ast.CallExpr); call != nil { - if id, _ := call.Fun.(*ast.Ident); id != nil { - if _, obj := check.scope.LookupParent(id.Name, token.NoPos); obj != nil { - if b, _ := obj.(*Builtin); b != nil && b.id == _Panic { - return true - } - } - } - } - - case *ast.ReturnStmt: - return true - - case *ast.BranchStmt: - if s.Tok == token.GOTO || s.Tok == token.FALLTHROUGH { - return true - } - - case *ast.BlockStmt: - return check.isTerminatingList(s.List, "") - - case *ast.IfStmt: - if s.Else != nil && - check.isTerminating(s.Body, "") && - check.isTerminating(s.Else, "") { - return true - } - - case *ast.SwitchStmt: - return check.isTerminatingSwitch(s.Body, label) - - case *ast.TypeSwitchStmt: - return check.isTerminatingSwitch(s.Body, label) - - case *ast.SelectStmt: - for _, s := range s.Body.List { - cc := s.(*ast.CommClause) - if !check.isTerminatingList(cc.Body, "") || hasBreakList(cc.Body, label, true) { - return false - } - - } - return true - - case *ast.ForStmt: - if s.Cond == nil && !hasBreak(s.Body, label, true) { - return true - } - } - - return false -} - -func (check *Checker) isTerminatingList(list []ast.Stmt, label string) bool { - // trailing empty statements are permitted - skip them - for i := len(list) - 1; i >= 0; i-- { - if _, ok := list[i].(*ast.EmptyStmt); !ok { - return check.isTerminating(list[i], label) - } - } - return false // all statements are empty -} - -func (check *Checker) isTerminatingSwitch(body *ast.BlockStmt, label string) bool { - hasDefault := false - for _, s := range body.List { - cc := s.(*ast.CaseClause) - if cc.List == nil { - hasDefault = true - } - if !check.isTerminatingList(cc.Body, "") || hasBreakList(cc.Body, label, true) { - return false - } - } - return hasDefault -} - -// TODO(gri) For nested breakable statements, the current implementation of hasBreak -// will traverse the same subtree repeatedly, once for each label. Replace -// with a single-pass label/break matching phase. - -// hasBreak reports if s is or contains a break statement -// referring to the label-ed statement or implicit-ly the -// closest outer breakable statement. -func hasBreak(s ast.Stmt, label string, implicit bool) bool { - switch s := s.(type) { - default: - unreachable() - - case *ast.BadStmt, *ast.DeclStmt, *ast.EmptyStmt, *ast.ExprStmt, - *ast.SendStmt, *ast.IncDecStmt, *ast.AssignStmt, *ast.GoStmt, - *ast.DeferStmt, *ast.ReturnStmt: - // no chance - - case *ast.LabeledStmt: - return hasBreak(s.Stmt, label, implicit) - - case *ast.BranchStmt: - if s.Tok == token.BREAK { - if s.Label == nil { - return implicit - } - if s.Label.Name == label { - return true - } - } - - case *ast.BlockStmt: - return hasBreakList(s.List, label, implicit) - - case *ast.IfStmt: - if hasBreak(s.Body, label, implicit) || - s.Else != nil && hasBreak(s.Else, label, implicit) { - return true - } - - case *ast.CaseClause: - return hasBreakList(s.Body, label, implicit) - - case *ast.SwitchStmt: - if label != "" && hasBreak(s.Body, label, false) { - return true - } - - case *ast.TypeSwitchStmt: - if label != "" && hasBreak(s.Body, label, false) { - return true - } - - case *ast.CommClause: - return hasBreakList(s.Body, label, implicit) - - case *ast.SelectStmt: - if label != "" && hasBreak(s.Body, label, false) { - return true - } - - case *ast.ForStmt: - if label != "" && hasBreak(s.Body, label, false) { - return true - } - - case *ast.RangeStmt: - if label != "" && hasBreak(s.Body, label, false) { - return true - } - } - - return false -} - -func hasBreakList(list []ast.Stmt, label string, implicit bool) bool { - for _, s := range list { - if hasBreak(s, label, implicit) { - return true - } - } - return false -} diff --git a/third_party/forked/golang/go/types/scope.go b/third_party/forked/golang/go/types/scope.go deleted file mode 100644 index 39e42d758ad..00000000000 --- a/third_party/forked/golang/go/types/scope.go +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright 2013 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. - -// This file implements Scopes. - -package types - -import ( - "bytes" - "fmt" - "go/token" - "io" - "sort" - "strings" -) - -// TODO(gri) Provide scopes with a name or other mechanism so that -// objects can use that information for better printing. - -// A Scope maintains a set of objects and links to its containing -// (parent) and contained (children) scopes. Objects may be inserted -// and looked up by name. The zero value for Scope is a ready-to-use -// empty scope. -type Scope struct { - parent *Scope - children []*Scope - elems map[string]Object // lazily allocated - pos, end token.Pos // scope extent; may be invalid - comment string // for debugging only - isFunc bool // set if this is a function scope (internal use only) -} - -// NewScope returns a new, empty scope contained in the given parent -// scope, if any. The comment is for debugging only. -func NewScope(parent *Scope, pos, end token.Pos, comment string) *Scope { - s := &Scope{parent, nil, nil, pos, end, comment, false} - // don't add children to Universe scope! - if parent != nil && parent != Universe { - parent.children = append(parent.children, s) - } - return s -} - -// Parent returns the scope's containing (parent) scope. -func (s *Scope) Parent() *Scope { return s.parent } - -// Len() returns the number of scope elements. -func (s *Scope) Len() int { return len(s.elems) } - -// Names returns the scope's element names in sorted order. -func (s *Scope) Names() []string { - names := make([]string, len(s.elems)) - i := 0 - for name := range s.elems { - names[i] = name - i++ - } - sort.Strings(names) - return names -} - -// NumChildren() returns the number of scopes nested in s. -func (s *Scope) NumChildren() int { return len(s.children) } - -// Child returns the i'th child scope for 0 <= i < NumChildren(). -func (s *Scope) Child(i int) *Scope { return s.children[i] } - -// Lookup returns the object in scope s with the given name if such an -// object exists; otherwise the result is nil. -func (s *Scope) Lookup(name string) Object { - return s.elems[name] -} - -// LookupParent follows the parent chain of scopes starting with s until -// it finds a scope where Lookup(name) returns a non-nil object, and then -// returns that scope and object. If a valid position pos is provided, -// only objects that were declared at or before pos are considered. -// If no such scope and object exists, the result is (nil, nil). -// -// Note that obj.Parent() may be different from the returned scope if the -// object was inserted into the scope and already had a parent at that -// time (see Insert, below). This can only happen for dot-imported objects -// whose scope is the scope of the package that exported them. -func (s *Scope) LookupParent(name string, pos token.Pos) (*Scope, Object) { - for ; s != nil; s = s.parent { - if obj := s.elems[name]; obj != nil && (!pos.IsValid() || obj.scopePos() <= pos) { - return s, obj - } - } - return nil, nil -} - -// Insert attempts to insert an object obj into scope s. -// If s already contains an alternative object alt with -// the same name, Insert leaves s unchanged and returns alt. -// Otherwise it inserts obj, sets the object's parent scope -// if not already set, and returns nil. -func (s *Scope) Insert(obj Object) Object { - name := obj.Name() - if alt := s.elems[name]; alt != nil { - return alt - } - if s.elems == nil { - s.elems = make(map[string]Object) - } - s.elems[name] = obj - if obj.Parent() == nil { - obj.setParent(s) - } - return nil -} - -// Pos and End describe the scope's source code extent [pos, end). -// The results are guaranteed to be valid only if the type-checked -// AST has complete position information. The extent is undefined -// for Universe and package scopes. -func (s *Scope) Pos() token.Pos { return s.pos } -func (s *Scope) End() token.Pos { return s.end } - -// Contains returns true if pos is within the scope's extent. -// The result is guaranteed to be valid only if the type-checked -// AST has complete position information. -func (s *Scope) Contains(pos token.Pos) bool { - return s.pos <= pos && pos < s.end -} - -// Innermost returns the innermost (child) scope containing -// pos. If pos is not within any scope, the result is nil. -// The result is also nil for the Universe scope. -// The result is guaranteed to be valid only if the type-checked -// AST has complete position information. -func (s *Scope) Innermost(pos token.Pos) *Scope { - // Package scopes do not have extents since they may be - // discontiguous, so iterate over the package's files. - if s.parent == Universe { - for _, s := range s.children { - if inner := s.Innermost(pos); inner != nil { - return inner - } - } - } - - if s.Contains(pos) { - for _, s := range s.children { - if s.Contains(pos) { - return s.Innermost(pos) - } - } - return s - } - return nil -} - -// WriteTo writes a string representation of the scope to w, -// with the scope elements sorted by name. -// The level of indentation is controlled by n >= 0, with -// n == 0 for no indentation. -// If recurse is set, it also writes nested (children) scopes. -func (s *Scope) WriteTo(w io.Writer, n int, recurse bool) { - const ind = ". " - indn := strings.Repeat(ind, n) - - fmt.Fprintf(w, "%s%s scope %p {", indn, s.comment, s) - if len(s.elems) == 0 { - fmt.Fprintf(w, "}\n") - return - } - - fmt.Fprintln(w) - indn1 := indn + ind - for _, name := range s.Names() { - fmt.Fprintf(w, "%s%s\n", indn1, s.elems[name]) - } - - if recurse { - for _, s := range s.children { - fmt.Fprintln(w) - s.WriteTo(w, n+1, recurse) - } - } - - fmt.Fprintf(w, "%s}", indn) -} - -// String returns a string representation of the scope, for debugging. -func (s *Scope) String() string { - var buf bytes.Buffer - s.WriteTo(&buf, 0, false) - return buf.String() -} diff --git a/third_party/forked/golang/go/types/selection.go b/third_party/forked/golang/go/types/selection.go deleted file mode 100644 index 124e0d39f02..00000000000 --- a/third_party/forked/golang/go/types/selection.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2013 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. - -// This file implements Selections. - -package types - -import ( - "bytes" - "fmt" -) - -// SelectionKind describes the kind of a selector expression x.f -// (excluding qualified identifiers). -type SelectionKind int - -const ( - FieldVal SelectionKind = iota // x.f is a struct field selector - MethodVal // x.f is a method selector - MethodExpr // x.f is a method expression -) - -// A Selection describes a selector expression x.f. -// For the declarations: -// -// type T struct{ x int; E } -// type E struct{} -// func (e E) m() {} -// var p *T -// -// the following relations exist: -// -// Selector Kind Recv Obj Type Index Indirect -// -// p.x FieldVal T x int {0} true -// p.m MethodVal *T m func (e *T) m() {1, 0} true -// T.m MethodExpr T m func m(_ T) {1, 0} false -// -type Selection struct { - kind SelectionKind - recv Type // type of x - obj Object // object denoted by x.f - index []int // path from x to x.f - indirect bool // set if there was any pointer indirection on the path -} - -// Kind returns the selection kind. -func (s *Selection) Kind() SelectionKind { return s.kind } - -// Recv returns the type of x in x.f. -func (s *Selection) Recv() Type { return s.recv } - -// Obj returns the object denoted by x.f; a *Var for -// a field selection, and a *Func in all other cases. -func (s *Selection) Obj() Object { return s.obj } - -// Type returns the type of x.f, which may be different from the type of f. -// See Selection for more information. -func (s *Selection) Type() Type { - switch s.kind { - case MethodVal: - // The type of x.f is a method with its receiver type set - // to the type of x. - sig := *s.obj.(*Func).typ.(*Signature) - recv := *sig.recv - recv.typ = s.recv - sig.recv = &recv - return &sig - - case MethodExpr: - // The type of x.f is a function (without receiver) - // and an additional first argument with the same type as x. - // TODO(gri) Similar code is already in call.go - factor! - // TODO(gri) Compute this eagerly to avoid allocations. - sig := *s.obj.(*Func).typ.(*Signature) - arg0 := *sig.recv - sig.recv = nil - arg0.typ = s.recv - var params []*Var - if sig.params != nil { - params = sig.params.vars - } - sig.params = NewTuple(append([]*Var{&arg0}, params...)...) - return &sig - } - - // In all other cases, the type of x.f is the type of x. - return s.obj.Type() -} - -// Index describes the path from x to f in x.f. -// The last index entry is the field or method index of the type declaring f; -// either: -// -// 1) the list of declared methods of a named type; or -// 2) the list of methods of an interface type; or -// 3) the list of fields of a struct type. -// -// The earlier index entries are the indices of the embedded fields implicitly -// traversed to get from (the type of) x to f, starting at embedding depth 0. -func (s *Selection) Index() []int { return s.index } - -// Indirect reports whether any pointer indirection was required to get from -// x to f in x.f. -func (s *Selection) Indirect() bool { return s.indirect } - -func (s *Selection) String() string { return SelectionString(s, nil) } - -// SelectionString returns the string form of s. -// The Qualifier controls the printing of -// package-level objects, and may be nil. -// -// Examples: -// "field (T) f int" -// "method (T) f(X) Y" -// "method expr (T) f(X) Y" -// -func SelectionString(s *Selection, qf Qualifier) string { - var k string - switch s.kind { - case FieldVal: - k = "field " - case MethodVal: - k = "method " - case MethodExpr: - k = "method expr " - default: - unreachable() - } - var buf bytes.Buffer - buf.WriteString(k) - buf.WriteByte('(') - WriteType(&buf, s.Recv(), qf) - fmt.Fprintf(&buf, ") %s", s.obj.Name()) - if T := s.Type(); s.kind == FieldVal { - buf.WriteByte(' ') - WriteType(&buf, T, qf) - } else { - WriteSignature(&buf, T.(*Signature), qf) - } - return buf.String() -} diff --git a/third_party/forked/golang/go/types/sizes.go b/third_party/forked/golang/go/types/sizes.go deleted file mode 100644 index eb274799f42..00000000000 --- a/third_party/forked/golang/go/types/sizes.go +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright 2013 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. - -// This file implements Sizes. - -package types - -// Sizes defines the sizing functions for package unsafe. -type Sizes interface { - // Alignof returns the alignment of a variable of type T. - // Alignof must implement the alignment guarantees required by the spec. - Alignof(T Type) int64 - - // Offsetsof returns the offsets of the given struct fields, in bytes. - // Offsetsof must implement the offset guarantees required by the spec. - Offsetsof(fields []*Var) []int64 - - // Sizeof returns the size of a variable of type T. - // Sizeof must implement the size guarantees required by the spec. - Sizeof(T Type) int64 -} - -// StdSizes is a convenience type for creating commonly used Sizes. -// It makes the following simplifying assumptions: -// -// - The size of explicitly sized basic types (int16, etc.) is the -// specified size. -// - The size of strings and interfaces is 2*WordSize. -// - The size of slices is 3*WordSize. -// - The size of an array of n elements corresponds to the size of -// a struct of n consecutive fields of the array's element type. -// - The size of a struct is the offset of the last field plus that -// field's size. As with all element types, if the struct is used -// in an array its size must first be aligned to a multiple of the -// struct's alignment. -// - All other types have size WordSize. -// - Arrays and structs are aligned per spec definition; all other -// types are naturally aligned with a maximum alignment MaxAlign. -// -// *StdSizes implements Sizes. -// -type StdSizes struct { - WordSize int64 // word size in bytes - must be >= 4 (32bits) - MaxAlign int64 // maximum alignment in bytes - must be >= 1 -} - -func (s *StdSizes) Alignof(T Type) int64 { - // For arrays and structs, alignment is defined in terms - // of alignment of the elements and fields, respectively. - switch t := T.Underlying().(type) { - case *Array: - // spec: "For a variable x of array type: unsafe.Alignof(x) - // is the same as unsafe.Alignof(x[0]), but at least 1." - return s.Alignof(t.elem) - case *Struct: - // spec: "For a variable x of struct type: unsafe.Alignof(x) - // is the largest of the values unsafe.Alignof(x.f) for each - // field f of x, but at least 1." - max := int64(1) - for _, f := range t.fields { - if a := s.Alignof(f.typ); a > max { - max = a - } - } - return max - case *Slice, *Interface: - // Multiword data structures are effectively structs - // in which each element has size WordSize. - return s.WordSize - case *Basic: - // Strings are like slices and interfaces. - if t.Info()&IsString != 0 { - return s.WordSize - } - } - a := s.Sizeof(T) // may be 0 - // spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1." - if a < 1 { - return 1 - } - // complex{64,128} are aligned like [2]float{32,64}. - if isComplex(T) { - a /= 2 - } - if a > s.MaxAlign { - return s.MaxAlign - } - return a -} - -func (s *StdSizes) Offsetsof(fields []*Var) []int64 { - offsets := make([]int64, len(fields)) - var o int64 - for i, f := range fields { - a := s.Alignof(f.typ) - o = align(o, a) - offsets[i] = o - o += s.Sizeof(f.typ) - } - return offsets -} - -var basicSizes = [...]byte{ - Bool: 1, - Int8: 1, - Int16: 2, - Int32: 4, - Int64: 8, - Uint8: 1, - Uint16: 2, - Uint32: 4, - Uint64: 8, - Float32: 4, - Float64: 8, - Complex64: 8, - Complex128: 16, -} - -func (s *StdSizes) Sizeof(T Type) int64 { - switch t := T.Underlying().(type) { - case *Basic: - assert(isTyped(T)) - k := t.kind - if int(k) < len(basicSizes) { - if s := basicSizes[k]; s > 0 { - return int64(s) - } - } - if k == String { - return s.WordSize * 2 - } - case *Array: - n := t.len - if n <= 0 { - return 0 - } - // n > 0 - a := s.Alignof(t.elem) - z := s.Sizeof(t.elem) - return align(z, a)*(n-1) + z - case *Slice: - return s.WordSize * 3 - case *Struct: - n := t.NumFields() - if n == 0 { - return 0 - } - offsets := s.Offsetsof(t.fields) - return offsets[n-1] + s.Sizeof(t.fields[n-1].typ) - case *Interface: - return s.WordSize * 2 - } - return s.WordSize // catch-all -} - -// common architecture word sizes and alignments -var gcArchSizes = map[string]*StdSizes{ - "386": {4, 4}, - "arm": {4, 4}, - "arm64": {8, 8}, - "amd64": {8, 8}, - "amd64p32": {4, 8}, - "mips": {4, 4}, - "mipsle": {4, 4}, - "mips64": {8, 8}, - "mips64le": {8, 8}, - "ppc64": {8, 8}, - "ppc64le": {8, 8}, - "s390x": {8, 8}, - // When adding more architectures here, - // update the doc string of SizesFor below. -} - -// SizesFor returns the Sizes used by a compiler for an architecture. -// The result is nil if a compiler/architecture pair is not known. -// -// Supported architectures for compiler "gc": -// "386", "arm", "arm64", "amd64", "amd64p32", "mips", "mipsle", -// "mips64", "mips64le", "ppc64", "ppc64le", "s390x". -func SizesFor(compiler, arch string) Sizes { - if compiler != "gc" { - return nil - } - s, ok := gcArchSizes[arch] - if !ok { - return nil - } - return s -} - -// stdSizes is used if Config.Sizes == nil. -var stdSizes = SizesFor("gc", "amd64") - -func (conf *Config) alignof(T Type) int64 { - if s := conf.Sizes; s != nil { - if a := s.Alignof(T); a >= 1 { - return a - } - panic("Config.Sizes.Alignof returned an alignment < 1") - } - return stdSizes.Alignof(T) -} - -func (conf *Config) offsetsof(T *Struct) []int64 { - var offsets []int64 - if T.NumFields() > 0 { - // compute offsets on demand - if s := conf.Sizes; s != nil { - offsets = s.Offsetsof(T.fields) - // sanity checks - if len(offsets) != T.NumFields() { - panic("Config.Sizes.Offsetsof returned the wrong number of offsets") - } - for _, o := range offsets { - if o < 0 { - panic("Config.Sizes.Offsetsof returned an offset < 0") - } - } - } else { - offsets = stdSizes.Offsetsof(T.fields) - } - } - return offsets -} - -// offsetof returns the offset of the field specified via -// the index sequence relative to typ. All embedded fields -// must be structs (rather than pointer to structs). -func (conf *Config) offsetof(typ Type, index []int) int64 { - var o int64 - for _, i := range index { - s := typ.Underlying().(*Struct) - o += conf.offsetsof(s)[i] - typ = s.fields[i].typ - } - return o -} - -func (conf *Config) sizeof(T Type) int64 { - if s := conf.Sizes; s != nil { - if z := s.Sizeof(T); z >= 0 { - return z - } - panic("Config.Sizes.Sizeof returned a size < 0") - } - return stdSizes.Sizeof(T) -} - -// align returns the smallest y >= x such that y % a == 0. -func align(x, a int64) int64 { - y := x + a - 1 - return y - y%a -} diff --git a/third_party/forked/golang/go/types/stmt.go b/third_party/forked/golang/go/types/stmt.go deleted file mode 100644 index 5221bcc7c12..00000000000 --- a/third_party/forked/golang/go/types/stmt.go +++ /dev/null @@ -1,870 +0,0 @@ -// Copyright 2012 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. - -// This file implements typechecking of statements. - -package types - -import ( - "fmt" - "go/ast" - "go/constant" - "go/token" - "sort" -) - -func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *ast.BlockStmt) { - if trace { - if name == "" { - name = "" - } - fmt.Printf("--- %s: %s {\n", name, sig) - defer fmt.Println("--- ") - } - - // set function scope extent - sig.scope.pos = body.Pos() - sig.scope.end = body.End() - - // save/restore current context and setup function context - // (and use 0 indentation at function start) - defer func(ctxt context, indent int) { - check.context = ctxt - check.indent = indent - }(check.context, check.indent) - check.context = context{ - decl: decl, - scope: sig.scope, - sig: sig, - } - check.indent = 0 - - check.stmtList(0, body.List) - - if check.hasLabel { - check.labels(body) - } - - if sig.results.Len() > 0 && !check.isTerminating(body, "") { - check.error(body.Rbrace, "missing return") - } - - // spec: "Implementation restriction: A compiler may make it illegal to - // declare a variable inside a function body if the variable is never used." - // (One could check each scope after use, but that distributes this check - // over several places because CloseScope is not always called explicitly.) - check.usage(sig.scope) -} - -func (check *Checker) usage(scope *Scope) { - var unused []*Var - for _, elem := range scope.elems { - if v, _ := elem.(*Var); v != nil && !v.used { - unused = append(unused, v) - } - } - sort.Slice(unused, func(i, j int) bool { - return unused[i].pos < unused[j].pos - }) - for _, v := range unused { - check.softErrorf(v.pos, "%s declared but not used", v.name) - } - - for _, scope := range scope.children { - // Don't go inside closure scopes a second time; - // they are handled explicitly by funcBody. - if !scope.isFunc { - check.usage(scope) - } - } -} - -// stmtContext is a bitset describing which -// control-flow statements are permissible, -// and provides additional context information -// for better error messages. -type stmtContext uint - -const ( - // permissible control-flow statements - breakOk stmtContext = 1 << iota - continueOk - fallthroughOk - - // additional context information - finalSwitchCase -) - -func (check *Checker) simpleStmt(s ast.Stmt) { - if s != nil { - check.stmt(0, s) - } -} - -func trimTrailingEmptyStmts(list []ast.Stmt) []ast.Stmt { - for i := len(list); i > 0; i-- { - if _, ok := list[i-1].(*ast.EmptyStmt); !ok { - return list[:i] - } - } - return nil -} - -func (check *Checker) stmtList(ctxt stmtContext, list []ast.Stmt) { - ok := ctxt&fallthroughOk != 0 - inner := ctxt &^ fallthroughOk - list = trimTrailingEmptyStmts(list) // trailing empty statements are "invisible" to fallthrough analysis - for i, s := range list { - inner := inner - if ok && i+1 == len(list) { - inner |= fallthroughOk - } - check.stmt(inner, s) - } -} - -func (check *Checker) multipleDefaults(list []ast.Stmt) { - var first ast.Stmt - for _, s := range list { - var d ast.Stmt - switch c := s.(type) { - case *ast.CaseClause: - if len(c.List) == 0 { - d = s - } - case *ast.CommClause: - if c.Comm == nil { - d = s - } - default: - check.invalidAST(s.Pos(), "case/communication clause expected") - } - if d != nil { - if first != nil { - check.errorf(d.Pos(), "multiple defaults (first at %s)", check.fset.Position(first.Pos())) - } else { - first = d - } - } - } -} - -func (check *Checker) openScope(s ast.Stmt, comment string) { - scope := NewScope(check.scope, s.Pos(), s.End(), comment) - check.recordScope(s, scope) - check.scope = scope -} - -func (check *Checker) closeScope() { - check.scope = check.scope.Parent() -} - -func assignOp(op token.Token) token.Token { - // token_test.go verifies the token ordering this function relies on - if token.ADD_ASSIGN <= op && op <= token.AND_NOT_ASSIGN { - return op + (token.ADD - token.ADD_ASSIGN) - } - return token.ILLEGAL -} - -func (check *Checker) suspendedCall(keyword string, call *ast.CallExpr) { - var x operand - var msg string - switch check.rawExpr(&x, call, nil) { - case conversion: - msg = "requires function call, not conversion" - case expression: - msg = "discards result of" - case statement: - return - default: - unreachable() - } - check.errorf(x.pos(), "%s %s %s", keyword, msg, &x) -} - -// goVal returns the Go value for val, or nil. -func goVal(val constant.Value) interface{} { - // val should exist, but be conservative and check - if val == nil { - return nil - } - // Match implementation restriction of other compilers. - // gc only checks duplicates for integer, floating-point - // and string values, so only create Go values for these - // types. - switch val.Kind() { - case constant.Int: - if x, ok := constant.Int64Val(val); ok { - return x - } - if x, ok := constant.Uint64Val(val); ok { - return x - } - case constant.Float: - if x, ok := constant.Float64Val(val); ok { - return x - } - case constant.String: - return constant.StringVal(val) - } - return nil -} - -// A valueMap maps a case value (of a basic Go type) to a list of positions -// where the same case value appeared, together with the corresponding case -// types. -// Since two case values may have the same "underlying" value but different -// types we need to also check the value's types (e.g., byte(1) vs myByte(1)) -// when the switch expression is of interface type. -type ( - valueMap map[interface{}][]valueType // underlying Go value -> valueType - valueType struct { - pos token.Pos - typ Type - } -) - -func (check *Checker) caseValues(x *operand, values []ast.Expr, seen valueMap) { -L: - for _, e := range values { - var v operand - check.expr(&v, e) - if x.mode == invalid || v.mode == invalid { - continue L - } - check.convertUntyped(&v, x.typ) - if v.mode == invalid { - continue L - } - // Order matters: By comparing v against x, error positions are at the case values. - res := v // keep original v unchanged - check.comparison(&res, x, token.EQL) - if res.mode == invalid { - continue L - } - if v.mode != constant_ { - continue L // we're done - } - // look for duplicate values - if val := goVal(v.val); val != nil { - // look for duplicate types for a given value - // (quadratic algorithm, but these lists tend to be very short) - for _, vt := range seen[val] { - if Identical(v.typ, vt.typ) { - check.errorf(v.pos(), "duplicate case %s in expression switch", &v) - check.error(vt.pos, "\tprevious case") // secondary error, \t indented - continue L - } - } - seen[val] = append(seen[val], valueType{v.pos(), v.typ}) - } - } -} - -func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[Type]token.Pos) (T Type) { -L: - for _, e := range types { - T = check.typOrNil(e) - if T == Typ[Invalid] { - continue L - } - // look for duplicate types - // (quadratic algorithm, but type switches tend to be reasonably small) - for t, pos := range seen { - if T == nil && t == nil || T != nil && t != nil && Identical(T, t) { - // talk about "case" rather than "type" because of nil case - Ts := "nil" - if T != nil { - Ts = T.String() - } - check.errorf(e.Pos(), "duplicate case %s in type switch", Ts) - check.error(pos, "\tprevious case") // secondary error, \t indented - continue L - } - } - seen[T] = e.Pos() - if T != nil { - check.typeAssertion(e.Pos(), x, xtyp, T) - } - } - return -} - -// stmt typechecks statement s. -func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { - // statements cannot use iota in general - // (constant declarations set it explicitly) - assert(check.iota == nil) - - // statements must end with the same top scope as they started with - if debug { - defer func(scope *Scope) { - // don't check if code is panicking - if p := recover(); p != nil { - panic(p) - } - assert(scope == check.scope) - }(check.scope) - } - - inner := ctxt &^ (fallthroughOk | finalSwitchCase) - switch s := s.(type) { - case *ast.BadStmt, *ast.EmptyStmt: - // ignore - - case *ast.DeclStmt: - check.declStmt(s.Decl) - - case *ast.LabeledStmt: - check.hasLabel = true - check.stmt(ctxt, s.Stmt) - - case *ast.ExprStmt: - // spec: "With the exception of specific built-in functions, - // function and method calls and receive operations can appear - // in statement context. Such statements may be parenthesized." - var x operand - kind := check.rawExpr(&x, s.X, nil) - var msg string - switch x.mode { - default: - if kind == statement { - return - } - msg = "is not used" - case builtin: - msg = "must be called" - case typexpr: - msg = "is not an expression" - } - check.errorf(x.pos(), "%s %s", &x, msg) - - case *ast.SendStmt: - var ch, x operand - check.expr(&ch, s.Chan) - check.expr(&x, s.Value) - if ch.mode == invalid || x.mode == invalid { - return - } - - tch, ok := ch.typ.Underlying().(*Chan) - if !ok { - check.invalidOp(s.Arrow, "cannot send to non-chan type %s", ch.typ) - return - } - - if tch.dir == RecvOnly { - check.invalidOp(s.Arrow, "cannot send to receive-only type %s", tch) - return - } - - check.assignment(&x, tch.elem, "send") - - case *ast.IncDecStmt: - var op token.Token - switch s.Tok { - case token.INC: - op = token.ADD - case token.DEC: - op = token.SUB - default: - check.invalidAST(s.TokPos, "unknown inc/dec operation %s", s.Tok) - return - } - - var x operand - check.expr(&x, s.X) - if x.mode == invalid { - return - } - if !isNumeric(x.typ) { - check.invalidOp(s.X.Pos(), "%s%s (non-numeric type %s)", s.X, s.Tok, x.typ) - return - } - - Y := &ast.BasicLit{ValuePos: s.X.Pos(), Kind: token.INT, Value: "1"} // use x's position - check.binary(&x, nil, s.X, Y, op) - if x.mode == invalid { - return - } - check.assignVar(s.X, &x) - - case *ast.AssignStmt: - switch s.Tok { - case token.ASSIGN, token.DEFINE: - if len(s.Lhs) == 0 { - check.invalidAST(s.Pos(), "missing lhs in assignment") - return - } - if s.Tok == token.DEFINE { - check.shortVarDecl(s.TokPos, s.Lhs, s.Rhs) - } else { - // regular assignment - check.assignVars(s.Lhs, s.Rhs) - } - - default: - // assignment operations - if len(s.Lhs) != 1 || len(s.Rhs) != 1 { - check.errorf(s.TokPos, "assignment operation %s requires single-valued expressions", s.Tok) - return - } - op := assignOp(s.Tok) - if op == token.ILLEGAL { - check.invalidAST(s.TokPos, "unknown assignment operation %s", s.Tok) - return - } - var x operand - check.binary(&x, nil, s.Lhs[0], s.Rhs[0], op) - if x.mode == invalid { - return - } - check.assignVar(s.Lhs[0], &x) - } - - case *ast.GoStmt: - check.suspendedCall("go", s.Call) - - case *ast.DeferStmt: - check.suspendedCall("defer", s.Call) - - case *ast.ReturnStmt: - res := check.sig.results - if res.Len() > 0 { - // function returns results - // (if one, say the first, result parameter is named, all of them are named) - if len(s.Results) == 0 && res.vars[0].name != "" { - // spec: "Implementation restriction: A compiler may disallow an empty expression - // list in a "return" statement if a different entity (constant, type, or variable) - // with the same name as a result parameter is in scope at the place of the return." - for _, obj := range res.vars { - if _, alt := check.scope.LookupParent(obj.name, check.pos); alt != nil && alt != obj { - check.errorf(s.Pos(), "result parameter %s not in scope at return", obj.name) - check.errorf(alt.Pos(), "\tinner declaration of %s", obj) - // ok to continue - } - } - } else { - // return has results or result parameters are unnamed - check.initVars(res.vars, s.Results, s.Return) - } - } else if len(s.Results) > 0 { - check.error(s.Results[0].Pos(), "no result values expected") - check.use(s.Results...) - } - - case *ast.BranchStmt: - if s.Label != nil { - check.hasLabel = true - return // checked in 2nd pass (check.labels) - } - switch s.Tok { - case token.BREAK: - if ctxt&breakOk == 0 { - check.error(s.Pos(), "break not in for, switch, or select statement") - } - case token.CONTINUE: - if ctxt&continueOk == 0 { - check.error(s.Pos(), "continue not in for statement") - } - case token.FALLTHROUGH: - if ctxt&fallthroughOk == 0 { - msg := "fallthrough statement out of place" - if ctxt&finalSwitchCase != 0 { - msg = "cannot fallthrough final case in switch" - } - check.error(s.Pos(), msg) - } - default: - check.invalidAST(s.Pos(), "branch statement: %s", s.Tok) - } - - case *ast.BlockStmt: - check.openScope(s, "block") - defer check.closeScope() - - check.stmtList(inner, s.List) - - case *ast.IfStmt: - check.openScope(s, "if") - defer check.closeScope() - - check.simpleStmt(s.Init) - var x operand - check.expr(&x, s.Cond) - if x.mode != invalid && !isBoolean(x.typ) { - check.error(s.Cond.Pos(), "non-boolean condition in if statement") - } - check.stmt(inner, s.Body) - // The parser produces a correct AST but if it was modified - // elsewhere the else branch may be invalid. Check again. - switch s.Else.(type) { - case nil, *ast.BadStmt: - // valid or error already reported - case *ast.IfStmt, *ast.BlockStmt: - check.stmt(inner, s.Else) - default: - check.error(s.Else.Pos(), "invalid else branch in if statement") - } - - case *ast.SwitchStmt: - inner |= breakOk - check.openScope(s, "switch") - defer check.closeScope() - - check.simpleStmt(s.Init) - var x operand - if s.Tag != nil { - check.expr(&x, s.Tag) - // By checking assignment of x to an invisible temporary - // (as a compiler would), we get all the relevant checks. - check.assignment(&x, nil, "switch expression") - } else { - // spec: "A missing switch expression is - // equivalent to the boolean value true." - x.mode = constant_ - x.typ = Typ[Bool] - x.val = constant.MakeBool(true) - x.expr = &ast.Ident{NamePos: s.Body.Lbrace, Name: "true"} - } - - check.multipleDefaults(s.Body.List) - - seen := make(valueMap) // map of seen case values to positions and types - for i, c := range s.Body.List { - clause, _ := c.(*ast.CaseClause) - if clause == nil { - check.invalidAST(c.Pos(), "incorrect expression switch case") - continue - } - check.caseValues(&x, clause.List, seen) - check.openScope(clause, "case") - inner := inner - if i+1 < len(s.Body.List) { - inner |= fallthroughOk - } else { - inner |= finalSwitchCase - } - check.stmtList(inner, clause.Body) - check.closeScope() - } - - case *ast.TypeSwitchStmt: - inner |= breakOk - check.openScope(s, "type switch") - defer check.closeScope() - - check.simpleStmt(s.Init) - - // A type switch guard must be of the form: - // - // TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" . - // - // The parser is checking syntactic correctness; - // remaining syntactic errors are considered AST errors here. - // TODO(gri) better factoring of error handling (invalid ASTs) - // - var lhs *ast.Ident // lhs identifier or nil - var rhs ast.Expr - switch guard := s.Assign.(type) { - case *ast.ExprStmt: - rhs = guard.X - case *ast.AssignStmt: - if len(guard.Lhs) != 1 || guard.Tok != token.DEFINE || len(guard.Rhs) != 1 { - check.invalidAST(s.Pos(), "incorrect form of type switch guard") - return - } - - lhs, _ = guard.Lhs[0].(*ast.Ident) - if lhs == nil { - check.invalidAST(s.Pos(), "incorrect form of type switch guard") - return - } - - if lhs.Name == "_" { - // _ := x.(type) is an invalid short variable declaration - check.softErrorf(lhs.Pos(), "no new variable on left side of :=") - lhs = nil // avoid declared but not used error below - } else { - check.recordDef(lhs, nil) // lhs variable is implicitly declared in each cause clause - } - - rhs = guard.Rhs[0] - - default: - check.invalidAST(s.Pos(), "incorrect form of type switch guard") - return - } - - // rhs must be of the form: expr.(type) and expr must be an interface - expr, _ := rhs.(*ast.TypeAssertExpr) - if expr == nil || expr.Type != nil { - check.invalidAST(s.Pos(), "incorrect form of type switch guard") - return - } - var x operand - check.expr(&x, expr.X) - if x.mode == invalid { - return - } - xtyp, _ := x.typ.Underlying().(*Interface) - if xtyp == nil { - check.errorf(x.pos(), "%s is not an interface", &x) - return - } - - check.multipleDefaults(s.Body.List) - - var lhsVars []*Var // list of implicitly declared lhs variables - seen := make(map[Type]token.Pos) // map of seen types to positions - for _, s := range s.Body.List { - clause, _ := s.(*ast.CaseClause) - if clause == nil { - check.invalidAST(s.Pos(), "incorrect type switch case") - continue - } - // Check each type in this type switch case. - T := check.caseTypes(&x, xtyp, clause.List, seen) - check.openScope(clause, "case") - // If lhs exists, declare a corresponding variable in the case-local scope. - if lhs != nil { - // spec: "The TypeSwitchGuard may include a short variable declaration. - // When that form is used, the variable is declared at the beginning of - // the implicit block in each clause. In clauses with a case listing - // exactly one type, the variable has that type; otherwise, the variable - // has the type of the expression in the TypeSwitchGuard." - if len(clause.List) != 1 || T == nil { - T = x.typ - } - obj := NewVar(lhs.Pos(), check.pkg, lhs.Name, T) - scopePos := clause.Pos() + token.Pos(len("default")) // for default clause (len(List) == 0) - if n := len(clause.List); n > 0 { - scopePos = clause.List[n-1].End() - } - check.declare(check.scope, nil, obj, scopePos) - check.recordImplicit(clause, obj) - // For the "declared but not used" error, all lhs variables act as - // one; i.e., if any one of them is 'used', all of them are 'used'. - // Collect them for later analysis. - lhsVars = append(lhsVars, obj) - } - check.stmtList(inner, clause.Body) - check.closeScope() - } - - // If lhs exists, we must have at least one lhs variable that was used. - if lhs != nil { - var used bool - for _, v := range lhsVars { - if v.used { - used = true - } - v.used = true // avoid usage error when checking entire function - } - if !used { - check.softErrorf(lhs.Pos(), "%s declared but not used", lhs.Name) - } - } - - case *ast.SelectStmt: - inner |= breakOk - - check.multipleDefaults(s.Body.List) - - for _, s := range s.Body.List { - clause, _ := s.(*ast.CommClause) - if clause == nil { - continue // error reported before - } - - // clause.Comm must be a SendStmt, RecvStmt, or default case - valid := false - var rhs ast.Expr // rhs of RecvStmt, or nil - switch s := clause.Comm.(type) { - case nil, *ast.SendStmt: - valid = true - case *ast.AssignStmt: - if len(s.Rhs) == 1 { - rhs = s.Rhs[0] - } - case *ast.ExprStmt: - rhs = s.X - } - - // if present, rhs must be a receive operation - if rhs != nil { - if x, _ := unparen(rhs).(*ast.UnaryExpr); x != nil && x.Op == token.ARROW { - valid = true - } - } - - if !valid { - check.error(clause.Comm.Pos(), "select case must be send or receive (possibly with assignment)") - continue - } - - check.openScope(s, "case") - if clause.Comm != nil { - check.stmt(inner, clause.Comm) - } - check.stmtList(inner, clause.Body) - check.closeScope() - } - - case *ast.ForStmt: - inner |= breakOk | continueOk - check.openScope(s, "for") - defer check.closeScope() - - check.simpleStmt(s.Init) - if s.Cond != nil { - var x operand - check.expr(&x, s.Cond) - if x.mode != invalid && !isBoolean(x.typ) { - check.error(s.Cond.Pos(), "non-boolean condition in for statement") - } - } - check.simpleStmt(s.Post) - // spec: "The init statement may be a short variable - // declaration, but the post statement must not." - if s, _ := s.Post.(*ast.AssignStmt); s != nil && s.Tok == token.DEFINE { - check.softErrorf(s.Pos(), "cannot declare in post statement") - // Don't call useLHS here because we want to use the lhs in - // this erroneous statement so that we don't get errors about - // these lhs variables being declared but not used. - check.use(s.Lhs...) // avoid follow-up errors - } - check.stmt(inner, s.Body) - - case *ast.RangeStmt: - inner |= breakOk | continueOk - check.openScope(s, "for") - defer check.closeScope() - - // check expression to iterate over - var x operand - check.expr(&x, s.X) - - // determine key/value types - var key, val Type - if x.mode != invalid { - switch typ := x.typ.Underlying().(type) { - case *Basic: - if isString(typ) { - key = Typ[Int] - val = universeRune // use 'rune' name - } - case *Array: - key = Typ[Int] - val = typ.elem - case *Slice: - key = Typ[Int] - val = typ.elem - case *Pointer: - if typ, _ := typ.base.Underlying().(*Array); typ != nil { - key = Typ[Int] - val = typ.elem - } - case *Map: - key = typ.key - val = typ.elem - case *Chan: - key = typ.elem - val = Typ[Invalid] - if typ.dir == SendOnly { - check.errorf(x.pos(), "cannot range over send-only channel %s", &x) - // ok to continue - } - if s.Value != nil { - check.errorf(s.Value.Pos(), "iteration over %s permits only one iteration variable", &x) - // ok to continue - } - } - } - - if key == nil { - check.errorf(x.pos(), "cannot range over %s", &x) - // ok to continue - } - - // check assignment to/declaration of iteration variables - // (irregular assignment, cannot easily map to existing assignment checks) - - // lhs expressions and initialization value (rhs) types - lhs := [2]ast.Expr{s.Key, s.Value} - rhs := [2]Type{key, val} // key, val may be nil - - if s.Tok == token.DEFINE { - // short variable declaration; variable scope starts after the range clause - // (the for loop opens a new scope, so variables on the lhs never redeclare - // previously declared variables) - var vars []*Var - for i, lhs := range lhs { - if lhs == nil { - continue - } - - // determine lhs variable - var obj *Var - if ident, _ := lhs.(*ast.Ident); ident != nil { - // declare new variable - name := ident.Name - obj = NewVar(ident.Pos(), check.pkg, name, nil) - check.recordDef(ident, obj) - // _ variables don't count as new variables - if name != "_" { - vars = append(vars, obj) - } - } else { - check.errorf(lhs.Pos(), "cannot declare %s", lhs) - obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable - } - - // initialize lhs variable - if typ := rhs[i]; typ != nil { - x.mode = value - x.expr = lhs // we don't have a better rhs expression to use here - x.typ = typ - check.initVar(obj, &x, "range clause") - } else { - obj.typ = Typ[Invalid] - obj.used = true // don't complain about unused variable - } - } - - // declare variables - if len(vars) > 0 { - scopePos := s.X.End() - for _, obj := range vars { - // spec: "The scope of a constant or variable identifier declared inside - // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl - // for short variable declarations) and ends at the end of the innermost - // containing block." - check.declare(check.scope, nil /* recordDef already called */, obj, scopePos) - } - } else { - check.error(s.TokPos, "no new variables on left side of :=") - } - } else { - // ordinary assignment - for i, lhs := range lhs { - if lhs == nil { - continue - } - if typ := rhs[i]; typ != nil { - x.mode = value - x.expr = lhs // we don't have a better rhs expression to use here - x.typ = typ - check.assignVar(lhs, &x) - } - } - } - - check.stmt(inner, s.Body) - - default: - check.error(s.Pos(), "invalid statement") - } -} diff --git a/third_party/forked/golang/go/types/type.go b/third_party/forked/golang/go/types/type.go deleted file mode 100644 index 5db03f8f0ca..00000000000 --- a/third_party/forked/golang/go/types/type.go +++ /dev/null @@ -1,464 +0,0 @@ -// Copyright 2011 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 types - -import "sort" - -// A Type represents a type of Go. -// All types implement the Type interface. -type Type interface { - // Underlying returns the underlying type of a type. - Underlying() Type - - // String returns a string representation of a type. - String() string -} - -// BasicKind describes the kind of basic type. -type BasicKind int - -const ( - Invalid BasicKind = iota // type is invalid - - // predeclared types - Bool - Int - Int8 - Int16 - Int32 - Int64 - Uint - Uint8 - Uint16 - Uint32 - Uint64 - Uintptr - Float32 - Float64 - Complex64 - Complex128 - String - UnsafePointer - - // types for untyped values - UntypedBool - UntypedInt - UntypedRune - UntypedFloat - UntypedComplex - UntypedString - UntypedNil - - // aliases - Byte = Uint8 - Rune = Int32 -) - -// BasicInfo is a set of flags describing properties of a basic type. -type BasicInfo int - -// Properties of basic types. -const ( - IsBoolean BasicInfo = 1 << iota - IsInteger - IsUnsigned - IsFloat - IsComplex - IsString - IsUntyped - - IsOrdered = IsInteger | IsFloat | IsString - IsNumeric = IsInteger | IsFloat | IsComplex - IsConstType = IsBoolean | IsNumeric | IsString -) - -// A Basic represents a basic type. -type Basic struct { - kind BasicKind - info BasicInfo - name string -} - -// Kind returns the kind of basic type b. -func (b *Basic) Kind() BasicKind { return b.kind } - -// Info returns information about properties of basic type b. -func (b *Basic) Info() BasicInfo { return b.info } - -// Name returns the name of basic type b. -func (b *Basic) Name() string { return b.name } - -// An Array represents an array type. -type Array struct { - len int64 - elem Type -} - -// NewArray returns a new array type for the given element type and length. -// A negative length indicates an unknown length. -func NewArray(elem Type, len int64) *Array { return &Array{len, elem} } - -// Len returns the length of array a. -// A negative result indicates an unknown length. -func (a *Array) Len() int64 { return a.len } - -// Elem returns element type of array a. -func (a *Array) Elem() Type { return a.elem } - -// A Slice represents a slice type. -type Slice struct { - elem Type -} - -// NewSlice returns a new slice type for the given element type. -func NewSlice(elem Type) *Slice { return &Slice{elem} } - -// Elem returns the element type of slice s. -func (s *Slice) Elem() Type { return s.elem } - -// A Struct represents a struct type. -type Struct struct { - fields []*Var - tags []string // field tags; nil if there are no tags -} - -// NewStruct returns a new struct with the given fields and corresponding field tags. -// If a field with index i has a tag, tags[i] must be that tag, but len(tags) may be -// only as long as required to hold the tag with the largest index i. Consequently, -// if no field has a tag, tags may be nil. -func NewStruct(fields []*Var, tags []string) *Struct { - var fset objset - for _, f := range fields { - if f.name != "_" && fset.insert(f) != nil { - panic("multiple fields with the same name") - } - } - if len(tags) > len(fields) { - panic("more tags than fields") - } - return &Struct{fields: fields, tags: tags} -} - -// NumFields returns the number of fields in the struct (including blank and anonymous fields). -func (s *Struct) NumFields() int { return len(s.fields) } - -// Field returns the i'th field for 0 <= i < NumFields(). -func (s *Struct) Field(i int) *Var { return s.fields[i] } - -// Tag returns the i'th field tag for 0 <= i < NumFields(). -func (s *Struct) Tag(i int) string { - if i < len(s.tags) { - return s.tags[i] - } - return "" -} - -// A Pointer represents a pointer type. -type Pointer struct { - base Type // element type -} - -// NewPointer returns a new pointer type for the given element (base) type. -func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} } - -// Elem returns the element type for the given pointer p. -func (p *Pointer) Elem() Type { return p.base } - -// A Tuple represents an ordered list of variables; a nil *Tuple is a valid (empty) tuple. -// Tuples are used as components of signatures and to represent the type of multiple -// assignments; they are not first class types of Go. -type Tuple struct { - vars []*Var -} - -// NewTuple returns a new tuple for the given variables. -func NewTuple(x ...*Var) *Tuple { - if len(x) > 0 { - return &Tuple{x} - } - return nil -} - -// Len returns the number variables of tuple t. -func (t *Tuple) Len() int { - if t != nil { - return len(t.vars) - } - return 0 -} - -// At returns the i'th variable of tuple t. -func (t *Tuple) At(i int) *Var { return t.vars[i] } - -// A Signature represents a (non-builtin) function or method type. -// The receiver is ignored when comparing signatures for identity. -type Signature struct { - // We need to keep the scope in Signature (rather than passing it around - // and store it in the Func Object) because when type-checking a function - // literal we call the general type checker which returns a general Type. - // We then unpack the *Signature and use the scope for the literal body. - scope *Scope // function scope, present for package-local signatures - recv *Var // nil if not a method - params *Tuple // (incoming) parameters from left to right; or nil - results *Tuple // (outgoing) results from left to right; or nil - variadic bool // true if the last parameter's type is of the form ...T (or string, for append built-in only) -} - -// NewSignature returns a new function type for the given receiver, parameters, -// and results, either of which may be nil. If variadic is set, the function -// is variadic, it must have at least one parameter, and the last parameter -// must be of unnamed slice type. -func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { - if variadic { - n := params.Len() - if n == 0 { - panic("types.NewSignature: variadic function must have at least one parameter") - } - if _, ok := params.At(n - 1).typ.(*Slice); !ok { - panic("types.NewSignature: variadic parameter must be of unnamed slice type") - } - } - return &Signature{nil, recv, params, results, variadic} -} - -// Recv returns the receiver of signature s (if a method), or nil if a -// function. It is ignored when comparing signatures for identity. -// -// For an abstract method, Recv returns the enclosing interface either -// as a *Named or an *Interface. Due to embedding, an interface may -// contain methods whose receiver type is a different interface. -func (s *Signature) Recv() *Var { return s.recv } - -// Params returns the parameters of signature s, or nil. -func (s *Signature) Params() *Tuple { return s.params } - -// Results returns the results of signature s, or nil. -func (s *Signature) Results() *Tuple { return s.results } - -// Variadic reports whether the signature s is variadic. -func (s *Signature) Variadic() bool { return s.variadic } - -// An Interface represents an interface type. -type Interface struct { - methods []*Func // ordered list of explicitly declared methods - embeddeds []*Named // ordered list of explicitly embedded types - - allMethods []*Func // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset) -} - -// emptyInterface represents the empty (completed) interface -var emptyInterface = Interface{allMethods: markComplete} - -// markComplete is used to mark an empty interface as completely -// set up by setting the allMethods field to a non-nil empty slice. -var markComplete = make([]*Func, 0) - -// NewInterface returns a new (incomplete) interface for the given methods and embedded types. -// To compute the method set of the interface, Complete must be called. -func NewInterface(methods []*Func, embeddeds []*Named) *Interface { - typ := new(Interface) - - if len(methods) == 0 && len(embeddeds) == 0 { - return typ - } - - var mset objset - for _, m := range methods { - if mset.insert(m) != nil { - panic("multiple methods with the same name") - } - // set receiver - // TODO(gri) Ideally, we should use a named type here instead of - // typ, for less verbose printing of interface method signatures. - m.typ.(*Signature).recv = NewVar(m.pos, m.pkg, "", typ) - } - sort.Sort(byUniqueMethodName(methods)) - - if embeddeds != nil { - sort.Sort(byUniqueTypeName(embeddeds)) - } - - typ.methods = methods - typ.embeddeds = embeddeds - return typ -} - -// NumExplicitMethods returns the number of explicitly declared methods of interface t. -func (t *Interface) NumExplicitMethods() int { return len(t.methods) } - -// ExplicitMethod returns the i'th explicitly declared method of interface t for 0 <= i < t.NumExplicitMethods(). -// The methods are ordered by their unique Id. -func (t *Interface) ExplicitMethod(i int) *Func { return t.methods[i] } - -// NumEmbeddeds returns the number of embedded types in interface t. -func (t *Interface) NumEmbeddeds() int { return len(t.embeddeds) } - -// Embedded returns the i'th embedded type of interface t for 0 <= i < t.NumEmbeddeds(). -// The types are ordered by the corresponding TypeName's unique Id. -func (t *Interface) Embedded(i int) *Named { return t.embeddeds[i] } - -// NumMethods returns the total number of methods of interface t. -func (t *Interface) NumMethods() int { return len(t.allMethods) } - -// Method returns the i'th method of interface t for 0 <= i < t.NumMethods(). -// The methods are ordered by their unique Id. -func (t *Interface) Method(i int) *Func { return t.allMethods[i] } - -// Empty returns true if t is the empty interface. -func (t *Interface) Empty() bool { return len(t.allMethods) == 0 } - -// Complete computes the interface's method set. It must be called by users of -// NewInterface after the interface's embedded types are fully defined and -// before using the interface type in any way other than to form other types. -// Complete returns the receiver. -func (t *Interface) Complete() *Interface { - if t.allMethods != nil { - return t - } - - var allMethods []*Func - if t.embeddeds == nil { - if t.methods == nil { - allMethods = make([]*Func, 0, 1) - } else { - allMethods = t.methods - } - } else { - allMethods = append(allMethods, t.methods...) - for _, et := range t.embeddeds { - it := et.Underlying().(*Interface) - it.Complete() - for _, tm := range it.allMethods { - // Make a copy of the method and adjust its receiver type. - newm := *tm - newmtyp := *tm.typ.(*Signature) - newm.typ = &newmtyp - newmtyp.recv = NewVar(newm.pos, newm.pkg, "", t) - allMethods = append(allMethods, &newm) - } - } - sort.Sort(byUniqueMethodName(allMethods)) - } - t.allMethods = allMethods - - return t -} - -// A Map represents a map type. -type Map struct { - key, elem Type -} - -// NewMap returns a new map for the given key and element types. -func NewMap(key, elem Type) *Map { - return &Map{key, elem} -} - -// Key returns the key type of map m. -func (m *Map) Key() Type { return m.key } - -// Elem returns the element type of map m. -func (m *Map) Elem() Type { return m.elem } - -// A Chan represents a channel type. -type Chan struct { - dir ChanDir - elem Type -} - -// A ChanDir value indicates a channel direction. -type ChanDir int - -// The direction of a channel is indicated by one of these constants. -const ( - SendRecv ChanDir = iota - SendOnly - RecvOnly -) - -// NewChan returns a new channel type for the given direction and element type. -func NewChan(dir ChanDir, elem Type) *Chan { - return &Chan{dir, elem} -} - -// Dir returns the direction of channel c. -func (c *Chan) Dir() ChanDir { return c.dir } - -// Elem returns the element type of channel c. -func (c *Chan) Elem() Type { return c.elem } - -// A Named represents a named type. -type Named struct { - obj *TypeName // corresponding declared object - underlying Type // possibly a *Named during setup; never a *Named once set up completely - methods []*Func // methods declared for this type (not the method set of this type) -} - -// NewNamed returns a new named type for the given type name, underlying type, and associated methods. -// If the given type name obj doesn't have a type yet, its type is set to the returned named type. -// The underlying type must not be a *Named. -func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { - if _, ok := underlying.(*Named); ok { - panic("types.NewNamed: underlying type must not be *Named") - } - typ := &Named{obj: obj, underlying: underlying, methods: methods} - if obj.typ == nil { - obj.typ = typ - } - return typ -} - -// Obj returns the type name for the named type t. -func (t *Named) Obj() *TypeName { return t.obj } - -// NumMethods returns the number of explicit methods whose receiver is named type t. -func (t *Named) NumMethods() int { return len(t.methods) } - -// Method returns the i'th method of named type t for 0 <= i < t.NumMethods(). -func (t *Named) Method(i int) *Func { return t.methods[i] } - -// SetUnderlying sets the underlying type and marks t as complete. -func (t *Named) SetUnderlying(underlying Type) { - if underlying == nil { - panic("types.Named.SetUnderlying: underlying type must not be nil") - } - if _, ok := underlying.(*Named); ok { - panic("types.Named.SetUnderlying: underlying type must not be *Named") - } - t.underlying = underlying -} - -// AddMethod adds method m unless it is already in the method list. -func (t *Named) AddMethod(m *Func) { - if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 { - t.methods = append(t.methods, m) - } -} - -// Implementations for Type methods. - -func (t *Basic) Underlying() Type { return t } -func (t *Array) Underlying() Type { return t } -func (t *Slice) Underlying() Type { return t } -func (t *Struct) Underlying() Type { return t } -func (t *Pointer) Underlying() Type { return t } -func (t *Tuple) Underlying() Type { return t } -func (t *Signature) Underlying() Type { return t } -func (t *Interface) Underlying() Type { return t } -func (t *Map) Underlying() Type { return t } -func (t *Chan) Underlying() Type { return t } -func (t *Named) Underlying() Type { return t.underlying } - -func (t *Basic) String() string { return TypeString(t, nil) } -func (t *Array) String() string { return TypeString(t, nil) } -func (t *Slice) String() string { return TypeString(t, nil) } -func (t *Struct) String() string { return TypeString(t, nil) } -func (t *Pointer) String() string { return TypeString(t, nil) } -func (t *Tuple) String() string { return TypeString(t, nil) } -func (t *Signature) String() string { return TypeString(t, nil) } -func (t *Interface) String() string { return TypeString(t, nil) } -func (t *Map) String() string { return TypeString(t, nil) } -func (t *Chan) String() string { return TypeString(t, nil) } -func (t *Named) String() string { return TypeString(t, nil) } diff --git a/third_party/forked/golang/go/types/typestring.go b/third_party/forked/golang/go/types/typestring.go deleted file mode 100644 index a9c0bfde1f9..00000000000 --- a/third_party/forked/golang/go/types/typestring.go +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright 2013 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. - -// This file implements printing of types. - -package types - -import ( - "bytes" - "fmt" -) - -// A Qualifier controls how named package-level objects are printed in -// calls to TypeString, ObjectString, and SelectionString. -// -// These three formatting routines call the Qualifier for each -// package-level object O, and if the Qualifier returns a non-empty -// string p, the object is printed in the form p.O. -// If it returns an empty string, only the object name O is printed. -// -// Using a nil Qualifier is equivalent to using (*Package).Path: the -// object is qualified by the import path, e.g., "encoding/json.Marshal". -// -type Qualifier func(*Package) string - -// RelativeTo(pkg) returns a Qualifier that fully qualifies members of -// all packages other than pkg. -func RelativeTo(pkg *Package) Qualifier { - if pkg == nil { - return nil - } - return func(other *Package) string { - if pkg == other { - return "" // same package; unqualified - } - return other.Path() - } -} - -// If gcCompatibilityMode is set, printing of types is modified -// to match the representation of some types in the gc compiler: -// -// - byte and rune lose their alias name and simply stand for -// uint8 and int32 respectively -// - embedded interfaces get flattened (the embedding info is lost, -// and certain recursive interface types cannot be printed anymore) -// -// This makes it easier to compare packages computed with the type- -// checker vs packages imported from gc export data. -// -// Caution: This flag affects all uses of WriteType, globally. -// It is only provided for testing in conjunction with -// gc-generated data. -// -// This flag is exported in the x/tools/go/types package. We don't -// need it at the moment in the std repo and so we don't export it -// anymore. We should eventually try to remove it altogether. -// TODO(gri) remove this -var gcCompatibilityMode bool - -// TypeString returns the string representation of typ. -// The Qualifier controls the printing of -// package-level objects, and may be nil. -func TypeString(typ Type, qf Qualifier) string { - var buf bytes.Buffer - WriteType(&buf, typ, qf) - return buf.String() -} - -// WriteType writes the string representation of typ to buf. -// The Qualifier controls the printing of -// package-level objects, and may be nil. -func WriteType(buf *bytes.Buffer, typ Type, qf Qualifier) { - writeType(buf, typ, qf, make([]Type, 0, 8)) -} - -func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { - // Theoretically, this is a quadratic lookup algorithm, but in - // practice deeply nested composite types with unnamed component - // types are uncommon. This code is likely more efficient than - // using a map. - for _, t := range visited { - if t == typ { - fmt.Fprintf(buf, "○%T", typ) // cycle to typ - return - } - } - visited = append(visited, typ) - - switch t := typ.(type) { - case nil: - buf.WriteString("") - - case *Basic: - if t.kind == UnsafePointer { - buf.WriteString("unsafe.") - } - if gcCompatibilityMode { - // forget the alias names - switch t.kind { - case Byte: - t = Typ[Uint8] - case Rune: - t = Typ[Int32] - } - } - buf.WriteString(t.name) - - case *Array: - fmt.Fprintf(buf, "[%d]", t.len) - writeType(buf, t.elem, qf, visited) - - case *Slice: - buf.WriteString("[]") - writeType(buf, t.elem, qf, visited) - - case *Struct: - buf.WriteString("struct{") - for i, f := range t.fields { - if i > 0 { - buf.WriteString("; ") - } - if !f.anonymous { - buf.WriteString(f.name) - buf.WriteByte(' ') - } - writeType(buf, f.typ, qf, visited) - if tag := t.Tag(i); tag != "" { - fmt.Fprintf(buf, " %q", tag) - } - } - buf.WriteByte('}') - - case *Pointer: - buf.WriteByte('*') - writeType(buf, t.base, qf, visited) - - case *Tuple: - writeTuple(buf, t, false, qf, visited) - - case *Signature: - buf.WriteString("func") - writeSignature(buf, t, qf, visited) - - case *Interface: - // We write the source-level methods and embedded types rather - // than the actual method set since resolved method signatures - // may have non-printable cycles if parameters have anonymous - // interface types that (directly or indirectly) embed the - // current interface. For instance, consider the result type - // of m: - // - // type T interface{ - // m() interface{ T } - // } - // - buf.WriteString("interface{") - empty := true - if gcCompatibilityMode { - // print flattened interface - // (useful to compare against gc-generated interfaces) - for i, m := range t.allMethods { - if i > 0 { - buf.WriteString("; ") - } - buf.WriteString(m.name) - writeSignature(buf, m.typ.(*Signature), qf, visited) - empty = false - } - } else { - // print explicit interface methods and embedded types - for i, m := range t.methods { - if i > 0 { - buf.WriteString("; ") - } - buf.WriteString(m.name) - writeSignature(buf, m.typ.(*Signature), qf, visited) - empty = false - } - for i, typ := range t.embeddeds { - if i > 0 || len(t.methods) > 0 { - buf.WriteString("; ") - } - writeType(buf, typ, qf, visited) - empty = false - } - } - if t.allMethods == nil || len(t.methods) > len(t.allMethods) { - if !empty { - buf.WriteByte(' ') - } - buf.WriteString("/* incomplete */") - } - buf.WriteByte('}') - - case *Map: - buf.WriteString("map[") - writeType(buf, t.key, qf, visited) - buf.WriteByte(']') - writeType(buf, t.elem, qf, visited) - - case *Chan: - var s string - var parens bool - switch t.dir { - case SendRecv: - s = "chan " - // chan (<-chan T) requires parentheses - if c, _ := t.elem.(*Chan); c != nil && c.dir == RecvOnly { - parens = true - } - case SendOnly: - s = "chan<- " - case RecvOnly: - s = "<-chan " - default: - panic("unreachable") - } - buf.WriteString(s) - if parens { - buf.WriteByte('(') - } - writeType(buf, t.elem, qf, visited) - if parens { - buf.WriteByte(')') - } - - case *Named: - s := "" - if obj := t.obj; obj != nil { - if obj.pkg != nil { - writePackage(buf, obj.pkg, qf) - } - // TODO(gri): function-local named types should be displayed - // differently from named types at package level to avoid - // ambiguity. - s = obj.name - } - buf.WriteString(s) - - default: - // For externally defined implementations of Type. - buf.WriteString(t.String()) - } -} - -func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visited []Type) { - buf.WriteByte('(') - if tup != nil { - for i, v := range tup.vars { - if i > 0 { - buf.WriteString(", ") - } - if v.name != "" { - buf.WriteString(v.name) - buf.WriteByte(' ') - } - typ := v.typ - if variadic && i == len(tup.vars)-1 { - if s, ok := typ.(*Slice); ok { - buf.WriteString("...") - typ = s.elem - } else { - // special case: - // append(s, "foo"...) leads to signature func([]byte, string...) - if t, ok := typ.Underlying().(*Basic); !ok || t.kind != String { - panic("internal error: string type expected") - } - writeType(buf, typ, qf, visited) - buf.WriteString("...") - continue - } - } - writeType(buf, typ, qf, visited) - } - } - buf.WriteByte(')') -} - -// WriteSignature writes the representation of the signature sig to buf, -// without a leading "func" keyword. -// The Qualifier controls the printing of -// package-level objects, and may be nil. -func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { - writeSignature(buf, sig, qf, make([]Type, 0, 8)) -} - -func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) { - writeTuple(buf, sig.params, sig.variadic, qf, visited) - - n := sig.results.Len() - if n == 0 { - // no result - return - } - - buf.WriteByte(' ') - if n == 1 && sig.results.vars[0].name == "" { - // single unnamed result - writeType(buf, sig.results.vars[0].typ, qf, visited) - return - } - - // multiple or named result(s) - writeTuple(buf, sig.results, false, qf, visited) -} diff --git a/third_party/forked/golang/go/types/typexpr.go b/third_party/forked/golang/go/types/typexpr.go deleted file mode 100644 index e4e42e7993b..00000000000 --- a/third_party/forked/golang/go/types/typexpr.go +++ /dev/null @@ -1,722 +0,0 @@ -// Copyright 2013 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. - -// This file implements type-checking of identifiers and type expressions. - -package types - -import ( - "go/ast" - "go/constant" - "go/token" - "sort" - "strconv" -) - -// ident type-checks identifier e and initializes x with the value or type of e. -// If an error occurred, x.mode is set to invalid. -// For the meaning of def and path, see check.typ, below. -// -func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, path []*TypeName) { - x.mode = invalid - x.expr = e - - scope, obj := check.scope.LookupParent(e.Name, check.pos) - if obj == nil { - if e.Name == "_" { - check.errorf(e.Pos(), "cannot use _ as value or type") - } else { - check.errorf(e.Pos(), "undeclared name: %s", e.Name) - } - return - } - check.recordUse(e, obj) - - check.objDecl(obj, def, path) - typ := obj.Type() - assert(typ != nil) - - // The object may be dot-imported: If so, remove its package from - // the map of unused dot imports for the respective file scope. - // (This code is only needed for dot-imports. Without them, - // we only have to mark variables, see *Var case below). - if pkg := obj.Pkg(); pkg != check.pkg && pkg != nil { - delete(check.unusedDotImports[scope], pkg) - } - - switch obj := obj.(type) { - case *PkgName: - check.errorf(e.Pos(), "use of package %s not in selector", obj.name) - return - - case *Const: - check.addDeclDep(obj) - if typ == Typ[Invalid] { - return - } - if obj == universeIota { - if check.iota == nil { - check.errorf(e.Pos(), "cannot use iota outside constant declaration") - return - } - x.val = check.iota - } else { - x.val = obj.val - } - assert(x.val != nil) - x.mode = constant_ - - case *TypeName: - x.mode = typexpr - // check for cycle - // (it's ok to iterate forward because each named type appears at most once in path) - for i, prev := range path { - if prev == obj { - check.errorf(obj.pos, "illegal cycle in declaration of %s", obj.name) - // print cycle - for _, obj := range path[i:] { - check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented - } - check.errorf(obj.Pos(), "\t%s", obj.Name()) - // maintain x.mode == typexpr despite error - typ = Typ[Invalid] - break - } - } - - case *Var: - // It's ok to mark non-local variables, but ignore variables - // from other packages to avoid potential race conditions with - // dot-imported variables. - if obj.pkg == check.pkg { - obj.used = true - } - check.addDeclDep(obj) - if typ == Typ[Invalid] { - return - } - x.mode = variable - - case *Func: - check.addDeclDep(obj) - x.mode = value - - case *Builtin: - x.id = obj.id - x.mode = builtin - - case *Nil: - x.mode = value - - default: - unreachable() - } - - x.typ = typ -} - -// typExpr type-checks the type expression e and returns its type, or Typ[Invalid]. -// If def != nil, e is the type specification for the named type def, declared -// in a type declaration, and def.underlying will be set to the type of e before -// any components of e are type-checked. Path contains the path of named types -// referring to this type. -// -func (check *Checker) typExpr(e ast.Expr, def *Named, path []*TypeName) (T Type) { - if trace { - check.trace(e.Pos(), "%s", e) - check.indent++ - defer func() { - check.indent-- - check.trace(e.Pos(), "=> %s", T) - }() - } - - T = check.typExprInternal(e, def, path) - assert(isTyped(T)) - check.recordTypeAndValue(e, typexpr, T, nil) - - return -} - -func (check *Checker) typ(e ast.Expr) Type { - return check.typExpr(e, nil, nil) -} - -// funcType type-checks a function or method type. -func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast.FuncType) { - scope := NewScope(check.scope, token.NoPos, token.NoPos, "function") - scope.isFunc = true - check.recordScope(ftyp, scope) - - recvList, _ := check.collectParams(scope, recvPar, false) - params, variadic := check.collectParams(scope, ftyp.Params, true) - results, _ := check.collectParams(scope, ftyp.Results, false) - - if recvPar != nil { - // recv parameter list present (may be empty) - // spec: "The receiver is specified via an extra parameter section preceding the - // method name. That parameter section must declare a single parameter, the receiver." - var recv *Var - switch len(recvList) { - case 0: - check.error(recvPar.Pos(), "method is missing receiver") - recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below - default: - // more than one receiver - check.error(recvList[len(recvList)-1].Pos(), "method must have exactly one receiver") - fallthrough // continue with first receiver - case 1: - recv = recvList[0] - } - // spec: "The receiver type must be of the form T or *T where T is a type name." - // (ignore invalid types - error was reported before) - if t, _ := deref(recv.typ); t != Typ[Invalid] { - var err string - if T, _ := t.(*Named); T != nil { - // spec: "The type denoted by T is called the receiver base type; it must not - // be a pointer or interface type and it must be declared in the same package - // as the method." - if T.obj.pkg != check.pkg { - err = "type not defined in this package" - } else { - // TODO(gri) This is not correct if the underlying type is unknown yet. - switch u := T.underlying.(type) { - case *Basic: - // unsafe.Pointer is treated like a regular pointer - if u.kind == UnsafePointer { - err = "unsafe.Pointer" - } - case *Pointer, *Interface: - err = "pointer or interface type" - } - } - } else { - err = "basic or unnamed type" - } - if err != "" { - check.errorf(recv.pos, "invalid receiver %s (%s)", recv.typ, err) - // ok to continue - } - } - sig.recv = recv - } - - sig.scope = scope - sig.params = NewTuple(params...) - sig.results = NewTuple(results...) - sig.variadic = variadic -} - -// typExprInternal drives type checking of types. -// Must only be called by typExpr. -// -func (check *Checker) typExprInternal(e ast.Expr, def *Named, path []*TypeName) Type { - switch e := e.(type) { - case *ast.BadExpr: - // ignore - error reported before - - case *ast.Ident: - var x operand - check.ident(&x, e, def, path) - - switch x.mode { - case typexpr: - typ := x.typ - def.setUnderlying(typ) - return typ - case invalid: - // ignore - error reported before - case novalue: - check.errorf(x.pos(), "%s used as type", &x) - default: - check.errorf(x.pos(), "%s is not a type", &x) - } - - case *ast.SelectorExpr: - var x operand - check.selector(&x, e) - - switch x.mode { - case typexpr: - typ := x.typ - def.setUnderlying(typ) - return typ - case invalid: - // ignore - error reported before - case novalue: - check.errorf(x.pos(), "%s used as type", &x) - default: - check.errorf(x.pos(), "%s is not a type", &x) - } - - case *ast.ParenExpr: - return check.typExpr(e.X, def, path) - - case *ast.ArrayType: - if e.Len != nil { - typ := new(Array) - def.setUnderlying(typ) - typ.len = check.arrayLength(e.Len) - typ.elem = check.typExpr(e.Elt, nil, path) - return typ - - } else { - typ := new(Slice) - def.setUnderlying(typ) - typ.elem = check.typ(e.Elt) - return typ - } - - case *ast.StructType: - typ := new(Struct) - def.setUnderlying(typ) - check.structType(typ, e, path) - return typ - - case *ast.StarExpr: - typ := new(Pointer) - def.setUnderlying(typ) - typ.base = check.typ(e.X) - return typ - - case *ast.FuncType: - typ := new(Signature) - def.setUnderlying(typ) - check.funcType(typ, nil, e) - return typ - - case *ast.InterfaceType: - typ := new(Interface) - def.setUnderlying(typ) - check.interfaceType(typ, e, def, path) - return typ - - case *ast.MapType: - typ := new(Map) - def.setUnderlying(typ) - - typ.key = check.typ(e.Key) - typ.elem = check.typ(e.Value) - - // spec: "The comparison operators == and != must be fully defined - // for operands of the key type; thus the key type must not be a - // function, map, or slice." - // - // Delay this check because it requires fully setup types; - // it is safe to continue in any case (was issue 6667). - check.delay(func() { - if !Comparable(typ.key) { - check.errorf(e.Key.Pos(), "invalid map key type %s", typ.key) - } - }) - - return typ - - case *ast.ChanType: - typ := new(Chan) - def.setUnderlying(typ) - - dir := SendRecv - switch e.Dir { - case ast.SEND | ast.RECV: - // nothing to do - case ast.SEND: - dir = SendOnly - case ast.RECV: - dir = RecvOnly - default: - check.invalidAST(e.Pos(), "unknown channel direction %d", e.Dir) - // ok to continue - } - - typ.dir = dir - typ.elem = check.typ(e.Value) - return typ - - default: - check.errorf(e.Pos(), "%s is not a type", e) - } - - typ := Typ[Invalid] - def.setUnderlying(typ) - return typ -} - -// typeOrNil type-checks the type expression (or nil value) e -// and returns the typ of e, or nil. -// If e is neither a type nor nil, typOrNil returns Typ[Invalid]. -// -func (check *Checker) typOrNil(e ast.Expr) Type { - var x operand - check.rawExpr(&x, e, nil) - switch x.mode { - case invalid: - // ignore - error reported before - case novalue: - check.errorf(x.pos(), "%s used as type", &x) - case typexpr: - return x.typ - case value: - if x.isNil() { - return nil - } - fallthrough - default: - check.errorf(x.pos(), "%s is not a type", &x) - } - return Typ[Invalid] -} - -// arrayLength type-checks the array length expression e -// and returns the constant length >= 0, or a value < 0 -// to indicate an error (and thus an unknown length). -func (check *Checker) arrayLength(e ast.Expr) int64 { - var x operand - check.expr(&x, e) - if x.mode != constant_ { - if x.mode != invalid { - check.errorf(x.pos(), "array length %s must be constant", &x) - } - return -1 - } - if isUntyped(x.typ) || isInteger(x.typ) { - if val := constant.ToInt(x.val); val.Kind() == constant.Int { - if representableConst(val, check.conf, Typ[Int], nil) { - if n, ok := constant.Int64Val(val); ok && n >= 0 { - return n - } - check.errorf(x.pos(), "invalid array length %s", &x) - return -1 - } - } - } - check.errorf(x.pos(), "array length %s must be integer", &x) - return -1 -} - -func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, variadic bool) { - if list == nil { - return - } - - var named, anonymous bool - for i, field := range list.List { - ftype := field.Type - if t, _ := ftype.(*ast.Ellipsis); t != nil { - ftype = t.Elt - if variadicOk && i == len(list.List)-1 { - variadic = true - } else { - check.invalidAST(field.Pos(), "... not permitted") - // ignore ... and continue - } - } - typ := check.typ(ftype) - // The parser ensures that f.Tag is nil and we don't - // care if a constructed AST contains a non-nil tag. - if len(field.Names) > 0 { - // named parameter - for _, name := range field.Names { - if name.Name == "" { - check.invalidAST(name.Pos(), "anonymous parameter") - // ok to continue - } - par := NewParam(name.Pos(), check.pkg, name.Name, typ) - check.declare(scope, name, par, scope.pos) - params = append(params, par) - } - named = true - } else { - // anonymous parameter - par := NewParam(ftype.Pos(), check.pkg, "", typ) - check.recordImplicit(field, par) - params = append(params, par) - anonymous = true - } - } - - if named && anonymous { - check.invalidAST(list.Pos(), "list contains both named and anonymous parameters") - // ok to continue - } - - // For a variadic function, change the last parameter's type from T to []T. - if variadic && len(params) > 0 { - last := params[len(params)-1] - last.typ = &Slice{elem: last.typ} - } - - return -} - -func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool { - if alt := oset.insert(obj); alt != nil { - check.errorf(pos, "%s redeclared", obj.Name()) - check.reportAltDecl(alt) - return false - } - return true -} - -func (check *Checker) interfaceType(iface *Interface, ityp *ast.InterfaceType, def *Named, path []*TypeName) { - // empty interface: common case - if ityp.Methods == nil { - return - } - - // The parser ensures that field tags are nil and we don't - // care if a constructed AST contains non-nil tags. - - // use named receiver type if available (for better error messages) - var recvTyp Type = iface - if def != nil { - recvTyp = def - } - - // Phase 1: Collect explicitly declared methods, the corresponding - // signature (AST) expressions, and the list of embedded - // type (AST) expressions. Do not resolve signatures or - // embedded types yet to avoid cycles referring to this - // interface. - - var ( - mset objset - signatures []ast.Expr // list of corresponding method signatures - embedded []ast.Expr // list of embedded types - ) - for _, f := range ityp.Methods.List { - if len(f.Names) > 0 { - // The parser ensures that there's only one method - // and we don't care if a constructed AST has more. - name := f.Names[0] - pos := name.Pos() - // spec: "As with all method sets, in an interface type, - // each method must have a unique non-blank name." - if name.Name == "_" { - check.errorf(pos, "invalid method name _") - continue - } - // Don't type-check signature yet - use an - // empty signature now and update it later. - // Since we know the receiver, set it up now - // (required to avoid crash in ptrRecv; see - // e.g. test case for issue 6638). - // TODO(gri) Consider marking methods signatures - // as incomplete, for better error messages. See - // also the T4 and T5 tests in testdata/cycles2.src. - sig := new(Signature) - sig.recv = NewVar(pos, check.pkg, "", recvTyp) - m := NewFunc(pos, check.pkg, name.Name, sig) - if check.declareInSet(&mset, pos, m) { - iface.methods = append(iface.methods, m) - iface.allMethods = append(iface.allMethods, m) - signatures = append(signatures, f.Type) - check.recordDef(name, m) - } - } else { - // embedded type - embedded = append(embedded, f.Type) - } - } - - // Phase 2: Resolve embedded interfaces. Because an interface must not - // embed itself (directly or indirectly), each embedded interface - // can be fully resolved without depending on any method of this - // interface (if there is a cycle or another error, the embedded - // type resolves to an invalid type and is ignored). - // In particular, the list of methods for each embedded interface - // must be complete (it cannot depend on this interface), and so - // those methods can be added to the list of all methods of this - // interface. - - for _, e := range embedded { - pos := e.Pos() - typ := check.typExpr(e, nil, path) - // Determine underlying embedded (possibly incomplete) type - // by following its forward chain. - named, _ := typ.(*Named) - under := underlying(named) - embed, _ := under.(*Interface) - if embed == nil { - if typ != Typ[Invalid] { - check.errorf(pos, "%s is not an interface", typ) - } - continue - } - iface.embeddeds = append(iface.embeddeds, named) - // collect embedded methods - if embed.allMethods == nil { - check.errorf(pos, "internal error: incomplete embedded interface %s (issue #18395)", named) - } - for _, m := range embed.allMethods { - if check.declareInSet(&mset, pos, m) { - iface.allMethods = append(iface.allMethods, m) - } - } - } - - // Phase 3: At this point all methods have been collected for this interface. - // It is now safe to type-check the signatures of all explicitly - // declared methods, even if they refer to this interface via a cycle - // and embed the methods of this interface in a parameter of interface - // type. - - for i, m := range iface.methods { - expr := signatures[i] - typ := check.typ(expr) - sig, _ := typ.(*Signature) - if sig == nil { - if typ != Typ[Invalid] { - check.invalidAST(expr.Pos(), "%s is not a method signature", typ) - } - continue // keep method with empty method signature - } - // update signature, but keep recv that was set up before - old := m.typ.(*Signature) - sig.recv = old.recv - *old = *sig // update signature (don't replace it!) - } - - // TODO(gri) The list of explicit methods is only sorted for now to - // produce the same Interface as NewInterface. We may be able to - // claim source order in the future. Revisit. - sort.Sort(byUniqueMethodName(iface.methods)) - - // TODO(gri) The list of embedded types is only sorted for now to - // produce the same Interface as NewInterface. We may be able to - // claim source order in the future. Revisit. - sort.Sort(byUniqueTypeName(iface.embeddeds)) - - if iface.allMethods == nil { - iface.allMethods = make([]*Func, 0) // mark interface as complete - } else { - sort.Sort(byUniqueMethodName(iface.allMethods)) - } -} - -// byUniqueTypeName named type lists can be sorted by their unique type names. -type byUniqueTypeName []*Named - -func (a byUniqueTypeName) Len() int { return len(a) } -func (a byUniqueTypeName) Less(i, j int) bool { return a[i].obj.Id() < a[j].obj.Id() } -func (a byUniqueTypeName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -// byUniqueMethodName method lists can be sorted by their unique method names. -type byUniqueMethodName []*Func - -func (a byUniqueMethodName) Len() int { return len(a) } -func (a byUniqueMethodName) Less(i, j int) bool { return a[i].Id() < a[j].Id() } -func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -func (check *Checker) tag(t *ast.BasicLit) string { - if t != nil { - if t.Kind == token.STRING { - if val, err := strconv.Unquote(t.Value); err == nil { - return val - } - } - check.invalidAST(t.Pos(), "incorrect tag syntax: %q", t.Value) - } - return "" -} - -func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeName) { - list := e.Fields - if list == nil { - return - } - - // struct fields and tags - var fields []*Var - var tags []string - - // for double-declaration checks - var fset objset - - // current field typ and tag - var typ Type - var tag string - add := func(ident *ast.Ident, anonymous bool, pos token.Pos) { - if tag != "" && tags == nil { - tags = make([]string, len(fields)) - } - if tags != nil { - tags = append(tags, tag) - } - - name := ident.Name - fld := NewField(pos, check.pkg, name, typ, anonymous) - // spec: "Within a struct, non-blank field names must be unique." - if name == "_" || check.declareInSet(&fset, pos, fld) { - fields = append(fields, fld) - check.recordDef(ident, fld) - } - } - - for _, f := range list.List { - typ = check.typExpr(f.Type, nil, path) - tag = check.tag(f.Tag) - if len(f.Names) > 0 { - // named fields - for _, name := range f.Names { - add(name, false, name.Pos()) - } - } else { - // anonymous field - // spec: "An embedded type must be specified as a type name T or as a pointer - // to a non-interface type name *T, and T itself may not be a pointer type." - pos := f.Type.Pos() - name := anonymousFieldIdent(f.Type) - if name == nil { - check.invalidAST(pos, "anonymous field type %s has no name", f.Type) - continue - } - t, isPtr := deref(typ) - // Because we have a name, typ must be of the form T or *T, where T is the name - // of a (named or alias) type, and t (= deref(typ)) must be the type of T. - switch t := t.Underlying().(type) { - case *Basic: - if t == Typ[Invalid] { - // error was reported before - continue - } - - // unsafe.Pointer is treated like a regular pointer - if t.kind == UnsafePointer { - check.errorf(pos, "anonymous field type cannot be unsafe.Pointer") - continue - } - - case *Pointer: - check.errorf(pos, "anonymous field type cannot be a pointer") - continue - - case *Interface: - if isPtr { - check.errorf(pos, "anonymous field type cannot be a pointer to an interface") - continue - } - } - add(name, true, pos) - } - } - - styp.fields = fields - styp.tags = tags -} - -func anonymousFieldIdent(e ast.Expr) *ast.Ident { - switch e := e.(type) { - case *ast.Ident: - return e - case *ast.StarExpr: - // *T is valid, but **T is not - if _, ok := e.X.(*ast.StarExpr); !ok { - return anonymousFieldIdent(e.X) - } - case *ast.SelectorExpr: - return e.Sel - } - return nil // invalid anonymous field -} diff --git a/third_party/forked/golang/go/types/universe.go b/third_party/forked/golang/go/types/universe.go deleted file mode 100644 index 07d7078ae25..00000000000 --- a/third_party/forked/golang/go/types/universe.go +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright 2011 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. - -// This file sets up the universe scope and the unsafe package. - -package types - -import ( - "go/constant" - "go/token" - "strings" -) - -var ( - Universe *Scope - Unsafe *Package - universeIota *Const - universeByte *Basic // uint8 alias, but has name "byte" - universeRune *Basic // int32 alias, but has name "rune" -) - -// Typ contains the predeclared *Basic types indexed by their -// corresponding BasicKind. -// -// The *Basic type for Typ[Byte] will have the name "uint8". -// Use Universe.Lookup("byte").Type() to obtain the specific -// alias basic type named "byte" (and analogous for "rune"). -var Typ = []*Basic{ - Invalid: {Invalid, 0, "invalid type"}, - - Bool: {Bool, IsBoolean, "bool"}, - Int: {Int, IsInteger, "int"}, - Int8: {Int8, IsInteger, "int8"}, - Int16: {Int16, IsInteger, "int16"}, - Int32: {Int32, IsInteger, "int32"}, - Int64: {Int64, IsInteger, "int64"}, - Uint: {Uint, IsInteger | IsUnsigned, "uint"}, - Uint8: {Uint8, IsInteger | IsUnsigned, "uint8"}, - Uint16: {Uint16, IsInteger | IsUnsigned, "uint16"}, - Uint32: {Uint32, IsInteger | IsUnsigned, "uint32"}, - Uint64: {Uint64, IsInteger | IsUnsigned, "uint64"}, - Uintptr: {Uintptr, IsInteger | IsUnsigned, "uintptr"}, - Float32: {Float32, IsFloat, "float32"}, - Float64: {Float64, IsFloat, "float64"}, - Complex64: {Complex64, IsComplex, "complex64"}, - Complex128: {Complex128, IsComplex, "complex128"}, - String: {String, IsString, "string"}, - UnsafePointer: {UnsafePointer, 0, "Pointer"}, - - UntypedBool: {UntypedBool, IsBoolean | IsUntyped, "untyped bool"}, - UntypedInt: {UntypedInt, IsInteger | IsUntyped, "untyped int"}, - UntypedRune: {UntypedRune, IsInteger | IsUntyped, "untyped rune"}, - UntypedFloat: {UntypedFloat, IsFloat | IsUntyped, "untyped float"}, - UntypedComplex: {UntypedComplex, IsComplex | IsUntyped, "untyped complex"}, - UntypedString: {UntypedString, IsString | IsUntyped, "untyped string"}, - UntypedNil: {UntypedNil, IsUntyped, "untyped nil"}, -} - -var aliases = [...]*Basic{ - {Byte, IsInteger | IsUnsigned, "byte"}, - {Rune, IsInteger, "rune"}, -} - -func defPredeclaredTypes() { - for _, t := range Typ { - def(NewTypeName(token.NoPos, nil, t.name, t)) - } - for _, t := range aliases { - def(NewTypeName(token.NoPos, nil, t.name, t)) - } - - // Error has a nil package in its qualified name since it is in no package - res := NewVar(token.NoPos, nil, "", Typ[String]) - sig := &Signature{results: NewTuple(res)} - err := NewFunc(token.NoPos, nil, "Error", sig) - typ := &Named{underlying: NewInterface([]*Func{err}, nil).Complete()} - sig.recv = NewVar(token.NoPos, nil, "", typ) - def(NewTypeName(token.NoPos, nil, "error", typ)) -} - -var predeclaredConsts = [...]struct { - name string - kind BasicKind - val constant.Value -}{ - {"true", UntypedBool, constant.MakeBool(true)}, - {"false", UntypedBool, constant.MakeBool(false)}, - {"iota", UntypedInt, constant.MakeInt64(0)}, -} - -func defPredeclaredConsts() { - for _, c := range predeclaredConsts { - def(NewConst(token.NoPos, nil, c.name, Typ[c.kind], c.val)) - } -} - -func defPredeclaredNil() { - def(&Nil{object{name: "nil", typ: Typ[UntypedNil]}}) -} - -// A builtinId is the id of a builtin function. -type builtinId int - -const ( - // universe scope - _Append builtinId = iota - _Cap - _Close - _Complex - _Copy - _Delete - _Imag - _Len - _Make - _New - _Panic - _Print - _Println - _Real - _Recover - - // package unsafe - _Alignof - _Offsetof - _Sizeof - - // testing support - _Assert - _Trace -) - -var predeclaredFuncs = [...]struct { - name string - nargs int - variadic bool - kind exprKind -}{ - _Append: {"append", 1, true, expression}, - _Cap: {"cap", 1, false, expression}, - _Close: {"close", 1, false, statement}, - _Complex: {"complex", 2, false, expression}, - _Copy: {"copy", 2, false, statement}, - _Delete: {"delete", 2, false, statement}, - _Imag: {"imag", 1, false, expression}, - _Len: {"len", 1, false, expression}, - _Make: {"make", 1, true, expression}, - _New: {"new", 1, false, expression}, - _Panic: {"panic", 1, false, statement}, - _Print: {"print", 0, true, statement}, - _Println: {"println", 0, true, statement}, - _Real: {"real", 1, false, expression}, - _Recover: {"recover", 0, false, statement}, - - _Alignof: {"Alignof", 1, false, expression}, - _Offsetof: {"Offsetof", 1, false, expression}, - _Sizeof: {"Sizeof", 1, false, expression}, - - _Assert: {"assert", 1, false, statement}, - _Trace: {"trace", 0, true, statement}, -} - -func defPredeclaredFuncs() { - for i := range predeclaredFuncs { - id := builtinId(i) - if id == _Assert || id == _Trace { - continue // only define these in testing environment - } - def(newBuiltin(id)) - } -} - -// DefPredeclaredTestFuncs defines the assert and trace built-ins. -// These built-ins are intended for debugging and testing of this -// package only. -func DefPredeclaredTestFuncs() { - if Universe.Lookup("assert") != nil { - return // already defined - } - def(newBuiltin(_Assert)) - def(newBuiltin(_Trace)) -} - -func init() { - Universe = NewScope(nil, token.NoPos, token.NoPos, "universe") - Unsafe = NewPackage("unsafe", "unsafe") - Unsafe.complete = true - - defPredeclaredTypes() - defPredeclaredConsts() - defPredeclaredNil() - defPredeclaredFuncs() - - universeIota = Universe.Lookup("iota").(*Const) - universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic) - universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic) -} - -// Objects with names containing blanks are internal and not entered into -// a scope. Objects with exported names are inserted in the unsafe package -// scope; other objects are inserted in the universe scope. -// -func def(obj Object) { - name := obj.Name() - if strings.Contains(name, " ") { - return // nothing to do - } - // fix Obj link for named types - if typ, ok := obj.Type().(*Named); ok { - typ.obj = obj.(*TypeName) - } - // exported identifiers go into package unsafe - scope := Universe - if obj.Exported() { - scope = Unsafe.scope - // set Pkg field - switch obj := obj.(type) { - case *TypeName: - obj.pkg = Unsafe - case *Builtin: - obj.pkg = Unsafe - default: - unreachable() - } - } - if scope.Insert(obj) != nil { - panic("internal error: double declaration") - } -}