Skip to content

Commit 6c63c12

Browse files
authored
Merge pull request #357 from bytecodealliance/ydnar/issue356
wit/bindgen: improve WIT world matching, warn if ambiguous
2 parents 0020099 + 40e7cd8 commit 6c63c12

File tree

4 files changed

+41
-7
lines changed

4 files changed

+41
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
1313
- [#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.
1414
- [#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).
1515
- [#352](https://github.com/bytecodealliance/go-modules/issues/352): do not use `tuple` types as data shape for `variant` or `result` types, as they may contain a `bool` or not be packed.
16+
- [#356](https://github.com/bytecodealliance/go-modules/issues/356): sort WIT packages topologically by dependency before matching WIT world when generating Go bindings. Warn if there is an ambiguous match.
1617

1718
## [v0.6.2] — 2025-03-16
1819

wit/bindgen/generator.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,39 @@ func newGenerator(res *wit.Resolve, opts ...Option) (*generator, error) {
163163
g.opts.cmPackage = cmPackage
164164
}
165165
g.res = res
166-
for _, g.world = range res.Worlds {
167-
if g.world.Match(g.opts.world) {
168-
break
169-
}
170-
// otherwise choose the last world
166+
167+
// Sort WIT packages topologically
168+
packages := slices.Clone(res.Packages)
169+
slices.SortFunc(packages, wit.ComparePackages)
170+
slices.Reverse(packages)
171+
172+
// Select WIT world
173+
var first *wit.World
174+
for _, pkg := range packages {
175+
pkg.Worlds.All()(func(_ string, w *wit.World) bool {
176+
if first == nil {
177+
first = w
178+
}
179+
if w.Match(g.opts.world) {
180+
name := w.Package.Name
181+
name.Extension = w.Name
182+
if g.world == nil {
183+
g.opts.logger.Infof("WIT world: %s", name.String())
184+
g.world = w
185+
} else {
186+
g.opts.logger.Warnf("Warning: ambiguous WIT world: %s", name.String())
187+
}
188+
}
189+
return true
190+
})
191+
}
192+
193+
// Fall back to first world
194+
if g.world == nil {
195+
g.world = first
171196
}
197+
198+
// Instantiate a wasm-tools instance.
172199
g.wasmTools, err = wasmtools.New(context.Background())
173200
if err != nil {
174201
return nil, err

wit/package.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,13 @@ func (p *Package) dependsOn(dep Node) bool {
4848
return done
4949
}
5050

51-
func comparePackages(a, b *Package) int {
51+
// ComparePackages compares two WIT packages, based on dependence.
52+
// When used with [slices.SortFunc], this function will sort packages
53+
// based on their mutual dependence. Packages with fewer or no dependencies will sort last.
54+
// If package a depends on package b, this function returns 1.
55+
// If package b depends on package a, this function returns -1.
56+
// If package a == package b, this function returns 0.
57+
func ComparePackages(a, b *Package) int {
5258
// fmt.Fprintln(os.Stderr, "comparing "+b.Name.String()+" to "+a.Name.String())
5359
switch {
5460
case a == b:

wit/wit.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ func (*Resolve) WITKind() string { return "resolve" }
133133
func (r *Resolve) WIT(ctx Node, _ string) string {
134134
// Sort packages topologically by dependency
135135
packages := slices.Clone(r.Packages)
136-
slices.SortFunc(packages, comparePackages)
136+
slices.SortFunc(packages, ComparePackages)
137137
slices.Reverse(packages)
138138

139139
var b strings.Builder

0 commit comments

Comments
 (0)