Rustc note providing malformed code when run with proc_macro
⚓ Rust 📅 2025-12-13 👤 surdeus 👁️ 1When I try to run this code, it fails:
#[derive(MyFrom)]
struct MyTupleGeneric<T> {
name: T
}
where this is the proc_macro I used:
extern crate proc_macro;
use proc_macro::TokenStream;
use syn::{parse_macro_input, Data, DeriveInput, Fields};
use quote::quote;
use syn::spanned::Spanned;
#[proc_macro_derive(MyFrom)]
pub fn my_derive(input: TokenStream) -> TokenStream {
let derived_input = parse_macro_input!(input as DeriveInput);
let ident = &derived_input.ident;
if let Data::Struct(data) = derived_input.data {
match data.fields {
Fields::Named(fields) => {
if fields.named.len() != 1 {
return syn::Error::new(fields.span(), "#[derive(MyFrom)] cannot be implemented on anything other than a struct with one field").to_compile_error().into();
}
let field = fields.named.first().unwrap();
let name = field.ident.as_ref().unwrap();
let field_type = field.ty.clone();
if derived_input.generics.params.is_empty() {
quote! {
impl From<#field_type> for #ident {
fn from(value: #field_type) -> Self {
Self {
#name: value
}
}
}
}.into()
} else {
let generics = derived_input.generics.params;
if let Some(where_clause) = derived_input.generics.where_clause {
quote! {
impl<#generics> From<#field_type> for #ident #where_clause {
fn from(value: #field_type) -> Self {
Self {
#name: value
}
}
}
}.into()
} else {
quote! {
impl<#generics> From<#field_type> for #ident {
fn from(value: #field_type) -> Self {
Self {
#name: value
}
}
}
}.into()
}
}
},
Fields::Unnamed(fields) => {
if fields.unnamed.len() != 1 {
return syn::Error::new(fields.span(), "#[derive(MyFrom)] cannot be implemented on anything other than a struct with one field").to_compile_error().into();
}
let field = fields.unnamed.first().unwrap();
let field_type = field.ty.clone();
if derived_input.generics.params.is_empty() {
quote! {
impl From<#field_type> for #ident {
fn from(value: #field_type) -> Self {
Self(value)
}
}
}.into()
} else {
let generics = derived_input.generics.params;
if let Some(where_clause) = derived_input.generics.where_clause {
quote! {
impl<#generics> From<#field_type> for #ident #where_clause {
fn from(value: #field_type) -> Self {
Self(value)
}
}
}.into()
} else {
quote! {
impl<#generics> From<#field_type> for #ident {
fn from(value: #field_type) -> Self {
Self(value)
}
}
}.into()
}
}
},
Fields::Unit => {
syn::Error::new(ident.span(), "#[derive(MyFrom)] cannot be implemented on anything other than a struct with one field").to_compile_error().into()
}
}
} else {
syn::Error::new(ident.span(), "#[derive(MyFrom)] cannot be implemented on anything other than a struct with one field").to_compile_error().into()
}
}
returns this very malformed error:
error[E0107]: missing generics for struct `MyTupleGeneric`
--> derive_from\tests\from_works.rs:12:8
|
12 | struct MyTupleGeneric<T> {
| ^^^^^^^^^^^^^^ expected 1 generic argument
|
note: struct defined here, with 1 generic parameter: `T`
--> derive_from\tests\from_works.rs:12:8
|
12 | struct MyTupleGeneric<T> {
| ^^^^^^^^^^^^^^ -
help: add missing generic argument
|
12 | struct MyTupleGeneric<T><T> {
Shouldn't the missing generics be on the impl From block?
After I fixed it by adding the generic param to the ident, it worked well, but I am wondering why it showed this "wrong" note.
1 post - 1 participant
🏷️ Rust_feed