gotypes: stop directing people to golang.org/x/tools/go/loader

It is very obsolete. Use go/packages instead.

Also, add a go generate command to weave the README.

Fixes golang/go#60593

Change-Id: Ifaf3ffa588dc3e65fb1e96b39b249a9084d66451
Reviewed-on: https://go-review.googlesource.com/c/example/+/534695
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Auto-Submit: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Commit-Queue: Alan Donovan <adonovan@google.com>
diff --git a/go.mod b/go.mod
index 1996732..e876fb9 100644
--- a/go.mod
+++ b/go.mod
@@ -2,6 +2,10 @@
 
 go 1.18
 
-require golang.org/x/tools v0.0.0-20210112183307-1e6ecd4bf1b0
+require golang.org/x/tools v0.14.0
 
-require gopkg.in/yaml.v3 v3.0.1 // indirect
+require (
+	golang.org/x/mod v0.13.0 // indirect
+	golang.org/x/sys v0.13.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1
+)
diff --git a/go.sum b/go.sum
index 114d0dc..25e95bd 100644
--- a/go.sum
+++ b/go.sum
@@ -1,27 +1,11 @@
-github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
-golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20210112183307-1e6ecd4bf1b0 h1:iZhiQWrjyEuXG495d9MXkcmhrlxbQyGp0uNBY+YBZDk=
-golang.org/x/tools v0.0.0-20210112183307-1e6ecd4bf1b0/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
+golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
+golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
+golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/gotypes/README.md b/gotypes/README.md
index ee12bef..9923e10 100644
--- a/gotypes/README.md
+++ b/gotypes/README.md
@@ -86,7 +86,7 @@
 
 
 
