Skip to content

Commit a37a073

Browse files
fix: interface to concrete type by T(ifaceVal) is not allowed (#3757)
Closes [3412](#3412)
1 parent 9b5dc9c commit a37a073

File tree

3 files changed

+305
-2
lines changed

3 files changed

+305
-2
lines changed

Diff for: gnovm/pkg/gnolang/gno_test.go

+294
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,300 @@ func TestBuiltinIdentifiersShadowing(t *testing.T) {
128128
}
129129
}
130130

131+
func TestConvertTo(t *testing.T) {
132+
t.Parallel()
133+
134+
testFunc := func(source, msg string) {
135+
defer func() {
136+
if len(msg) == 0 {
137+
return
138+
}
139+
140+
r := recover()
141+
142+
if r == nil {
143+
t.Fail()
144+
}
145+
146+
err := r.(*PreprocessError)
147+
c := strings.Contains(err.Error(), msg)
148+
if !c {
149+
t.Fatalf(`expected "%s", got "%s"`, msg, r)
150+
}
151+
}()
152+
153+
m := NewMachine("test", nil)
154+
155+
n := MustParseFile("main.go", source)
156+
m.RunFiles(n)
157+
m.RunMain()
158+
}
159+
160+
type cases struct {
161+
source string
162+
msg string
163+
}
164+
165+
tests := []cases{
166+
{
167+
`package test
168+
func main() {
169+
var t interface{}
170+
t = 2
171+
var g = float32(t)
172+
println(g)
173+
}
174+
`, `test/main.go:5:12: cannot convert interface{} to float32: need type assertion`,
175+
},
176+
{
177+
`package test
178+
func main() {
179+
var t interface{}
180+
t = 2
181+
var g = int(t)
182+
println(g)
183+
}
184+
`, `test/main.go:5:14: cannot convert interface{} to int: need type assertion`,
185+
},
186+
{
187+
`package test
188+
func main() {
189+
var t interface{}
190+
t = 2
191+
var g = int8(t)
192+
println(g)
193+
}
194+
`, `test/main.go:5:14: cannot convert interface{} to int8: need type assertion`,
195+
},
196+
{
197+
`package test
198+
func main() {
199+
var t interface{}
200+
t = 2
201+
var g = int16(t)
202+
println(g)
203+
}
204+
`, `test/main.go:5:14: cannot convert interface{} to int16: need type assertion`,
205+
},
206+
{
207+
`package test
208+
func main() {
209+
var t interface{}
210+
t = 2
211+
var g = int32(t)
212+
println(g)
213+
}
214+
`, `test/main.go:5:16: cannot convert interface{} to int32: need type assertion`,
215+
},
216+
{
217+
`package test
218+
func main() {
219+
var t interface{}
220+
t = 2
221+
var g = int64(t)
222+
println(g)
223+
}
224+
`, `test/main.go:5:14: cannot convert interface{} to int64: need type assertion`,
225+
},
226+
{
227+
`package test
228+
func main() {
229+
var t interface{}
230+
t = 2
231+
var g = uint(t)
232+
println(g)
233+
}
234+
`, `test/main.go:5:14: cannot convert interface{} to uint: need type assertion`,
235+
},
236+
{
237+
`package test
238+
func main() {
239+
var t interface{}
240+
t = 2
241+
var g = uint8(t)
242+
println(g)
243+
}
244+
`, `test/main.go:5:14: cannot convert interface{} to uint8: need type assertion`,
245+
},
246+
{
247+
`package test
248+
func main() {
249+
var t interface{}
250+
t = 2
251+
var g = uint16(t)
252+
println(g)
253+
}
254+
`, `test/main.go:5:14: cannot convert interface{} to uint16: need type assertion`,
255+
},
256+
{
257+
`package test
258+
func main() {
259+
var t interface{}
260+
t = 2
261+
var g = uint32(t)
262+
println(g)
263+
}
264+
`, `test/main.go:5:14: cannot convert interface{} to uint32: need type assertion`,
265+
},
266+
{
267+
`package test
268+
func main() {
269+
var t interface{}
270+
t = 2
271+
var g = uint64(t)
272+
println(g)
273+
}
274+
`, `test/main.go:5:14: cannot convert interface{} to uint64: need type assertion`,
275+
},
276+
277+
// Built-in non-numeric types
278+
{
279+
`package test
280+
func main() {
281+
var t interface{}
282+
t = "hello"
283+
var g = string(t)
284+
println(g)
285+
}
286+
`, `test/main.go:5:14: cannot convert interface{} to string: need type assertion`,
287+
},
288+
{
289+
`package test
290+
func main() {
291+
var t interface{}
292+
t = true
293+
var g = bool(t)
294+
println(g)
295+
}
296+
`, `test/main.go:5:14: cannot convert interface{} to bool: need type assertion`,
297+
},
298+
{
299+
`package test
300+
func main() {
301+
var t interface{}
302+
t = 'a'
303+
var g = rune(t)
304+
println(g)
305+
}
306+
`, `test/main.go:5:14: cannot convert interface{} to int32: need type assertion`,
307+
},
308+
{
309+
`package test
310+
func main() {
311+
var t interface{}
312+
t = byte(65)
313+
var g = byte(t)
314+
println(g)
315+
}
316+
`, `test/main.go:5:14: cannot convert interface{} to uint8: need type assertion`,
317+
},
318+
319+
{
320+
`package test
321+
type MyInt int
322+
func main() {
323+
var t interface{}
324+
t = MyInt(2)
325+
var g = MyInt(t)
326+
println(g)
327+
}
328+
`, `test/main.go:6:14: cannot convert interface{} to test.MyInt: need type assertion`,
329+
},
330+
{
331+
`package test
332+
333+
func main() {
334+
const a int = -1
335+
println(uint(a))
336+
}`,
337+
`test/main.go:5:14: cannot convert constant of type IntKind to UintKind`,
338+
},
339+
{
340+
`package test
341+
342+
func main() {
343+
const a int = -1
344+
println(uint8(a))
345+
}`,
346+
`test/main.go:5:14: cannot convert constant of type IntKind to Uint8Kind`,
347+
},
348+
{
349+
`package test
350+
351+
func main() {
352+
const a int = -1
353+
println(uint16(a))
354+
}`,
355+
`test/main.go:5:14: cannot convert constant of type IntKind to Uint16Kind`,
356+
},
357+
{
358+
`package test
359+
360+
func main() {
361+
const a int = -1
362+
println(uint32(a))
363+
}`,
364+
`test/main.go:5:14: cannot convert constant of type IntKind to Uint32Kind`,
365+
},
366+
{
367+
`package test
368+
369+
func main() {
370+
const a int = -1
371+
println(uint64(a))
372+
}`,
373+
`test/main.go:5:14: cannot convert constant of type IntKind to Uint64Kind`,
374+
},
375+
{
376+
`package test
377+
378+
func main() {
379+
const a float32 = 1.5
380+
println(int32(a))
381+
}`,
382+
`test/main.go:5:14: cannot convert constant of type Float32Kind to Int32Kind`,
383+
},
384+
{
385+
`package test
386+
387+
func main() {
388+
println(int32(1.5))
389+
}`,
390+
`test/main.go:4:14: cannot convert (const (1.5 <untyped> bigdec)) to integer type`,
391+
},
392+
{
393+
`package test
394+
395+
func main() {
396+
const a float64 = 1.5
397+
println(int64(a))
398+
}`,
399+
`test/main.go:5:14: cannot convert constant of type Float64Kind to Int64Kind`,
400+
},
401+
{
402+
`package test
403+
404+
func main() {
405+
println(int64(1.5))
406+
}`,
407+
`test/main.go:4:14: cannot convert (const (1.5 <untyped> bigdec)) to integer type`,
408+
},
409+
{
410+
`package test
411+
412+
func main() {
413+
const f = float64(1.0)
414+
println(int64(f))
415+
}`,
416+
``,
417+
},
418+
}
419+
420+
for _, tc := range tests {
421+
testFunc(tc.source, tc.msg)
422+
}
423+
}
424+
131425
// run empty main().
132426
func TestRunEmptyMain(t *testing.T) {
133427
t.Parallel()

Diff for: gnovm/pkg/gnolang/preprocess.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -1441,7 +1441,16 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node {
14411441
checkOrConvertType(store, last, n, &n.Args[0], ct, false)
14421442
}
14431443
default:
1444-
// do nothing
1444+
ctBase := baseOf(ct)
1445+
atBase := baseOf(at)
1446+
1447+
_, isCTInterface := ctBase.(*InterfaceType)
1448+
_, isCTNative := ctBase.(*NativeType)
1449+
_, isATInterface := atBase.(*InterfaceType)
1450+
1451+
if (!isCTInterface && !isCTNative) && isATInterface {
1452+
panic(fmt.Sprintf("cannot convert %v to %v: need type assertion", at.TypeID(), ct.TypeID()))
1453+
}
14451454
}
14461455
// general case, for non-const untyped && no nested untyped shift
14471456
// after handling const, and special cases recursively, set the target node type

Diff for: gnovm/tests/files/interface39b.gno

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ type Stringer interface {
1414

1515
func main() {
1616
var f Stringer = &foo{bar: "bar"}
17-
println(*((*foo)(f)))
17+
println(*f.(*foo))
1818
}
1919

2020
// Output:

0 commit comments

Comments
 (0)