Skip to content
This repository has been archived by the owner on Sep 20, 2022. It is now read-only.

cannot use y (type StringBox) as type Box__string in argument to Val__string #25

Open
go-li opened this issue Aug 11, 2018 · 2 comments

Comments

@go-li
Copy link

go-li commented Aug 11, 2018

Hello. Manually implementing and passing a concrete struct as a generic struct function parameter does not work. This does not work:

package main

import "fmt"

type StringBox struct {
	v string
}

type Box[T] struct {
	v T
}

func Val[T](b Box[T]) T {
	return b.v
}

func main() {
	y := StringBox{v: "Hi, Fo!"}
	fmt.Println(Val[string](y))
}

However there is a related approach that works in folang (but is not supported in go-li):

package main

import "fmt"

type Box[T] struct {
	v T
}

func Val[T](b Box[T]) T {
	return b.v
}

func main() {
	x := Box[string]{v: "Hello, Fo!"}
	fmt.Println(Val[string](x))
}

in go-li language manually implementing generic structs and generic interfaces is frequently used pattern. Will you allow such a pattern in folang?

@go-li
Copy link
Author

go-li commented Aug 11, 2018

Just for reference here is the go-li version. The Same function takes Box and returns Box, from parameter, the goli transpiler is able to infer that Box is a StringBox and uses this as the result type too. It collects this from the call site. The Box -> StringBox is stored in a callsite-specific type-to-type map.

package main

type StringBox struct {
	v *string
}

type Box struct {
	v *
}

func Same(_ *, b Box) Box {
	return b
}

func Val(_ *, b Box) * {
	return b.v
}


func strptr(s string) *string {
	return &s
}

func main() {
	y := StringBox{v: strptr("Hi, Go-li!")}

	z := Same((*string)(nil), y)

	println(*Val((*string)(nil), z))
}

Paste this to the transpiler playground. http://go-li.github.io/xgtest.html

@albrow
Copy link
Owner

albrow commented Aug 11, 2018

@go-li thank you for reporting this issue.

In this case, the compiler is behaving as intended (although I do want to improve the error message here by catching it earlier on in the Fo type checker). Let me explain.

func Val[T](b Box[T]) T {
	return b.v
}

Val is a generic function which expects a Box[T] as an argument. While Box[string] and StringBox have the same fields, they are not the same type. You cannot supply a StringBox when a Box[string] is expected.

This is not so different from how vanilla Go works. In Go, even if two named struct types have the same fields, they are not the same type. You cannot use one in place of the other. Consider this vanilla Go example:

package main

import "fmt"

type StringBox struct {
	v string
}

type OtherStringBox struct {
	v string
}

func Val(b StringBox) string {
	return b.v
}

func main() {
	y := OtherStringBox{v: "Hi, Fo!"}
	fmt.Println(Val(y))
}

The Go compiler reports the error message: cannot use y (type OtherStringBox) as type StringBox in argument to Val.

I would like for Fo to adhere as closely as possible to the existing Go semantics. I believe this will help with adoption of the language and reduce complexity and confusion. The fact that two named struct types are not considered the same even when they have the same fields is not something I want to change.

I'm leaving this issue open because I do want to improve the error message in cases like this.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants