Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement: better error messages for missing struct fields? #393

Closed
maurges opened this issue Jul 24, 2022 · 6 comments
Closed

Enhancement: better error messages for missing struct fields? #393

maurges opened this issue Jul 24, 2022 · 6 comments

Comments

@maurges
Copy link

maurges commented Jul 24, 2022

Currently missing fields in struct gives no line info, not even the typename info, which makes it hard to find where in the row of same-y declarations you missed a field. For example:

#[derive(serde::Deserialize, Debug)]
struct Test {
    f1: i64,
    f2: String,
}

fn main() {
    let s = r#"
Test (
    f1: 55,
)
"#;
    let x: Result<Test, _> = ron::from_str(s);
    println!("{:?}", x);
}

gives: Err(Error { code: Message("missing field f2"), position: Position { line: 0, col: 0 } })

It would be great if I could get line info, or at least the name "Test" of the record.

Also there is a similar problem with enum variants. Which seems doubly strange, as when I write an incorrect constructor for a struct, like replacing "Test" with "NotTest" in the example above, I get precise error location and type info.

@juntyr
Copy link
Member

juntyr commented Jul 24, 2022

On master, #356 is already included (this was excluded from v0.7.1 in #382), which does give the correct line info (also for enum variants):

Err(SpannedError { code: Message("missing field `f2`"), position: Position { line: 4, col: 1 } })

I'll check if we could also give the name of the struct or enum variant where the field is missing

@torkleyy
Copy link
Contributor

I think we should make necessary API breaking changes now (if any) and then release master as 0.8, so the new features, especially better errors, become available.

@juntyr
Copy link
Member

juntyr commented Jul 24, 2022

Ok, so the error message here comes from serde's default implementation of Error::missing_field, which just generates this string. If we wanted, ron could overwrite all or some of the Error methods to capture the results in nicer error variants - this might be a good idea on its own, just to make error handling easier.

If we then have such variants, we could populate them with extra optional information that would be None by default, e.g. the name of the surrounding struct, the name of the field etc. While this might make for fantastic error messages in some cases, it could also bloat the error type. For now, I don't think adding this functionality to ron is necessary.

@d86leader What I use for such nice contextual error messages is the serde_path_to_error crate:

let mut de_ron = ron::Deserializer::from_str_with_options(ron_str, ron_options)?;

let mut track = serde_path_to_error::Track::new();
let de = serde_path_to_error::Deserializer::new(&mut de_ron, &mut track);

let result = match Test::deserialize(de) {
    Ok(args) => Ok(args),
    Err(err) => {
        let path = track.path();
        let err = de_ron.span_error(err);

        Err(format!(
            "{}{} @ ({}):\n{}",
            path,
            if path.iter().count() >= 1 { "" } else { "*" },
            err.position,
            err.code,
        ))
    },
}

@maurges
Copy link
Author

maurges commented Jul 24, 2022

Thanks! I agree, if there is line info, having constructor or type name is not necessarily necessary. I will close this issue then.

Can't wait for 0.8, with this and supplying extensions via decoder options!

@maurges maurges closed this as completed Jul 24, 2022
@juntyr
Copy link
Member

juntyr commented Jul 24, 2022

@torkleyy Do you think we should convert serde's errors into nice error variants? For the invalid_[type|value|length] error methods we wouldn't be able to do better than stringifying the expected vs provided elements anyways, but we could very nicely represent the unknown_variant, unknown_field, missing_field, and duplicate_field errors.

@torkleyy
Copy link
Contributor

If we can provide better error information without overly cluttering the codebase, absolutely, yes!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants