| Index: service/datastore/pls_test.go
 | 
| diff --git a/service/datastore/pls_test.go b/service/datastore/pls_test.go
 | 
| index 4f8d46004262326b0db8340fb6990f6bb11b27c6..ca048a00c24b9d97c2b41386fcd3e9b400f35d9c 100644
 | 
| --- a/service/datastore/pls_test.go
 | 
| +++ b/service/datastore/pls_test.go
 | 
| @@ -124,11 +124,11 @@ type G1 struct {
 | 
|  }
 | 
|  
 | 
|  type K0 struct {
 | 
| -	K Key
 | 
| +	K *Key
 | 
|  }
 | 
|  
 | 
|  type K1 struct {
 | 
| -	K []Key
 | 
| +	K []*Key
 | 
|  }
 | 
|  
 | 
|  type N0 struct {
 | 
| @@ -331,7 +331,7 @@ type MismatchTypes struct {
 | 
|  	S  string
 | 
|  	B  bool
 | 
|  	F  float32
 | 
| -	K  Key
 | 
| +	K  *Key
 | 
|  	T  time.Time
 | 
|  	G  GeoPoint
 | 
|  	IS []int
 | 
| @@ -527,124 +527,12 @@ type Impossible4 struct {
 | 
|  	Values []Complex
 | 
|  }
 | 
|  
 | 
| -// TODO(riannucci): see if there's a way to NOT have this be a duplicate of
 | 
| -// key.Generic. I couldn't figure out the package interdependency, and this
 | 
| -// allows things to be in separate packages.
 | 
| -type genericKey struct {
 | 
| -	kind string
 | 
| -	sid  string
 | 
| -	iid  int64
 | 
| -
 | 
| -	aid string
 | 
| -	ns  string
 | 
| -
 | 
| -	parent *genericKey
 | 
| -}
 | 
| -
 | 
| -func (g *genericKey) Kind() string      { return g.kind }
 | 
| -func (g *genericKey) StringID() string  { return g.sid }
 | 
| -func (g *genericKey) IntID() int64      { return g.iid }
 | 
| -func (g *genericKey) AppID() string     { return g.aid }
 | 
| -func (g *genericKey) Namespace() string { return g.ns }
 | 
| -func (g *genericKey) Parent() Key       { return g.parent }
 | 
| -
 | 
| -func marshalDSKey(b *bytes.Buffer, k *genericKey) {
 | 
| -	if k.parent != nil {
 | 
| -		marshalDSKey(b, k.parent)
 | 
| -	}
 | 
| -	b.WriteByte('/')
 | 
| -	b.WriteString(k.kind)
 | 
| -	b.WriteByte(',')
 | 
| -	if k.sid != "" {
 | 
| -		b.WriteString(k.sid)
 | 
| -	} else {
 | 
| -		b.WriteString(strconv.FormatInt(k.iid, 10))
 | 
| -	}
 | 
| -}
 | 
| -
 | 
| -func (g *genericKey) String() string {
 | 
| -	if g == nil {
 | 
| -		return ""
 | 
| -	}
 | 
| -	b := bytes.NewBuffer(make([]byte, 0, 512))
 | 
| -	marshalDSKey(b, g)
 | 
| -	return b.String()
 | 
| -}
 | 
| -
 | 
| -func (g *genericKey) Incomplete() bool {
 | 
| -	return g.iid == 0 && g.sid == ""
 | 
| -}
 | 
| -
 | 
| -func (g *genericKey) Valid(allowSpecial bool, aid, ns string) bool {
 | 
| -	if g == nil {
 | 
| -		return false
 | 
| -	}
 | 
| -	if aid != g.AppID() || ns != g.Namespace() {
 | 
| -		return false
 | 
| -	}
 | 
| -	for ; g != nil; g = g.parent {
 | 
| -		if !allowSpecial && len(g.Kind()) >= 2 && g.Kind()[:2] == "__" {
 | 
| -			return false
 | 
| -		}
 | 
| -		if g.Kind() == "" || g.AppID() == "" {
 | 
| -			return false
 | 
| -		}
 | 
| -		if g.StringID() != "" && g.IntID() != 0 {
 | 
| -			return false
 | 
| -		}
 | 
| -		if g.parent != nil {
 | 
| -			if g.parent.Incomplete() {
 | 
| -				return false
 | 
| -			}
 | 
| -			if g.parent.AppID() != g.AppID() || g.parent.Namespace() != g.Namespace() {
 | 
| -				return false
 | 
| -			}
 | 
| -		}
 | 
| -	}
 | 
| -	return true
 | 
| -}
 | 
| -
 | 
| -func (g *genericKey) PartialValid(aid, ns string) bool {
 | 
| -	if g.Incomplete() {
 | 
| -		g = mkKey(g.AppID(), g.Namespace(), g.Kind(), 1, g.Parent()).(*genericKey)
 | 
| -	}
 | 
| -	return g.Valid(false, aid, ns)
 | 
| -}
 | 
| -
 | 
| -var _ Key = (*genericKey)(nil)
 | 
| -
 | 
| -func mkKey(aid, ns string, pairs ...interface{}) Key {
 | 
| -	ret := (*genericKey)(nil)
 | 
| -	if len(pairs)%2 != 0 {
 | 
| -		ret, _ = pairs[len(pairs)-1].(*genericKey)
 | 
| -		pairs = pairs[:len(pairs)-1]
 | 
| -	}
 | 
| -	for i := 0; i < len(pairs); i += 2 {
 | 
| -		kind := pairs[i].(string)
 | 
| -		id := pairs[i+1]
 | 
| -		ret = &genericKey{
 | 
| -			kind:   kind,
 | 
| -			aid:    aid,
 | 
| -			ns:     ns,
 | 
| -			parent: ret,
 | 
| -		}
 | 
| -		ret.sid, _ = id.(string)
 | 
| -		iid, ok := id.(int)
 | 
| -		if ok {
 | 
| -			ret.iid = int64(iid)
 | 
| -		} else {
 | 
| -			ret.iid, _ = id.(int64)
 | 
| -		}
 | 
| -	}
 | 
| -	return ret
 | 
| -}
 | 
| -
 | 
|  type DerivedKey struct {
 | 
| -	K *genericKey
 | 
| +	K *Key
 | 
|  }
 | 
|  
 | 
|  type IfaceKey struct {
 | 
| -	K Key
 | 
| +	K *Key
 | 
|  }
 | 
|  
 | 
|  type testCase struct {
 | 
| @@ -735,13 +623,13 @@ var testCases = []testCase{
 | 
|  	},
 | 
|  	{
 | 
|  		desc: "all nil keys in slice",
 | 
| -		src:  &K1{[]Key{nil, nil}},
 | 
| -		want: &K1{[]Key{nil, nil}},
 | 
| +		src:  &K1{[]*Key{nil, nil}},
 | 
| +		want: &K1{[]*Key{nil, nil}},
 | 
|  	},
 | 
|  	{
 | 
|  		desc: "some nil keys in slice",
 | 
| -		src:  &K1{[]Key{testKey1a, nil, testKey2a}},
 | 
| -		want: &K1{[]Key{testKey1b, nil, testKey2b}},
 | 
| +		src:  &K1{[]*Key{testKey1a, nil, testKey2a}},
 | 
| +		want: &K1{[]*Key{testKey1b, nil, testKey2b}},
 | 
|  	},
 | 
|  	{
 | 
|  		desc:    "overflow",
 | 
| @@ -909,14 +797,14 @@ var testCases = []testCase{
 | 
|  		loadErr: "nope",
 | 
|  	},
 | 
|  	{
 | 
| -		desc: "allow concrete Key implementors (save)",
 | 
| -		src:  &DerivedKey{testKey2a.(*genericKey)},
 | 
| +		desc: "allow concrete *Key implementors (save)",
 | 
| +		src:  &DerivedKey{testKey2a},
 | 
|  		want: &IfaceKey{testKey2b},
 | 
|  	},
 | 
|  	{
 | 
| -		desc: "allow concrete Key implementors (load)",
 | 
| +		desc: "allow concrete *Key implementors (load)",
 | 
|  		src:  &IfaceKey{testKey2b},
 | 
| -		want: &DerivedKey{testKey2a.(*genericKey)},
 | 
| +		want: &DerivedKey{testKey2a},
 | 
|  	},
 | 
|  	{
 | 
|  		desc:    "save []float64 load []int64",
 | 
| @@ -1103,7 +991,7 @@ var testCases = []testCase{
 | 
|  			B bool
 | 
|  			S string
 | 
|  			F float64
 | 
| -			K Key
 | 
| +			K *Key
 | 
|  			T time.Time
 | 
|  			J []int64
 | 
|  		}{
 | 
| 
 |