go.net/context: split the implementations of Background, WithValue,
WithCancel, and WithTimeout to use different concrete types.  Update the
tests and documentation.

This change reduces the size of context structs, reduces the number of
allocations (see TestAllocs) and removes unnecessary pointers from the
heap, such as the timer field for non-timer contexts.

IMPORTANT: I've removed the code in these functions that handles nil Context parameters.  Passing a nil parent Context will now cause a panic.

LGTM=bcmills
R=bcmills, crawshaw
CC=adonovan, golang-codereviews, rsc
https://golang.org/cl/116400043
diff --git a/context/context_test.go b/context/context_test.go
index b97c25c..2342a86 100644
--- a/context/context_test.go
+++ b/context/context_test.go
@@ -13,8 +13,9 @@
 	"time"
 )
 
-// otherContext is a Context that's not a *ctx.  This lets us test code paths
-// that differ based on the underlying type of the Context.
+// otherContext is a Context that's not one of the types defined in context.go.
+// This lets us test code paths that differ based on the underlying type of the
+// Context.
 type otherContext struct {
 	Context
 }
@@ -52,7 +53,7 @@
 func TestWithCancel(t *testing.T) {
 	c1, cancel := WithCancel(Background())
 	o := otherContext{c1}
-	c2 := newCtx(o, maybeCanceled)
+	c2, _ := WithCancel(o)
 	contexts := []Context{c1, o, c2}
 
 	for i, c := range contexts {
@@ -86,82 +87,87 @@
 }
 
 func TestParentFinishesChild(t *testing.T) {
+	// Context tree:
+	// parent -> cancelChild
+	// parent -> valueChild -> timerChild
 	parent, cancel := WithCancel(Background())
-	pctx := parent.(*ctx)
-	child1 := newCtx(parent, maybeCanceled)
-	child2 := newCtx(parent, neverCanceled)
+	cancelChild, stop := WithCancel(parent)
+	defer stop()
+	valueChild := WithValue(parent, "key", "value")
+	timerChild, stop := WithTimeout(valueChild, 10000*time.Hour)
+	defer stop()
 
 	select {
 	case x := <-parent.Done():
 		t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
-	case x := <-child1.Done():
-		t.Errorf("<-child1.Done() == %v want nothing (it should block)", x)
-	case x := <-child2.Done():
-		t.Errorf("<-child2.Done() == %v want nothing (it should block)", x)
+	case x := <-cancelChild.Done():
+		t.Errorf("<-cancelChild.Done() == %v want nothing (it should block)", x)
+	case x := <-timerChild.Done():
+		t.Errorf("<-timerChild.Done() == %v want nothing (it should block)", x)
+	case x := <-valueChild.Done():
+		t.Errorf("<-valueChild.Done() == %v want nothing (it should block)", x)
 	default:
 	}
 
-	pctx.mu.Lock()
-	if len(pctx.children) != 2 ||
-		!pctx.children[child1] || child1.parent != pctx ||
-		!pctx.children[child2] || child2.parent != pctx {
-		t.Errorf("bad linkage: pctx.children = %v, child1.parent = %v, child2.parent = %v",
-			pctx.children, child1.parent, child2.parent)
+	// The parent's children should contain the two cancelable children.
+	pc := parent.(*cancelCtx)
+	cc := cancelChild.(*cancelCtx)
+	tc := timerChild.(*timerCtx)
+	pc.mu.Lock()
+	if len(pc.children) != 2 || !pc.children[cc] || !pc.children[tc] {
+		t.Errorf("bad linkage: pc.children = %v, want %v and %v",
+			pc.children, cc, tc)
 	}
-	pctx.mu.Unlock()
+	pc.mu.Unlock()
+
+	if p, ok := parentCancelCtx(cc.Context); !ok || p != pc {
+		t.Errorf("bad linkage: parentCancelCtx(cancelChild.Context) = %v, %v want %v, true", p, ok, pc)
+	}
+	if p, ok := parentCancelCtx(tc.Context); !ok || p != pc {
+		t.Errorf("bad linkage: parentCancelCtx(timerChild.Context) = %v, %v want %v, true", p, ok, pc)
+	}
 
 	cancel()
 
-	pctx.mu.Lock()
-	if len(pctx.children) != 0 {
-		t.Errorf("pctx.cancel didn't clear pctx.children = %v", pctx.children)
+	pc.mu.Lock()
+	if len(pc.children) != 0 {
+		t.Errorf("pc.cancel didn't clear pc.children = %v", pc.children)
 	}
-	pctx.mu.Unlock()
+	pc.mu.Unlock()
 
 	// parent and children should all be finished.
-	select {
-	case <-parent.Done():
-	default:
-		t.Errorf("<-parent.Done() blocked, but shouldn't have")
+	check := func(ctx Context, name string) {
+		select {
+		case <-ctx.Done():
+		default:
+			t.Errorf("<-%s.Done() blocked, but shouldn't have", name)
+		}
+		if e := ctx.Err(); e != Canceled {
+			t.Errorf("%s.Err() == %v want %v", name, e, Canceled)
+		}
 	}
-	if e := parent.Err(); e != Canceled {
-		t.Errorf("parent.Err() == %v want %v", e, Canceled)
-	}
-	select {
-	case <-child1.Done():
-	default:
-		t.Errorf("<-child1.Done() blocked, but shouldn't have")
-	}
-	if e := child1.Err(); e != Canceled {
-		t.Errorf("child1.Err() == %v want %v", e, Canceled)
-	}
-	select {
-	case <-child2.Done():
-	default:
-		t.Errorf("<-child2.Done() blocked, but shouldn't have")
-	}
-	if e := child2.Err(); e != Canceled {
-		t.Errorf("child2.Err() == %v want %v", e, Canceled)
-	}
+	check(parent, "parent")
+	check(cancelChild, "cancelChild")
+	check(valueChild, "valueChild")
+	check(timerChild, "timerChild")
 
-	// New should return a canceled context on a canceled parent.
-	child3 := newCtx(parent, neverCanceled)
+	// WithCancel should return a canceled context on a canceled parent.
+	precanceledChild := WithValue(parent, "key", "value")
 	select {
-	case <-child3.Done():
+	case <-precanceledChild.Done():
 	default:
-		t.Errorf("<-child3.Done() blocked, but shouldn't have")
+		t.Errorf("<-precanceledChild.Done() blocked, but shouldn't have")
 	}
-	if e := child3.Err(); e != Canceled {
-		t.Errorf("child3.Err() == %v want %v", e, Canceled)
+	if e := precanceledChild.Err(); e != Canceled {
+		t.Errorf("precanceledChild.Err() == %v want %v", e, Canceled)
 	}
 }
 
 func TestChildFinishesFirst(t *testing.T) {
-	for _, parentMayCancel := range []bool{neverCanceled, maybeCanceled} {
-		parent := newCtx(nil, parentMayCancel)
+	cancelable, stop := WithCancel(Background())
+	defer stop()
+	for _, parent := range []Context{Background(), cancelable} {
 		child, cancel := WithCancel(parent)
-		pctx := parent
-		cctx := child.(*ctx)
 
 		select {
 		case x := <-parent.Done():
@@ -171,25 +177,29 @@
 		default:
 		}
 
-		if cctx.parent != pctx {
-			t.Errorf("bad linkage: cctx.parent = %v, parent = %v", cctx.parent, pctx)
+		cc := child.(*cancelCtx)
+		pc, pcok := parent.(*cancelCtx) // pcok == false when parent == Background()
+		if p, ok := parentCancelCtx(cc.Context); ok != pcok || (ok && pc != p) {
+			t.Errorf("bad linkage: parentCancelCtx(cc.Context) = %v, %v want %v, %v", p, ok, pc, pcok)
 		}
 
-		if parentMayCancel {
-			pctx.mu.Lock()
-			if len(pctx.children) != 1 || !pctx.children[cctx] {
-				t.Errorf("bad linkage: pctx.children = %v, cctx = %v", pctx.children, cctx)
+		if pcok {
+			pc.mu.Lock()
+			if len(pc.children) != 1 || !pc.children[cc] {
+				t.Errorf("bad linkage: pc.children = %v, cc = %v", pc.children, cc)
 			}
-			pctx.mu.Unlock()
+			pc.mu.Unlock()
 		}
 
 		cancel()
 
-		pctx.mu.Lock()
-		if len(pctx.children) != 0 {
-			t.Errorf("child.Cancel didn't remove self from pctx.children = %v", pctx.children)
+		if pcok {
+			pc.mu.Lock()
+			if len(pc.children) != 0 {
+				t.Errorf("child's cancel didn't remove self from pc.children = %v", pc.children)
+			}
+			pc.mu.Unlock()
 		}
-		pctx.mu.Unlock()
 
 		// child should be finished.
 		select {
@@ -225,35 +235,35 @@
 }
 
 func TestDeadline(t *testing.T) {
-	c, _ := WithDeadline(nil, time.Now().Add(100*time.Millisecond))
+	c, _ := WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
 	testDeadline(c, 200*time.Millisecond, t)
 
-	c, _ = WithDeadline(nil, time.Now().Add(100*time.Millisecond))
+	c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
 	o := otherContext{c}
 	testDeadline(o, 200*time.Millisecond, t)
 
-	c, _ = WithDeadline(nil, time.Now().Add(100*time.Millisecond))
+	c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
 	o = otherContext{c}
 	c, _ = WithDeadline(o, time.Now().Add(300*time.Millisecond))
 	testDeadline(c, 200*time.Millisecond, t)
 }
 
 func TestTimeout(t *testing.T) {
-	c, _ := WithTimeout(nil, 100*time.Millisecond)
+	c, _ := WithTimeout(Background(), 100*time.Millisecond)
 	testDeadline(c, 200*time.Millisecond, t)
 
-	c, _ = WithTimeout(nil, 100*time.Millisecond)
+	c, _ = WithTimeout(Background(), 100*time.Millisecond)
 	o := otherContext{c}
 	testDeadline(o, 200*time.Millisecond, t)
 
-	c, _ = WithTimeout(nil, 100*time.Millisecond)
+	c, _ = WithTimeout(Background(), 100*time.Millisecond)
 	o = otherContext{c}
 	c, _ = WithTimeout(o, 300*time.Millisecond)
 	testDeadline(c, 200*time.Millisecond, t)
 }
 
 func TestCancelledTimeout(t *testing.T) {
-	c, _ := WithTimeout(nil, 200*time.Millisecond)
+	c, _ := WithTimeout(Background(), 200*time.Millisecond)
 	o := otherContext{c}
 	c, cancel := WithTimeout(o, 400*time.Millisecond)
 	cancel()
@@ -291,7 +301,7 @@
 	c0 := Background()
 	check(c0, "c0", "", "", "")
 
-	c1 := WithValue(nil, k1, "c1k1")
+	c1 := WithValue(Background(), k1, "c1k1")
 	check(c1, "c1", "c1k1", "", "")
 
 	c2 := WithValue(c1, k2, "c2k2")
@@ -306,7 +316,7 @@
 	o0 := otherContext{Background()}
 	check(o0, "o0", "", "", "")
 
-	o1 := otherContext{WithValue(nil, k1, "c1k1")}
+	o1 := otherContext{WithValue(Background(), k1, "c1k1")}
 	check(o1, "o1", "c1k1", "", "")
 
 	o2 := WithValue(o1, k2, "o2k2")
@@ -339,7 +349,7 @@
 				c := WithValue(bg, k1, nil)
 				c.Value(k1)
 			},
-			limit:      3,
+			limit:      1,
 			gccgoLimit: 3,
 		},
 		{
@@ -348,7 +358,7 @@
 				c, _ := WithTimeout(bg, 15*time.Millisecond)
 				<-c.Done()
 			},
-			limit:      9,
+			limit:      8,
 			gccgoLimit: 13,
 		},
 		{
@@ -358,7 +368,7 @@
 				cancel()
 				<-c.Done()
 			},
-			limit:      7,
+			limit:      5,
 			gccgoLimit: 8,
 		},
 		{
@@ -368,7 +378,7 @@
 				cancel()
 				<-c.Done()
 			},
-			limit:      16,
+			limit:      8,
 			gccgoLimit: 25,
 		},
 	} {