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

enhance ToGoValue() in cadence.Value #2531

Closed
wants to merge 5 commits into from

Conversation

bjartek
Copy link
Contributor

@bjartek bjartek commented Jun 5, 2023

Description

Started on suggesting new ToGo() values


  • Targeted PR against master branch
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work
  • Code follows the standards mentioned here
  • Updated relevant documentation
  • Re-reviewed Files changed in the Github PR explorer
  • Added appropriate labels

@bjartek bjartek changed the title started on this, still missing struct/resource to not be array but ac… enhance ToGoValue() in cadence.Value Jun 5, 2023
@bjartek bjartek marked this pull request as ready for review June 5, 2023 19:26
values.go Outdated
return string(v)
value := string(v)
if value == "" {
return nil
Copy link
Member

Choose a reason for hiding this comment

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

Why return nil here for an empty string?

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 guess this is just a leftover from my blindly porting over the overflow code. The reasoning there was to make the output as terse as possible.

I can change this all the places here because I think that in cadence we should not make this distinction.

@@ -333,7 +338,7 @@ func (Address) MeteredType(common.MemoryGauge) Type {
}

func (v Address) ToGoValue() any {
return [AddressLength]byte(v)
return v.String()
Copy link
Member

Choose a reason for hiding this comment

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

Why change to a string here? A Go byte array seems like a better mapping

Copy link
Contributor Author

@bjartek bjartek Jun 15, 2023

Choose a reason for hiding this comment

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

The reason i did this is that i just find 0x123 easier to work with and reason about then a byte array, but that might just be me.

if err != nil {
panic(err)
}
return value
Copy link
Member

Choose a reason for hiding this comment

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

Fixed point numbers are not floating point numbers. This potentially a lossy conversion, as some fixed-point values cannot be represented as floating point numbers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Interesting, what situations would that occur in?

Comment on lines +1577 to +1579
if len(ret) == 0 {
return nil
}
Copy link
Member

Choose a reason for hiding this comment

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

Maybe move this to the top of the function, before unnecessarily allocating an empty slice

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we want to skip nil values in the list we cant do this. Do we want to do that or not? I personally prefer it, but if you do not want it I can change it around.

values.go Outdated
@@ -1617,12 +1636,18 @@ func (v Dictionary) WithType(dictionaryType *DictionaryType) Dictionary {
}

func (v Dictionary) ToGoValue() any {
ret := map[any]any{}
ret := map[string]any{}
Copy link
Member

Choose a reason for hiding this comment

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

Why change the key type to always being a string? What if the key type of the dictionary is e.g. Int?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Another thing left over from overflow. Will fix.

@turbolent turbolent self-assigned this Jun 6, 2023
values_test.go Outdated
value: NewArray([]Value{
NewInt(10),
Copy link
Member

Choose a reason for hiding this comment

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

Instead of changing the existing value, add an additional one

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The old test has an array that has both and int and a string, I can always add it back i just though it was very strange.

@@ -1493,7 +1502,11 @@ func (v UFix64) MeteredType(common.MemoryGauge) Type {
}

func (v UFix64) ToGoValue() any {
return uint64(v)
value, err := strconv.ParseFloat(v.String(), 64)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

But here it is OK to use ParseFloat or can we not do that as per the comment in Fix64?

@bjartek
Copy link
Contributor Author

bjartek commented Jun 15, 2023

Sorry for the delay here, I added some comments and fixed some things!

@turbolent turbolent added the Go API Breaking Change Breaks programs which use the Cadence repo as a Go dependency label Jun 28, 2023
@bjartek
Copy link
Contributor Author

bjartek commented Aug 21, 2023

Status?

@turbolent turbolent assigned SupunS and unassigned turbolent Aug 22, 2023
@turbolent
Copy link
Member

@SupunS Could you please own this?

@SupunS
Copy link
Member

SupunS commented Aug 22, 2023

Yeah, can do. I'll have a look later today.

In the meantime, were there any particular use-case(s) we wanted to enhance, or is this just a general improvement?

@SupunS
Copy link
Member

SupunS commented Sep 5, 2023

@turbolent
Copy link
Member

Given there are many different use cases and needs, and there is no "correct" Go type to return in all cases.
Developers might expect a certain Go type to be returned, but the return type is any, so it makes the API vry brittle.

It might be a good idea to "remove" this method from Value, and instead:

  • Have developers define/use their own
  • Provide multiple implementations of the method as stand-alone functions. For example, we already have well-defined conversion functions, like ByteArrayValueToByteSlice ("Cadence byte array [UInt8] to Go byte slice []byte").
    We could extract/refactor the existing methods in a similar way, and have this PR add additional conversion functions.

How does that sound @bjartek?

@turbolent
Copy link
Member

ToGoValue got removed in #3291. As mentioned above, maybe the removed functions and the new variants of the functions in this PR can be converted to co-existing global functions that convert to concrete return types (instead of any with ToGoValue).

@bjartek
Copy link
Contributor Author

bjartek commented May 1, 2024

I dont have much time for this atm :( a lot to do.

@turbolent
Copy link
Member

I dont have much time for this atm :( a lot to do.

No worries! We can pick this up after shipping Cadence 1.0, thank you for these contributions and your patience with getting them in

@bjartek
Copy link
Contributor Author

bjartek commented May 1, 2024

When will the removal of ToGoValue() hit a network? I think i use that in overflow/underflow.

@turbolent
Copy link
Member

When will the removal of ToGoValue() hit a network?

It's not affecting networks, only code that imports Cadence / the cadence package. So basically, as soon as that code updates to the latest version.

@bjartek
Copy link
Contributor Author

bjartek commented May 2, 2024

Why was removing ToGoValue() not a flip? this is a pretty breaking change.

@turbolent
Copy link
Member

@bjartek We only have FLIPs for the language, not the implementation. The fact that we expose some functionality from this implementation of the language is just a side-effect, there are no guarantees about what is exposed from it.

In any case, the functionality got removed from the package, but it can be easily provided by third-party code (e.g. another open-source Go module, or directly as part of an application), none of the underlying functionality needed for it is gone.

@bjartek
Copy link
Contributor Author

bjartek commented May 2, 2024

Can I ask why it is removed? Ref Hyrums law. The cost og this change could be quite high.

@turbolent
Copy link
Member

turbolent commented May 2, 2024

See my comment above: #2531 (comment). I had also tried to explain it here: onflow/flow-go#5820 (comment)

The goal of #3290 was to remove access by index. Value.ToGoValue for composites (structs, resources, etc.) still returned field values as a slice, which basically left a "loop-hole", where users could keep making wrong assumptions (order of fields). Changing the result of ToGoValue for composites, e.g. to return a map, would have silently (!) broken all users of the function, because they likely expected (used a cast to) a slice, e.g. Struct.ToGoValue.([]cadence.Value).

The removal was literally a result of this PR: We cannot change the implementations of ToGoValue, because downstream, users actually depend on a particular result type.

@bjartek
Copy link
Contributor Author

bjartek commented May 2, 2024

Ok. So when will this version of cadence be used? Because this is more work for everybody and they need to know that they have to do the work.

@turbolent
Copy link
Member

@bjartek I though I had already answered the same question above: #2531 (comment).

This change only affects developers using the Go package, and the changes are in the release notes.

@bjartek
Copy link
Contributor Author

bjartek commented May 8, 2024

So i assume this can just be closed then?

@turbolent
Copy link
Member

@bjartek yeah, I guess we can close this, given in it's current form it won't apply. We can definitely add such conversion functionality back to the code, but ideally in a well-defined (so it matches e.g. JS SDK) and strongly typed fashion (no any return type).

@turbolent turbolent closed this May 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Go API Breaking Change Breaks programs which use the Cadence repo as a Go dependency Improvement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants