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