tg.grepStdout(`^runtime/cgo$`, "missing runtime/cgo")
tg.run("list", "-deps", "-f", "{{if .DepOnly}}{{.ImportPath}}{{end}}", "sort")
- tg.grepStdout(`^reflect$`, "missing reflect")
+ tg.grepStdout(`^internal/reflectlite$`, "missing internal/reflectlite")
tg.grepStdoutNot(`^sort`, "unexpected sort")
}
return p
}
+ // The sort package depends on internal/reflectlite, but during bootstrap
+ // the path rewriting causes the normal internal checks to fail.
+ // Instead, just ignore the internal rules during bootstrap.
+ if p.Standard && strings.HasPrefix(importerPath, "bootstrap/") {
+ return p
+ }
+
// The stack includes p.ImportPath.
// If that's the only thing on the stack, we started
// with a name given on the command line, not an
"image/color/palette": {"L2", "image/color"},
"internal/fmtsort": {"reflect", "sort"},
"reflect": {"L2"},
- "sort": {"reflect"},
+ "sort": {"internal/reflectlite"},
"L3": {
"L2",
// these dependency paths:
badPaths := []struct{ from, to string }{
{"net", "unicode"},
+ {"os", "unicode"},
}
for _, path := range badPaths {
if how := depPath(path.from, path.to); how != "" {
- t.Logf("TODO(issue 30440): policy violation: %s", how)
+ t.Errorf("policy violation: %s", how)
}
}
var haveImport = map[string]bool{}
for _, file := range files {
name := file.Name()
+ if name == "slice_pre113.go" {
+ // This file is ignored by build tags which aren't
+ // handled by this findImports func.
+ continue
+ }
if !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") {
continue
}
--- /dev/null
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package reflectlite
+
+import "unsafe"
+
+// Swapper returns a function that swaps the elements in the provided
+// slice.
+//
+// Swapper panics if the provided interface is not a slice.
+func Swapper(slice interface{}) func(i, j int) {
+ v := ValueOf(slice)
+ if v.Kind() != Slice {
+ panic(&ValueError{Method: "Swapper", Kind: v.Kind()})
+ }
+ // Fast path for slices of size 0 and 1. Nothing to swap.
+ switch v.Len() {
+ case 0:
+ return func(i, j int) { panic("reflect: slice index out of range") }
+ case 1:
+ return func(i, j int) {
+ if i != 0 || j != 0 {
+ panic("reflect: slice index out of range")
+ }
+ }
+ }
+
+ typ := v.Type().Elem().(*rtype)
+ size := typ.Size()
+ hasPtr := typ.ptrdata != 0
+
+ // Some common & small cases, without using memmove:
+ if hasPtr {
+ if size == ptrSize {
+ ps := *(*[]unsafe.Pointer)(v.ptr)
+ return func(i, j int) { ps[i], ps[j] = ps[j], ps[i] }
+ }
+ if typ.Kind() == String {
+ ss := *(*[]string)(v.ptr)
+ return func(i, j int) { ss[i], ss[j] = ss[j], ss[i] }
+ }
+ } else {
+ switch size {
+ case 8:
+ is := *(*[]int64)(v.ptr)
+ return func(i, j int) { is[i], is[j] = is[j], is[i] }
+ case 4:
+ is := *(*[]int32)(v.ptr)
+ return func(i, j int) { is[i], is[j] = is[j], is[i] }
+ case 2:
+ is := *(*[]int16)(v.ptr)
+ return func(i, j int) { is[i], is[j] = is[j], is[i] }
+ case 1:
+ is := *(*[]int8)(v.ptr)
+ return func(i, j int) { is[i], is[j] = is[j], is[i] }
+ }
+ }
+
+ s := (*sliceHeader)(v.ptr)
+ tmp := unsafe_New(typ) // swap scratch space
+
+ return func(i, j int) {
+ if uint(i) >= uint(s.Len) || uint(j) >= uint(s.Len) {
+ panic("reflect: slice index out of range")
+ }
+ val1 := arrayAt(s.Data, i, size, "i < s.Len")
+ val2 := arrayAt(s.Data, j, size, "j < s.Len")
+ typedmemmove(typ, tmp, val1)
+ typedmemmove(typ, val1, val2)
+ typedmemmove(typ, val2, tmp)
+ }
+}
// will be the empty string.
PkgPath() string
+ // Size returns the number of bytes needed to store
+ // a value of the given type; it is analogous to unsafe.Sizeof.
+ Size() uintptr
+
// Kind returns the specific kind of this type.
Kind() Kind
return s
}
+func (t *rtype) Size() uintptr { return t.size }
+
func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
+func (t *rtype) pointers() bool { return t.ptrdata != 0 }
+
func (t *rtype) common() *rtype { return t }
func (t *rtype) exportedMethods() []method {
"unsafe"
)
+const ptrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const
+
// Value is the reflection interface to a Go value.
//
// Not all methods apply to all kinds of values. Restrictions,
return 0
}
+// pointer returns the underlying pointer represented by v.
+// v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer
+func (v Value) pointer() unsafe.Pointer {
+ if v.typ.size != ptrSize || !v.typ.pointers() {
+ panic("can't call pointer on a non-pointer Value")
+ }
+ if v.flag&flagIndir != 0 {
+ return *(*unsafe.Pointer)(v.ptr)
+ }
+ return v.ptr
+}
+
// packEface converts v to the empty interface.
func packEface(v Value) interface{} {
t := v.typ
return v.kind()
}
+// implemented in runtime:
+func chanlen(unsafe.Pointer) int
+func maplen(unsafe.Pointer) int
+
+// Len returns v's length.
+// It panics if v's Kind is not Array, Chan, Map, Slice, or String.
+func (v Value) Len() int {
+ k := v.kind()
+ switch k {
+ case Array:
+ tt := (*arrayType)(unsafe.Pointer(v.typ))
+ return int(tt.len)
+ case Chan:
+ return chanlen(v.pointer())
+ case Map:
+ return maplen(v.pointer())
+ case Slice:
+ // Slice is bigger than a word; assume flagIndir.
+ return (*sliceHeader)(v.ptr).Len
+ case String:
+ // String is bigger than a word; assume flagIndir.
+ return (*stringHeader)(v.ptr).Len
+ }
+ panic(&ValueError{"reflect.Value.Len", v.kind()})
+}
+
// NumMethod returns the number of exported methods in the value's method set.
func (v Value) numMethod() int {
if v.typ == nil {
panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String())
}
+// arrayAt returns the i-th element of p,
+// an array whose elements are eltSize bytes wide.
+// The array pointed at by p must have at least i+1 elements:
+// it is invalid (but impossible to check here) to pass i >= len,
+// because then the result will point outside the array.
+// whySafe must explain why i < len. (Passing "i < len" is fine;
+// the benefit is to surface this assumption at the call site.)
+func arrayAt(p unsafe.Pointer, i int, eltSize uintptr, whySafe string) unsafe.Pointer {
+ return add(p, uintptr(i)*eltSize, "i < len")
+}
+
func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer)
// typedmemmove copies a value of type t to dst from src.
return int(c.qcount)
}
+//go:linkname reflectlite_chanlen internal/reflectlite.chanlen
+func reflectlite_chanlen(c *hchan) int {
+ if c == nil {
+ return 0
+ }
+ return int(c.qcount)
+}
+
//go:linkname reflect_chancap reflect.chancap
func reflect_chancap(c *hchan) int {
if c == nil {
return h.count
}
+//go:linkname reflectlite_maplen internal/reflectlite.maplen
+func reflectlite_maplen(h *hmap) int {
+ if h == nil {
+ return 0
+ }
+ if raceenabled {
+ callerpc := getcallerpc()
+ racereadpc(unsafe.Pointer(h), callerpc, funcPC(reflect_maplen))
+ }
+ return h.count
+}
+
//go:linkname reflect_ismapkey reflect.ismapkey
func reflect_ismapkey(t *_type) bool {
return ismapkey(t)
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !compiler_bootstrap go1.8
+// +build !compiler_bootstrap go1.13
package sort
-import "reflect"
+import (
+ "internal/reflectlite"
+)
// Slice sorts the provided slice given the provided less function.
//
//
// The function panics if the provided interface is not a slice.
func Slice(slice interface{}, less func(i, j int) bool) {
- rv := reflect.ValueOf(slice)
- swap := reflect.Swapper(slice)
+ rv := reflectlite.ValueOf(slice)
+ swap := reflectlite.Swapper(slice)
length := rv.Len()
quickSort_func(lessSwap{less, swap}, 0, length, maxDepth(length))
}
//
// The function panics if the provided interface is not a slice.
func SliceStable(slice interface{}, less func(i, j int) bool) {
- rv := reflect.ValueOf(slice)
- swap := reflect.Swapper(slice)
+ rv := reflectlite.ValueOf(slice)
+ swap := reflectlite.Swapper(slice)
stable_func(lessSwap{less, swap}, rv.Len())
}
//
// The function panics if the provided interface is not a slice.
func SliceIsSorted(slice interface{}, less func(i, j int) bool) bool {
- rv := reflect.ValueOf(slice)
+ rv := reflectlite.ValueOf(slice)
n := rv.Len()
for i := n - 1; i > 0; i-- {
if less(i, i-1) {
--- /dev/null
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.8,!go1.13
+
+package sort
+
+import "reflect"
+
+// Slice sorts the provided slice given the provided less function.
+//
+// The sort is not guaranteed to be stable. For a stable sort, use
+// SliceStable.
+//
+// The function panics if the provided interface is not a slice.
+func Slice(slice interface{}, less func(i, j int) bool) {
+ rv := reflect.ValueOf(slice)
+ swap := reflect.Swapper(slice)
+ length := rv.Len()
+ quickSort_func(lessSwap{less, swap}, 0, length, maxDepth(length))
+}
+
+// SliceStable sorts the provided slice given the provided less
+// function while keeping the original order of equal elements.
+//
+// The function panics if the provided interface is not a slice.
+func SliceStable(slice interface{}, less func(i, j int) bool) {
+ rv := reflect.ValueOf(slice)
+ swap := reflect.Swapper(slice)
+ stable_func(lessSwap{less, swap}, rv.Len())
+}
+
+// SliceIsSorted tests whether a slice is sorted.
+//
+// The function panics if the provided interface is not a slice.
+func SliceIsSorted(slice interface{}, less func(i, j int) bool) bool {
+ rv := reflect.ValueOf(slice)
+ n := rv.Len()
+ for i := n - 1; i > 0; i-- {
+ if less(i, i-1) {
+ return false
+ }
+ }
+ return true
+}