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

Deserializing internally tagged enum: error line information inaccurate #1621

Closed
karlri opened this issue Sep 6, 2019 · 3 comments
Closed

Comments

@karlri
Copy link

karlri commented Sep 6, 2019

When deserializing a internally tagged enum, everything works as expected when the input is correct, however:

If an error occurs while deserializing "inside" the internally tagged enum, the error line information points to the wrong place.

Note, simpler way to trigger bug in comments section.

Example code:

use serde_derive::*;
use serde_json::*;

#[derive(Deserialize)]
pub struct Event {
    event_id: u32,
    #[serde(flatten)]
    variant: EventVariant,
}

#[derive(Deserialize)]
#[serde(tag = "kind")]
pub enum EventVariant {
    Trigger { at: String },
    Interval { start: String, end: String },
}

fn main() {
    // at: 14 is wrong, it should be string. Expect error on line 3.
    let json_str = r#"{
        "kind": "Trigger",
        "at": 14,
        "event_id": 42
    }"#;
    let res: Result<Event> = from_str(json_str);
    match res {
        Err(e) => {
            assert_eq!(e.line(), 3)
        },
        Ok(_) => unreachable!()
    }
}

The result of running this code:

thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `5`,
 right: `3`', src/main.rs:29:13

Problem:
Line information is incorrect.

Actual behavior:
error line refers to end of outermost struct: line 5

Expected behavior:
error line refers to the exact line where the parse error occurred: line 3

@karlri karlri changed the title Deserializing flattened internally tagged enum: error line information inaccurate Deserializing internally tagged enum: error line information inaccurate Sep 10, 2019
@karlri
Copy link
Author

karlri commented Sep 10, 2019

Determined it has nothing to do with flatten. It is internal tagging only that triggers the issue.

Event simpler example:

use serde_derive::*;
use serde_json::*;

#[derive(Deserialize, Debug)]
#[serde(tag = "kind")]
pub enum EventVariant {
    Trigger { at: String },
    Interval { start: String, end: String },
}

fn main() {
    // at: 14 is wrong, it should be string. Expect error on line 3.
    let json_str = r#"{
        "kind": "Trigger",
        "at": 14
    }"#;
    let res: Result<EventVariant> = from_str(json_str);
    match res {
        Err(e) => {
            println!("{:?}", e);
            assert_eq!(e.line(), 3)
        },
        Ok(_) => unreachable!()
    }
}

Output:

Error("invalid type: integer `14`, expected a string", line: 0, column: 0)
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `0`,
 right: `3`', src/main.rs:21:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

@1tgr
Copy link

1tgr commented Mar 31, 2020

It looks to be due to the use of the TaggedContentVisitor to read the entire map into memory before parsing it in accordance with the "kind" field. By the time the data in memory is parsed, the reader has already advanced to the end of the map.

@dtolnay
Copy link
Member

dtolnay commented Jul 9, 2023

Line/column-numbering is format-specific functionality, so I think this ends up being a duplicate of #1183.

@dtolnay dtolnay closed this as completed Jul 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants