Repository: bytecodealliance/wasm-tools
Pull request #1806 (2024-09-19 15:13:11)

optionally allow output world name when importizing
Allow specifying output world name when importizing. This would allow multiple importized worlds to be merged. 


Patch:
diff --git a/crates/wit-parser/src/resolve.rs b/crates/wit-parser/src/resolve.rs
index 29050291..40379ae9 100644
--- a/crates/wit-parser/src/resolve.rs
+++ b/crates/wit-parser/src/resolve.rs
@@ -1021,7 +1021,7 @@ package {name} is defined in two different locations:\n\
     /// bindings in a context that is importing the original world. This
     /// is intended to be used as part of language tooling when depending on
     /// other components.
-    pub fn importize(&mut self, world_id: WorldId) -> Result<()> {
+    pub fn importize(&mut self, world_id: WorldId, out_world_name: Option<String>) -> Result<()> {
         // Rename the world to avoid having it get confused with the original
         // name of the world. Add `-importized` to it for now. Precisely how
         // this new world is created may want to be updated over time if this
@@ -1029,8 +1029,13 @@ package {name} is defined in two different locations:\n\
         let world = &mut self.worlds[world_id];
         let pkg = &mut self.packages[world.package.unwrap()];
         pkg.worlds.shift_remove(&world.name);
-        world.name.push_str("-importized");
-        pkg.worlds.insert(world.name.clone(), world_id);
+        if let Some(name) = out_world_name {
+            world.name = name.clone();
+            pkg.worlds.insert(name, world_id);
+        } else {
+            world.name.push_str("-importized");
+            pkg.worlds.insert(world.name.clone(), world_id);
+        }
 
         // Trim all non-type definitions from imports. Types can be used by
         // exported functions, for example, so they're preserved.
diff --git a/fuzz/src/roundtrip_wit.rs b/fuzz/src/roundtrip_wit.rs
index c1cf5bdf..f954bfb5 100644
--- a/fuzz/src/roundtrip_wit.rs
+++ b/fuzz/src/roundtrip_wit.rs
@@ -62,7 +62,7 @@ pub fn run(u: &mut Unstructured<'_>) -> Result<()> {
         // valid.
         log::debug!("... importizing this world");
         let mut resolve2 = resolve.clone();
-        let _ = resolve2.importize(id);
+        let _ = resolve2.importize(id, None);
     }
 
     if decoded_bindgens.len() < 2 {
diff --git a/src/bin/wasm-tools/component.rs b/src/bin/wasm-tools/component.rs
index e8e1b408..7857d86e 100644
--- a/src/bin/wasm-tools/component.rs
+++ b/src/bin/wasm-tools/component.rs
@@ -511,6 +511,10 @@ pub struct WitOpts {
     #[clap(long, conflicts_with = "importize_world")]
     importize: bool,
 
+    /// The name of the world to generate when using `--importize` or `importize-world`.
+    #[clap(long = "importize-out-world-name")]
+    importize_out_world_name: Option<String>,
+
     /// Generates a WIT world to import a component which corresponds to the
     /// selected world.
     ///
@@ -549,9 +553,13 @@ impl WitOpts {
         let mut decoded = self.decode_input()?;
 
         if self.importize {
-            self.importize(&mut decoded, None)?;
+            self.importize(&mut decoded, None, self.importize_out_world_name.as_ref())?;
         } else if self.importize_world.is_some() {
-            self.importize(&mut decoded, self.importize_world.as_deref())?;
+            self.importize(
+                &mut decoded,
+                self.importize_world.as_deref(),
+                self.importize_out_world_name.as_ref(),
+            )?;
         }
 
         // Now that the WIT document has been decoded, it's time to emit it.
@@ -636,7 +644,12 @@ impl WitOpts {
         }
     }
 
-    fn importize(&self, decoded: &mut DecodedWasm, world: Option<&str>) -> Result<()> {
+    fn importize(
+        &self,
+        decoded: &mut DecodedWasm,
+        world: Option<&str>,
+        out_world_name: Option<&String>,
+    ) -> Result<()> {
         let (resolve, world_id) = match (&mut *decoded, world) {
             (DecodedWasm::Component(resolve, world), None) => (resolve, *world),
             (DecodedWasm::Component(..), Some(_)) => {
@@ -653,7 +666,7 @@ impl WitOpts {
         // let pkg = decoded.package();
         // let world_id = decoded.resolve().select_world(main, None)?;
         resolve
-            .importize(world_id)
+            .importize(world_id, out_world_name.cloned())
             .context("failed to move world exports to imports")?;
         let resolve = mem::take(resolve);
         *decoded = DecodedWasm::Component(resolve, world_id);


Test patch:
diff --git a/tests/cli/importize.wit b/tests/cli/importize.wit
index 26a70649..46b1d4da 100644
--- a/tests/cli/importize.wit
+++ b/tests/cli/importize.wit
@@ -1,4 +1,5 @@
 // RUN[simple]: component wit --importize-world simple %
+// RUN[simple-rename]: component wit --importize-world simple-rename --importize-out-world-name test-rename  %
 // RUN[simple-component]: component embed --dummy --world simple % | \
 //                        component wit --importize
 // RUN[with-deps]: component wit --importize-world with-deps %
@@ -34,6 +35,10 @@ world simple {
     export t;
 }
 
+world simple-rename {
+    export t;
+}
+
 world with-deps {
     export qux;
 }
diff --git a/tests/cli/importize.wit.simple-rename.stdout b/tests/cli/importize.wit.simple-rename.stdout
new file mode 100644
index 00000000..b921e7e2
--- /dev/null
+++ b/tests/cli/importize.wit.simple-rename.stdout
@@ -0,0 +1,97 @@
+/// RUN[simple]: component wit --importize-world simple %
+/// RUN[simple-rename]: component wit --importize-world simple-rename --importize-out-world-name test-rename  %
+/// RUN[simple-component]: component embed --dummy --world simple % | /
+/// component wit --importize
+/// RUN[with-deps]: component wit --importize-world with-deps %
+/// RUN[simple-toplevel]: component wit --importize-world simple-toplevel %
+/// RUN[toplevel-deps]: component wit --importize-world toplevel-deps %
+/// FAIL[fail1]: component wit --importize-world fail1 %
+/// RUN[trim-imports]: component wit --importize-world trim-imports %
+/// RUN[tricky-import]: component wit --importize-world tricky-import %
+package importize:importize;
+
+interface t {
+  resource r;
+}
+
+interface bar {
+  use t.{r};
+
+  record foo {
+    x: string,
+  }
+
+  importize: func(name: r);
+}
+
+interface qux {
+  use bar.{foo};
+
+  blah: func(boo: foo);
+}
+
+interface something-else-dep {
+  type t = u32;
+}
+
+interface a {
+}
+
+interface b {
+}
+
+interface with-dep {
+  type t = u32;
+}
+
+world simple {
+  export t;
+}
+world with-deps {
+  import t;
+  import bar;
+
+  export qux;
+}
+world simple-toplevel {
+  export foo: func();
+  export something: interface {
+    foo: func();
+  }
+}
+world toplevel-deps {
+  import something-else-dep;
+
+  type s = u32;
+
+  export bar: func() -> s;
+  export something-else: interface {
+    use something-else-dep.{t};
+
+    bar: func() -> t;
+  }
+}
+world fail1 {
+  type foo = u32;
+
+  export foo: func() -> foo;
+}
+world trim-imports {
+  import a;
+  import foo: func();
+  import bar: interface {
+  }
+
+  type t = u32;
+
+  export b;
+}
+world tricky-import {
+  import with-dep;
+  use with-dep.{t};
+
+  export f: func() -> t;
+}
+world test-rename {
+  import t;
+}
diff --git a/tests/cli/importize.wit.simple-toplevel.stdout b/tests/cli/importize.wit.simple-toplevel.stdout
index 4b279899..7c79702d 100644
--- a/tests/cli/importize.wit.simple-toplevel.stdout
+++ b/tests/cli/importize.wit.simple-toplevel.stdout
@@ -1,4 +1,5 @@
 /// RUN[simple]: component wit --importize-world simple %
+/// RUN[simple-rename]: component wit --importize-world simple-rename --importize-out-world-name test-rename  %
 /// RUN[simple-component]: component embed --dummy --world simple % | /
 /// component wit --importize
 /// RUN[with-deps]: component wit --importize-world with-deps %
@@ -46,6 +47,9 @@ interface with-dep {
 world simple {
   export t;
 }
+world simple-rename {
+  export t;
+}
 world with-deps {
   import t;
   import bar;
diff --git a/tests/cli/importize.wit.simple.stdout b/tests/cli/importize.wit.simple.stdout
index 74df901e..80547c60 100644
--- a/tests/cli/importize.wit.simple.stdout
+++ b/tests/cli/importize.wit.simple.stdout
@@ -1,4 +1,5 @@
 /// RUN[simple]: component wit --importize-world simple %
+/// RUN[simple-rename]: component wit --importize-world simple-rename --importize-out-world-name test-rename  %
 /// RUN[simple-component]: component embed --dummy --world simple % | /
 /// component wit --importize
 /// RUN[with-deps]: component wit --importize-world with-deps %
@@ -43,6 +44,9 @@ interface with-dep {
   type t = u32;
 }
 
+world simple-rename {
+  export t;
+}
 world with-deps {
   import t;
   import bar;
diff --git a/tests/cli/importize.wit.toplevel-deps.stdout b/tests/cli/importize.wit.toplevel-deps.stdout
index 05b41d4c..17b1c0e3 100644
--- a/tests/cli/importize.wit.toplevel-deps.stdout
+++ b/tests/cli/importize.wit.toplevel-deps.stdout
@@ -1,4 +1,5 @@
 /// RUN[simple]: component wit --importize-world simple %
+/// RUN[simple-rename]: component wit --importize-world simple-rename --importize-out-world-name test-rename  %
 /// RUN[simple-component]: component embed --dummy --world simple % | /
 /// component wit --importize
 /// RUN[with-deps]: component wit --importize-world with-deps %
@@ -46,6 +47,9 @@ interface with-dep {
 world simple {
   export t;
 }
+world simple-rename {
+  export t;
+}
 world with-deps {
   import t;
   import bar;
diff --git a/tests/cli/importize.wit.tricky-import.stdout b/tests/cli/importize.wit.tricky-import.stdout
index c237d71a..f5cb951c 100644
--- a/tests/cli/importize.wit.tricky-import.stdout
+++ b/tests/cli/importize.wit.tricky-import.stdout
@@ -1,4 +1,5 @@
 /// RUN[simple]: component wit --importize-world simple %
+/// RUN[simple-rename]: component wit --importize-world simple-rename --importize-out-world-name test-rename  %
 /// RUN[simple-component]: component embed --dummy --world simple % | /
 /// component wit --importize
 /// RUN[with-deps]: component wit --importize-world with-deps %
@@ -46,6 +47,9 @@ interface with-dep {
 world simple {
   export t;
 }
+world simple-rename {
+  export t;
+}
 world with-deps {
   import t;
   import bar;
diff --git a/tests/cli/importize.wit.trim-imports.stdout b/tests/cli/importize.wit.trim-imports.stdout
index 933c0358..a0539ef9 100644
--- a/tests/cli/importize.wit.trim-imports.stdout
+++ b/tests/cli/importize.wit.trim-imports.stdout
@@ -1,4 +1,5 @@
 /// RUN[simple]: component wit --importize-world simple %
+/// RUN[simple-rename]: component wit --importize-world simple-rename --importize-out-world-name test-rename  %
 /// RUN[simple-component]: component embed --dummy --world simple % | /
 /// component wit --importize
 /// RUN[with-deps]: component wit --importize-world with-deps %
@@ -46,6 +47,9 @@ interface with-dep {
 world simple {
   export t;
 }
+world simple-rename {
+  export t;
+}
 world with-deps {
   import t;
   import bar;
diff --git a/tests/cli/importize.wit.with-deps.stdout b/tests/cli/importize.wit.with-deps.stdout
index 96e7d320..1a48a029 100644
--- a/tests/cli/importize.wit.with-deps.stdout
+++ b/tests/cli/importize.wit.with-deps.stdout
@@ -1,4 +1,5 @@
 /// RUN[simple]: component wit --importize-world simple %
+/// RUN[simple-rename]: component wit --importize-world simple-rename --importize-out-world-name test-rename  %
 /// RUN[simple-component]: component embed --dummy --world simple % | /
 /// component wit --importize
 /// RUN[with-deps]: component wit --importize-world with-deps %
@@ -46,6 +47,9 @@ interface with-dep {
 world simple {
   export t;
 }
+world simple-rename {
+  export t;
+}
 world simple-toplevel {
   export foo: func();
   export something: interface {