Skip to content

Commit

Permalink
Fix error for invalid deku_id generation on generic enum (#411)
Browse files Browse the repository at this point in the history
Add/Fixup lifetime for generated code for enum ext id finding.
Lifetime __deku needs to be added to the deku_id_type, and the impl.
  • Loading branch information
wcampbell0x2a authored Apr 30, 2024
1 parent d6bf743 commit b6a46d5
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 3 deletions.
9 changes: 7 additions & 2 deletions deku-derive/src/macros/deku_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,12 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {

// Implement `DekuEnumExt`
if let Some(deku_id_type) = deku_id_type {
tokens.extend(quote! {
impl #imp DekuEnumExt<#lifetime, (#deku_id_type)> for #ident #wher {
if !imp.to_token_stream().is_empty() {
// Generics (#imp) are not supported, as our __deku
// would need to be appended to #imp
} else {
tokens.extend(quote! {
impl<'__deku> #imp ::#crate_::DekuEnumExt<#lifetime, (#deku_id_type)> for #ident #wher {
#[inline]
fn deku_id(&self) -> core::result::Result<(#deku_id_type), DekuError> {
match self {
Expand All @@ -420,6 +424,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
}
}
});
}
}

// println!("{}", tokens.to_string());
Expand Down
5 changes: 5 additions & 0 deletions deku-derive/src/macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use syn::parse::Parser;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::token::Comma;
use syn::Lifetime;

use crate::Num;

Expand Down Expand Up @@ -211,6 +212,10 @@ fn gen_type_from_ctx_id(
if let syn::FnArg::Typed(pat_type) = arg {
if let syn::Pat::Ident(ident) = &*pat_type.pat {
if id == ident.ident {
let mut pat_type = pat_type.clone();
if let syn::Type::Reference(r) = pat_type.ty.as_mut() {
r.lifetime = Some(Lifetime::new("'__deku", Span::call_site()));
}
let ty = &pat_type.ty;
t = Some(quote! {#ty});
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ pub trait DekuUpdate {
}

/// "Extended Enum" trait: obtain additional enum information
pub trait DekuEnumExt<'a, T> {
pub trait DekuEnumExt<'__deku, T> {
/// Obtain `id` of a given enum variant
fn deku_id(&self) -> Result<T, DekuError>;
}
Expand Down
13 changes: 13 additions & 0 deletions tests/test_compile/cases/no_deku_id_generic_enum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use deku::prelude::*;

#[derive(DekuRead)]
#[deku(id_type = "u8")]
pub enum Body<T: for<'a> DekuReader<'a>> {
#[deku(id = "0x0001")]
First(T),
}

fn main() {
let n = Body::<u8>::First(1);
n.deku_id();
}
12 changes: 12 additions & 0 deletions tests/test_compile/cases/no_deku_id_generic_enum.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0599]: no method named `deku_id` found for enum `Body` in the current scope
--> tests/test_compile/cases/no_deku_id_generic_enum.rs:12:7
|
5 | pub enum Body<T: for<'a> DekuReader<'a>> {
| ---------------------------------------- method `deku_id` not found for this enum
...
12 | n.deku_id();
| ^^^^^^^ method not found in `Body<u8>`
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `deku_id`, perhaps you need to implement it:
candidate #1: `deku::DekuEnumExt`

0 comments on commit b6a46d5

Please sign in to comment.