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