Repository: bytecodealliance/wasmtime
Pull request #8483 (2024-04-25 23:53:58)

Migrate the `wasmtime-slab` crate to `no_std`
Nothing major here other than renaming crate imports and such.

<!--
Please make sure you include the following information:

- If this work has been discussed elsewhere, please include a link to that
  conversation. If it was discussed in an issue, just mention "issue #...".

- Explain why this change is needed. If the details are in an issue already,
  this can be brief.

Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.html

Please ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->



Patch:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index f1a352437..f2b5a0c93 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -372,6 +372,9 @@ jobs:
     - run: cargo check -p wasmtime-asm-macros
       env:
         CARGO_BUILD_TARGET: x86_64-unknown-none
+    - run: cargo check -p wasmtime-slab
+      env:
+        CARGO_BUILD_TARGET: x86_64-unknown-none
 
     # Check that wasmtime-runtime compiles with panic=abort since there's some
     # #[cfg] for specifically panic=abort there.
@@ -508,7 +511,7 @@ jobs:
     strategy:
       fail-fast: true
       matrix:
-        os: [ubuntu-latest, macos-latest, macos-14, windows-latest]
+        os: [ubuntu-latest, macos-latest, windows-latest]
 
     steps:
     - uses: actions/checkout@v4
diff --git a/ci/build-build-matrix.js b/ci/build-build-matrix.js
index b51be1801..9b67ef5a9 100644
--- a/ci/build-build-matrix.js
+++ b/ci/build-build-matrix.js
@@ -36,7 +36,7 @@ const array = [
   },
   {
     "build": "aarch64-macos",
-    "os": "macos-14",
+    "os": "macos-latest",
     "target": "aarch64-apple-darwin",
   },
   {
diff --git a/crates/slab/src/lib.rs b/crates/slab/src/lib.rs
index ca0173496..aa3d213a9 100644
--- a/crates/slab/src/lib.rs
+++ b/crates/slab/src/lib.rs
@@ -120,18 +120,23 @@
 //! }
 //! ```
 
+#![no_std]
 #![forbid(unsafe_code)]
 #![deny(missing_docs, missing_debug_implementations)]
 
-use std::num::NonZeroU32;
+extern crate alloc;
+
+use alloc::vec::Vec;
+use core::fmt;
+use core::num::NonZeroU32;
 
 /// An identifier for an allocated value inside a `slab`.
 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
 #[repr(transparent)]
 pub struct Id(EntryIndex);
 
-impl std::fmt::Debug for Id {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+impl fmt::Debug for Id {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_tuple("Id").field(&self.0.index()).finish()
     }
 }
@@ -167,11 +172,11 @@ pub struct Slab<T> {
     len: u32,
 }
 
-impl<T> std::fmt::Debug for Slab<T>
+impl<T> fmt::Debug for Slab<T>
 where
-    T: std::fmt::Debug,
+    T: fmt::Debug,
 {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_map().entries(self.iter()).finish()
     }
 }
@@ -218,7 +223,7 @@ impl<T> Default for Slab<T> {
     }
 }
 
