rust-lang/rust · error · syn::Error

Expected a string literal

Error message

Expected a string literal

What it means

Emitted by doc_comment_from_desc in the rustc_queries! macro. When a query has no explicit doc comment (///), the macro auto-generates one from the desc modifier's expression list. The first expression must be a string literal (a format string like "computes type of {}"). If the first expression is not an Expr::Lit containing a Lit::Str, this error fires at the span of the entire expression list. This only happens when no manual doc comment is provided — if you add ///, doc_comment_from_desc is never called.

Solutions

  1. Ensure the desc block starts with a string literal: desc { "description for `{}`", key }.
  2. Alternatively, add a /// doc comment above the query — then desc's format is not inspected for auto-doc generation, though desc still requires a string literal for the query description closure.
  3. Remember that desc's first element is always a format string; subsequent comma-separated expressions are the format arguments.

Example fix

// before (no doc comment, desc doesn't start with a string literal):
query foo(key: DefId) -> Ty<'tcx> { desc { key, "foo" } }
// after: start with a string literal format string
query foo(key: DefId) -> Ty<'tcx> { desc { "foo for `{}`", key } }
// or add a manual doc comment:
/// Computes foo for the given definition.
query foo(key: DefId) -> Ty<'tcx> { desc { "foo for `{}`", key } }
Defensive patterns

Strategy: validation

Validate before calling

// Ensure every desc block starts with a string literal, or add a doc comment.
// Static check in your editor: verify the first token inside desc { } is a "...".
// If you add a /// comment above the query, doc_comment_from_desc is bypassed
// and this error won't fire (though desc still needs a string literal for the description).

Try / catch

// Compile-time error from the proc macro — cannot be caught at runtime.
// Fix by making the first element of desc { } a string literal.

Prevention

When it happens

Trigger: Writing a query without a /// doc comment where the desc block's first element is not a string literal. For example: desc { 42, key } or desc { tcx.item_name(key), key } or an empty desc { }. The first token must be a quoted string.

Common situations: Writing a desc block that starts with a format_args! macro call or an expression instead of a plain string literal; forgetting the format string and only putting expression arguments.

Related errors


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/3b30689c8d342b2a. Report an issue: GitHub.

Appendix: source

Thrown at compiler/rustc_macros/src/query.rs:316

        eval_always: #eval_always,
        feedable: #feedable,
        handle_cycle_error: #handle_cycle_error,
        no_force: #no_force,
        no_hash: #no_hash,
        returns_error_guaranteed: #returns_error_guaranteed,
        separate_provide_extern: #separate_provide_extern,
        // tidy-alphabetical-end
    }
}

fn doc_comment_from_desc(list: &Punctuated<Expr, token::Comma>) -> Result<Attribute> {
    use ::syn::*;
    let mut iter = list.iter();
    let format_str: String = match iter.next() {
        Some(&Expr::Lit(ExprLit { lit: Lit::Str(ref lit_str), .. })) => {
            lit_str.value().replace("`{}`", "{}") // We add them later anyways for consistency
        }
        _ => return Err(Error::new(list.span(), "Expected a string literal")),
    };
    let mut fmt_fragments = format_str.split("{}");
    let mut doc_string = fmt_fragments.next().unwrap().to_string();
    iter.map(::quote::ToTokens::to_token_stream).zip(fmt_fragments).for_each(
        |(tts, next_fmt_fragment)| {
            use ::core::fmt::Write;
            write!(
                &mut doc_string,
                " `{}` {}",
                tts.to_string().replace(" . ", "."),
                next_fmt_fragment,
            )
            .unwrap();
        },
    );
    let doc_string = format!("[query description - consider adding a doc-comment!] {doc_string}");
    Ok(parse_quote! { #[doc = #doc_string] })
}

View on GitHub (pinned to 7088e4b63a)