test: add tests for escape analysis of interface conversions

The false positives (var incorrectly escapes) are marked with BAD.

Change-Id: If64fabb6ea96de44a1177d9ab12e2ccc579fe0c4
Reviewed-on: https://go-review.googlesource.com/5294
Reviewed-by: Keith Randall <khr@golang.org>
diff --git a/test/escape2n.go b/test/escape2n.go
index 5e58537..59f64c0 100644
--- a/test/escape2n.go
+++ b/test/escape2n.go
@@ -475,12 +475,13 @@
 
 func foo67() {
 	var mv MV
-	foo63(mv)
+	foo63(mv) // ERROR "mv does not escape"
 }
 
 func foo68() {
 	var mv MV
-	foo64(mv) // escapes but it's an int so irrelevant
+	// escapes but it's an int so irrelevant
+	foo64(mv) // ERROR "mv escapes to heap"
 }
 
 func foo69(m M) { // ERROR "leaking param: m"
@@ -488,7 +489,7 @@
 }
 
 func foo70(mv1 *MV, m M) { // ERROR "leaking param: mv1" "leaking param: m"
-	m = mv1
+	m = mv1 // ERROR "mv1 escapes to heap"
 	foo64(m)
 }
 
@@ -619,62 +620,62 @@
 }
 
 func foo75(z *int) { // ERROR "z does not escape"
-	myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+	myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" "1 escapes to heap" "2 escapes to heap" "3 escapes to heap"
 }
 
 func foo75a(z *int) { // ERROR "z does not escape"
-	myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+	myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" "1 escapes to heap" "2 escapes to heap" "3 escapes to heap"
 }
 
 func foo75esc(z *int) { // ERROR "leaking param: z"
-	gxx = myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+	gxx = myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" "1 escapes to heap" "2 escapes to heap" "3 escapes to heap"
 }
 
 func foo75aesc(z *int) { // ERROR "z does not escape"
 	var ppi **interface{}       // assignments to pointer dereferences lose track
-	*ppi = myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+	*ppi = myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap" "1 escapes to heap" "2 escapes to heap" "3 escapes to heap"
 }
 
 func foo75aesc1(z *int) { // ERROR "z does not escape"
-	sink = myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+	sink = myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap" "myprint1\(z, 1, 2, 3\) escapes to heap" "1 escapes to heap" "2 escapes to heap" "3 escapes to heap"
 }
 
 // BAD: z does not escape here
 func foo76(z *int) { // ERROR "leaking param: z"
-	myprint(nil, z) // ERROR "[.][.][.] argument does not escape"
+	myprint(nil, z) // ERROR "[.][.][.] argument does not escape" "z escapes to heap"
 }
 
 // BAD: z does not escape here
 func foo76a(z *int) { // ERROR "leaking param: z"
-	myprint1(nil, z) // ERROR "[.][.][.] argument does not escape"
+	myprint1(nil, z) // ERROR "[.][.][.] argument does not escape" "z escapes to heap"
 }
 
 func foo76b() {
-	myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+	myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" "1 escapes to heap" "2 escapes to heap" "3 escapes to heap"
 }
 
 func foo76c() {
-	myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+	myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" "1 escapes to heap" "2 escapes to heap" "3 escapes to heap"
 }
 
 func foo76d() {
-	defer myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+	defer myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" "1 escapes to heap" "2 escapes to heap" "3 escapes to heap"
 }
 
 func foo76e() {
-	defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+	defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" "1 escapes to heap" "2 escapes to heap" "3 escapes to heap"
 }
 
 func foo76f() {
 	for {
 		// TODO: This one really only escapes its scope, but we don't distinguish yet.
-		defer myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+		defer myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap" "1 escapes to heap" "2 escapes to heap" "3 escapes to heap"
 	}
 }
 
 func foo76g() {
 	for {
-		defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+		defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap" "1 escapes to heap" "2 escapes to heap" "3 escapes to heap"
 	}
 }
 
