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

reflect: use int in StringHeader and SliceHeader on non-AVR platforms #4156

Merged
merged 4 commits into from
May 14, 2024

Conversation

ydnar
Copy link
Contributor

@ydnar ydnar commented Feb 26, 2024

In #1284, the recommended mechanism to use SliceHeader or StringHeader on TinyGo is with build tags. Unfortunately this isn't an option if your code imports golang.org/x/tools, which uses SliceHeader and StringHeader extensively, assuming that Len and Cap fields are type int.

This PR adds a single un-exported type to the TinyGo reflect package, intw, which is a word-sized integer type. It is aliased to int on most platforms, and uintptr when compiled with the avr build tag:

//go:build !avr

package reflect

// intw is an integer type, used in places where an int is typically required,
// except architectures where the size of an int != word size.
// See https://github.com/tinygo-org/tinygo/issues/1284.
type intw = int

Fixes #1284.

@aykevl
Copy link
Member

aykevl commented Feb 27, 2024

This has been discussed before, and the conclusion was that it wasn't the right solution. I still hold that opinion. Also, I'm not sure x/tools will compile even with this patch: there are still a lot of incompatibilities in the parsing libraries.

I hope that in about half a year or so x/tools will have a minimum version of Go 1.20 so that it can use unsafe.Slice and unsafe.String instead, which is in my opinion a much better API (reflect.*Header exposes the underlying memory layout, and clearly indicates these types are not portable across compilers).

@ydnar
Copy link
Contributor Author

ydnar commented Feb 27, 2024

Confirmed that x/tools does compile with this patch (and #4157).

Copy link
Member

@aykevl aykevl left a comment

Choose a reason for hiding this comment

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

On second thought, maybe we should just treat reflect.*Header as a deprecated non-portable API. So we'll just aim for the most portable code, not the most correct/clean code. Code that wants to be compatible with all Go compilers should use unsafe.String and the like instead.


Regarding the actual PR, I appreciate that you're adding tests but they don't really test anything useful:

  • They really just repeat the type definition.
  • The reflect package doesn't even pass tests on AVR (it's too big) so adding a test for AVR specifically is useless.

A PR like this is difficult to test, but if you want to add tests you could instead check that the sizes match. You can in fact even do this without a test, with the following code:

// Check that StringHeader is the same size as a string value.
var _ [unsafe.Sizeof("")]byte = [unsafe.Sizeof(StringHeader{})]byte{}

This will be a no-op when the string value is the same size as reflect.StringHeader, and is a compile error otherwise. You can do the same thing for slices (using unsafe.Sizeof([]byte(nil) for example).

@ydnar
Copy link
Contributor Author

ydnar commented Mar 2, 2024

Thanks for the feedback! I'll update the PR and tests.

Copy link
Member

@aykevl aykevl left a comment

Choose a reason for hiding this comment

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

Looks good to me!

@aykevl aykevl merged commit fe27b67 into tinygo-org:dev May 14, 2024
16 checks passed
@aykevl
Copy link
Member

aykevl commented May 14, 2024

Thank you for the contribution and for the fixes afterwards!

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.

2 participants