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