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// 27package types 28 29import ( 30 "bytes" 31 "fmt" 32 "go/ast" 33 "go/constant" 34 "go/token" 35 _ "unsafe" // for go:linkname 36) 37 38// An Error describes a type-checking error; it implements the error interface. 39// A "soft" error is an error that still permits a valid interpretation of a 40// package (such as "unused variable"); "hard" errors may lead to unpredictable 41// behavior if ignored. 42type Error struct { 43 Fset *token.FileSet // file set for interpretation of Pos 44 Pos token.Pos // error position 45 Msg string // error message 46 Soft bool // if set, error is "soft" 47 48 // go116code is a future API, unexported as the set of error codes is large 49 // and likely to change significantly during experimentation. Tools wishing 50 // to preview this feature may read go116code using reflection (see 51 // errorcodes_test.go), but beware that there is no guarantee of future 52 // compatibility. 53 go116code errorCode 54 go116start token.Pos 55 go116end token.Pos 56} 57 58// Error returns an error string formatted as follows: 59// filename:line:column: message 60func (err Error) Error() string { 61 return fmt.Sprintf("%s: %s", err.Fset.Position(err.Pos), err.Msg) 62} 63 64// An Importer resolves import paths to Packages. 65// 66// CAUTION: This interface does not support the import of locally 67// vendored packages. See https://golang.org/s/go15vendor. 68// If possible, external implementations should implement ImporterFrom. 69type Importer interface { 70 // Import returns the imported package for the given import path. 71 // The semantics is like for ImporterFrom.ImportFrom except that 72 // dir and mode are ignored (since they are not present). 73 Import(path string) (*Package, error) 74} 75 76// ImportMode is reserved for future use. 77type ImportMode int 78 79// An ImporterFrom resolves import paths to packages; it 80// supports vendoring per https://golang.org/s/go15vendor. 81// Use go/importer to obtain an ImporterFrom implementation. 82type ImporterFrom interface { 83 // Importer is present for backward-compatibility. Calling 84 // Import(path) is the same as calling ImportFrom(path, "", 0); 85 // i.e., locally vendored packages may not be found. 86 // The types package does not call Import if an ImporterFrom 87 // is present. 88 Importer 89 90 // ImportFrom returns the imported package for the given import 91 // path when imported by a package file located in dir. 92 // If the import failed, besides returning an error, ImportFrom 93 // is encouraged to cache and return a package anyway, if one 94 // was created. This will reduce package inconsistencies and 95 // follow-on type checker errors due to the missing package. 96 // The mode value must be 0; it is reserved for future use. 97 // Two calls to ImportFrom with the same path and dir must 98 // return the same package. 99 ImportFrom(path, dir string, mode ImportMode) (*Package, error) 100} 101 102// A Config specifies the configuration for type checking. 103// The zero value for Config is a ready-to-use default configuration. 104type Config struct { 105 // goVersion describes the accepted Go language version. The string 106 // must follow the format "go%d.%d" (e.g. "go1.12") or it must be 107 // empty; an empty string indicates the latest language version. 108 // If the format is invalid, invoking the type checker will cause a 109 // panic. 110 goVersion string 111 112 // If IgnoreFuncBodies is set, function bodies are not 113 // type-checked. 114 IgnoreFuncBodies bool 115 116 // If FakeImportC is set, `import "C"` (for packages requiring Cgo) 117 // declares an empty "C" package and errors are omitted for qualified 118 // identifiers referring to package C (which won't find an object). 119 // This feature is intended for the standard library cmd/api tool. 120 // 121 // Caution: Effects may be unpredictable due to follow-on errors. 122 // Do not use casually! 123 FakeImportC bool 124 125 // If go115UsesCgo is set, the type checker expects the 126 // _cgo_gotypes.go file generated by running cmd/cgo to be 127 // provided as a package source file. Qualified identifiers 128 // referring to package C will be resolved to cgo-provided 129 // declarations within _cgo_gotypes.go. 130 // 131 // It is an error to set both FakeImportC and go115UsesCgo. 132 go115UsesCgo bool 133 134 // If Error != nil, it is called with each error found 135 // during type checking; err has dynamic type Error. 136 // Secondary errors (for instance, to enumerate all types 137 // involved in an invalid recursive type declaration) have 138 // error strings that start with a '\t' character. 139 // If Error == nil, type-checking stops with the first 140 // error found. 141 Error func(err error) 142 143 // An importer is used to import packages referred to from 144 // import declarations. 145 // If the installed importer implements ImporterFrom, the type 146 // checker calls ImportFrom instead of Import. 147 // The type checker reports an error if an importer is needed 148 // but none was installed. 149 Importer Importer 150 151 // If Sizes != nil, it provides the sizing functions for package unsafe. 152 // Otherwise SizesFor("gc", "amd64") is used instead. 153 Sizes Sizes 154 155 // If DisableUnusedImportCheck is set, packages are not checked 156 // for unused imports. 157 DisableUnusedImportCheck bool 158} 159 160//go:linkname srcimporter_setUsesCgo 161func srcimporter_setUsesCgo(conf *Config) { 162 conf.go115UsesCgo = true 163} 164 165// The Info struct is found in api_notypeparams.go and api_typeparams.go. 166 167// TypeOf returns the type of expression e, or nil if not found. 168// Precondition: the Types, Uses and Defs maps are populated. 169// 170func (info *Info) TypeOf(e ast.Expr) Type { 171 if t, ok := info.Types[e]; ok { 172 return t.Type 173 } 174 if id, _ := e.(*ast.Ident); id != nil { 175 if obj := info.ObjectOf(id); obj != nil { 176 return obj.Type() 177 } 178 } 179 return nil 180} 181 182// ObjectOf returns the object denoted by the specified id, 183// or nil if not found. 184// 185// If id is an embedded struct field, ObjectOf returns the field (*Var) 186// it defines, not the type (*TypeName) it uses. 187// 188// Precondition: the Uses and Defs maps are populated. 189// 190func (info *Info) ObjectOf(id *ast.Ident) Object { 191 if obj := info.Defs[id]; obj != nil { 192 return obj 193 } 194 return info.Uses[id] 195} 196 197// TypeAndValue reports the type and value (for constants) 198// of the corresponding expression. 199type TypeAndValue struct { 200 mode operandMode 201 Type Type 202 Value constant.Value 203} 204 205// IsVoid reports whether the corresponding expression 206// is a function call without results. 207func (tv TypeAndValue) IsVoid() bool { 208 return tv.mode == novalue 209} 210 211// IsType reports whether the corresponding expression specifies a type. 212func (tv TypeAndValue) IsType() bool { 213 return tv.mode == typexpr 214} 215 216// IsBuiltin reports whether the corresponding expression denotes 217// a (possibly parenthesized) built-in function. 218func (tv TypeAndValue) IsBuiltin() bool { 219 return tv.mode == builtin 220} 221 222// IsValue reports whether the corresponding expression is a value. 223// Builtins are not considered values. Constant values have a non- 224// nil Value. 225func (tv TypeAndValue) IsValue() bool { 226 switch tv.mode { 227 case constant_, variable, mapindex, value, commaok, commaerr: 228 return true 229 } 230 return false 231} 232 233// IsNil reports whether the corresponding expression denotes the 234// predeclared value nil. 235func (tv TypeAndValue) IsNil() bool { 236 return tv.mode == value && tv.Type == Typ[UntypedNil] 237} 238 239// Addressable reports whether the corresponding expression 240// is addressable (https://golang.org/ref/spec#Address_operators). 241func (tv TypeAndValue) Addressable() bool { 242 return tv.mode == variable 243} 244 245// Assignable reports whether the corresponding expression 246// is assignable to (provided a value of the right type). 247func (tv TypeAndValue) Assignable() bool { 248 return tv.mode == variable || tv.mode == mapindex 249} 250 251// HasOk reports whether the corresponding expression may be 252// used on the rhs of a comma-ok assignment. 253func (tv TypeAndValue) HasOk() bool { 254 return tv.mode == commaok || tv.mode == mapindex 255} 256 257// _Inferred reports the _Inferred type arguments and signature 258// for a parameterized function call that uses type inference. 259type _Inferred struct { 260 Targs []Type 261 Sig *Signature 262} 263 264// An Initializer describes a package-level variable, or a list of variables in case 265// of a multi-valued initialization expression, and the corresponding initialization 266// expression. 267type Initializer struct { 268 Lhs []*Var // var Lhs = Rhs 269 Rhs ast.Expr 270} 271 272func (init *Initializer) String() string { 273 var buf bytes.Buffer 274 for i, lhs := range init.Lhs { 275 if i > 0 { 276 buf.WriteString(", ") 277 } 278 buf.WriteString(lhs.Name()) 279 } 280 buf.WriteString(" = ") 281 WriteExpr(&buf, init.Rhs) 282 return buf.String() 283} 284 285// Check type-checks a package and returns the resulting package object and 286// the first error if any. Additionally, if info != nil, Check populates each 287// of the non-nil maps in the Info struct. 288// 289// The package is marked as complete if no errors occurred, otherwise it is 290// incomplete. See Config.Error for controlling behavior in the presence of 291// errors. 292// 293// The package is specified by a list of *ast.Files and corresponding 294// file set, and the package path the package is identified with. 295// The clean path must not be empty or dot ("."). 296func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, info *Info) (*Package, error) { 297 pkg := NewPackage(path, "") 298 return pkg, NewChecker(conf, fset, pkg, info).Files(files) 299} 300 301// AssertableTo reports whether a value of type V can be asserted to have type T. 302func AssertableTo(V *Interface, T Type) bool { 303 m, _ := (*Checker)(nil).assertableTo(V, T) 304 return m == nil 305} 306 307// AssignableTo reports whether a value of type V is assignable to a variable of type T. 308func AssignableTo(V, T Type) bool { 309 x := operand{mode: value, typ: V} 310 ok, _ := x.assignableTo(nil, T, nil) // check not needed for non-constant x 311 return ok 312} 313 314// ConvertibleTo reports whether a value of type V is convertible to a value of type T. 315func ConvertibleTo(V, T Type) bool { 316 x := operand{mode: value, typ: V} 317 return x.convertibleTo(nil, T, nil) // check not needed for non-constant x 318} 319 320// Implements reports whether type V implements interface T. 321func Implements(V Type, T *Interface) bool { 322 f, _ := MissingMethod(V, T, true) 323 return f == nil 324} 325 326// Identical reports whether x and y are identical types. 327// Receivers of Signature types are ignored. 328func Identical(x, y Type) bool { 329 return (*Checker)(nil).identical(x, y) 330} 331 332// IdenticalIgnoreTags reports whether x and y are identical types if tags are ignored. 333// Receivers of Signature types are ignored. 334func IdenticalIgnoreTags(x, y Type) bool { 335 return (*Checker)(nil).identicalIgnoreTags(x, y) 336} 337