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