Serde: Confusing error message when deserializer does not support deserializing `&'a str`

Created on 11 Jul 2017  Â·  3Comments  Â·  Source: serde-rs/serde

I am not sure if this is a docopt issue, or an issue with serde. Please hear me out, and let me know if I should file this under docopt instead.

Consider the following example:

#[macro_use]
extern crate serde_derive;
extern crate docopt;

use docopt::Docopt;

const USAGE: &'static str = "
Simple borrowing

Usage:
  borrow <name>

Options:
  -h --help     Show this screen.
";

#[derive(Debug, Deserialize)]
struct Args<'a> {
    arg_name: &'a str
}

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());
    println!("{:?}", args);
}

When I run cargo run test, I get a weird error invalid type: string "testing", expected a borrowed string. The error message was really confusing, and I thought it was because of incorrect usage on my part.

Digging around the source code, it seems like the deserializer for docopt just does not support deserializing borrowed string. (Deserializer::deserialize_str function always calls Visitor::visit_str.)

Would this be a case where the error message from serde is confusing, or the deserializer is not implemented correctly?

support

Most helpful comment

@dtolnay The original issue doesn't seem to be addressed though? Just got also beaten by this error message, and if I wouldn't find this particular issue, could spend much more time trying to find a mistake in my own code.

Basically, I was trying to parse a bunch of JSON-based tests, and in the middle of parsing was getting

invalid type: string "�", expected a borrowed string"

It took a while to realize the reason for this. Indeed, serde_json can't return a slice if a string contained escaped characters, as in that case it must create a heap-allocated copy to unescape them.

Would it make sense to improve error message to clarify this?

Or maybe, deserializer could somehow return references to temporarily allocated strings to make these cases transparent to consumer (not sure if that's possible though)?

Or maybe better to prohibit deserializing slices altogether in deserializers that might need unescaping, for consistency?

In any case, it would be nice to clarify this situation.

All 3 comments

Looks like a docopt bug. The signature of Docopt::deserialize should be:

- fn deserialize<'a, 'de: 'a, D>(&'a self) -> Result<D, Error>
-     where D: Deserialize<'de>;
+ fn deserialize<D>(&self) -> Result<D, Error>
+     where D: DeserializeOwned;

I've submitted a PR to docopt. I'll close this issue since this is not a problem with serde.

@dtolnay The original issue doesn't seem to be addressed though? Just got also beaten by this error message, and if I wouldn't find this particular issue, could spend much more time trying to find a mistake in my own code.

Basically, I was trying to parse a bunch of JSON-based tests, and in the middle of parsing was getting

invalid type: string "�", expected a borrowed string"

It took a while to realize the reason for this. Indeed, serde_json can't return a slice if a string contained escaped characters, as in that case it must create a heap-allocated copy to unescape them.

Would it make sense to improve error message to clarify this?

Or maybe, deserializer could somehow return references to temporarily allocated strings to make these cases transparent to consumer (not sure if that's possible though)?

Or maybe better to prohibit deserializing slices altogether in deserializers that might need unescaping, for consistency?

In any case, it would be nice to clarify this situation.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Yamakaky picture Yamakaky  Â·  3Comments

dtolnay picture dtolnay  Â·  3Comments

spease picture spease  Â·  3Comments

kleimkuhler picture kleimkuhler  Â·  3Comments

dtolnay picture dtolnay  Â·  4Comments