Emit shim implementation on macro error

finchie
Sep 8, 2025, 6:50 AM
TFKGE6LRNSG2N5Z3LIITYG7WH2VOLWQO7AESTWRWV52BFHESU26AC

Dependencies

  • [2] OWXLFLRM Merge `cli_macros` shim into `fluent_embed`
  • [3] CESJ4CTO Move macro-specific code into `macro_impl` module
  • [4] 73C6NOJ7 Fix minimal `Localize` implementation on errors
  • [5] 7JPOCQEI Add explicit error handling for macro parsing
  • [6] LU6IFZFG Remove `std::io::Write` trait bound from `Localize`
  • [7] QJC4IQIT Refactor `Localize` functions to infallibly return `String`
  • [8] NEBSVXIA Apply Clippy fixes
  • [9] 6XEMHUGS Use full `Locale` instead of `LanguageIdentifier` subset
  • [10] RUCC2HKZ Rename from `fluent_embed` to `l10n_embed`
  • [11] EKXWNEPK Rename `Localize::message_for_locale` to `Localize::localize_for`
  • [12] RA3H7PWC Refactor `Localize` for performance
  • [13] PGBXJWIH Move `l10n_embed` re-exports into `macro_prelude` module
  • [14] LIO32J4B Fix compiler error when `expand` feature is disabled
  • [15] XGRU7WZE Add `expand` feature for proc-macro debugging
  • [*] O77KA6C4 Create `fluent_embed` crate

Change contents

  • edit in l10n_embed_derive/src/lib.rs at line 16
    [3.5274][10.1870:1959](),[10.1959][9.1709:1710](),[3.5365][9.1709:1710]()
    // No errors found, emit the generated `l10n_embed::Localize` implementation
  • replacement in l10n_embed_derive/src/lib.rs at line 33
    [3.5498][3.5498:5545](),[3.5545][8.1243:1328]()
    // Emit the relevant error message
    macro_impl::error::emit(error, &attribute_stream, &derive_input_stream);
    [3.5498]
    [2.906]
    // Using the `proc_macro_error2` crate to generate errors ignores
    // the token stream returned from this function, so use the `set_dummy` function
    // to make sure a macro error is as self-contained as possible:
    // - Derive input streams are not consumed, so structs/enums don't "disappear" when macro returns error
    // - Generate a shim trait implementation when possible so that editor completions still work as expected
    proc_macro_error2::set_dummy(
    match syn::parse2::<syn::DeriveInput>(derive_input_stream.clone()) {
    // Generate a minimal `Localize` implementation so the error is self-contained
    Ok(derive_input) => {
    let ident = derive_input.ident;
    let (impl_generics, type_generics, where_clause) =
    derive_input.generics.split_for_impl();
  • replacement in l10n_embed_derive/src/lib.rs at line 46
    [2.907][4.0:91](),[4.91][5.2117:2362]()
    // Generate a minimal `Localize` implementation so the error is self-contained
    match syn::parse2::<syn::DeriveInput>(derive_input_stream.clone()) {
    Ok(derive_input) => {
    let ident = derive_input.ident;
    quote! {
    #derive_input_stream
    [2.907]
    [9.1794]
    quote! {
    #derive_input_stream
  • replacement in l10n_embed_derive/src/lib.rs at line 49
    [9.1795][10.2022:2087](),[10.2087][12.4287:4328](),[6.476][5.2937:2976](),[11.745][5.2937:2976](),[7.1403][5.2937:2976](),[12.4328][5.2937:2976](),[5.2937][5.2937:2976](),[5.2976][12.4329:4479](),[7.1446][5.3194:3278](),[12.4479][5.3194:3278](),[5.3194][5.3194:3278]()
    impl ::l10n_embed::Localize for #ident {
    fn localize(
    &self,
    context: &::l10n_embed::Context,
    buffer: &mut String,
    ) {
    unimplemented!("Encountered error in derive macro")
    [9.1795]
    [5.3278]
    impl #impl_generics ::l10n_embed::Localize for #ident #type_generics #where_clause {
    fn localize(
    &self,
    context: &::l10n_embed::Context,
    buffer: &mut String,
    ) {
    unimplemented!("Encountered error in derive macro")
    }
  • replacement in l10n_embed_derive/src/lib.rs at line 60
    [3.5945][9.1874:1892](),[9.1892][5.3354:3505](),[5.3354][5.3354:3505](),[5.3505][3.5963:5977](),[3.5963][3.5963:5977]()
    }
    // Unable to fail gracefully if the ident is unknown, so just return the original input
    Err(_) => derive_input_stream,
    }
    [3.5945]
    [3.5977]
    // Unable to implement Localize if the ident is unknown, so just return the original input
    Err(_) => derive_input_stream.clone(),
    },
    );
    // Emit the relevant error message
    macro_impl::error::emit(error, &attribute_stream, &derive_input_stream);
    // `proc_macro_error2` will output the relevant token stream, but the function still needs to return something
    quote!()