@@ -10,8 +10,8 @@ type hashIface interface {
10
10
Sum () []byte
11
11
}
12
12
13
- type clonableHashIface interface {
14
- Sum () [] byte
13
+ type cloneableHashIface interface {
14
+ hashIface
15
15
Clone () hashIface
16
16
}
17
17
@@ -42,42 +42,42 @@ func newHash() hashIface { // ERROR "can inline newHash$"
42
42
}
43
43
44
44
func cloneHash1 (h hashIface ) hashIface { // ERROR "can inline cloneHash1$" "leaking param: h$"
45
- if h , ok := h .(clonableHashIface ); ok {
45
+ if h , ok := h .(cloneableHashIface ); ok {
46
46
return h .Clone ()
47
47
}
48
48
return & hash {} // ERROR "&hash{} escapes to heap$"
49
49
}
50
50
51
51
func cloneHash2 (h hashIface ) hashIface { // ERROR "can inline cloneHash2$" "leaking param: h$"
52
- if h , ok := h .(clonableHashIface ); ok {
52
+ if h , ok := h .(cloneableHashIface ); ok {
53
53
return h .Clone ()
54
54
}
55
55
return nil
56
56
}
57
57
58
58
func cloneHash3 (h hashIface ) hashIface { // ERROR "can inline cloneHash3$" "leaking param: h$"
59
- if h , ok := h .(clonableHashIface ); ok {
59
+ if h , ok := h .(cloneableHashIface ); ok {
60
60
return h .Clone ()
61
61
}
62
62
return & hash2 {} // ERROR "&hash2{} escapes to heap$"
63
63
}
64
64
65
65
func cloneHashWithBool1 (h hashIface ) (hashIface , bool ) { // ERROR "can inline cloneHashWithBool1$" "leaking param: h$"
66
- if h , ok := h .(clonableHashIface ); ok {
66
+ if h , ok := h .(cloneableHashIface ); ok {
67
67
return h .Clone (), true
68
68
}
69
69
return & hash {}, false // ERROR "&hash{} escapes to heap$"
70
70
}
71
71
72
72
func cloneHashWithBool2 (h hashIface ) (hashIface , bool ) { // ERROR "can inline cloneHashWithBool2$" "leaking param: h$"
73
- if h , ok := h .(clonableHashIface ); ok {
73
+ if h , ok := h .(cloneableHashIface ); ok {
74
74
return h .Clone (), true
75
75
}
76
76
return nil , false
77
77
}
78
78
79
79
func cloneHashWithBool3 (h hashIface ) (hashIface , bool ) { // ERROR "can inline cloneHashWithBool3$" "leaking param: h$"
80
- if h , ok := h .(clonableHashIface ); ok {
80
+ if h , ok := h .(cloneableHashIface ); ok {
81
81
return h .Clone (), true
82
82
}
83
83
return & hash2 {}, false // ERROR "&hash2{} escapes to heap$"
@@ -105,3 +105,35 @@ func interleavedWithTypeAssertions() {
105
105
h7 , _ := cloneHashWithBool3 (h1 ) // ERROR "&hash2{} escapes to heap$" "devirtualizing h.Clone to \*hash$" "inlining call to \(\*hash\).Clone" "inlining call to cloneHashWithBool3" "moved to heap: c$"
106
106
_ = h7 .Sum ()
107
107
}
108
+
109
+ type cloneableHashError interface {
110
+ hashIface
111
+ Clone () (hashIface , error )
112
+ }
113
+
114
+ type hash3 struct { state [32 ]byte }
115
+
116
+ func newHash3 () hashIface { // ERROR "can inline newHash3$"
117
+ return & hash3 {} // ERROR "&hash3{} escapes to heap$"
118
+ }
119
+
120
+ func (h * hash3 ) Sum () []byte { // ERROR "can inline \(\*hash3\).Sum$" "h does not escape$"
121
+ return make ([]byte , 32 ) // ERROR "make\(\[\]byte, 32\) escapes to heap$"
122
+ }
123
+
124
+ func (h * hash3 ) Clone () (hashIface , error ) { // ERROR "can inline \(\*hash3\).Clone$" "h does not escape$"
125
+ c := * h // ERROR "moved to heap: c$"
126
+ return & c , nil
127
+ }
128
+
129
+ func interleavedCloneableHashError () {
130
+ h1 := newHash3 () // ERROR "&hash3{} does not escape$" "inlining call to newHash3"
131
+ _ = h1 .Sum () // ERROR "devirtualizing h1.Sum to \*hash3$" "inlining call to \(\*hash3\).Sum" "make\(\[\]byte, 32\) does not escape$"
132
+
133
+ if h1 , ok := h1 .(cloneableHashError ); ok {
134
+ h2 , err := h1 .Clone () // ERROR "devirtualizing h1.Clone to \*hash3$" "inlining call to \(\*hash3\).Clone"
135
+ if err == nil {
136
+ _ = h2 .Sum () // ERROR "devirtualizing h2.Sum to \*hash3$" "inlining call to \(\*hash3\).Sum" "make\(\[\]byte, 32\) does not escape$"
137
+ }
138
+ }
139
+ }
0 commit comments