Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add stubs for more unimplemented reflect methods #2574

Closed
wants to merge 5 commits into from

Conversation

kyleconroy
Copy link
Contributor

@kyleconroy kyleconroy commented Jan 24, 2022

I'm current working on solving #447 by getting https://github.com/protocolbuffers/protobuf-go to compile with TinyGo. In combination with https://github.com/planetscale/vtprotobuf, I think there's a chance I get the code generated by protoc to compile and run without any changes.

This is my first attempt to "implement" some of the missing methods in the reflect package. This is my first time contributing to TinyGo, so I have no idea if I'm doing things correctly. Please let me know!

I've included some code copied directly from the Go source code. Is this allowed? How do I mark that code?

Comment on lines +129 to +144
// Method represents a single method.
type Method struct {
// Name is the method name.
Name string

// PkgPath is the package path that qualifies a lower case (unexported)
// method name. It is empty for upper case (exported) method names.
// The combination of PkgPath and Name uniquely identifies a method
// in a method set.
// See https://golang.org/ref/spec#Uniqueness_of_identifiers
PkgPath string

Type Type // method type
Func Value // func with receiver as first argument
Index int // index for Type.Method
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copied from Go source

Comment on lines +795 to +798
if e.Kind == 0 {
return "reflect: call of " + e.Method + " on zero Value"
}
return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copied from Go source

@@ -187,7 +187,7 @@ func (v Value) Bool() bool {
return uintptr(v.value) != 0
}
default:
panic(&ValueError{"Bool"})
panic(&ValueError{Method: "Bool"})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how all the spacing got messed up here. Happy to fix this up if this is something you'd like to merge.

@@ -788,10 +788,14 @@ type stringHeader struct {

type ValueError struct {
Method string
Kind Kind
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to match the ValueError from Go

Comment on lines 724 to 725
// panic("unimplemented: (reflect.Type).PkgPath()")
return "<unimplemented>"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need this to return a string for protocol buffers to work, but I'm happy to put the panic back in so the code at least compiles.

@dkegel-fastly
Copy link
Contributor

Copying source from upstream is fine, just make sure the file has copyright headers.

I haven't looked at reflect, so I'm not the person to comment, but:
Please include a test for the particular thing you're fixing. (e.g. a test that uses DeepEquals to compare two things that have the type you're improving support for).

@jrauschenbusch
Copy link

Do you also plan to implement reflect methods required by gob?

https://tinygo.org/docs/reference/lang-support/stdlib/#encodinggob

@kyleconroy
Copy link
Contributor Author

Please include a test for the particular thing you're fixing.

Will do, not sure how unimplemented methods are currently tested.

Do you also plan to implement reflect methods required by gob?

I do not. If you look at my change, I'm not implementing any methods, only adding unimplemented stubs so that the default code generated by protoc compiles. That code will still fail at runtime.

@dkegel-fastly dkegel-fastly changed the title Add more unimplemented reflect methods Add stubs for more unimplemented reflect methods Jan 31, 2022
@dkegel-fastly
Copy link
Contributor

Oh, I didn't realize you were just adding stubs. Changed title to reflect what you said.

You can add smoke tests that only verify compilation, and I've done that before, but I'm not sure it's worth it in this case.

@kyleconroy
Copy link
Contributor Author

@dkegel-fastly Would it be possible to approve the 3 workflows for this PR? I'd like to know if my change passes all the tests.

@dkegel-fastly
Copy link
Contributor

that is kind of a surprising failure...

@kyleconroy
Copy link
Contributor Author

@dkegel-fastly I've rebased on the latest dev, can you approve the tests again?

@kyleconroy
Copy link
Contributor Author

Great, looks like all the tests are passing. Anything else I need to do to get this merged in?

@dkegel-fastly
Copy link
Contributor

dkegel-fastly commented Feb 6, 2022

Check with @dgryski, he may have suggestions. In slack, he wrote "I wonder if stubbing more of reflect would allow text/template to build and be used for simple things (that don't use the bits we faked)".

I just checked tinygo building example_test.go from upstream's text/template against dev and against your branch. Resulting errors (ones you got rid of are marked with a dash):

  SendDir not declared by package reflect
  etyp.FieldByName undefined (type reflect.Type has no field or method FieldByName)
  item.Slice3 undefined (type reflect.Value has no field or method Slice3)
- ptr.MethodByName undefined (type reflect.Value has no field or method MethodByName)
  receiver.Type().FieldByName undefined (type reflect.Type has no field or method FieldByName)
- typ.In undefined (type reflect.Type has no field or method In)
  typ.IsVariadic undefined (type reflect.Type has no field or method IsVariadic)
  typ.NumIn undefined (type reflect.Type has no field or method NumIn)
  typ.NumOut undefined (type reflect.Type has no field or method NumOut)
- typ.Out undefined (type reflect.Type has no field or method Out)
  v.Type().NumOut undefined (type reflect.Type has no field or method NumOut)
  val.Recv undefined (type reflect.Value has no field or method Recv)
  val.Type().ChanDir undefined (type reflect.Type has no field or method ChanDir)

Whew. Well, getting text/template to build its example_test.go means stubbing another ten methods. That's a lot.

Is there some open source package that your patch rescues? That might help.

@kyleconroy
Copy link
Contributor Author

Is there some open source package that your patch rescues? That might help.

Yes! This patch, combined with https://github.com/planetscale/vtprotobuf, allows tinygo programs to use Protocol Buffers*. I'm also happy to add stubs for the rest of those methods if it will mean this gets merged.

  • There is still one small change you have to make to the generated code, but I'd commit to fixing that once this is merged.

@dkegel-fastly
Copy link
Contributor

Closing in favor of #2624.

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

Successfully merging this pull request may close these issues.

3 participants