github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/internal/gcimporter/ureader_yes.go (about) 1 // Copyright 2021 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 // Derived from go/internal/gcimporter/ureader.go 6 7 //go:build go1.18 8 // +build go1.18 9 10 package gcimporter 11 12 import ( 13 "go/token" 14 "go/types" 15 "sort" 16 "strings" 17 18 "golang.org/x/tools/internal/pkgbits" 19 ) 20 21 // A pkgReader holds the shared state for reading a unified IR package 22 // description. 23 type pkgReader struct { 24 pkgbits.PkgDecoder 25 26 fake fakeFileSet 27 28 ctxt *types.Context 29 imports map[string]*types.Package // previously imported packages, indexed by path 30 31 // lazily initialized arrays corresponding to the unified IR 32 // PosBase, Pkg, and Type sections, respectively. 33 posBases []string // position bases (i.e., file names) 34 pkgs []*types.Package 35 typs []types.Type 36 37 // laterFns holds functions that need to be invoked at the end of 38 // import reading. 39 laterFns []func() 40 // laterFors is used in case of 'type A B' to ensure that B is processed before A. 41 laterFors map[types.Type]int 42 43 // ifaces holds a list of constructed Interfaces, which need to have 44 // Complete called after importing is done. 45 ifaces []*types.Interface 46 } 47 48 // later adds a function to be invoked at the end of import reading. 49 func (pr *pkgReader) later(fn func()) { 50 pr.laterFns = append(pr.laterFns, fn) 51 } 52 53 // See cmd/compile/internal/noder.derivedInfo. 54 type derivedInfo struct { 55 idx pkgbits.Index 56 needed bool 57 } 58 59 // See cmd/compile/internal/noder.typeInfo. 60 type typeInfo struct { 61 idx pkgbits.Index 62 derived bool 63 } 64 65 func UImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) { 66 s := string(data) 67 s = s[:strings.LastIndex(s, "\n$$\n")] 68 input := pkgbits.NewPkgDecoder(path, s) 69 pkg = readUnifiedPackage(fset, nil, imports, input) 70 return 71 } 72 73 // laterFor adds a function to be invoked at the end of import reading, and records the type that function is finishing. 74 func (pr *pkgReader) laterFor(t types.Type, fn func()) { 75 if pr.laterFors == nil { 76 pr.laterFors = make(map[types.Type]int) 77 } 78 pr.laterFors[t] = len(pr.laterFns) 79 pr.laterFns = append(pr.laterFns, fn) 80 } 81 82 // readUnifiedPackage reads a package description from the given 83 // unified IR export data decoder. 84 func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[string]*types.Package, input pkgbits.PkgDecoder) *types.Package { 85 pr := pkgReader{ 86 PkgDecoder: input, 87 88 fake: fakeFileSet{ 89 fset: fset, 90 files: make(map[string]*fileInfo), 91 }, 92 93 ctxt: ctxt, 94 imports: imports, 95 96 posBases: make([]string, input.NumElems(pkgbits.RelocPosBase)), 97 pkgs: make([]*types.Package, input.NumElems(pkgbits.RelocPkg)), 98 typs: make([]types.Type, input.NumElems(pkgbits.RelocType)), 99 } 100 defer pr.fake.setLines() 101 102 r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic) 103 pkg := r.pkg() 104 r.Bool() // has init 105 106 for i, n := 0, r.Len(); i < n; i++ { 107 // As if r.obj(), but avoiding the Scope.Lookup call, 108 // to avoid eager loading of imports. 109 r.Sync(pkgbits.SyncObject) 110 assert(!r.Bool()) 111 r.p.objIdx(r.Reloc(pkgbits.RelocObj)) 112 assert(r.Len() == 0) 113 } 114 115 r.Sync(pkgbits.SyncEOF) 116 117 for _, fn := range pr.laterFns { 118 fn() 119 } 120 121 for _, iface := range pr.ifaces { 122 iface.Complete() 123 } 124 125 // Imports() of pkg are all of the transitive packages that were loaded. 126 var imps []*types.Package 127 for _, imp := range pr.pkgs { 128 if imp != nil && imp != pkg { 129 imps = append(imps, imp) 130 } 131 } 132 sort.Sort(byPath(imps)) 133 pkg.SetImports(imps) 134 135 pkg.MarkComplete() 136 return pkg 137 } 138 139 // A reader holds the state for reading a single unified IR element 140 // within a package. 141 type reader struct { 142 pkgbits.Decoder 143 144 p *pkgReader 145 146 dict *readerDict 147 } 148 149 // A readerDict holds the state for type parameters that parameterize 150 // the current unified IR element. 151 type readerDict struct { 152 // bounds is a slice of typeInfos corresponding to the underlying 153 // bounds of the element's type parameters. 154 bounds []typeInfo 155 156 // tparams is a slice of the constructed TypeParams for the element. 157 tparams []*types.TypeParam 158 159 // devived is a slice of types derived from tparams, which may be 160 // instantiated while reading the current element. 161 derived []derivedInfo 162 derivedTypes []types.Type // lazily instantiated from derived 163 } 164 165 func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader { 166 return &reader{ 167 Decoder: pr.NewDecoder(k, idx, marker), 168 p: pr, 169 } 170 } 171 172 func (pr *pkgReader) tempReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader { 173 return &reader{ 174 Decoder: pr.TempDecoder(k, idx, marker), 175 p: pr, 176 } 177 } 178 179 func (pr *pkgReader) retireReader(r *reader) { 180 pr.RetireDecoder(&r.Decoder) 181 } 182 183 // @@@ Positions 184 185 func (r *reader) pos() token.Pos { 186 r.Sync(pkgbits.SyncPos) 187 if !r.Bool() { 188 return token.NoPos 189 } 190 191 // TODO(mdempsky): Delta encoding. 192 posBase := r.posBase() 193 line := r.Uint() 194 col := r.Uint() 195 return r.p.fake.pos(posBase, int(line), int(col)) 196 } 197 198 func (r *reader) posBase() string { 199 return r.p.posBaseIdx(r.Reloc(pkgbits.RelocPosBase)) 200 } 201 202 func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) string { 203 if b := pr.posBases[idx]; b != "" { 204 return b 205 } 206 207 var filename string 208 { 209 r := pr.tempReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase) 210 211 // Within types2, position bases have a lot more details (e.g., 212 // keeping track of where //line directives appeared exactly). 213 // 214 // For go/types, we just track the file name. 215 216 filename = r.String() 217 218 if r.Bool() { // file base 219 // Was: "b = token.NewTrimmedFileBase(filename, true)" 220 } else { // line base 221 pos := r.pos() 222 line := r.Uint() 223 col := r.Uint() 224 225 // Was: "b = token.NewLineBase(pos, filename, true, line, col)" 226 _, _, _ = pos, line, col 227 } 228 pr.retireReader(r) 229 } 230 b := filename 231 pr.posBases[idx] = b 232 return b 233 } 234 235 // @@@ Packages 236 237 func (r *reader) pkg() *types.Package { 238 r.Sync(pkgbits.SyncPkg) 239 return r.p.pkgIdx(r.Reloc(pkgbits.RelocPkg)) 240 } 241 242 func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types.Package { 243 // TODO(mdempsky): Consider using some non-nil pointer to indicate 244 // the universe scope, so we don't need to keep re-reading it. 245 if pkg := pr.pkgs[idx]; pkg != nil { 246 return pkg 247 } 248 249 pkg := pr.newReader(pkgbits.RelocPkg, idx, pkgbits.SyncPkgDef).doPkg() 250 pr.pkgs[idx] = pkg 251 return pkg 252 } 253 254 func (r *reader) doPkg() *types.Package { 255 path := r.String() 256 switch path { 257 case "": 258 path = r.p.PkgPath() 259 case "builtin": 260 return nil // universe 261 case "unsafe": 262 return types.Unsafe 263 } 264 265 if pkg := r.p.imports[path]; pkg != nil { 266 return pkg 267 } 268 269 name := r.String() 270 271 pkg := types.NewPackage(path, name) 272 r.p.imports[path] = pkg 273 274 return pkg 275 } 276 277 // @@@ Types 278 279 func (r *reader) typ() types.Type { 280 return r.p.typIdx(r.typInfo(), r.dict) 281 } 282 283 func (r *reader) typInfo() typeInfo { 284 r.Sync(pkgbits.SyncType) 285 if r.Bool() { 286 return typeInfo{idx: pkgbits.Index(r.Len()), derived: true} 287 } 288 return typeInfo{idx: r.Reloc(pkgbits.RelocType), derived: false} 289 } 290 291 func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types.Type { 292 idx := info.idx 293 var where *types.Type 294 if info.derived { 295 where = &dict.derivedTypes[idx] 296 idx = dict.derived[idx].idx 297 } else { 298 where = &pr.typs[idx] 299 } 300 301 if typ := *where; typ != nil { 302 return typ 303 } 304 305 var typ types.Type 306 { 307 r := pr.tempReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx) 308 r.dict = dict 309 310 typ = r.doTyp() 311 assert(typ != nil) 312 pr.retireReader(r) 313 } 314 // See comment in pkgReader.typIdx explaining how this happens. 315 if prev := *where; prev != nil { 316 return prev 317 } 318 319 *where = typ 320 return typ 321 } 322 323 func (r *reader) doTyp() (res types.Type) { 324 switch tag := pkgbits.CodeType(r.Code(pkgbits.SyncType)); tag { 325 default: 326 errorf("unhandled type tag: %v", tag) 327 panic("unreachable") 328 329 case pkgbits.TypeBasic: 330 return types.Typ[r.Len()] 331 332 case pkgbits.TypeNamed: 333 obj, targs := r.obj() 334 name := obj.(*types.TypeName) 335 if len(targs) != 0 { 336 t, _ := types.Instantiate(r.p.ctxt, name.Type(), targs, false) 337 return t 338 } 339 return name.Type() 340 341 case pkgbits.TypeTypeParam: 342 return r.dict.tparams[r.Len()] 343 344 case pkgbits.TypeArray: 345 len := int64(r.Uint64()) 346 return types.NewArray(r.typ(), len) 347 case pkgbits.TypeChan: 348 dir := types.ChanDir(r.Len()) 349 return types.NewChan(dir, r.typ()) 350 case pkgbits.TypeMap: 351 return types.NewMap(r.typ(), r.typ()) 352 case pkgbits.TypePointer: 353 return types.NewPointer(r.typ()) 354 case pkgbits.TypeSignature: 355 return r.signature(nil, nil, nil) 356 case pkgbits.TypeSlice: 357 return types.NewSlice(r.typ()) 358 case pkgbits.TypeStruct: 359 return r.structType() 360 case pkgbits.TypeInterface: 361 return r.interfaceType() 362 case pkgbits.TypeUnion: 363 return r.unionType() 364 } 365 } 366 367 func (r *reader) structType() *types.Struct { 368 fields := make([]*types.Var, r.Len()) 369 var tags []string 370 for i := range fields { 371 pos := r.pos() 372 pkg, name := r.selector() 373 ftyp := r.typ() 374 tag := r.String() 375 embedded := r.Bool() 376 377 fields[i] = types.NewField(pos, pkg, name, ftyp, embedded) 378 if tag != "" { 379 for len(tags) < i { 380 tags = append(tags, "") 381 } 382 tags = append(tags, tag) 383 } 384 } 385 return types.NewStruct(fields, tags) 386 } 387 388 func (r *reader) unionType() *types.Union { 389 terms := make([]*types.Term, r.Len()) 390 for i := range terms { 391 terms[i] = types.NewTerm(r.Bool(), r.typ()) 392 } 393 return types.NewUnion(terms) 394 } 395 396 func (r *reader) interfaceType() *types.Interface { 397 methods := make([]*types.Func, r.Len()) 398 embeddeds := make([]types.Type, r.Len()) 399 implicit := len(methods) == 0 && len(embeddeds) == 1 && r.Bool() 400 401 for i := range methods { 402 pos := r.pos() 403 pkg, name := r.selector() 404 mtyp := r.signature(nil, nil, nil) 405 methods[i] = types.NewFunc(pos, pkg, name, mtyp) 406 } 407 408 for i := range embeddeds { 409 embeddeds[i] = r.typ() 410 } 411 412 iface := types.NewInterfaceType(methods, embeddeds) 413 if implicit { 414 iface.MarkImplicit() 415 } 416 417 // We need to call iface.Complete(), but if there are any embedded 418 // defined types, then we may not have set their underlying 419 // interface type yet. So we need to defer calling Complete until 420 // after we've called SetUnderlying everywhere. 421 // 422 // TODO(mdempsky): After CL 424876 lands, it should be safe to call 423 // iface.Complete() immediately. 424 r.p.ifaces = append(r.p.ifaces, iface) 425 426 return iface 427 } 428 429 func (r *reader) signature(recv *types.Var, rtparams, tparams []*types.TypeParam) *types.Signature { 430 r.Sync(pkgbits.SyncSignature) 431 432 params := r.params() 433 results := r.params() 434 variadic := r.Bool() 435 436 return types.NewSignatureType(recv, rtparams, tparams, params, results, variadic) 437 } 438 439 func (r *reader) params() *types.Tuple { 440 r.Sync(pkgbits.SyncParams) 441 442 params := make([]*types.Var, r.Len()) 443 for i := range params { 444 params[i] = r.param() 445 } 446 447 return types.NewTuple(params...) 448 } 449 450 func (r *reader) param() *types.Var { 451 r.Sync(pkgbits.SyncParam) 452 453 pos := r.pos() 454 pkg, name := r.localIdent() 455 typ := r.typ() 456 457 return types.NewParam(pos, pkg, name, typ) 458 } 459 460 // @@@ Objects 461 462 func (r *reader) obj() (types.Object, []types.Type) { 463 r.Sync(pkgbits.SyncObject) 464 465 assert(!r.Bool()) 466 467 pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj)) 468 obj := pkgScope(pkg).Lookup(name) 469 470 targs := make([]types.Type, r.Len()) 471 for i := range targs { 472 targs[i] = r.typ() 473 } 474 475 return obj, targs 476 } 477 478 func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) { 479 480 var objPkg *types.Package 481 var objName string 482 var tag pkgbits.CodeObj 483 { 484 rname := pr.tempReader(pkgbits.RelocName, idx, pkgbits.SyncObject1) 485 486 objPkg, objName = rname.qualifiedIdent() 487 assert(objName != "") 488 489 tag = pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj)) 490 pr.retireReader(rname) 491 } 492 493 if tag == pkgbits.ObjStub { 494 assert(objPkg == nil || objPkg == types.Unsafe) 495 return objPkg, objName 496 } 497 498 // Ignore local types promoted to global scope (#55110). 499 if _, suffix := splitVargenSuffix(objName); suffix != "" { 500 return objPkg, objName 501 } 502 503 if objPkg.Scope().Lookup(objName) == nil { 504 dict := pr.objDictIdx(idx) 505 506 r := pr.newReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1) 507 r.dict = dict 508 509 declare := func(obj types.Object) { 510 objPkg.Scope().Insert(obj) 511 } 512 513 switch tag { 514 default: 515 panic("weird") 516 517 case pkgbits.ObjAlias: 518 pos := r.pos() 519 typ := r.typ() 520 declare(types.NewTypeName(pos, objPkg, objName, typ)) 521 522 case pkgbits.ObjConst: 523 pos := r.pos() 524 typ := r.typ() 525 val := r.Value() 526 declare(types.NewConst(pos, objPkg, objName, typ, val)) 527 528 case pkgbits.ObjFunc: 529 pos := r.pos() 530 tparams := r.typeParamNames() 531 sig := r.signature(nil, nil, tparams) 532 declare(types.NewFunc(pos, objPkg, objName, sig)) 533 534 case pkgbits.ObjType: 535 pos := r.pos() 536 537 obj := types.NewTypeName(pos, objPkg, objName, nil) 538 named := types.NewNamed(obj, nil, nil) 539 declare(obj) 540 541 named.SetTypeParams(r.typeParamNames()) 542 543 setUnderlying := func(underlying types.Type) { 544 // If the underlying type is an interface, we need to 545 // duplicate its methods so we can replace the receiver 546 // parameter's type (#49906). 547 if iface, ok := underlying.(*types.Interface); ok && iface.NumExplicitMethods() != 0 { 548 methods := make([]*types.Func, iface.NumExplicitMethods()) 549 for i := range methods { 550 fn := iface.ExplicitMethod(i) 551 sig := fn.Type().(*types.Signature) 552 553 recv := types.NewVar(fn.Pos(), fn.Pkg(), "", named) 554 methods[i] = types.NewFunc(fn.Pos(), fn.Pkg(), fn.Name(), types.NewSignature(recv, sig.Params(), sig.Results(), sig.Variadic())) 555 } 556 557 embeds := make([]types.Type, iface.NumEmbeddeds()) 558 for i := range embeds { 559 embeds[i] = iface.EmbeddedType(i) 560 } 561 562 newIface := types.NewInterfaceType(methods, embeds) 563 r.p.ifaces = append(r.p.ifaces, newIface) 564 underlying = newIface 565 } 566 567 named.SetUnderlying(underlying) 568 } 569 570 // Since go.dev/cl/455279, we can assume rhs.Underlying() will 571 // always be non-nil. However, to temporarily support users of 572 // older snapshot releases, we continue to fallback to the old 573 // behavior for now. 574 // 575 // TODO(mdempsky): Remove fallback code and simplify after 576 // allowing time for snapshot users to upgrade. 577 rhs := r.typ() 578 if underlying := rhs.Underlying(); underlying != nil { 579 setUnderlying(underlying) 580 } else { 581 pk := r.p 582 pk.laterFor(named, func() { 583 // First be sure that the rhs is initialized, if it needs to be initialized. 584 delete(pk.laterFors, named) // prevent cycles 585 if i, ok := pk.laterFors[rhs]; ok { 586 f := pk.laterFns[i] 587 pk.laterFns[i] = func() {} // function is running now, so replace it with a no-op 588 f() // initialize RHS 589 } 590 setUnderlying(rhs.Underlying()) 591 }) 592 } 593 594 for i, n := 0, r.Len(); i < n; i++ { 595 named.AddMethod(r.method()) 596 } 597 598 case pkgbits.ObjVar: 599 pos := r.pos() 600 typ := r.typ() 601 declare(types.NewVar(pos, objPkg, objName, typ)) 602 } 603 } 604 605 return objPkg, objName 606 } 607 608 func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict { 609 610 var dict readerDict 611 612 { 613 r := pr.tempReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1) 614 if implicits := r.Len(); implicits != 0 { 615 errorf("unexpected object with %v implicit type parameter(s)", implicits) 616 } 617 618 dict.bounds = make([]typeInfo, r.Len()) 619 for i := range dict.bounds { 620 dict.bounds[i] = r.typInfo() 621 } 622 623 dict.derived = make([]derivedInfo, r.Len()) 624 dict.derivedTypes = make([]types.Type, len(dict.derived)) 625 for i := range dict.derived { 626 dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()} 627 } 628 629 pr.retireReader(r) 630 } 631 // function references follow, but reader doesn't need those 632 633 return &dict 634 } 635 636 func (r *reader) typeParamNames() []*types.TypeParam { 637 r.Sync(pkgbits.SyncTypeParamNames) 638 639 // Note: This code assumes it only processes objects without 640 // implement type parameters. This is currently fine, because 641 // reader is only used to read in exported declarations, which are 642 // always package scoped. 643 644 if len(r.dict.bounds) == 0 { 645 return nil 646 } 647 648 // Careful: Type parameter lists may have cycles. To allow for this, 649 // we construct the type parameter list in two passes: first we 650 // create all the TypeNames and TypeParams, then we construct and 651 // set the bound type. 652 653 r.dict.tparams = make([]*types.TypeParam, len(r.dict.bounds)) 654 for i := range r.dict.bounds { 655 pos := r.pos() 656 pkg, name := r.localIdent() 657 658 tname := types.NewTypeName(pos, pkg, name, nil) 659 r.dict.tparams[i] = types.NewTypeParam(tname, nil) 660 } 661 662 typs := make([]types.Type, len(r.dict.bounds)) 663 for i, bound := range r.dict.bounds { 664 typs[i] = r.p.typIdx(bound, r.dict) 665 } 666 667 // TODO(mdempsky): This is subtle, elaborate further. 668 // 669 // We have to save tparams outside of the closure, because 670 // typeParamNames() can be called multiple times with the same 671 // dictionary instance. 672 // 673 // Also, this needs to happen later to make sure SetUnderlying has 674 // been called. 675 // 676 // TODO(mdempsky): Is it safe to have a single "later" slice or do 677 // we need to have multiple passes? See comments on CL 386002 and 678 // go.dev/issue/52104. 679 tparams := r.dict.tparams 680 r.p.later(func() { 681 for i, typ := range typs { 682 tparams[i].SetConstraint(typ) 683 } 684 }) 685 686 return r.dict.tparams 687 } 688 689 func (r *reader) method() *types.Func { 690 r.Sync(pkgbits.SyncMethod) 691 pos := r.pos() 692 pkg, name := r.selector() 693 694 rparams := r.typeParamNames() 695 sig := r.signature(r.param(), rparams, nil) 696 697 _ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go. 698 return types.NewFunc(pos, pkg, name, sig) 699 } 700 701 func (r *reader) qualifiedIdent() (*types.Package, string) { return r.ident(pkgbits.SyncSym) } 702 func (r *reader) localIdent() (*types.Package, string) { return r.ident(pkgbits.SyncLocalIdent) } 703 func (r *reader) selector() (*types.Package, string) { return r.ident(pkgbits.SyncSelector) } 704 705 func (r *reader) ident(marker pkgbits.SyncMarker) (*types.Package, string) { 706 r.Sync(marker) 707 return r.pkg(), r.String() 708 } 709 710 // pkgScope returns pkg.Scope(). 711 // If pkg is nil, it returns types.Universe instead. 712 // 713 // TODO(mdempsky): Remove after x/tools can depend on Go 1.19. 714 func pkgScope(pkg *types.Package) *types.Scope { 715 if pkg != nil { 716 return pkg.Scope() 717 } 718 return types.Universe 719 }