github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/types2/object.go (about) 1 // Copyright 2013 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 types2 6 7 import ( 8 "bytes" 9 "fmt" 10 "go/constant" 11 "unicode" 12 "unicode/utf8" 13 14 "github.com/go-asm/go/cmd/compile/syntax" 15 ) 16 17 // An Object describes a named language entity such as a package, 18 // constant, type, variable, function (incl. methods), or label. 19 // All objects implement the Object interface. 20 type Object interface { 21 Parent() *Scope // scope in which this object is declared; nil for methods and struct fields 22 Pos() syntax.Pos // position of object identifier in declaration 23 Pkg() *Package // package to which this object belongs; nil for labels and objects in the Universe scope 24 Name() string // package local object name 25 Type() Type // object type 26 Exported() bool // reports whether the name starts with a capital letter 27 Id() string // object name if exported, qualified name if not exported (see func Id) 28 29 // String returns a human-readable string of the object. 30 String() string 31 32 // order reflects a package-level object's source order: if object 33 // a is before object b in the source, then a.order() < b.order(). 34 // order returns a value > 0 for package-level objects; it returns 35 // 0 for all other objects (including objects in file scopes). 36 order() uint32 37 38 // color returns the object's color. 39 color() color 40 41 // setType sets the type of the object. 42 setType(Type) 43 44 // setOrder sets the order number of the object. It must be > 0. 45 setOrder(uint32) 46 47 // setColor sets the object's color. It must not be white. 48 setColor(color color) 49 50 // setParent sets the parent scope of the object. 51 setParent(*Scope) 52 53 // sameId reports whether obj.Id() and Id(pkg, name) are the same. 54 sameId(pkg *Package, name string) bool 55 56 // scopePos returns the start position of the scope of this Object 57 scopePos() syntax.Pos 58 59 // setScopePos sets the start position of the scope for this Object. 60 setScopePos(pos syntax.Pos) 61 } 62 63 func isExported(name string) bool { 64 ch, _ := utf8.DecodeRuneInString(name) 65 return unicode.IsUpper(ch) 66 } 67 68 // Id returns name if it is exported, otherwise it 69 // returns the name qualified with the package path. 70 func Id(pkg *Package, name string) string { 71 if isExported(name) { 72 return name 73 } 74 // unexported names need the package path for differentiation 75 // (if there's no package, make sure we don't start with '.' 76 // as that may change the order of methods between a setup 77 // inside a package and outside a package - which breaks some 78 // tests) 79 path := "_" 80 // pkg is nil for objects in Universe scope and possibly types 81 // introduced via Eval (see also comment in object.sameId) 82 if pkg != nil && pkg.path != "" { 83 path = pkg.path 84 } 85 return path + "." + name 86 } 87 88 // An object implements the common parts of an Object. 89 type object struct { 90 parent *Scope 91 pos syntax.Pos 92 pkg *Package 93 name string 94 typ Type 95 order_ uint32 96 color_ color 97 scopePos_ syntax.Pos 98 } 99 100 // color encodes the color of an object (see Checker.objDecl for details). 101 type color uint32 102 103 // An object may be painted in one of three colors. 104 // Color values other than white or black are considered grey. 105 const ( 106 white color = iota 107 black 108 grey // must be > white and black 109 ) 110 111 func (c color) String() string { 112 switch c { 113 case white: 114 return "white" 115 case black: 116 return "black" 117 default: 118 return "grey" 119 } 120 } 121 122 // colorFor returns the (initial) color for an object depending on 123 // whether its type t is known or not. 124 func colorFor(t Type) color { 125 if t != nil { 126 return black 127 } 128 return white 129 } 130 131 // Parent returns the scope in which the object is declared. 132 // The result is nil for methods and struct fields. 133 func (obj *object) Parent() *Scope { return obj.parent } 134 135 // Pos returns the declaration position of the object's identifier. 136 func (obj *object) Pos() syntax.Pos { return obj.pos } 137 138 // Pkg returns the package to which the object belongs. 139 // The result is nil for labels and objects in the Universe scope. 140 func (obj *object) Pkg() *Package { return obj.pkg } 141 142 // Name returns the object's (package-local, unqualified) name. 143 func (obj *object) Name() string { return obj.name } 144 145 // Type returns the object's type. 146 func (obj *object) Type() Type { return obj.typ } 147 148 // Exported reports whether the object is exported (starts with a capital letter). 149 // It doesn't take into account whether the object is in a local (function) scope 150 // or not. 151 func (obj *object) Exported() bool { return isExported(obj.name) } 152 153 // Id is a wrapper for Id(obj.Pkg(), obj.Name()). 154 func (obj *object) Id() string { return Id(obj.pkg, obj.name) } 155 156 func (obj *object) String() string { panic("abstract") } 157 func (obj *object) order() uint32 { return obj.order_ } 158 func (obj *object) color() color { return obj.color_ } 159 func (obj *object) scopePos() syntax.Pos { return obj.scopePos_ } 160 161 func (obj *object) setParent(parent *Scope) { obj.parent = parent } 162 func (obj *object) setType(typ Type) { obj.typ = typ } 163 func (obj *object) setOrder(order uint32) { assert(order > 0); obj.order_ = order } 164 func (obj *object) setColor(color color) { assert(color != white); obj.color_ = color } 165 func (obj *object) setScopePos(pos syntax.Pos) { obj.scopePos_ = pos } 166 167 func (obj *object) sameId(pkg *Package, name string) bool { 168 // spec: 169 // "Two identifiers are different if they are spelled differently, 170 // or if they appear in different packages and are not exported. 171 // Otherwise, they are the same." 172 if name != obj.name { 173 return false 174 } 175 // obj.Name == name 176 if obj.Exported() { 177 return true 178 } 179 // not exported, so packages must be the same (pkg == nil for 180 // fields in Universe scope; this can only happen for types 181 // introduced via Eval) 182 if pkg == nil || obj.pkg == nil { 183 return pkg == obj.pkg 184 } 185 // pkg != nil && obj.pkg != nil 186 return pkg.path == obj.pkg.path 187 } 188 189 // less reports whether object a is ordered before object b. 190 // 191 // Objects are ordered nil before non-nil, exported before 192 // non-exported, then by name, and finally (for non-exported 193 // functions) by package path. 194 func (a *object) less(b *object) bool { 195 if a == b { 196 return false 197 } 198 199 // Nil before non-nil. 200 if a == nil { 201 return true 202 } 203 if b == nil { 204 return false 205 } 206 207 // Exported functions before non-exported. 208 ea := isExported(a.name) 209 eb := isExported(b.name) 210 if ea != eb { 211 return ea 212 } 213 214 // Order by name and then (for non-exported names) by package. 215 if a.name != b.name { 216 return a.name < b.name 217 } 218 if !ea { 219 return a.pkg.path < b.pkg.path 220 } 221 222 return false 223 } 224 225 // A PkgName represents an imported Go package. 226 // PkgNames don't have a type. 227 type PkgName struct { 228 object 229 imported *Package 230 used bool // set if the package was used 231 } 232 233 // NewPkgName returns a new PkgName object representing an imported package. 234 // The remaining arguments set the attributes found with all Objects. 235 func NewPkgName(pos syntax.Pos, pkg *Package, name string, imported *Package) *PkgName { 236 return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, black, nopos}, imported, false} 237 } 238 239 // Imported returns the package that was imported. 240 // It is distinct from Pkg(), which is the package containing the import statement. 241 func (obj *PkgName) Imported() *Package { return obj.imported } 242 243 // A Const represents a declared constant. 244 type Const struct { 245 object 246 val constant.Value 247 } 248 249 // NewConst returns a new constant with value val. 250 // The remaining arguments set the attributes found with all Objects. 251 func NewConst(pos syntax.Pos, pkg *Package, name string, typ Type, val constant.Value) *Const { 252 return &Const{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, val} 253 } 254 255 // Val returns the constant's value. 256 func (obj *Const) Val() constant.Value { return obj.val } 257 258 func (*Const) isDependency() {} // a constant may be a dependency of an initialization expression 259 260 // A TypeName represents a name for a (defined or alias) type. 261 type TypeName struct { 262 object 263 } 264 265 // NewTypeName returns a new type name denoting the given typ. 266 // The remaining arguments set the attributes found with all Objects. 267 // 268 // The typ argument may be a defined (Named) type or an alias type. 269 // It may also be nil such that the returned TypeName can be used as 270 // argument for NewNamed, which will set the TypeName's type as a side- 271 // effect. 272 func NewTypeName(pos syntax.Pos, pkg *Package, name string, typ Type) *TypeName { 273 return &TypeName{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}} 274 } 275 276 // NewTypeNameLazy returns a new defined type like NewTypeName, but it 277 // lazily calls resolve to finish constructing the Named object. 278 func NewTypeNameLazy(pos syntax.Pos, pkg *Package, name string, load func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName { 279 obj := NewTypeName(pos, pkg, name, nil) 280 NewNamed(obj, nil, nil).loader = load 281 return obj 282 } 283 284 // IsAlias reports whether obj is an alias name for a type. 285 func (obj *TypeName) IsAlias() bool { 286 switch t := obj.typ.(type) { 287 case nil: 288 return false 289 // case *Alias: 290 // handled by default case 291 case *Basic: 292 // unsafe.Pointer is not an alias. 293 if obj.pkg == Unsafe { 294 return false 295 } 296 // Any user-defined type name for a basic type is an alias for a 297 // basic type (because basic types are pre-declared in the Universe 298 // scope, outside any package scope), and so is any type name with 299 // a different name than the name of the basic type it refers to. 300 // Additionally, we need to look for "byte" and "rune" because they 301 // are aliases but have the same names (for better error messages). 302 return obj.pkg != nil || t.name != obj.name || t == universeByte || t == universeRune 303 case *Named: 304 return obj != t.obj 305 case *TypeParam: 306 return obj != t.obj 307 default: 308 return true 309 } 310 } 311 312 // A Variable represents a declared variable (including function parameters and results, and struct fields). 313 type Var struct { 314 object 315 embedded bool // if set, the variable is an embedded struct field, and name is the type name 316 isField bool // var is struct field 317 used bool // set if the variable was used 318 origin *Var // if non-nil, the Var from which this one was instantiated 319 } 320 321 // NewVar returns a new variable. 322 // The arguments set the attributes found with all Objects. 323 func NewVar(pos syntax.Pos, pkg *Package, name string, typ Type) *Var { 324 return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}} 325 } 326 327 // NewParam returns a new variable representing a function parameter. 328 func NewParam(pos syntax.Pos, pkg *Package, name string, typ Type) *Var { 329 return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, used: true} // parameters are always 'used' 330 } 331 332 // NewField returns a new variable representing a struct field. 333 // For embedded fields, the name is the unqualified type name 334 // under which the field is accessible. 335 func NewField(pos syntax.Pos, pkg *Package, name string, typ Type, embedded bool) *Var { 336 return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, embedded: embedded, isField: true} 337 } 338 339 // Anonymous reports whether the variable is an embedded field. 340 // Same as Embedded; only present for backward-compatibility. 341 func (obj *Var) Anonymous() bool { return obj.embedded } 342 343 // Embedded reports whether the variable is an embedded field. 344 func (obj *Var) Embedded() bool { return obj.embedded } 345 346 // IsField reports whether the variable is a struct field. 347 func (obj *Var) IsField() bool { return obj.isField } 348 349 // Origin returns the canonical Var for its receiver, i.e. the Var object 350 // recorded in Info.Defs. 351 // 352 // For synthetic Vars created during instantiation (such as struct fields or 353 // function parameters that depend on type arguments), this will be the 354 // corresponding Var on the generic (uninstantiated) type. For all other Vars 355 // Origin returns the receiver. 356 func (obj *Var) Origin() *Var { 357 if obj.origin != nil { 358 return obj.origin 359 } 360 return obj 361 } 362 363 func (*Var) isDependency() {} // a variable may be a dependency of an initialization expression 364 365 // A Func represents a declared function, concrete method, or abstract 366 // (interface) method. Its Type() is always a *Signature. 367 // An abstract method may belong to many interfaces due to embedding. 368 type Func struct { 369 object 370 hasPtrRecv_ bool // only valid for methods that don't have a type yet; use hasPtrRecv() to read 371 origin *Func // if non-nil, the Func from which this one was instantiated 372 } 373 374 // NewFunc returns a new function with the given signature, representing 375 // the function's type. 376 func NewFunc(pos syntax.Pos, pkg *Package, name string, sig *Signature) *Func { 377 // don't store a (typed) nil signature 378 var typ Type 379 if sig != nil { 380 typ = sig 381 } 382 return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, false, nil} 383 } 384 385 // FullName returns the package- or receiver-type-qualified name of 386 // function or method obj. 387 func (obj *Func) FullName() string { 388 var buf bytes.Buffer 389 writeFuncName(&buf, obj, nil) 390 return buf.String() 391 } 392 393 // Scope returns the scope of the function's body block. 394 // The result is nil for imported or instantiated functions and methods 395 // (but there is also no mechanism to get to an instantiated function). 396 func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope } 397 398 // Origin returns the canonical Func for its receiver, i.e. the Func object 399 // recorded in Info.Defs. 400 // 401 // For synthetic functions created during instantiation (such as methods on an 402 // instantiated Named type or interface methods that depend on type arguments), 403 // this will be the corresponding Func on the generic (uninstantiated) type. 404 // For all other Funcs Origin returns the receiver. 405 func (obj *Func) Origin() *Func { 406 if obj.origin != nil { 407 return obj.origin 408 } 409 return obj 410 } 411 412 // Pkg returns the package to which the function belongs. 413 // 414 // The result is nil for methods of types in the Universe scope, 415 // like method Error of the error built-in interface type. 416 func (obj *Func) Pkg() *Package { return obj.object.Pkg() } 417 418 // hasPtrRecv reports whether the receiver is of the form *T for the given method obj. 419 func (obj *Func) hasPtrRecv() bool { 420 // If a method's receiver type is set, use that as the source of truth for the receiver. 421 // Caution: Checker.funcDecl (decl.go) marks a function by setting its type to an empty 422 // signature. We may reach here before the signature is fully set up: we must explicitly 423 // check if the receiver is set (we cannot just look for non-nil obj.typ). 424 if sig, _ := obj.typ.(*Signature); sig != nil && sig.recv != nil { 425 _, isPtr := deref(sig.recv.typ) 426 return isPtr 427 } 428 429 // If a method's type is not set it may be a method/function that is: 430 // 1) client-supplied (via NewFunc with no signature), or 431 // 2) internally created but not yet type-checked. 432 // For case 1) we can't do anything; the client must know what they are doing. 433 // For case 2) we can use the information gathered by the resolver. 434 return obj.hasPtrRecv_ 435 } 436 437 func (*Func) isDependency() {} // a function may be a dependency of an initialization expression 438 439 // A Label represents a declared label. 440 // Labels don't have a type. 441 type Label struct { 442 object 443 used bool // set if the label was used 444 } 445 446 // NewLabel returns a new label. 447 func NewLabel(pos syntax.Pos, pkg *Package, name string) *Label { 448 return &Label{object{pos: pos, pkg: pkg, name: name, typ: Typ[Invalid], color_: black}, false} 449 } 450 451 // A Builtin represents a built-in function. 452 // Builtins don't have a valid type. 453 type Builtin struct { 454 object 455 id builtinId 456 } 457 458 func newBuiltin(id builtinId) *Builtin { 459 return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid], color_: black}, id} 460 } 461 462 // Nil represents the predeclared value nil. 463 type Nil struct { 464 object 465 } 466 467 func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { 468 var tname *TypeName 469 typ := obj.Type() 470 471 switch obj := obj.(type) { 472 case *PkgName: 473 fmt.Fprintf(buf, "package %s", obj.Name()) 474 if path := obj.imported.path; path != "" && path != obj.name { 475 fmt.Fprintf(buf, " (%q)", path) 476 } 477 return 478 479 case *Const: 480 buf.WriteString("const") 481 482 case *TypeName: 483 tname = obj 484 buf.WriteString("type") 485 if isTypeParam(typ) { 486 buf.WriteString(" parameter") 487 } 488 489 case *Var: 490 if obj.isField { 491 buf.WriteString("field") 492 } else { 493 buf.WriteString("var") 494 } 495 496 case *Func: 497 buf.WriteString("func ") 498 writeFuncName(buf, obj, qf) 499 if typ != nil { 500 WriteSignature(buf, typ.(*Signature), qf) 501 } 502 return 503 504 case *Label: 505 buf.WriteString("label") 506 typ = nil 507 508 case *Builtin: 509 buf.WriteString("builtin") 510 typ = nil 511 512 case *Nil: 513 buf.WriteString("nil") 514 return 515 516 default: 517 panic(fmt.Sprintf("writeObject(%T)", obj)) 518 } 519 520 buf.WriteByte(' ') 521 522 // For package-level objects, qualify the name. 523 if obj.Pkg() != nil && obj.Pkg().scope.Lookup(obj.Name()) == obj { 524 buf.WriteString(packagePrefix(obj.Pkg(), qf)) 525 } 526 buf.WriteString(obj.Name()) 527 528 if typ == nil { 529 return 530 } 531 532 if tname != nil { 533 switch t := typ.(type) { 534 case *Basic: 535 // Don't print anything more for basic types since there's 536 // no more information. 537 return 538 case *Named: 539 if t.TypeParams().Len() > 0 { 540 newTypeWriter(buf, qf).tParamList(t.TypeParams().list()) 541 } 542 } 543 if tname.IsAlias() { 544 buf.WriteString(" =") 545 } else if t, _ := typ.(*TypeParam); t != nil { 546 typ = t.bound 547 } else { 548 // TODO(gri) should this be fromRHS for *Named? 549 typ = under(typ) 550 } 551 } 552 553 // Special handling for any: because WriteType will format 'any' as 'any', 554 // resulting in the object string `type any = any` rather than `type any = 555 // interface{}`. To avoid this, swap in a different empty interface. 556 if obj == universeAny { 557 assert(Identical(typ, &emptyInterface)) 558 typ = &emptyInterface 559 } 560 561 buf.WriteByte(' ') 562 WriteType(buf, typ, qf) 563 } 564 565 func packagePrefix(pkg *Package, qf Qualifier) string { 566 if pkg == nil { 567 return "" 568 } 569 var s string 570 if qf != nil { 571 s = qf(pkg) 572 } else { 573 s = pkg.Path() 574 } 575 if s != "" { 576 s += "." 577 } 578 return s 579 } 580 581 // ObjectString returns the string form of obj. 582 // The Qualifier controls the printing of 583 // package-level objects, and may be nil. 584 func ObjectString(obj Object, qf Qualifier) string { 585 var buf bytes.Buffer 586 writeObject(&buf, obj, qf) 587 return buf.String() 588 } 589 590 func (obj *PkgName) String() string { return ObjectString(obj, nil) } 591 func (obj *Const) String() string { return ObjectString(obj, nil) } 592 func (obj *TypeName) String() string { return ObjectString(obj, nil) } 593 func (obj *Var) String() string { return ObjectString(obj, nil) } 594 func (obj *Func) String() string { return ObjectString(obj, nil) } 595 func (obj *Label) String() string { return ObjectString(obj, nil) } 596 func (obj *Builtin) String() string { return ObjectString(obj, nil) } 597 func (obj *Nil) String() string { return ObjectString(obj, nil) } 598 599 func writeFuncName(buf *bytes.Buffer, f *Func, qf Qualifier) { 600 if f.typ != nil { 601 sig := f.typ.(*Signature) 602 if recv := sig.Recv(); recv != nil { 603 buf.WriteByte('(') 604 if _, ok := recv.Type().(*Interface); ok { 605 // gcimporter creates abstract methods of 606 // named interfaces using the interface type 607 // (not the named type) as the receiver. 608 // Don't print it in full. 609 buf.WriteString("interface") 610 } else { 611 WriteType(buf, recv.Type(), qf) 612 } 613 buf.WriteByte(')') 614 buf.WriteByte('.') 615 } else if f.pkg != nil { 616 buf.WriteString(packagePrefix(f.pkg, qf)) 617 } 618 } 619 buf.WriteString(f.name) 620 }