Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
### Fixed

- [#306](https://github.com/bytecodealliance/go-modules/issues/306): do not emit incompatible version feature gates when serializing WIT. For example, if a world with version `0.1.0` *includes* a world from another package with a `@since(version = 0.2.0)` feature gate, then strip that feature gate when serializing to WIT if the version is greater than the world’s package version.
- [#350](https://github.com/bytecodealliance/go-modules/issues/350): correctly align `record` size to the highest alignment of its fields, per [specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#element-size).


## [v0.6.2] — 2025-03-16
Expand Down
34 changes: 34 additions & 0 deletions cm/result_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,3 +387,37 @@ func TestIssue344BoolResult(t *testing.T) {
t.Errorf("*v.OK(): %v, expected %v", got, want)
}
}

func TestIssue350(t *testing.T) {
type Shape struct {
_ HostLayout
shape [unsafe.Sizeof(Tuple3[uint16, Result[uint64, uint64, struct{}], uint8]{})]byte
// Previously, with bug in (*Record).Size() algorithm:
// shape [unsafe.Sizeof(Option[[3]string]{})]byte
}
type O Option[[3]string]
type E Tuple3[uint16, Result[uint64, uint64, struct{}], uint8]
type T Result[Shape, O, E]

shapeSize := unsafe.Sizeof(Shape{})
errSize := unsafe.Sizeof(E{})

if errSize > shapeSize {
t.Errorf("size of err type (%d) > size of shape type (%d)", errSize, shapeSize)

var e E
base := uintptr(unsafe.Pointer(&e))
f0 := uintptr(unsafe.Pointer(&e.F0)) - base
f1 := uintptr(unsafe.Pointer(&e.F1)) - base
f2 := uintptr(unsafe.Pointer(&e.F2)) - base
t.Logf("Offsets: F0: %d F1: %d F2 %d", f0, f1, f2)
}

// _ = Err[T](
// Err, uint8]{
// F0: 0,
// F1: OK[Result[uint64, uint64, struct{}]](0),
// F2: 0,
// },
// )
}
2 changes: 1 addition & 1 deletion wit/abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
// [Canonical ABI] [size], [alignment], and [flat] representation.
//
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
// [size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#size
// [size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#element-size
// [alignment]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#alignment
// [flat]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#flattening
type ABI interface {
Expand Down
18 changes: 14 additions & 4 deletions wit/abi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func TestDiscriminant(t *testing.T) {
}
}

func TestTypeSize(t *testing.T) {
func TestTypeSizeAndAlign(t *testing.T) {
tests := []struct {
name string
v Type
Expand All @@ -119,6 +119,10 @@ func TestTypeSize(t *testing.T) {
{"f64", F64{}, 8, 8},
{"char", Char{}, 4, 4},
{"string", String{}, 8, 4},
{"option<string>", &TypeDef{Kind: &Option{Type: String{}}}, 12, 4},
{"option<f32>", &TypeDef{Kind: &Option{Type: F32{}}}, 8, 4},
{"variant", &TypeDef{Kind: &Variant{Cases: []Case{{Type: String{}}, {Type: F64{}}}}}, 16, 8},
{"record", &TypeDef{Kind: &Record{Fields: []Field{{Type: U16{}}, {Type: &TypeDef{Kind: &Result{OK: U64{}}}}, {Type: U8{}}}}}, 32, 8},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -156,6 +160,7 @@ func TestTypeFlat(t *testing.T) {
{"option<string>", &TypeDef{Kind: &Option{Type: String{}}}, []Type{U32{}, PointerTo(U8{}), U32{}}},
{"option<f32>", &TypeDef{Kind: &Option{Type: F32{}}}, []Type{U32{}, F32{}}},
{"variant", &TypeDef{Kind: &Variant{Cases: []Case{{Type: String{}}, {Type: F64{}}}}}, []Type{U32{}, U64{}, U32{}}},
{"record", &TypeDef{Kind: &Record{Fields: []Field{{Type: U16{}}, {Type: &TypeDef{Kind: &Result{OK: U64{}}}}, {Type: U8{}}}}}, []Type{U32{}, U32{}, U64{}, U32{}}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -177,9 +182,6 @@ func witFor[T Node](nodes ...T) []string {

// TestHasBorrow verifies that HasBorrow returns true for WIT types that contain a Borrow type.
func TestHasBorrow(t *testing.T) {
makeBorrow := func() *TypeDef { return &TypeDef{Kind: &Borrow{}} }
makeTypeDef := func(kind TypeDefKind) *TypeDef { return &TypeDef{Kind: kind} }

testCases := []struct {
name string
typeDef *TypeDef
Expand Down Expand Up @@ -211,3 +213,11 @@ func TestHasBorrow(t *testing.T) {
})
}
}

func makeTypeDef(kind TypeDefKind) *TypeDef {
return &TypeDef{Kind: kind}
}

func makeBorrow() *TypeDef {
return &TypeDef{Kind: &Borrow{}}
}
2 changes: 1 addition & 1 deletion wit/enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (e *Enum) Despecialize() TypeDefKind {
// type that can represent 0...len(e.Cases).
// It is first [despecialized] into a [Variant] with no associated types, then sized.
//
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#size
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#element-size
// [despecialized]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#despecialization
func (e *Enum) Size() uintptr {
return e.Despecialize().Size()
Expand Down
2 changes: 1 addition & 1 deletion wit/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type Flags struct {

// Size returns the [ABI byte size] of [Flags] f.
//
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#size
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#element-size
func (f *Flags) Size() uintptr {
n := len(f.Flags)
switch {
Expand Down
2 changes: 1 addition & 1 deletion wit/future.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type Future struct {

// Size returns the [ABI byte size] for a [Future].
//
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#size
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#element-size
func (*Future) Size() uintptr { return 4 }

// Align returns the [ABI byte alignment] a [Future].
Expand Down
2 changes: 1 addition & 1 deletion wit/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type List struct {

// Size returns the [ABI byte size] for a [List].
//
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#size
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#element-size
func (*List) Size() uintptr { return 8 } // [2]int32

// Align returns the [ABI byte alignment] a [List].
Expand Down
2 changes: 1 addition & 1 deletion wit/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func (o *Option) Despecialize() TypeDefKind {
// Size returns the [ABI byte size] for [Option] o.
// It is first [despecialized] into a [Variant] with two cases, "none" and "some(T)", then sized.
//
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#size
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#element-size
// [despecialized]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#despecialization
func (o *Option) Size() uintptr {
return o.Despecialize().Size()
Expand Down
2 changes: 1 addition & 1 deletion wit/pointer.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type Pointer struct {

// Size returns the [ABI byte size] for [Pointer].
//
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#size
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#element-size
func (*Pointer) Size() uintptr { return 4 }

// Align returns the [ABI byte alignment] for [Pointer].
Expand Down
4 changes: 2 additions & 2 deletions wit/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ type Record struct {

// Size returns the [ABI byte size] for [Record] r.
//
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#size
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#element-size
func (r *Record) Size() uintptr {
var s uintptr
for _, f := range r.Fields {
s = Align(s, f.Type.Align())
s += f.Type.Size()
}
return s
return Align(s, r.Align())
}

// Align returns the [ABI byte alignment] for [Record] r.
Expand Down
4 changes: 2 additions & 2 deletions wit/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type Resource struct{ _typeDefKind }

// Size returns the [ABI byte size] for [Resource].
//
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#size
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#element-size
func (*Resource) Size() uintptr { return 4 }

// Align returns the [ABI byte alignment] for [Resource].
Expand Down Expand Up @@ -45,7 +45,7 @@ func (_handle) isHandle() {}

// Size returns the [ABI byte size] for this [Handle].
//
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#size
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#element-size
func (_handle) Size() uintptr { return 4 }

// Align returns the [ABI byte alignment] for this [Handle].
Expand Down
2 changes: 1 addition & 1 deletion wit/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (r *Result) Types() []Type {
// Size returns the [ABI byte size] for [Result] r.
// It is first [despecialized] into a [Variant] with two cases "ok" and "error", then sized.
//
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#size
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#element-size
// [despecialized]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#despecialization
func (r *Result) Size() uintptr {
return r.Despecialize().Size()
Expand Down
2 changes: 1 addition & 1 deletion wit/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type Stream struct {

// Size returns the [ABI byte size] for a [Stream].
//
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#size
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#element-size
func (*Stream) Size() uintptr { return 4 }

// Align returns the [ABI byte alignment] a [Stream].
Expand Down
2 changes: 1 addition & 1 deletion wit/tuple.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (t *Tuple) Despecialize() TypeDefKind {
// Size returns the [ABI byte size] for [Tuple] t.
// It is first [despecialized] into a [Record] with 0-based integer field names, then sized.
//
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#size
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#element-size
// [despecialized]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#despecialization
func (t *Tuple) Size() uintptr {
return t.Despecialize().Size()
Expand Down
2 changes: 1 addition & 1 deletion wit/variant.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (v *Variant) Types() []Type {

// Size returns the [ABI byte size] for [Variant] v.
//
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#size
// [ABI byte size]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#element-size
func (v *Variant) Size() uintptr {
s := Discriminant(len(v.Cases)).Size()
s = Align(s, v.maxCaseAlign())
Expand Down