Skip to content

bound attribute fails with non-helpful error when using associated type bound #3033

@tvsfx

Description

@tvsfx

Problem description

I just ran into an unexpected, hard-to-debug error trying to use serde(bound), which occurs when trying to use associated type bounds. This is a minimized example:

use serde::Deserialize;

#[derive(Deserialize)]
#[serde(bound(deserialize = "Struct: Trait<Assoc : Bound>"))]
struct Bla;

with feature syn/full disabled, this gives:

error: expected `,`
 --> src/main.rs:4:29
  |
4 | #[serde(bound(deserialize = "Struct: Trait<Assoc : Bound>"))]
  |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

when enabling this feature, we get:

error[E0412]: cannot find type `Struct` in this scope
 --> src/main.rs:4:29
  |
4 | #[serde(bound(deserialize = "Struct: Trait<Assoc : Bound>"))]
  |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
  |
...

i.e., the parsing phase was successful.

Given the minimal error message, it was hard to figure out what exact feature in syn was causing this (our tests succeeded but builds failed, since another dev dependency was setting syn/full).

Workaround

Enabling the syn/full feature works but is quite heavy-handed. Rewriting the bound as "<Struct as Trait>::Assoc : Bound" also works but is more verbose and unexpected, since the original syntax is supported in rust.

Cause

I went digging through the serde/syn code and found that what happens internally is essentially the following:

use proc_macro2::Span;
use syn::punctuated::Punctuated;
use syn::LitStr;
use syn::Token;
fn main() {
    let lit_string = LitStr::new("Struct: Trait<Assoc : Bound> ", Span::call_site());
    println!(
        "{:#?}",
        lit_string.parse_with(Punctuated::<syn::WherePredicate, Token![,]>::parse_terminated)
    );
}

which indeed manifests the error unless the syn/full feature is active.
The problematic feature gate that causes parsing to fail is here: https://docs.rs/syn/latest/src/syn/path.rs.html#366-401

Potential fixes

In decreasing order of goodness, but also decreasing order of work (this issue might have to moved to the syn crate depending on which one of these is applicable):

  1. Make the derive features more consistent between serde and syn, or introduce a new syn feature that bridges this gap. Not sure how much work/realistic this is.
  2. Improve error message on the serde side.
  3. Improve documentation about this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions