So the net package doesn't indirectly depend on unicode tables.
But we're still not quite there, because a new test added in this CL
reveals that we still have a path to unicode via:
deps_test.go:570:
TODO(issue 30440): policy violation: net => sort => reflect => unicode
Updates #30440
Change-Id: I710c2061dfbaa8e866c92e6c824bd8df35784165
Reviewed-on: https://go-review.googlesource.com/c/go/+/169080
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
import (
"errors"
- "fmt"
"internal/reflectlite"
"sync"
"time"
return err
}
+type stringer interface {
+ String() string
+}
+
+func contextName(c Context) string {
+ if s, ok := c.(stringer); ok {
+ return s.String()
+ }
+ return reflectlite.TypeOf(c).String()
+}
+
func (c *cancelCtx) String() string {
- return fmt.Sprintf("%v.WithCancel", c.Context)
+ return contextName(c.Context) + ".WithCancel"
}
// cancel closes c.done, cancels each of c's children, and, if
}
func (c *timerCtx) String() string {
- return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, time.Until(c.deadline))
+ return contextName(c.cancelCtx.Context) + ".WithDeadline(" +
+ c.deadline.String() + " [" +
+ time.Until(c.deadline).String() + "])"
}
func (c *timerCtx) cancel(removeFromParent bool, err error) {
key, val interface{}
}
+// stringify tries a bit to stringify v, without using fmt, since we don't
+// want context depending on the unicode tables. This is only used by
+// *valueCtx.String().
+func stringify(v interface{}) string {
+ if s, ok := v.(stringer); ok {
+ return s.String()
+ }
+ if s, ok := v.(string); ok {
+ return s
+ }
+ return "<not Stringer>"
+}
+
func (c *valueCtx) String() string {
- return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
+ return contextName(c.Context) + ".WithValue(type " +
+ reflectlite.TypeOf(c.key).String() +
+ ", val " + stringify(c.val) + ")"
}
func (c *valueCtx) Value(key interface{}) interface{} {
c1 := WithValue(Background(), k1, "c1k1")
check(c1, "c1", "c1k1", "", "")
- if got, want := fmt.Sprint(c1), `context.Background.WithValue(1, "c1k1")`; got != want {
+ if got, want := fmt.Sprint(c1), `context.Background.WithValue(type context.key1, val c1k1)`; got != want {
t.Errorf("c.String() = %q want %q", got, want)
}
"compress/gzip": {"L4", "compress/flate"},
"compress/lzw": {"L4"},
"compress/zlib": {"L4", "compress/flate"},
- "context": {"errors", "fmt", "internal/reflectlite", "sync", "time"},
+ "context": {"errors", "internal/reflectlite", "sync", "time"},
"database/sql": {"L4", "container/list", "context", "database/sql/driver", "database/sql/internal"},
"database/sql/driver": {"L4", "context", "time", "database/sql/internal"},
"debug/dwarf": {"L4"},
}
sort.Strings(all)
+ sawImport := map[string]map[string]bool{} // from package => to package => true
+
for _, pkg := range all {
imports, err := findImports(pkg)
if err != nil {
t.Error(err)
continue
}
+ if sawImport[pkg] == nil {
+ sawImport[pkg] = map[string]bool{}
+ }
ok := allowed(pkg)
var bad []string
for _, imp := range imports {
+ sawImport[pkg][imp] = true
if !ok[imp] {
bad = append(bad, imp)
}
t.Errorf("unexpected dependency: %s imports %v", pkg, bad)
}
}
+
+ // depPath returns the path between the given from and to packages.
+ // It returns the empty string if there's no dependency path.
+ var depPath func(string, string) string
+ depPath = func(from, to string) string {
+ if sawImport[from][to] {
+ return from + " => " + to
+ }
+ for pkg := range sawImport[from] {
+ if p := depPath(pkg, to); p != "" {
+ return from + " => " + p
+ }
+ }
+ return ""
+ }
+
+ // Also test some high-level policy goals are being met by not finding
+ // these dependency paths:
+ badPaths := []struct{ from, to string }{
+ {"net", "unicode"},
+ }
+
+ for _, path := range badPaths {
+ if how := depPath(path.from, path.to); how != "" {
+ t.Logf("TODO(issue 30440): policy violation: %s", how)
+ }
+ }
+
}
var buildIgnore = []byte("\n// +build ignore")
// Comparable reports whether values of this type are comparable.
Comparable() bool
+ // String returns a string representation of the type.
+ // The string representation may use shortened package names
+ // (e.g., base64 instead of "encoding/base64") and is not
+ // guaranteed to be unique among types. To test for type identity,
+ // compare the Types directly.
+ String() string
+
// Elem returns a type's element type.
// It panics if the type's Kind is not Ptr.
Elem() Type