-impl<T> std::ops::Index<Id> for Slab<T> {
+impl<T> core::ops::Index<Id> for Slab<T> {
     type Output = T;
 
     #[inline]
@@ -228,7 +233,7 @@ impl<T> std::ops::Index<Id> for Slab<T> {
     }
 }
 
-impl<T> std::ops::IndexMut<Id> for Slab<T> {
+impl<T> core::ops::IndexMut<Id> for Slab<T> {
     #[inline]
     fn index_mut(&mut self, id: Id) -> &mut Self::Output {
         self.get_mut(id)
@@ -282,7 +287,7 @@ impl<T> Slab<T> {
         // we add some amount of minimum additional capacity, since doubling
         // zero capacity isn't useful.
         const MIN_CAPACITY: usize = 16;
-        let additional = std::cmp::max(self.entries.capacity(), MIN_CAPACITY);
+        let additional = core::cmp::max(self.entries.capacity(), MIN_CAPACITY);
         self.reserve(additional);
     }
 
@@ -419,7 +424,7 @@ impl<T> Slab<T> {
     /// deallocate an arbitrary value.
     #[inline]
     pub fn dealloc(&mut self, id: Id) -> T {
-        let entry = std::mem::replace(
+        let entry = core::mem::replace(
             self.entries
                 .get_mut(id.0.index())
                 .expect("id from a different slab"),
@@ -428,7 +433,7 @@ impl<T> Slab<T> {
         match entry {
             Entry::Free { .. } => panic!("attempt to deallocate an entry that is already vacant"),
             Entry::Occupied(value) => {
-                let next_free = std::mem::replace(&mut self.free, Some(id.0));
+                let next_free = core::mem::replace(&mut self.free, Some(id.0));
                 self.entries[id.0.index()] = Entry::Free { next_free };
                 self.len -= 1;
                 value
diff --git a/crates/wit-bindgen/src/lib.rs b/crates/wit-bindgen/src/lib.rs
index d5e0dcf15..2dee30e3e 100644
--- a/crates/wit-bindgen/src/lib.rs
+++ b/crates/wit-bindgen/src/lib.rs
@@ -1391,9 +1391,20 @@ impl<'a> InterfaceGenerator<'a> {
     {
         let info = self.info(id);
 
+        // We use a BTree set to make sure we don't have any duplicates and we have a stable order
+        let additional_derives: BTreeSet<String> = self
+            .gen
+            .opts
+            .additional_derive_attributes
+            .iter()
+            .cloned()
+            .collect();
+
         for (name, mode) in self.modes_of(id) {
             let name = to_rust_upper_camel_case(&name);
 
+            let mut derives = additional_derives.clone();
+
             self.rustdoc(docs);
             let lt = self.lifetime_for(&info, mode);
             self.push_str("#[derive(wasmtime::component::ComponentType)]\n");
@@ -1403,10 +1414,17 @@ impl<'a> InterfaceGenerator<'a> {
             self.push_str("#[derive(wasmtime::component::Lower)]\n");
             self.push_str(&format!("#[component({})]\n", derive_component));
             if info.is_copy() {
-                self.push_str("#[derive(Copy, Clone)]\n");
+                derives.extend(["Copy", "Clone"].into_iter().map(|s| s.to_string()));
             } else if info.is_clone() {
-                self.push_str("#[derive(Clone)]\n");
+                derives.insert("Clone".to_string());
+            }
+
+            if !derives.is_empty() {
+                self.push_str("#[derive(");
+                self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", "));
+                self.push_str(")]\n")
             }
+
             self.push_str(&format!("pub enum {name}"));
             self.print_generics(lt);
             self.push_str("{\n");


Test patch:
diff --git a/ci/build-test-matrix.js b/ci/build-test-matrix.js
index 22c8c8820..92bfedfc2 100644
--- a/ci/build-test-matrix.js
+++ b/ci/build-test-matrix.js
@@ -56,7 +56,7 @@ const array = [
     "isa": "x64"
   },
   {
-    "os": "macos-latest",
+    "os": "macos-13",
     "name": "Test macOS x86_64",
     "filter": "macos-x64",
     "extra_features": "--features wasmtime-wasi-nn/onnx"
diff --git a/crates/component-macro/tests/codegen.rs b/crates/component-macro/tests/codegen.rs
index 09fd32f22..f68f5930b 100644
--- a/crates/component-macro/tests/codegen.rs
+++ b/crates/component-macro/tests/codegen.rs
@@ -531,9 +531,16 @@ mod custom_derives {
             package my:inline;
 
             interface blah {
+                variant abc {
+                    a,
+                    b,
+                    c
+                }
+
                 record foo {
                     field1: string,
-                    field2: list<u32>
+                    field2: list<u32>,
+                    field3: abc
                 }
 
                 bar: func(cool: foo);
@@ -548,7 +555,7 @@ mod custom_derives {
         additional_derives: [serde::Serialize, serde::Deserialize, Hash, Clone, PartialEq, Eq],
     });
 
-    use my::inline::blah::{Foo, Host};
+    use my::inline::blah::{Abc, Foo, Host};
 
     struct X;
 
@@ -558,6 +565,7 @@ mod custom_derives {
             let _blah: HashSet<Foo, RandomState> = HashSet::from_iter([Foo {
                 field1: "hello".to_string(),
                 field2: vec![1, 2, 3],
+                field3: Abc::B,
             }]);
 
             // Check that the attributes from an external crate actually work. If they don't work,