-
Notifications
You must be signed in to change notification settings - Fork 375
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
fix: achieve type assertion parity with go #1689
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #1689 +/- ##
==========================================
+ Coverage 45.10% 48.25% +3.15%
==========================================
Files 464 408 -56
Lines 68039 62354 -5685
==========================================
- Hits 30689 30092 -597
+ Misses 34774 29752 -5022
+ Partials 2576 2510 -66 ☔ View full report in Codecov by Sentry. |
Hey nice work. took a peek mostly good. here are some of my questions:
package main
type ex int
func (ex) Error() string { return "" }
func main() {
r := []int(nil)
_, ok := r.(ex)
println(ok)
}
// Output:
// false
// Go_Output:
// invalid operation: r (variable of type []int) is not an interface the behavior is inconsistent with go. in this case, r has a static type of []int, so it actually can not be asserted to another concrete type.
package main
type ex int
func (ex) Error() string { return "" }
func main() {
defer func() {
r := _.(ex)
println(r)
}()
}
// Error:
// nil is not of type main.ex
// Go_Error:
// cannot use _ as value or type
package main
type A interface {
Do(s string)
}
func main() {
defer func() {
e := recover()
_ = e.(A)
}()
}
// Error:
// nil doesn't implement main.A
// Go_Error:
// panic: interface conversion: interface is nil, not main.A This pertains to the error message related to type assertions. According to the Go language specification, type assertions only happens from an interface type to other types. see https://go.dev/ref/spec#Type_assertions |
@ltzmaxwell so is it only the first case where the behavior is different between go and gno? The behavior of exampels 2 and 3 appear to be the same -- just the error messages are different. I'll fix the first and look at the ease of changing these error messages to something more specific. |
@ltzmaxwell I've made changes to address your comments. Let me know what you think. |
<!-- please provide a detailed description of the changes made in this pull request. --> Fixes gnolang#1650 This PR was originally intended to fix the case described in issue gnolang#1650, but it soon became apparent that there were other subtle inconsistencies between type assertions in go vs gno. The changes outlined here attempt to fix the issues and the new file tests ensure correctness. The summary below provides details as to the cases that were fixed for type assertions, both 1 and 2 -- 1 and 2 referring to the type assertion op codes, `OpTypeAssert1` and `OpTypeAssert2`. The former handles type assertions with one LHS argument that panic on assertion failure and the latter handles those with two LHS arguments that assigns a boolean value dependent on success or failure. ### Summary of type assertion changes - fail when the value being asserted has a nil type (i.e. the result of `recover()` when no panic has occurred). This applies for both cases where the type being asserted to is an interface or concrete type. - fail when asserting to an interface type and the underlying type of the value being asserted is also an interface type (non-concrete type) Also, is this an accurate assumption? https://github.com/gnolang/gno/blob/7d4e8e645ca1d2e89f5a8f2e85470e66b3253b33/gnovm/pkg/gnolang/op_expressions.go#L261 <details><summary>Contributors' checklist...</summary> - [x] Added new tests, or not needed, or not feasible - [x] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [x] Updated the official documentation or not needed - [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [x] Added references to related issues and PRs - [x] Provided any useful hints for running manual tests - [ ] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md). </details>
Fixes #1650
This PR was originally intended to fix the case described in issue #1650, but it soon became apparent that there were other subtle inconsistencies between type assertions in go vs gno. The changes outlined here attempt to fix the issues and the new file tests ensure correctness. The summary below provides details as to the cases that were fixed for type assertions, both 1 and 2 -- 1 and 2 referring to the type assertion op codes,
OpTypeAssert1
andOpTypeAssert2
. The former handles type assertions with one LHS argument that panic on assertion failure and the latter handles those with two LHS arguments that assigns a boolean value dependent on success or failure.Summary of type assertion changes
recover()
when no panic has occurred). This applies for both cases where the type being asserted to is an interface or concrete type.Also, is this an accurate assumption?
gno/gnovm/pkg/gnolang/op_expressions.go
Line 261 in 7d4e8e6
Contributors' checklist...
BREAKING CHANGE: xxx
message was included in the description