-The [`golang.org/x/tools/go/loader` package](https://pkg.go.dev/golang.org/x/tools/go/loader)
+The [`golang.org/x/tools/go/packages` package](https://pkg.go.dev/golang.org/x/tools/go/packages)
 from the `x/tools` repository is a client of the type
 checker that loads, parses, and type-checks a complete Go program from
 source code.
@@ -2190,13 +2190,11 @@
 ```
 var bytesFlag = flag.Int("bytes", 48, "maximum parameter size in bytes")
 
-var sizeof = (&types.StdSizes{8, 8}).Sizeof // the sizeof function
-
-func PrintHugeParams(fset *token.FileSet, info *types.Info, files []*ast.File) {
+func PrintHugeParams(fset *token.FileSet, info *types.Info, sizes types.Sizes, files []*ast.File) {
 	checkTuple := func(descr string, tuple *types.Tuple) {
 		for i := 0; i < tuple.Len(); i++ {
 			v := tuple.At(i)
-			if sz := sizeof(v.Type()); sz > int64(*bytesFlag) {
+			if sz := sizes.Sizeof(v.Type()); sz > int64(*bytesFlag) {
 				fmt.Printf("%s: %q %s: %s = %d bytes\n",
 					fset.Position(v.Pos()),
 					v.Name(), descr, v.Type(), sz)
@@ -2296,25 +2294,28 @@
 
 
 
-The [`golang.org/tools/x/go/loader` package](https://pkg.go.dev/golang.org/x/tools/go/loader)
-provides an alternative `Importer` that addresses
-some of these problems.
-It loads a complete program from source, performing
-[`cgo`](https://golang.org/cmd/cgo/cgo) preprocessing if
-necessary, followed by parsing and type-checking.
+The [`golang.org/tools/x/go/packages`
+package](https://pkg.go.dev/golang.org/x/tools/go/packages) provides
+a comprehensive means of loading packages from source.
+It runs `go list` to query the project metadata,
+performs [`cgo`](https://golang.org/cmd/cgo/cgo) preprocessing if necessary,
+reads and parses the source files,
+and optionally type-checks each package.
+It can load a whole program from source, or load just the initial
+packages from source and load all their dependencies from export data.
 It loads independent packages in parallel to hide I/O latency, and
 detects and reports import cycles.
 For each package, it provides the `types.Package` containing the
 package's lexical environment, the list of `ast.File` syntax
 trees for each file in the package, the `types.Info` containing
-type information for each syntax node, and a list of type errors
-associated with that package.
-(Please be aware that the `go/loader` package's API is likely to
-change before it finally stabilizes.)
+type information for each syntax node, a list of type errors
+associated with that package, and other information too.
+Since some of this information is more costly to compute,
+the API allows you to select which parts you need,
+but since this is a tutorial we'll generally request complete
+information so that it is easier to explore.
 
-
-
-The `doc` program below demonstrates a simple use of the loader.
+The `doc` program below demonstrates a simple use of `go/packages`.
 It is a rudimentary implementation of `go doc` that prints the type,
 methods, and documentation of the package-level object specified on
 the command line.
@@ -2324,10 +2325,10 @@
 ```
 $ ./doc net/http File
 type net/http.File interface{Readdir(count int) ([]os.FileInfo, error); Seek(offset int64, whence int) (int64, error); Stat() (os.FileInfo, error); io.Closer; io.Reader}
-/go/src/io/io.go:92:2: method (net/http.File) Close() error
-/go/src/io/io.go:71:2: method (net/http.File) Read(p []byte) (n int, err error)
+$GOROOT/src/io/io.go:92:2: method (net/http.File) Close() error
+$GOROOT/src/io/io.go:71:2: method (net/http.File) Read(p []byte) (n int, err error)
 /go/src/net/http/fs.go:65:2: method (net/http.File) Readdir(count int) ([]os.FileInfo, error)
-/go/src/net/http/fs.go:66:2: method (net/http.File) Seek(offset int64, whence int) (int64, error)
+$GOROOT/src/net/http/fs.go:66:2: method (net/http.File) Seek(offset int64, whence int) (int64, error)
 /go/src/net/http/fs.go:67:2: method (net/http.File) Stat() (os.FileInfo, error)
 
  A File is returned by a FileSystem's Open method and can be
@@ -2340,8 +2341,10 @@
 Observe that it prints the correct location of each method
 declaration, even though, due to embedding, some of
 `http.File`'s methods were declared in another package.
-Here's the first part of the program, showing how to load an entire
-program starting from the single package, `pkgpath`:
+Here's the first part of the program, showing how to load
+complete type information including typed syntax,
+for a single package `pkgpath`,
+plus exported type information for its dependencies.
 
 
 	// go get golang.org/x/example/gotypes/doc
@@ -2349,24 +2352,28 @@
 ```
 pkgpath, name := os.Args[1], os.Args[2]
 
-// The loader loads a complete Go program from source code.
-conf := loader.Config{ParserMode: parser.ParseComments}
-conf.Import(pkgpath)
-lprog, err := conf.Load()
+// Load complete type information for the specified packages,
+// along with type-annotated syntax.
+// Types for dependencies are loaded from export data.
+conf := &packages.Config{Mode: packages.LoadSyntax}
+pkgs, err := packages.Load(conf, pkgpath)
 if err != nil {
-	log.Fatal(err) // load error
+	log.Fatal(err) // failed to load anything
+}
+if packages.PrintErrors(pkgs) > 0 {
+	os.Exit(1) // some packages contained errors
 }
 
 // Find the package and package-level object.
-pkg := lprog.Package(pkgpath).Pkg
-obj := pkg.Scope().Lookup(name)
+pkg := pkgs[0]
+obj := pkg.Types.Scope().Lookup(name)
 if obj == nil {
-	log.Fatalf("%s.%s not found", pkg.Path(), name)
+	log.Fatalf("%s.%s not found", pkg.Types.Path(), name)
 }
 ```
 
 
-Notice that we instructed the parser to retain comments during parsing.
+By default, `go/packages`, instructs the parser to retain comments during parsing.
 The rest of the program prints the output:
 
 
@@ -2376,20 +2383,26 @@
 // Print the object and its methods (incl. location of definition).
 fmt.Println(obj)
 for _, sel := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {
-	fmt.Printf("%s: %s\n", lprog.Fset.Position(sel.Obj().Pos()), sel)
+	fmt.Printf("%s: %s\n", pkg.Fset.Position(sel.Obj().Pos()), sel)
 }
 
 // Find the path from the root of the AST to the object's position.
 // Walk up to the enclosing ast.Decl for the doc comment.
-_, path, _ := lprog.PathEnclosingInterval(obj.Pos(), obj.Pos())
-for _, n := range path {
-	switch n := n.(type) {
-	case *ast.GenDecl:
-		fmt.Println("\n", n.Doc.Text())
-		return
-	case *ast.FuncDecl:
-		fmt.Println("\n", n.Doc.Text())
-		return
+for _, file := range pkg.Syntax {
+	pos := obj.Pos()
+	if !(file.FileStart <= pos && pos < file.FileEnd) {
+		continue // not in this file
+	}
+	path, _ := astutil.PathEnclosingInterval(file, pos, pos)
+	for _, n := range path {
+		switch n := n.(type) {
+		case *ast.GenDecl:
+			fmt.Println("\n", n.Doc.Text())
+			return
+		case *ast.FuncDecl:
+			fmt.Println("\n", n.Doc.Text())
+			return
+		}
 	}
 }
 ```
@@ -2535,11 +2548,10 @@
 [`astutil.PathEnclosingInterval`](https://pkg.go.dev/golang.org/x/tools/go/ast/astutil#PathEnclosingInterval).
 It returns the enclosing `ast.Node`, and all its ancestors up to
 the root of the file.
-You must know which file `*ast.File` the `token.Pos` belongs to.
-Alternatively, you can search an entire program loaded by the
-`loader` package, using
-[`(*loader.Program).PathEnclosingInterval`](https://pkg.go.dev/golang.org/x/tools/go/loader#Program.PathEnclosingInterval).
-
+If you don't know which file `*ast.File` the `token.Pos` belongs to,
+you can iterate over the parsed files of the package and quickly test
+whether its position falls within the file's range,
+from `File.FileStart` to `File.FileEnd`.
 
 
 To map **from an `Object` to its declaring syntax**, call
diff --git a/gotypes/doc/main.go b/gotypes/doc/main.go
index 3140f47..8e7027f 100644
--- a/gotypes/doc/main.go
+++ b/gotypes/doc/main.go
@@ -4,12 +4,11 @@
 import (
 	"fmt"
 	"go/ast"
-	"go/parser"
 	"log"
 	"os"
 
-	// TODO: these will use std go/types after Feb 2016
-	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/packages"
 	"golang.org/x/tools/go/types/typeutil"
 )
 
@@ -20,19 +19,23 @@
 	//!+part1
 	pkgpath, name := os.Args[1], os.Args[2]
 
-	// The loader loads a complete Go program from source code.
-	conf := loader.Config{ParserMode: parser.ParseComments}
-	conf.Import(pkgpath)
-	lprog, err := conf.Load()
+	// Load complete type information for the specified packages,
+	// along with type-annotated syntax.
+	// Types for dependencies are loaded from export data.
+	conf := &packages.Config{Mode: packages.LoadSyntax}
+	pkgs, err := packages.Load(conf, pkgpath)
 	if err != nil {
-		log.Fatal(err) // load error
+		log.Fatal(err) // failed to load anything
+	}
+	if packages.PrintErrors(pkgs) > 0 {
+		os.Exit(1) // some packages contained errors
 	}
 
 	// Find the package and package-level object.
-	pkg := lprog.Package(pkgpath).Pkg
-	obj := pkg.Scope().Lookup(name)
+	pkg := pkgs[0]
+	obj := pkg.Types.Scope().Lookup(name)
 	if obj == nil {
-		log.Fatalf("%s.%s not found", pkg.Path(), name)
+		log.Fatalf("%s.%s not found", pkg.Types.Path(), name)
 	}
 	//!-part1
 	//!+part2
@@ -40,33 +43,42 @@
 	// Print the object and its methods (incl. location of definition).
 	fmt.Println(obj)
 	for _, sel := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {
-		fmt.Printf("%s: %s\n", lprog.Fset.Position(sel.Obj().Pos()), sel)
+		fmt.Printf("%s: %s\n", pkg.Fset.Position(sel.Obj().Pos()), sel)
 	}
 
 	// Find the path from the root of the AST to the object's position.
 	// Walk up to the enclosing ast.Decl for the doc comment.
-	_, path, _ := lprog.PathEnclosingInterval(obj.Pos(), obj.Pos())
-	for _, n := range path {
-		switch n := n.(type) {
-		case *ast.GenDecl:
-			fmt.Println("\n", n.Doc.Text())
-			return
-		case *ast.FuncDecl:
-			fmt.Println("\n", n.Doc.Text())
-			return
+	for _, file := range pkg.Syntax {
+		pos := obj.Pos()
+		if !(file.FileStart <= pos && pos < file.FileEnd) {
+			continue // not in this file
+		}
+		path, _ := astutil.PathEnclosingInterval(file, pos, pos)
+		for _, n := range path {
+			switch n := n.(type) {
+			case *ast.GenDecl:
+				fmt.Println("\n", n.Doc.Text())
+				return
+			case *ast.FuncDecl:
+				fmt.Println("\n", n.Doc.Text())
+				return
+			}
 		}
 	}
 	//!-part2
 }
 
+// (The $GOROOT below is the actual string that appears in file names
+// loaded from export data for packages in the standard library.)
+
 /*
 //!+output
 $ ./doc net/http File
 type net/http.File interface{Readdir(count int) ([]os.FileInfo, error); Seek(offset int64, whence int) (int64, error); Stat() (os.FileInfo, error); io.Closer; io.Reader}
-/go/src/io/io.go:92:2: method (net/http.File) Close() error
-/go/src/io/io.go:71:2: method (net/http.File) Read(p []byte) (n int, err error)
+$GOROOT/src/io/io.go:92:2: method (net/http.File) Close() error
+$GOROOT/src/io/io.go:71:2: method (net/http.File) Read(p []byte) (n int, err error)
 /go/src/net/http/fs.go:65:2: method (net/http.File) Readdir(count int) ([]os.FileInfo, error)
-/go/src/net/http/fs.go:66:2: method (net/http.File) Seek(offset int64, whence int) (int64, error)
+$GOROOT/src/net/http/fs.go:66:2: method (net/http.File) Seek(offset int64, whence int) (int64, error)
 /go/src/net/http/fs.go:67:2: method (net/http.File) Stat() (os.FileInfo, error)
 
  A File is returned by a FileSystem's Open method and can be
diff --git a/gotypes/gen.go b/gotypes/gen.go
new file mode 100644
index 0000000..bce6efe
--- /dev/null
+++ b/gotypes/gen.go
@@ -0,0 +1,3 @@
+//go:generate bash -c "go run ../internal/cmd/weave/weave.go ./go-types.md > README.md"
+
+package gotypes
diff --git a/gotypes/go-types.md b/gotypes/go-types.md
index 4cd3d81..ce5a430 100644
--- a/gotypes/go-types.md
+++ b/gotypes/go-types.md
@@ -62,7 +62,7 @@
 
 
 
-The [`golang.org/x/tools/go/loader` package](https://pkg.go.dev/golang.org/x/tools/go/loader)
+The [`golang.org/x/tools/go/packages` package](https://pkg.go.dev/golang.org/x/tools/go/packages)
 from the `x/tools` repository is a client of the type
 checker that loads, parses, and type-checks a complete Go program from
 source code.
@@ -1850,25 +1850,28 @@
 
 
 
-The [`golang.org/tools/x/go/loader` package](https://pkg.go.dev/golang.org/x/tools/go/loader)
-provides an alternative `Importer` that addresses
-some of these problems.
-It loads a complete program from source, performing
-[`cgo`](https://golang.org/cmd/cgo/cgo) preprocessing if
-necessary, followed by parsing and type-checking.
+The [`golang.org/tools/x/go/packages`
+package](https://pkg.go.dev/golang.org/x/tools/go/packages) provides
+a comprehensive means of loading packages from source.
+It runs `go list` to query the project metadata,
+performs [`cgo`](https://golang.org/cmd/cgo/cgo) preprocessing if necessary,
+reads and parses the source files,
+and optionally type-checks each package.
+It can load a whole program from source, or load just the initial
+packages from source and load all their dependencies from export data.
 It loads independent packages in parallel to hide I/O latency, and
 detects and reports import cycles.
 For each package, it provides the `types.Package` containing the
 package's lexical environment, the list of `ast.File` syntax
 trees for each file in the package, the `types.Info` containing
-type information for each syntax node, and a list of type errors
-associated with that package.
-(Please be aware that the `go/loader` package's API is likely to
-change before it finally stabilizes.)
+type information for each syntax node, a list of type errors
+associated with that package, and other information too.
+Since some of this information is more costly to compute,
+the API allows you to select which parts you need,
+but since this is a tutorial we'll generally request complete
+information so that it is easier to explore.
 
-
-
-The `doc` program below demonstrates a simple use of the loader.
+The `doc` program below demonstrates a simple use of `go/packages`.
 It is a rudimentary implementation of `go doc` that prints the type,
 methods, and documentation of the package-level object specified on
 the command line.
@@ -1881,14 +1884,16 @@
 Observe that it prints the correct location of each method
 declaration, even though, due to embedding, some of
 `http.File`'s methods were declared in another package.
-Here's the first part of the program, showing how to load an entire
-program starting from the single package, `pkgpath`:
+Here's the first part of the program, showing how to load
+complete type information including typed syntax,
+for a single package `pkgpath`,
+plus exported type information for its dependencies.
 
 
 %include doc/main.go part1
 
 
-Notice that we instructed the parser to retain comments during parsing.
+By default, `go/packages`, instructs the parser to retain comments during parsing.
 The rest of the program prints the output:
 
 
@@ -2035,11 +2040,10 @@
 [`astutil.PathEnclosingInterval`](https://pkg.go.dev/golang.org/x/tools/go/ast/astutil#PathEnclosingInterval).
 It returns the enclosing `ast.Node`, and all its ancestors up to
 the root of the file.
-You must know which file `*ast.File` the `token.Pos` belongs to.
-Alternatively, you can search an entire program loaded by the
-`loader` package, using
-[`(*loader.Program).PathEnclosingInterval`](https://pkg.go.dev/golang.org/x/tools/go/loader#Program.PathEnclosingInterval).
-
+If you don't know which file `*ast.File` the `token.Pos` belongs to,
+you can iterate over the parsed files of the package and quickly test
+whether its position falls within the file's range,
+from `File.FileStart` to `File.FileEnd`.
 
 
 To map **from an `Object` to its declaring syntax**, call
diff --git a/gotypes/hugeparam/main.go b/gotypes/hugeparam/main.go
index 80fc47e..9577a09 100644
--- a/gotypes/hugeparam/main.go
+++ b/gotypes/hugeparam/main.go
@@ -12,20 +12,19 @@
 	"go/token"
 	"go/types"
 	"log"
+	"os"
 
-	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/packages"
 )
 
 // !+
 var bytesFlag = flag.Int("bytes", 48, "maximum parameter size in bytes")
 
-var sizeof = (&types.StdSizes{8, 8}).Sizeof // the sizeof function
-
-func PrintHugeParams(fset *token.FileSet, info *types.Info, files []*ast.File) {
+func PrintHugeParams(fset *token.FileSet, info *types.Info, sizes types.Sizes, files []*ast.File) {
 	checkTuple := func(descr string, tuple *types.Tuple) {
 		for i := 0; i < tuple.Len(); i++ {
 			v := tuple.At(i)
-			if sz := sizeof(v.Type()); sz > int64(*bytesFlag) {
+			if sz := sizes.Sizeof(v.Type()); sz > int64(*bytesFlag) {
 				fmt.Printf("%s: %q %s: %s = %d bytes\n",
 					fset.Position(v.Pos()),
 					v.Name(), descr, v.Type(), sz)
@@ -54,19 +53,20 @@
 func main() {
 	flag.Parse()
 
-	// The loader loads a complete Go program from source code.
-	var conf loader.Config
-	_, err := conf.FromArgs(flag.Args(), false)
+	// Load complete type information for the specified packages,
+	// along with type-annotated syntax and the "sizeof" function.
+	// Types for dependencies are loaded from export data.
+	conf := &packages.Config{Mode: packages.LoadSyntax}
+	pkgs, err := packages.Load(conf, flag.Args()...)
 	if err != nil {
-		log.Fatal(err) // command syntax error
+		log.Fatal(err) // failed to load anything
 	}
-	lprog, err := conf.Load()
-	if err != nil {
-		log.Fatal(err) // load error
+	if packages.PrintErrors(pkgs) > 0 {
+		os.Exit(1) // some packages contained errors
 	}
 
-	for _, info := range lprog.InitialPackages() {
-		PrintHugeParams(lprog.Fset, &info.Info, info.Files)
+	for _, pkg := range pkgs {
+		PrintHugeParams(pkg.Fset, pkg.TypesInfo, pkg.TypesSizes, pkg.Syntax)
 	}
 }
 
diff --git a/gotypes/skeleton/main.go b/gotypes/skeleton/main.go
index 1e6ee82..ab79b2c 100644
--- a/gotypes/skeleton/main.go
+++ b/gotypes/skeleton/main.go
@@ -20,7 +20,7 @@
 	"unicode"
 	"unicode/utf8"
 
-	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/packages"
 )
 
 const usage = "Usage: skeleton <package> <interface> <concrete>"
@@ -76,15 +76,16 @@
 	}
 	pkgpath, ifacename, concname := os.Args[1], os.Args[2], os.Args[3]
 
-	// The loader loads a complete Go program from source code.
-	var conf loader.Config
-	conf.Import(pkgpath)
-	lprog, err := conf.Load()
+	// Load only exported type information for the specified package.
+	conf := &packages.Config{Mode: packages.NeedTypes}
+	pkgs, err := packages.Load(conf, pkgpath)
 	if err != nil {
-		log.Fatal(err) // load error
+		log.Fatal(err) // failed to load anything
 	}
-	pkg := lprog.Package(pkgpath).Pkg
-	if err := PrintSkeleton(pkg, ifacename, concname); err != nil {
+	if packages.PrintErrors(pkgs) > 0 {
+		os.Exit(1) // some packages contained errors
+	}
+	if err := PrintSkeleton(pkgs[0].Types, ifacename, concname); err != nil {
 		log.Fatal(err)
 	}
 }