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