瀏覽代碼

fix: derive dynamic RustSBI on struct with generics(type, const, lifetime, where clause)

Signed-off-by: Zhenchen Wang <m202372036@hust.edu.cn>
Zhenchen Wang 1 周之前
父節點
當前提交
6e454d9f04
共有 3 個文件被更改,包括 129 次插入3 次删除
  1. 1 0
      macros/Cargo.toml
  2. 17 3
      macros/src/lib.rs
  3. 111 0
      tests/dynamic-generics.rs

+ 1 - 0
macros/Cargo.toml

@@ -21,6 +21,7 @@ proc-macro = true
 [dependencies]
 quote = "1.0.33"
 syn = "2.0.39"
+proc-macro2 = "1.0.82"
 
 [features]
 default = []

+ 17 - 3
macros/src/lib.rs

@@ -3,8 +3,12 @@
 //! Do not use this crate directly.
 
 use proc_macro::TokenStream;
+use proc_macro2::Span;
 use quote::{quote, ToTokens};
-use syn::{parse_macro_input, Data, DeriveInput, Generics, Ident, Member};
+use syn::{
+    parse_macro_input, Data, DeriveInput, GenericParam, Generics, Ident, Lifetime, LifetimeParam,
+    Member,
+};
 
 #[derive(Clone)]
 enum ParseMode {
@@ -515,9 +519,19 @@ fn impl_derive_rustsbi_dynamic(name: &Ident, imp: DynamicImpl, generics: &Generi
         });
     }
 
+    let (_, origin_ty_generics, _) = generics.split_for_impl();
+    let prober_generics = {
+        let mut ans = generics.clone();
+        let lifetime = Lifetime::new("'_lt", Span::mixed_site());
+        ans.params
+            .insert(0, GenericParam::Lifetime(LifetimeParam::new(lifetime)));
+        ans
+    };
+    let (impl_generics, ty_generics, where_clause) = prober_generics.split_for_impl();
+
     let define_prober = quote! {
-        struct _Prober<'a>(&'a #name);
-        impl<'a> ::rustsbi::_ExtensionProbe for _Prober<'a> {
+        struct _Prober #impl_generics (&'_lt #name #origin_ty_generics) #where_clause;
+        impl #impl_generics ::rustsbi::_ExtensionProbe for _Prober #ty_generics #where_clause {
             #[inline(always)]
             fn probe_extension(&self, extension: usize) -> usize {
                 match extension {

+ 111 - 0
tests/dynamic-generics.rs

@@ -0,0 +1,111 @@
+use rustsbi::RustSBI;
+use sbi_spec::binary::SbiRet;
+
+// These structs should pass Rust build.
+
+#[derive(RustSBI)]
+#[rustsbi(dynamic)]
+struct WithGenerics<T: rustsbi::Timer> {
+    reset: DummyReset,
+    timer: T,
+    info: DummyEnvInfo,
+}
+
+#[derive(RustSBI)]
+#[rustsbi(dynamic)]
+struct WithWhereClause<T>
+where
+    T: rustsbi::Timer,
+{
+    reset: DummyReset,
+    timer: T,
+    info: DummyEnvInfo,
+}
+
+#[derive(RustSBI)]
+#[rustsbi(dynamic)]
+struct WithConstantGenerics<const N: usize> {
+    info: DummyEnvInfo,
+    _dummy: [u8; N],
+}
+
+#[derive(RustSBI)]
+#[rustsbi(dynamic)]
+struct WithLifetime<'a> {
+    info: &'a DummyEnvInfo,
+}
+
+#[derive(RustSBI)]
+#[rustsbi(dynamic)]
+struct WithEverythingCombined<'a, T: rustsbi::Timer, U, const N: usize>
+where
+    U: rustsbi::Reset,
+{
+    timer: T,
+    reset: U,
+    info: &'a DummyEnvInfo,
+    _dummy: [u8; N],
+}
+
+#[test]
+fn test_impl_id() {
+    let sbi = WithGenerics {
+        reset: DummyReset,
+        timer: DummyTimer,
+        info: DummyEnvInfo,
+    };
+    assert_eq!(sbi.handle_ecall(0x10, 0x1, [0; 6]).value, 4);
+    let sbi = WithWhereClause {
+        reset: DummyReset,
+        timer: DummyTimer,
+        info: DummyEnvInfo,
+    };
+    assert_eq!(sbi.handle_ecall(0x10, 0x1, [0; 6]).value, 4);
+    let sbi = WithConstantGenerics {
+        info: DummyEnvInfo,
+        _dummy: [0; 100],
+    };
+    assert_eq!(sbi.handle_ecall(0x10, 0x1, [0; 6]).value, 4);
+    let dummy_info = DummyEnvInfo;
+    let sbi = WithLifetime { info: &dummy_info };
+    assert_eq!(sbi.handle_ecall(0x10, 0x1, [0; 6]).value, 4);
+    let sbi = WithEverythingCombined {
+        timer: DummyTimer,
+        reset: DummyReset,
+        info: &dummy_info,
+        _dummy: [0; 10],
+    };
+    assert_eq!(sbi.handle_ecall(0x10, 0x1, [0; 6]).value, 4);
+}
+
+struct DummyReset;
+
+impl rustsbi::Reset for DummyReset {
+    fn system_reset(&self, _: u32, _: u32) -> SbiRet {
+        unimplemented!()
+    }
+}
+
+struct DummyTimer;
+
+impl rustsbi::Timer for DummyTimer {
+    fn set_timer(&self, _: u64) {
+        unimplemented!()
+    }
+}
+
+struct DummyEnvInfo;
+
+impl rustsbi::EnvInfo for DummyEnvInfo {
+    fn mvendorid(&self) -> usize {
+        unimplemented!()
+    }
+
+    fn marchid(&self) -> usize {
+        unimplemented!()
+    }
+
+    fn mimpid(&self) -> usize {
+        unimplemented!()
+    }
+}