Home | History | Annotate | Download | only in types
      1 // Copyright 2012 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // Package types declares the data types and implements
      6 // the algorithms for type-checking of Go packages. Use
      7 // Config.Check to invoke the type checker for a package.
      8 // Alternatively, create a new type checker with NewChecker
      9 // and invoke it incrementally by calling Checker.Files.
     10 //
     11 // Type-checking consists of several interdependent phases:
     12 //
     13 // Name resolution maps each identifier (ast.Ident) in the program to the
     14 // language object (Object) it denotes.
     15 // Use Info.{Defs,Uses,Implicits} for the results of name resolution.
     16 //
     17 // Constant folding computes the exact constant value (constant.Value)
     18 // for every expression (ast.Expr) that is a compile-time constant.
     19 // Use Info.Types[expr].Value for the results of constant folding.
     20 //
     21 // Type inference computes the type (Type) of every expression (ast.Expr)
     22 // and checks for compliance with the language specification.
     23 // Use Info.Types[expr].Type for the results of type inference.
     24 //
     25 // For a tutorial, see https://golang.org/s/types-tutorial.
     26 //
     27 package types // import "go/types"
     28 
     29 import (
     30 	"bytes"
     31 	"fmt"
     32 	"go/ast"
     33 	"go/constant"
     34 	"go/token"
     35 )
     36 
     37 // An Error describes a type-checking error; it implements the error interface.
     38 // A "soft" error is an error that still permits a valid interpretation of a
     39 // package (such as "unused variable"); "hard" errors may lead to unpredictable
     40 // behavior if ignored.
     41 type Error struct {
     42 	Fset *token.FileSet // file set for interpretation of Pos
     43 	Pos  token.Pos      // error position
     44 	Msg  string         // error message
     45 	Soft bool           // if set, error is "soft"
     46 }
     47 
     48 // Error returns an error string formatted as follows:
     49 // filename:line:column: message
     50 func (err Error) Error() string {
     51 	return fmt.Sprintf("%s: %s", err.Fset.Position(err.Pos), err.Msg)
     52 }
     53 
     54 // An Importer resolves import paths to Packages.
     55 //
     56 // CAUTION: This interface does not support the import of locally
     57 // vendored packages. See https://golang.org/s/go15vendor.
     58 // If possible, external implementations should implement ImporterFrom.
     59 type Importer interface {
     60 	// Import returns the imported package for the given import
     61 	// path, or an error if the package couldn't be imported.
     62 	// Two calls to Import with the same path return the same
     63 	// package.
     64 	Import(path string) (*Package, error)
     65 }
     66 
     67 // ImportMode is reserved for future use.
     68 type ImportMode int
     69 
     70 // An ImporterFrom resolves import paths to packages; it
     71 // supports vendoring per https://golang.org/s/go15vendor.
     72 // Use go/importer to obtain an ImporterFrom implementation.
     73 type ImporterFrom interface {
     74 	// Importer is present for backward-compatibility. Calling
     75 	// Import(path) is the same as calling ImportFrom(path, "", 0);
     76 	// i.e., locally vendored packages may not be found.
     77 	// The types package does not call Import if an ImporterFrom
     78 	// is present.
     79 	Importer
     80 
     81 	// ImportFrom returns the imported package for the given import
     82 	// path when imported by the package in srcDir, or an error
     83 	// if the package couldn't be imported. The mode value must
     84 	// be 0; it is reserved for future use.
     85 	// Two calls to ImportFrom with the same path and srcDir return
     86 	// the same package.
     87 	ImportFrom(path, srcDir string, mode ImportMode) (*Package, error)
     88 }
     89 
     90 // A Config specifies the configuration for type checking.
     91 // The zero value for Config is a ready-to-use default configuration.
     92 type Config struct {
     93 	// If IgnoreFuncBodies is set, function bodies are not
     94 	// type-checked.
     95 	IgnoreFuncBodies bool
     96 
     97 	// If FakeImportC is set, `import "C"` (for packages requiring Cgo)
     98 	// declares an empty "C" package and errors are omitted for qualified
     99 	// identifiers referring to package C (which won't find an object).
    100 	// This feature is intended for the standard library cmd/api tool.
    101 	//
    102 	// Caution: Effects may be unpredictable due to follow-up errors.
    103 	//          Do not use casually!
    104 	FakeImportC bool
    105 
    106 	// If Error != nil, it is called with each error found
    107 	// during type checking; err has dynamic type Error.
    108 	// Secondary errors (for instance, to enumerate all types
    109 	// involved in an invalid recursive type declaration) have
    110 	// error strings that start with a '\t' character.
    111 	// If Error == nil, type-checking stops with the first
    112 	// error found.
    113 	Error func(err error)
    114 
    115 	// An importer is used to import packages referred to from
    116 	// import declarations.
    117 	// If the installed importer implements ImporterFrom, the type
    118 	// checker calls ImportFrom instead of Import.
    119 	// The type checker reports an error if an importer is needed
    120 	// but none was installed.
    121 	Importer Importer
    122 
    123 	// If Sizes != nil, it provides the sizing functions for package unsafe.
    124 	// Otherwise &StdSizes{WordSize: 8, MaxAlign: 8} is used instead.
    125 	Sizes Sizes
    126 
    127 	// If DisableUnusedImportCheck is set, packages are not checked
    128 	// for unused imports.
    129 	DisableUnusedImportCheck bool
    130 }
    131 
    132 // Info holds result type information for a type-checked package.
    133 // Only the information for which a map is provided is collected.
    134 // If the package has type errors, the collected information may
    135 // be incomplete.
    136 type Info struct {
    137 	// Types maps expressions to their types, and for constant
    138 	// expressions, also their values. Invalid expressions are
    139 	// omitted.
    140 	//
    141 	// For (possibly parenthesized) identifiers denoting built-in
    142 	// functions, the recorded signatures are call-site specific:
    143 	// if the call result is not a constant, the recorded type is
    144 	// an argument-specific signature. Otherwise, the recorded type
    145 	// is invalid.
    146 	//
    147 	// The Types map does not record the type of every identifier,
    148 	// only those that appear where an arbitrary expression is
    149 	// permitted. For instance, the identifier f in a selector
    150 	// expression x.f is found only in the Selections map, the
    151 	// identifier z in a variable declaration 'var z int' is found
    152 	// only in the Defs map, and identifiers denoting packages in
    153 	// qualified identifiers are collected in the Uses map.
    154 	Types map[ast.Expr]TypeAndValue
    155 
    156 	// Defs maps identifiers to the objects they define (including
    157 	// package names, dots "." of dot-imports, and blank "_" identifiers).
    158 	// For identifiers that do not denote objects (e.g., the package name
    159 	// in package clauses, or symbolic variables t in t := x.(type) of
    160 	// type switch headers), the corresponding objects are nil.
    161 	//
    162 	// For an anonymous field, Defs returns the field *Var it defines.
    163 	//
    164 	// Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos()
    165 	Defs map[*ast.Ident]Object
    166 
    167 	// Uses maps identifiers to the objects they denote.
    168 	//
    169 	// For an anonymous field, Uses returns the *TypeName it denotes.
    170 	//
    171 	// Invariant: Uses[id].Pos() != id.Pos()
    172 	Uses map[*ast.Ident]Object
    173 
    174 	// Implicits maps nodes to their implicitly declared objects, if any.
    175 	// The following node and object types may appear:
    176 	//
    177 	//	node               declared object
    178 	//
    179 	//	*ast.ImportSpec    *PkgName for dot-imports and imports without renames
    180 	//	*ast.CaseClause    type-specific *Var for each type switch case clause (incl. default)
    181 	//      *ast.Field         anonymous parameter *Var
    182 	//
    183 	Implicits map[ast.Node]Object
    184 
    185 	// Selections maps selector expressions (excluding qualified identifiers)
    186 	// to their corresponding selections.
    187 	Selections map[*ast.SelectorExpr]*Selection
    188 
    189 	// Scopes maps ast.Nodes to the scopes they define. Package scopes are not
    190 	// associated with a specific node but with all files belonging to a package.
    191 	// Thus, the package scope can be found in the type-checked Package object.
    192 	// Scopes nest, with the Universe scope being the outermost scope, enclosing
    193 	// the package scope, which contains (one or more) files scopes, which enclose
    194 	// function scopes which in turn enclose statement and function literal scopes.
    195 	// Note that even though package-level functions are declared in the package
    196 	// scope, the function scopes are embedded in the file scope of the file
    197 	// containing the function declaration.
    198 	//
    199 	// The following node types may appear in Scopes:
    200 	//
    201 	//	*ast.File
    202 	//	*ast.FuncType
    203 	//	*ast.BlockStmt
    204 	//	*ast.IfStmt
    205 	//	*ast.SwitchStmt
    206 	//	*ast.TypeSwitchStmt
    207 	//	*ast.CaseClause
    208 	//	*ast.CommClause
    209 	//	*ast.ForStmt
    210 	//	*ast.RangeStmt
    211 	//
    212 	Scopes map[ast.Node]*Scope
    213 
    214 	// InitOrder is the list of package-level initializers in the order in which
    215 	// they must be executed. Initializers referring to variables related by an
    216 	// initialization dependency appear in topological order, the others appear
    217 	// in source order. Variables without an initialization expression do not
    218 	// appear in this list.
    219 	InitOrder []*Initializer
    220 }
    221 
    222 // TypeOf returns the type of expression e, or nil if not found.
    223 // Precondition: the Types, Uses and Defs maps are populated.
    224 //
    225 func (info *Info) TypeOf(e ast.Expr) Type {
    226 	if t, ok := info.Types[e]; ok {
    227 		return t.Type
    228 	}
    229 	if id, _ := e.(*ast.Ident); id != nil {
    230 		if obj := info.ObjectOf(id); obj != nil {
    231 			return obj.Type()
    232 		}
    233 	}
    234 	return nil
    235 }
    236 
    237 // ObjectOf returns the object denoted by the specified id,
    238 // or nil if not found.
    239 //
    240 // If id is an anonymous struct field, ObjectOf returns the field (*Var)
    241 // it uses, not the type (*TypeName) it defines.
    242 //
    243 // Precondition: the Uses and Defs maps are populated.
    244 //
    245 func (info *Info) ObjectOf(id *ast.Ident) Object {
    246 	if obj, _ := info.Defs[id]; obj != nil {
    247 		return obj
    248 	}
    249 	return info.Uses[id]
    250 }
    251 
    252 // TypeAndValue reports the type and value (for constants)
    253 // of the corresponding expression.
    254 type TypeAndValue struct {
    255 	mode  operandMode
    256 	Type  Type
    257 	Value constant.Value
    258 }
    259 
    260 // TODO(gri) Consider eliminating the IsVoid predicate. Instead, report
    261 // "void" values as regular values but with the empty tuple type.
    262 
    263 // IsVoid reports whether the corresponding expression
    264 // is a function call without results.
    265 func (tv TypeAndValue) IsVoid() bool {
    266 	return tv.mode == novalue
    267 }
    268 
    269 // IsType reports whether the corresponding expression specifies a type.
    270 func (tv TypeAndValue) IsType() bool {
    271 	return tv.mode == typexpr
    272 }
    273 
    274 // IsBuiltin reports whether the corresponding expression denotes
    275 // a (possibly parenthesized) built-in function.
    276 func (tv TypeAndValue) IsBuiltin() bool {
    277 	return tv.mode == builtin
    278 }
    279 
    280 // IsValue reports whether the corresponding expression is a value.
    281 // Builtins are not considered values. Constant values have a non-
    282 // nil Value.
    283 func (tv TypeAndValue) IsValue() bool {
    284 	switch tv.mode {
    285 	case constant_, variable, mapindex, value, commaok:
    286 		return true
    287 	}
    288 	return false
    289 }
    290 
    291 // IsNil reports whether the corresponding expression denotes the
    292 // predeclared value nil.
    293 func (tv TypeAndValue) IsNil() bool {
    294 	return tv.mode == value && tv.Type == Typ[UntypedNil]
    295 }
    296 
    297 // Addressable reports whether the corresponding expression
    298 // is addressable (https://golang.org/ref/spec#Address_operators).
    299 func (tv TypeAndValue) Addressable() bool {
    300 	return tv.mode == variable
    301 }
    302 
    303 // Assignable reports whether the corresponding expression
    304 // is assignable to (provided a value of the right type).
    305 func (tv TypeAndValue) Assignable() bool {
    306 	return tv.mode == variable || tv.mode == mapindex
    307 }
    308 
    309 // HasOk reports whether the corresponding expression may be
    310 // used on the lhs of a comma-ok assignment.
    311 func (tv TypeAndValue) HasOk() bool {
    312 	return tv.mode == commaok || tv.mode == mapindex
    313 }
    314 
    315 // An Initializer describes a package-level variable, or a list of variables in case
    316 // of a multi-valued initialization expression, and the corresponding initialization
    317 // expression.
    318 type Initializer struct {
    319 	Lhs []*Var // var Lhs = Rhs
    320 	Rhs ast.Expr
    321 }
    322 
    323 func (init *Initializer) String() string {
    324 	var buf bytes.Buffer
    325 	for i, lhs := range init.Lhs {
    326 		if i > 0 {
    327 			buf.WriteString(", ")
    328 		}
    329 		buf.WriteString(lhs.Name())
    330 	}
    331 	buf.WriteString(" = ")
    332 	WriteExpr(&buf, init.Rhs)
    333 	return buf.String()
    334 }
    335 
    336 // Check type-checks a package and returns the resulting package object and
    337 // the first error if any. Additionally, if info != nil, Check populates each
    338 // of the non-nil maps in the Info struct.
    339 //
    340 // The package is marked as complete if no errors occurred, otherwise it is
    341 // incomplete. See Config.Error for controlling behavior in the presence of
    342 // errors.
    343 //
    344 // The package is specified by a list of *ast.Files and corresponding
    345 // file set, and the package path the package is identified with.
    346 // The clean path must not be empty or dot (".").
    347 func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, info *Info) (*Package, error) {
    348 	pkg := NewPackage(path, "")
    349 	return pkg, NewChecker(conf, fset, pkg, info).Files(files)
    350 }
    351 
    352 // AssertableTo reports whether a value of type V can be asserted to have type T.
    353 func AssertableTo(V *Interface, T Type) bool {
    354 	m, _ := assertableTo(V, T)
    355 	return m == nil
    356 }
    357 
    358 // AssignableTo reports whether a value of type V is assignable to a variable of type T.
    359 func AssignableTo(V, T Type) bool {
    360 	x := operand{mode: value, typ: V}
    361 	return x.assignableTo(nil, T, nil) // config not needed for non-constant x
    362 }
    363 
    364 // ConvertibleTo reports whether a value of type V is convertible to a value of type T.
    365 func ConvertibleTo(V, T Type) bool {
    366 	x := operand{mode: value, typ: V}
    367 	return x.convertibleTo(nil, T) // config not needed for non-constant x
    368 }
    369 
    370 // Implements reports whether type V implements interface T.
    371 func Implements(V Type, T *Interface) bool {
    372 	f, _ := MissingMethod(V, T, true)
    373 	return f == nil
    374 }
    375