rust-lang / rust-lang/log

non-primitive cast error when using multiple key-value pairs in debug! macro inside async_trait

Open
#706 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
2.5k
Forks
289
Avg merge
55m
Merged PRs (30d)
1

Description

Description

When using the debug! (or other log-level) macro with multiple key-value pairs, compilation fails with the following error:

error[E0605]: non-primitive cast: `&[(&'static str, Value<'_>); 2]` as `&[(&str, Value<'_>)]`

However, when only one key-value pair is used, or when no key-values are included, it compiles and runs correctly.

### Example

This compiles fine:

debug!(host = "localhost", "Deleting documents");

But adding an additional key-value pair causes a compilation error:

debug!(host = "localhost", version = "1.0.0"; "Deleting documents");

This produces:

error[E0605]: non-primitive cast: `&[(&'static str, Value<'_>); 2]` as `&[(&str, Value<'_>)]`
Context

This happens inside a function annotated with #[async_trait], but the same pattern works fine outside of async traits.
It seems related to how Rust infers lifetimes and array types in macro expansions involving slices of tuples.

The generated code from the macro expands roughly into:

&[("host", host_value), ("version", version_value)] as &[(&str, Value)]

which causes the compiler to reject the cast because the inferred array type has 'static keys (&'static str) but the target expects &str.

### Workaround

Replacing the slice construction inside the macro with this expression fixes the issue:

&vec![
    ($crate::__log_key!($key), $crate::__log_value!($key $(:$capture)* = $($value)*))
] as &[_],

Using a vec![] and taking a reference seems to allow proper type coercion to &[(&str, Value)].

### Possible Cause

This likely comes from a type coercion mismatch between:
• the fixed array literal ([ ... ]) which has a concrete type like [(&'static str, Value<'>); N],
• and the expected trait-bound type &[(&str, Value<'
>)].

The compiler disallows this cast because arrays of tuples with different lifetimes on the first element are not directly coercible to slices of tuples with more general lifetimes.

Using vec![] allows dynamic slice coercion at runtime and avoids this limitation.

## Environment

•	Rust version: 1.81.0
•	Crate: log (latest release at time of writing)
•	Feature: kv enabled
•	Context: using within #[async_trait] functions

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the kv-enabled debug! expansion inside an #[async_trait] function with Rust 1.81. Inspect the generated key-value slice and compare the single-pair and multiple-pair cases, using the reported vec![] workaround as a reference. Done means both examples compile successfully without the non-primitive cast error.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
devtools
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.