@@ -692,7 +693,7 @@
 }
 
 func foo77c(z []interface{}) { // ERROR "leaking param: z"
-	sink = myprint1(nil, z...)
+	sink = myprint1(nil, z...) // ERROR "myprint1\(nil, z\.\.\.\) escapes to heap"
 }
 
 func dotdotdot() {
@@ -1151,16 +1152,16 @@
 
 func foo121() {
 	for i := 0; i < 10; i++ {
-		defer myprint(nil, i) // ERROR "[.][.][.] argument escapes to heap"
-		go myprint(nil, i)    // ERROR "[.][.][.] argument escapes to heap"
+		defer myprint(nil, i) // ERROR "[.][.][.] argument escapes to heap" "i escapes to heap"
+		go myprint(nil, i)    // ERROR "[.][.][.] argument escapes to heap" "i escapes to heap"
 	}
 }
 
 // same as foo121 but check across import
 func foo121b() {
 	for i := 0; i < 10; i++ {
-		defer fmt.Printf("%d", i) // ERROR "[.][.][.] argument escapes to heap"
-		go fmt.Printf("%d", i)    // ERROR "[.][.][.] argument escapes to heap"
+		defer fmt.Printf("%d", i) // ERROR "[.][.][.] argument escapes to heap" "i escapes to heap"
+		go fmt.Printf("%d", i)    // ERROR "[.][.][.] argument escapes to heap" "i escapes to heap"
 	}
 }
 
@@ -1347,7 +1348,7 @@
 		T *T
 	}
 	t := &T{} // ERROR "&T literal escapes to heap"
-	return U{
+	return U{ // ERROR "U literal escapes to heap"
 		X: t.X,
 		T: t,
 	}
@@ -1582,14 +1583,14 @@
 	// Literal does not escape, but element does.
 	i := 0        // ERROR "moved to heap: i"
 	x := &Lit{&i} // ERROR "&Lit literal does not escape" "&i escapes to heap"
-	sink = *x
+	sink = *x     // ERROR "\*x escapes to heap"
 }
 
 func ptrlitEscape() {
 	// Both literal and element escape.
 	i := 0        // ERROR "moved to heap: i"
 	x := &Lit{&i} // ERROR "&Lit literal escapes to heap" "&i escapes to heap"
-	sink = x
+	sink = x      // ERROR "x escapes to heap"
 }
 
 // self-assignments
@@ -1621,7 +1622,7 @@
 func (b *Buffer) bat() { // ERROR "leaking param: b"
 	o := new(Buffer) // ERROR "new\(Buffer\) escapes to heap"
 	o.buf1 = b.buf1[1:2]
-	sink = o
+	sink = o // ERROR "o escapes to heap"
 }
 
 func quux(sp *string, bp *[]byte) { // ERROR "sp does not escape" "bp does not escape"
@@ -1639,9 +1640,9 @@
 // to just x, and thus &i looks escaping.
 func fieldFlowTracking() {
 	var x StructWithString
-	i := 0   // ERROR "moved to heap: i"
-	x.p = &i // ERROR "&i escapes to heap"
-	sink = x.s
+	i := 0     // ERROR "moved to heap: i"
+	x.p = &i   // ERROR "&i escapes to heap"
+	sink = x.s // ERROR "x.s escapes to heap"
 }
 
 // String operations.
@@ -1670,7 +1671,7 @@
 	b := make([]byte, 20) // ERROR "does not escape"
 	s := string(b)        // ERROR "string\(b\) escapes to heap"
 	s1 := s[0:1]
-	sink = s1
+	sink = s1 // ERROR "s1 escapes to heap"
 }
 
 func addstr0() {
@@ -1700,7 +1701,7 @@
 	s1 := "b"
 	s := s0 + s1 // ERROR "s0 \+ s1 escapes to heap"
 	s2 := s[0:1]
-	sink = s2
+	sink = s2 // ERROR "s2 escapes to heap"
 }
 
 func intstring0() bool {
@@ -1777,7 +1778,7 @@
 	m[0] = 0
 	m[1]++
 	delete(m, 1)
-	sink = m[0]
+	sink = m[0] // ERROR "m\[0\] escapes to heap"
 }
 
 func makemap1() map[int]int {
@@ -1786,5 +1787,13 @@
 
 func makemap2() {
 	m := make(map[int]int) // ERROR "make\(map\[int\]int\) escapes to heap"
-	sink = m
+	sink = m               // ERROR "m escapes to heap"
+}
+
+func nonescapingEface(m map[interface{}]bool) bool { // ERROR "m does not escape"
+	return m["foo"] // ERROR `"foo" does not escape`
+}
+
+func nonescapingIface(m map[M]bool) bool { // ERROR "m does not escape"
+	return m[MV(0)] // ERROR "MV\(0\) does not escape"
 }