Skip to content

Commit cbe060d

Browse files
committed
cm: do not use bool in option and result for discriminator
Tinygo (LLVM) handles bool values in a tagged union differently than Go. Fixes #344.
1 parent 9d80dee commit cbe060d

3 files changed

Lines changed: 40 additions & 15 deletions

File tree

cm/option.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func None[T any]() Option[T] {
1818
func Some[T any](v T) Option[T] {
1919
return Option[T]{
2020
option: option[T]{
21-
isSome: true,
21+
isSome: 1,
2222
some: v,
2323
},
2424
}
@@ -29,19 +29,19 @@ func Some[T any](v T) Option[T] {
2929
// followed by storage for the associated type T.
3030
type option[T any] struct {
3131
_ HostLayout
32-
isSome bool
32+
isSome uint8
3333
some T
3434
}
3535

3636
// None returns true if o represents the none case.
3737
func (o *option[T]) None() bool {
38-
return !o.isSome
38+
return o.isSome == 0
3939
}
4040

4141
// Some returns a non-nil *T if o represents the some case,
4242
// or nil if o represents the none case.
4343
func (o *option[T]) Some() *T {
44-
if o.isSome {
44+
if o.isSome == 1 {
4545
return &o.some
4646
}
4747
return nil
@@ -51,7 +51,7 @@ func (o *option[T]) Some() *T {
5151
// or the zero value of T if o represents the none case.
5252
// This does not have a pointer receiver, so it can be chained.
5353
func (o option[T]) Value() T {
54-
if !o.isSome {
54+
if o.isSome == 0 {
5555
var zero T
5656
return zero
5757
}

cm/result.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type AnyResult[Shape, OK, Err any] interface {
3333
// result represents the internal representation of a Component Model result type.
3434
type result[Shape, OK, Err any] struct {
3535
_ HostLayout
36-
isErr bool
36+
isErr uint8
3737
_ [0]OK
3838
_ [0]Err
3939
data Shape // [unsafe.Sizeof(*(*Shape)(unsafe.Pointer(nil)))]byte
@@ -44,7 +44,7 @@ type result[Shape, OK, Err any] struct {
4444
func OK[R AnyResult[Shape, OK, Err], Shape, OK, Err any](ok OK) R {
4545
var r Result[Shape, OK, Err]
4646
r.validate()
47-
r.isErr = ResultOK
47+
r.isErr = 0
4848
*((*OK)(unsafe.Pointer(&r.data))) = ok
4949
return R(r)
5050
}
@@ -54,42 +54,42 @@ func OK[R AnyResult[Shape, OK, Err], Shape, OK, Err any](ok OK) R {
5454
func Err[R AnyResult[Shape, OK, Err], Shape, OK, Err any](err Err) R {
5555
var r Result[Shape, OK, Err]
5656
r.validate()
57-
r.isErr = ResultErr
57+
r.isErr = 1
5858
*((*Err)(unsafe.Pointer(&r.data))) = err
5959
return R(r)
6060
}
6161

6262
// SetOK sets r to an OK result.
6363
func (r *result[Shape, OK, Err]) SetOK(ok OK) {
6464
r.validate()
65-
r.isErr = ResultOK
65+
r.isErr = 0
6666
*((*OK)(unsafe.Pointer(&r.data))) = ok
6767
}
6868

6969
// SetErr sets r to an error result.
7070
func (r *result[Shape, OK, Err]) SetErr(err Err) {
7171
r.validate()
72-
r.isErr = ResultErr
72+
r.isErr = 1
7373
*((*Err)(unsafe.Pointer(&r.data))) = err
7474
}
7575

7676
// IsOK returns true if r represents the OK case.
7777
func (r *result[Shape, OK, Err]) IsOK() bool {
7878
r.validate()
79-
return !r.isErr
79+
return r.isErr == 0
8080
}
8181

8282
// IsErr returns true if r represents the error case.
8383
func (r *result[Shape, OK, Err]) IsErr() bool {
8484
r.validate()
85-
return r.isErr
85+
return r.isErr == 1
8686
}
8787

8888
// OK returns a non-nil *OK pointer if r represents the OK case.
8989
// If r represents an error, then it returns nil.
9090
func (r *result[Shape, OK, Err]) OK() *OK {
9191
r.validate()
92-
if r.isErr {
92+
if r.isErr == 1 {
9393
return nil
9494
}
9595
return (*OK)(unsafe.Pointer(&r.data))
@@ -99,7 +99,7 @@ func (r *result[Shape, OK, Err]) OK() *OK {
9999
// If r represents the OK case, then it returns nil.
100100
func (r *result[Shape, OK, Err]) Err() *Err {
101101
r.validate()
102-
if !r.isErr {
102+
if r.isErr == 0 {
103103
return nil
104104
}
105105
return (*Err)(unsafe.Pointer(&r.data))
@@ -109,7 +109,7 @@ func (r *result[Shape, OK, Err]) Err() *Err {
109109
// or (zero value of OK, Err, true) if r represents the error case.
110110
// This does not have a pointer receiver, so it can be chained.
111111
func (r result[Shape, OK, Err]) Result() (ok OK, err Err, isErr bool) {
112-
if r.isErr {
112+
if r.isErr == 1 {
113113
return ok, *(*Err)(unsafe.Pointer(&r.data)), true
114114
}
115115
return *(*OK)(unsafe.Pointer(&r.data)), err, false

cm/result_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,3 +350,28 @@ func TestIssue284NotTinyGo(t *testing.T) {
350350
}
351351
}
352352
}
353+
354+
func TestIssue344TupleOfOption(t *testing.T) {
355+
type T Result[[1]Option[uint64], uint64, [1]Option[uint64]]
356+
357+
want := uint64(2)
358+
v := T(OK[Result[[1]Option[uint64], uint64, [1]Option[uint64]]](want))
359+
got := *v.OK()
360+
361+
if got != want {
362+
t.Errorf("*v.OK(): %v, expected %v", got, want)
363+
}
364+
}
365+
366+
func TestIssue344TupleOfResult(t *testing.T) {
367+
type R Result[uint64, uint64, bool]
368+
type T Result[[1]R, uint64, [1]R]
369+
370+
want := uint64(2)
371+
v := T(OK[T](want))
372+
got := *v.OK()
373+
374+
if got != want {
375+
t.Errorf("*v.OK(): %v, expected %v", got, want)
376+
}
377+
}

0 commit comments

Comments
 (0)