github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/internal/gcimporter/iimport.go (about) 1 // Copyright 2018 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 // Indexed package import. 6 // See cmd/compile/internal/gc/iexport.go for the export data format. 7 8 // This file is a copy of $GOROOT/src/go/internal/gcimporter/iimport.go. 9 10 package gcimporter 11 12 import ( 13 "bytes" 14 "encoding/binary" 15 "fmt" 16 "go/constant" 17 "go/token" 18 "go/types" 19 "io" 20 "math/big" 21 "sort" 22 "strings" 23 24 "golang.org/x/tools/internal/typeparams" 25 ) 26 27 type intReader struct { 28 *bytes.Reader 29 path string 30 } 31 32 func (r *intReader) int64() int64 { 33 i, err := binary.ReadVarint(r.Reader) 34 if err != nil { 35 errorf("import %q: read varint error: %v", r.path, err) 36 } 37 return i 38 } 39 40 func (r *intReader) uint64() uint64 { 41 i, err := binary.ReadUvarint(r.Reader) 42 if err != nil { 43 errorf("import %q: read varint error: %v", r.path, err) 44 } 45 return i 46 } 47 48 // Keep this in sync with constants in iexport.go. 49 const ( 50 iexportVersionGo1_11 = 0 51 iexportVersionPosCol = 1 52 iexportVersionGo1_18 = 2 53 iexportVersionGenerics = 2 54 55 iexportVersionCurrent = 2 56 ) 57 58 type ident struct { 59 pkg *types.Package 60 name string 61 } 62 63 const predeclReserved = 32 64 65 type itag uint64 66 67 const ( 68 // Types 69 definedType itag = iota 70 pointerType 71 sliceType 72 arrayType 73 chanType 74 mapType 75 signatureType 76 structType 77 interfaceType 78 typeParamType 79 instanceType 80 unionType 81 ) 82 83 // IImportData imports a package from the serialized package data 84 // and returns 0 and a reference to the package. 85 // If the export data version is not recognized or the format is otherwise 86 // compromised, an error is returned. 87 func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) { 88 pkgs, err := iimportCommon(fset, imports, data, false, path, nil) 89 if err != nil { 90 return 0, nil, err 91 } 92 return 0, pkgs[0], nil 93 } 94 95 // IImportBundle imports a set of packages from the serialized package bundle. 96 func IImportBundle(fset *token.FileSet, imports map[string]*types.Package, data []byte) ([]*types.Package, error) { 97 return iimportCommon(fset, imports, data, true, "", nil) 98 } 99 100 func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data []byte, bundle bool, path string, insert InsertType) (pkgs []*types.Package, err error) { 101 const currentVersion = iexportVersionCurrent 102 version := int64(-1) 103 if !debug { 104 defer func() { 105 if e := recover(); e != nil { 106 if bundle { 107 err = fmt.Errorf("%v", e) 108 } else if version > currentVersion { 109 err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e) 110 } else { 111 err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e) 112 } 113 } 114 }() 115 } 116 117 r := &intReader{bytes.NewReader(data), path} 118 119 if bundle { 120 bundleVersion := r.uint64() 121 switch bundleVersion { 122 case bundleVersion: 123 default: 124 errorf("unknown bundle format version %d", bundleVersion) 125 } 126 } 127 128 version = int64(r.uint64()) 129 switch version { 130 case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11: 131 default: 132 if version > iexportVersionGo1_18 { 133 errorf("unstable iexport format version %d, just rebuild compiler and std library", version) 134 } else { 135 errorf("unknown iexport format version %d", version) 136 } 137 } 138 139 sLen := int64(r.uint64()) 140 var fLen int64 141 var fileOffset []uint64 142 if insert != nil { 143 // Shallow mode uses a different position encoding. 144 fLen = int64(r.uint64()) 145 fileOffset = make([]uint64, r.uint64()) 146 for i := range fileOffset { 147 fileOffset[i] = r.uint64() 148 } 149 } 150 dLen := int64(r.uint64()) 151 152 whence, _ := r.Seek(0, io.SeekCurrent) 153 stringData := data[whence : whence+sLen] 154 fileData := data[whence+sLen : whence+sLen+fLen] 155 declData := data[whence+sLen+fLen : whence+sLen+fLen+dLen] 156 r.Seek(sLen+fLen+dLen, io.SeekCurrent) 157 158 p := iimporter{ 159 version: int(version), 160 ipath: path, 161 insert: insert, 162 163 stringData: stringData, 164 stringCache: make(map[uint64]string), 165 fileOffset: fileOffset, 166 fileData: fileData, 167 fileCache: make([]*token.File, len(fileOffset)), 168 pkgCache: make(map[uint64]*types.Package), 169 170 declData: declData, 171 pkgIndex: make(map[*types.Package]map[string]uint64), 172 typCache: make(map[uint64]types.Type), 173 // Separate map for typeparams, keyed by their package and unique 174 // name. 175 tparamIndex: make(map[ident]types.Type), 176 177 fake: fakeFileSet{ 178 fset: fset, 179 files: make(map[string]*fileInfo), 180 }, 181 } 182 defer p.fake.setLines() // set lines for files in fset 183 184 for i, pt := range predeclared() { 185 p.typCache[uint64(i)] = pt 186 } 187 188 pkgList := make([]*types.Package, r.uint64()) 189 for i := range pkgList { 190 pkgPathOff := r.uint64() 191 pkgPath := p.stringAt(pkgPathOff) 192 pkgName := p.stringAt(r.uint64()) 193 _ = r.uint64() // package height; unused by go/types 194 195 if pkgPath == "" { 196 pkgPath = path 197 } 198 pkg := imports[pkgPath] 199 if pkg == nil { 200 pkg = types.NewPackage(pkgPath, pkgName) 201 imports[pkgPath] = pkg 202 } else if pkg.Name() != pkgName { 203 errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path) 204 } 205 if i == 0 && !bundle { 206 p.localpkg = pkg 207 } 208 209 p.pkgCache[pkgPathOff] = pkg 210 211 // Read index for package. 212 nameIndex := make(map[string]uint64) 213 nSyms := r.uint64() 214 // In shallow mode we don't expect an index for other packages. 215 assert(nSyms == 0 || p.localpkg == pkg || p.insert == nil) 216 for ; nSyms > 0; nSyms-- { 217 name := p.stringAt(r.uint64()) 218 nameIndex[name] = r.uint64() 219 } 220 221 p.pkgIndex[pkg] = nameIndex 222 pkgList[i] = pkg 223 } 224 225 if bundle { 226 pkgs = make([]*types.Package, r.uint64()) 227 for i := range pkgs { 228 pkg := p.pkgAt(r.uint64()) 229 imps := make([]*types.Package, r.uint64()) 230 for j := range imps { 231 imps[j] = p.pkgAt(r.uint64()) 232 } 233 pkg.SetImports(imps) 234 pkgs[i] = pkg 235 } 236 } else { 237 if len(pkgList) == 0 { 238 errorf("no packages found for %s", path) 239 panic("unreachable") 240 } 241 pkgs = pkgList[:1] 242 243 // record all referenced packages as imports 244 list := append(([]*types.Package)(nil), pkgList[1:]...) 245 sort.Sort(byPath(list)) 246 pkgs[0].SetImports(list) 247 } 248 249 for _, pkg := range pkgs { 250 if pkg.Complete() { 251 continue 252 } 253 254 names := make([]string, 0, len(p.pkgIndex[pkg])) 255 for name := range p.pkgIndex[pkg] { 256 names = append(names, name) 257 } 258 sort.Strings(names) 259 for _, name := range names { 260 p.doDecl(pkg, name) 261 } 262 263 // package was imported completely and without errors 264 pkg.MarkComplete() 265 } 266 267 // SetConstraint can't be called if the constraint type is not yet complete. 268 // When type params are created in the 'P' case of (*importReader).obj(), 269 // the associated constraint type may not be complete due to recursion. 270 // Therefore, we defer calling SetConstraint there, and call it here instead 271 // after all types are complete. 272 for _, d := range p.later { 273 typeparams.SetTypeParamConstraint(d.t, d.constraint) 274 } 275 276 for _, typ := range p.interfaceList { 277 typ.Complete() 278 } 279 280 return pkgs, nil 281 } 282 283 type setConstraintArgs struct { 284 t *typeparams.TypeParam 285 constraint types.Type 286 } 287 288 type iimporter struct { 289 version int 290 ipath string 291 292 localpkg *types.Package 293 insert func(pkg *types.Package, name string) // "shallow" mode only 294 295 stringData []byte 296 stringCache map[uint64]string 297 fileOffset []uint64 // fileOffset[i] is offset in fileData for info about file encoded as i 298 fileData []byte 299 fileCache []*token.File // memoized decoding of file encoded as i 300 pkgCache map[uint64]*types.Package 301 302 declData []byte 303 pkgIndex map[*types.Package]map[string]uint64 304 typCache map[uint64]types.Type 305 tparamIndex map[ident]types.Type 306 307 fake fakeFileSet 308 interfaceList []*types.Interface 309 310 // Arguments for calls to SetConstraint that are deferred due to recursive types 311 later []setConstraintArgs 312 313 indent int // for tracing support 314 } 315 316 func (p *iimporter) trace(format string, args ...interface{}) { 317 if !trace { 318 // Call sites should also be guarded, but having this check here allows 319 // easily enabling/disabling debug trace statements. 320 return 321 } 322 fmt.Printf(strings.Repeat("..", p.indent)+format+"\n", args...) 323 } 324 325 func (p *iimporter) doDecl(pkg *types.Package, name string) { 326 if debug { 327 p.trace("import decl %s", name) 328 p.indent++ 329 defer func() { 330 p.indent-- 331 p.trace("=> %s", name) 332 }() 333 } 334 // See if we've already imported this declaration. 335 if obj := pkg.Scope().Lookup(name); obj != nil { 336 return 337 } 338 339 off, ok := p.pkgIndex[pkg][name] 340 if !ok { 341 // In "shallow" mode, call back to the application to 342 // find the object and insert it into the package scope. 343 if p.insert != nil { 344 assert(pkg != p.localpkg) 345 p.insert(pkg, name) // "can't fail" 346 return 347 } 348 errorf("%v.%v not in index", pkg, name) 349 } 350 351 r := &importReader{p: p, currPkg: pkg} 352 r.declReader.Reset(p.declData[off:]) 353 354 r.obj(name) 355 } 356 357 func (p *iimporter) stringAt(off uint64) string { 358 if s, ok := p.stringCache[off]; ok { 359 return s 360 } 361 362 slen, n := binary.Uvarint(p.stringData[off:]) 363 if n <= 0 { 364 errorf("varint failed") 365 } 366 spos := off + uint64(n) 367 s := string(p.stringData[spos : spos+slen]) 368 p.stringCache[off] = s 369 return s 370 } 371 372 func (p *iimporter) fileAt(index uint64) *token.File { 373 file := p.fileCache[index] 374 if file == nil { 375 off := p.fileOffset[index] 376 file = p.decodeFile(intReader{bytes.NewReader(p.fileData[off:]), p.ipath}) 377 p.fileCache[index] = file 378 } 379 return file 380 } 381 382 func (p *iimporter) decodeFile(rd intReader) *token.File { 383 filename := p.stringAt(rd.uint64()) 384 size := int(rd.uint64()) 385 file := p.fake.fset.AddFile(filename, -1, size) 386 387 // SetLines requires a nondecreasing sequence. 388 // Because it is common for clients to derive the interval 389 // [start, start+len(name)] from a start position, and we 390 // want to ensure that the end offset is on the same line, 391 // we fill in the gaps of the sparse encoding with values 392 // that strictly increase by the largest possible amount. 393 // This allows us to avoid having to record the actual end 394 // offset of each needed line. 395 396 lines := make([]int, int(rd.uint64())) 397 var index, offset int 398 for i, n := 0, int(rd.uint64()); i < n; i++ { 399 index += int(rd.uint64()) 400 offset += int(rd.uint64()) 401 lines[index] = offset 402 403 // Ensure monotonicity between points. 404 for j := index - 1; j > 0 && lines[j] == 0; j-- { 405 lines[j] = lines[j+1] - 1 406 } 407 } 408 409 // Ensure monotonicity after last point. 410 for j := len(lines) - 1; j > 0 && lines[j] == 0; j-- { 411 size-- 412 lines[j] = size 413 } 414 415 if !file.SetLines(lines) { 416 errorf("SetLines failed: %d", lines) // can't happen 417 } 418 return file 419 } 420 421 func (p *iimporter) pkgAt(off uint64) *types.Package { 422 if pkg, ok := p.pkgCache[off]; ok { 423 return pkg 424 } 425 path := p.stringAt(off) 426 errorf("missing package %q in %q", path, p.ipath) 427 return nil 428 } 429 430 func (p *iimporter) typAt(off uint64, base *types.Named) types.Type { 431 if t, ok := p.typCache[off]; ok && canReuse(base, t) { 432 return t 433 } 434 435 if off < predeclReserved { 436 errorf("predeclared type missing from cache: %v", off) 437 } 438 439 r := &importReader{p: p} 440 r.declReader.Reset(p.declData[off-predeclReserved:]) 441 t := r.doType(base) 442 443 if canReuse(base, t) { 444 p.typCache[off] = t 445 } 446 return t 447 } 448 449 // canReuse reports whether the type rhs on the RHS of the declaration for def 450 // may be re-used. 451 // 452 // Specifically, if def is non-nil and rhs is an interface type with methods, it 453 // may not be re-used because we have a convention of setting the receiver type 454 // for interface methods to def. 455 func canReuse(def *types.Named, rhs types.Type) bool { 456 if def == nil { 457 return true 458 } 459 iface, _ := rhs.(*types.Interface) 460 if iface == nil { 461 return true 462 } 463 // Don't use iface.Empty() here as iface may not be complete. 464 return iface.NumEmbeddeds() == 0 && iface.NumExplicitMethods() == 0 465 } 466 467 type importReader struct { 468 p *iimporter 469 declReader bytes.Reader 470 currPkg *types.Package 471 prevFile string 472 prevLine int64 473 prevColumn int64 474 } 475 476 func (r *importReader) obj(name string) { 477 tag := r.byte() 478 pos := r.pos() 479 480 switch tag { 481 case 'A': 482 typ := r.typ() 483 484 r.declare(types.NewTypeName(pos, r.currPkg, name, typ)) 485 486 case 'C': 487 typ, val := r.value() 488 489 r.declare(types.NewConst(pos, r.currPkg, name, typ, val)) 490 491 case 'F', 'G': 492 var tparams []*typeparams.TypeParam 493 if tag == 'G' { 494 tparams = r.tparamList() 495 } 496 sig := r.signature(nil, nil, tparams) 497 r.declare(types.NewFunc(pos, r.currPkg, name, sig)) 498 499 case 'T', 'U': 500 // Types can be recursive. We need to setup a stub 501 // declaration before recursing. 502 obj := types.NewTypeName(pos, r.currPkg, name, nil) 503 named := types.NewNamed(obj, nil, nil) 504 // Declare obj before calling r.tparamList, so the new type name is recognized 505 // if used in the constraint of one of its own typeparams (see #48280). 506 r.declare(obj) 507 if tag == 'U' { 508 tparams := r.tparamList() 509 typeparams.SetForNamed(named, tparams) 510 } 511 512 underlying := r.p.typAt(r.uint64(), named).Underlying() 513 named.SetUnderlying(underlying) 514 515 if !isInterface(underlying) { 516 for n := r.uint64(); n > 0; n-- { 517 mpos := r.pos() 518 mname := r.ident() 519 recv := r.param() 520 521 // If the receiver has any targs, set those as the 522 // rparams of the method (since those are the 523 // typeparams being used in the method sig/body). 524 base := baseType(recv.Type()) 525 assert(base != nil) 526 targs := typeparams.NamedTypeArgs(base) 527 var rparams []*typeparams.TypeParam 528 if targs.Len() > 0 { 529 rparams = make([]*typeparams.TypeParam, targs.Len()) 530 for i := range rparams { 531 rparams[i] = targs.At(i).(*typeparams.TypeParam) 532 } 533 } 534 msig := r.signature(recv, rparams, nil) 535 536 named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig)) 537 } 538 } 539 540 case 'P': 541 // We need to "declare" a typeparam in order to have a name that 542 // can be referenced recursively (if needed) in the type param's 543 // bound. 544 if r.p.version < iexportVersionGenerics { 545 errorf("unexpected type param type") 546 } 547 name0 := tparamName(name) 548 tn := types.NewTypeName(pos, r.currPkg, name0, nil) 549 t := typeparams.NewTypeParam(tn, nil) 550 551 // To handle recursive references to the typeparam within its 552 // bound, save the partial type in tparamIndex before reading the bounds. 553 id := ident{r.currPkg, name} 554 r.p.tparamIndex[id] = t 555 var implicit bool 556 if r.p.version >= iexportVersionGo1_18 { 557 implicit = r.bool() 558 } 559 constraint := r.typ() 560 if implicit { 561 iface, _ := constraint.(*types.Interface) 562 if iface == nil { 563 errorf("non-interface constraint marked implicit") 564 } 565 typeparams.MarkImplicit(iface) 566 } 567 // The constraint type may not be complete, if we 568 // are in the middle of a type recursion involving type 569 // constraints. So, we defer SetConstraint until we have 570 // completely set up all types in ImportData. 571 r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint}) 572 573 case 'V': 574 typ := r.typ() 575 576 r.declare(types.NewVar(pos, r.currPkg, name, typ)) 577 578 default: 579 errorf("unexpected tag: %v", tag) 580 } 581 } 582 583 func (r *importReader) declare(obj types.Object) { 584 obj.Pkg().Scope().Insert(obj) 585 } 586 587 func (r *importReader) value() (typ types.Type, val constant.Value) { 588 typ = r.typ() 589 if r.p.version >= iexportVersionGo1_18 { 590 // TODO: add support for using the kind. 591 _ = constant.Kind(r.int64()) 592 } 593 594 switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType { 595 case types.IsBoolean: 596 val = constant.MakeBool(r.bool()) 597 598 case types.IsString: 599 val = constant.MakeString(r.string()) 600 601 case types.IsInteger: 602 var x big.Int 603 r.mpint(&x, b) 604 val = constant.Make(&x) 605 606 case types.IsFloat: 607 val = r.mpfloat(b) 608 609 case types.IsComplex: 610 re := r.mpfloat(b) 611 im := r.mpfloat(b) 612 val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) 613 614 default: 615 if b.Kind() == types.Invalid { 616 val = constant.MakeUnknown() 617 return 618 } 619 errorf("unexpected type %v", typ) // panics 620 panic("unreachable") 621 } 622 623 return 624 } 625 626 func intSize(b *types.Basic) (signed bool, maxBytes uint) { 627 if (b.Info() & types.IsUntyped) != 0 { 628 return true, 64 629 } 630 631 switch b.Kind() { 632 case types.Float32, types.Complex64: 633 return true, 3 634 case types.Float64, types.Complex128: 635 return true, 7 636 } 637 638 signed = (b.Info() & types.IsUnsigned) == 0 639 switch b.Kind() { 640 case types.Int8, types.Uint8: 641 maxBytes = 1 642 case types.Int16, types.Uint16: 643 maxBytes = 2 644 case types.Int32, types.Uint32: 645 maxBytes = 4 646 default: 647 maxBytes = 8 648 } 649 650 return 651 } 652 653 func (r *importReader) mpint(x *big.Int, typ *types.Basic) { 654 signed, maxBytes := intSize(typ) 655 656 maxSmall := 256 - maxBytes 657 if signed { 658 maxSmall = 256 - 2*maxBytes 659 } 660 if maxBytes == 1 { 661 maxSmall = 256 662 } 663 664 n, _ := r.declReader.ReadByte() 665 if uint(n) < maxSmall { 666 v := int64(n) 667 if signed { 668 v >>= 1 669 if n&1 != 0 { 670 v = ^v 671 } 672 } 673 x.SetInt64(v) 674 return 675 } 676 677 v := -n 678 if signed { 679 v = -(n &^ 1) >> 1 680 } 681 if v < 1 || uint(v) > maxBytes { 682 errorf("weird decoding: %v, %v => %v", n, signed, v) 683 } 684 b := make([]byte, v) 685 io.ReadFull(&r.declReader, b) 686 x.SetBytes(b) 687 if signed && n&1 != 0 { 688 x.Neg(x) 689 } 690 } 691 692 func (r *importReader) mpfloat(typ *types.Basic) constant.Value { 693 var mant big.Int 694 r.mpint(&mant, typ) 695 var f big.Float 696 f.SetInt(&mant) 697 if f.Sign() != 0 { 698 f.SetMantExp(&f, int(r.int64())) 699 } 700 return constant.Make(&f) 701 } 702 703 func (r *importReader) ident() string { 704 return r.string() 705 } 706 707 func (r *importReader) qualifiedIdent() (*types.Package, string) { 708 name := r.string() 709 pkg := r.pkg() 710 return pkg, name 711 } 712 713 func (r *importReader) pos() token.Pos { 714 if r.p.insert != nil { // shallow mode 715 return r.posv2() 716 } 717 if r.p.version >= iexportVersionPosCol { 718 r.posv1() 719 } else { 720 r.posv0() 721 } 722 723 if r.prevFile == "" && r.prevLine == 0 && r.prevColumn == 0 { 724 return token.NoPos 725 } 726 return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn)) 727 } 728 729 func (r *importReader) posv0() { 730 delta := r.int64() 731 if delta != deltaNewFile { 732 r.prevLine += delta 733 } else if l := r.int64(); l == -1 { 734 r.prevLine += deltaNewFile 735 } else { 736 r.prevFile = r.string() 737 r.prevLine = l 738 } 739 } 740 741 func (r *importReader) posv1() { 742 delta := r.int64() 743 r.prevColumn += delta >> 1 744 if delta&1 != 0 { 745 delta = r.int64() 746 r.prevLine += delta >> 1 747 if delta&1 != 0 { 748 r.prevFile = r.string() 749 } 750 } 751 } 752 753 func (r *importReader) posv2() token.Pos { 754 file := r.uint64() 755 if file == 0 { 756 return token.NoPos 757 } 758 tf := r.p.fileAt(file - 1) 759 return tf.Pos(int(r.uint64())) 760 } 761 762 func (r *importReader) typ() types.Type { 763 return r.p.typAt(r.uint64(), nil) 764 } 765 766 func isInterface(t types.Type) bool { 767 _, ok := t.(*types.Interface) 768 return ok 769 } 770 771 func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) } 772 func (r *importReader) string() string { return r.p.stringAt(r.uint64()) } 773 774 func (r *importReader) doType(base *types.Named) (res types.Type) { 775 k := r.kind() 776 if debug { 777 r.p.trace("importing type %d (base: %s)", k, base) 778 r.p.indent++ 779 defer func() { 780 r.p.indent-- 781 r.p.trace("=> %s", res) 782 }() 783 } 784 switch k { 785 default: 786 errorf("unexpected kind tag in %q: %v", r.p.ipath, k) 787 return nil 788 789 case definedType: 790 pkg, name := r.qualifiedIdent() 791 r.p.doDecl(pkg, name) 792 return pkg.Scope().Lookup(name).(*types.TypeName).Type() 793 case pointerType: 794 return types.NewPointer(r.typ()) 795 case sliceType: 796 return types.NewSlice(r.typ()) 797 case arrayType: 798 n := r.uint64() 799 return types.NewArray(r.typ(), int64(n)) 800 case chanType: 801 dir := chanDir(int(r.uint64())) 802 return types.NewChan(dir, r.typ()) 803 case mapType: 804 return types.NewMap(r.typ(), r.typ()) 805 case signatureType: 806 r.currPkg = r.pkg() 807 return r.signature(nil, nil, nil) 808 809 case structType: 810 r.currPkg = r.pkg() 811 812 fields := make([]*types.Var, r.uint64()) 813 tags := make([]string, len(fields)) 814 for i := range fields { 815 fpos := r.pos() 816 fname := r.ident() 817 ftyp := r.typ() 818 emb := r.bool() 819 tag := r.string() 820 821 fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb) 822 tags[i] = tag 823 } 824 return types.NewStruct(fields, tags) 825 826 case interfaceType: 827 r.currPkg = r.pkg() 828 829 embeddeds := make([]types.Type, r.uint64()) 830 for i := range embeddeds { 831 _ = r.pos() 832 embeddeds[i] = r.typ() 833 } 834 835 methods := make([]*types.Func, r.uint64()) 836 for i := range methods { 837 mpos := r.pos() 838 mname := r.ident() 839 840 // TODO(mdempsky): Matches bimport.go, but I 841 // don't agree with this. 842 var recv *types.Var 843 if base != nil { 844 recv = types.NewVar(token.NoPos, r.currPkg, "", base) 845 } 846 847 msig := r.signature(recv, nil, nil) 848 methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig) 849 } 850 851 typ := newInterface(methods, embeddeds) 852 r.p.interfaceList = append(r.p.interfaceList, typ) 853 return typ 854 855 case typeParamType: 856 if r.p.version < iexportVersionGenerics { 857 errorf("unexpected type param type") 858 } 859 pkg, name := r.qualifiedIdent() 860 id := ident{pkg, name} 861 if t, ok := r.p.tparamIndex[id]; ok { 862 // We're already in the process of importing this typeparam. 863 return t 864 } 865 // Otherwise, import the definition of the typeparam now. 866 r.p.doDecl(pkg, name) 867 return r.p.tparamIndex[id] 868 869 case instanceType: 870 if r.p.version < iexportVersionGenerics { 871 errorf("unexpected instantiation type") 872 } 873 // pos does not matter for instances: they are positioned on the original 874 // type. 875 _ = r.pos() 876 len := r.uint64() 877 targs := make([]types.Type, len) 878 for i := range targs { 879 targs[i] = r.typ() 880 } 881 baseType := r.typ() 882 // The imported instantiated type doesn't include any methods, so 883 // we must always use the methods of the base (orig) type. 884 // TODO provide a non-nil *Environment 885 t, _ := typeparams.Instantiate(nil, baseType, targs, false) 886 return t 887 888 case unionType: 889 if r.p.version < iexportVersionGenerics { 890 errorf("unexpected instantiation type") 891 } 892 terms := make([]*typeparams.Term, r.uint64()) 893 for i := range terms { 894 terms[i] = typeparams.NewTerm(r.bool(), r.typ()) 895 } 896 return typeparams.NewUnion(terms) 897 } 898 } 899 900 func (r *importReader) kind() itag { 901 return itag(r.uint64()) 902 } 903 904 func (r *importReader) signature(recv *types.Var, rparams []*typeparams.TypeParam, tparams []*typeparams.TypeParam) *types.Signature { 905 params := r.paramList() 906 results := r.paramList() 907 variadic := params.Len() > 0 && r.bool() 908 return typeparams.NewSignatureType(recv, rparams, tparams, params, results, variadic) 909 } 910 911 func (r *importReader) tparamList() []*typeparams.TypeParam { 912 n := r.uint64() 913 if n == 0 { 914 return nil 915 } 916 xs := make([]*typeparams.TypeParam, n) 917 for i := range xs { 918 // Note: the standard library importer is tolerant of nil types here, 919 // though would panic in SetTypeParams. 920 xs[i] = r.typ().(*typeparams.TypeParam) 921 } 922 return xs 923 } 924 925 func (r *importReader) paramList() *types.Tuple { 926 xs := make([]*types.Var, r.uint64()) 927 for i := range xs { 928 xs[i] = r.param() 929 } 930 return types.NewTuple(xs...) 931 } 932 933 func (r *importReader) param() *types.Var { 934 pos := r.pos() 935 name := r.ident() 936 typ := r.typ() 937 return types.NewParam(pos, r.currPkg, name, typ) 938 } 939 940 func (r *importReader) bool() bool { 941 return r.uint64() != 0 942 } 943 944 func (r *importReader) int64() int64 { 945 n, err := binary.ReadVarint(&r.declReader) 946 if err != nil { 947 errorf("readVarint: %v", err) 948 } 949 return n 950 } 951 952 func (r *importReader) uint64() uint64 { 953 n, err := binary.ReadUvarint(&r.declReader) 954 if err != nil { 955 errorf("readUvarint: %v", err) 956 } 957 return n 958 } 959 960 func (r *importReader) byte() byte { 961 x, err := r.declReader.ReadByte() 962 if err != nil { 963 errorf("declReader.ReadByte: %v", err) 964 } 965 return x 966 } 967 968 func baseType(typ types.Type) *types.Named { 969 // pointer receivers are never types.Named types 970 if p, _ := typ.(*types.Pointer); p != nil { 971 typ = p.Elem() 972 } 973 // receiver base types are always (possibly generic) types.Named types 974 n, _ := typ.(*types.Named) 975 return n 976 }