# Rustc's json output format

**URL:** <https://internals.rust-lang.org/t/rustcs-json-output-format/3446>\
**Category:** tools and infrastructure\
**Created:** [May 9, 2016, 9:15am UTC](https://internals.rust-lang.org/t/rustcs-json-output-format/3446 "2016-05-09T09:15:44Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![oli-obk](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/oli-obk/32/3168_2.png) [@oli-obk](https://internals.rust-lang.org/u/oli-obk)\
**Post date:** [May 9, 2016, 9:15am UTC](https://internals.rust-lang.org/t/rustcs-json-output-format/3446/1 "2016-05-09T09:15:44Z")

</div>

Continuing the discussion from [Editor compatibility and the new error format](https://internals.rust-lang.org/t/editor-compatibility-and-the-new-error-format/3435/25):

rustc can already produce json: `-Z unstable-options --error-format=json`, but it's rather crude/redundant so far. In the Atom plugin `build-cargo` I chose to simply ignore all output lines not starting with a `{` (so any cargo output). There's an open issue for cargo here: [Is it possible to get cargo's output as json? · Issue #1403 · rust-lang/cargo · GitHub](https://github.com/rust-lang/cargo/issues/1403)

> [@Editor compatibility and the new error format](https://internals.rust-lang.org/t/editor-compatibility-and-the-new-error-format/3435/23):
>
> JSON gives you the full details, which is best of all, but it's kind of unstable (something we should start a distinct thread about).

I'm quite happy with the current format. It allowed me to create error messages of the following look:

[https://cloud.githubusercontent.com/assets/332036/15097688/ddfc170c-1523-11e6-8394-d24a79d125ea.png](https://cloud.githubusercontent.com/assets/332036/15097688/ddfc170c-1523-11e6-8394-d24a79d125ea.png)

Once I run a markdown -\> html formatter over the explanation, it should look just like the error page.

The format is defined here: [https://github.com/rust-lang/rust/blob/master/src/libsyntax/errors/json.rs#L74-L146](https://github.com/rust-lang/rust/blob/master/src/libsyntax/errors/json.rs#L74-L146)

The format itself allows children to have children of their own, so technically someone parsing the format needs to allow for that case, even though rustc never produces it. Maybe the format should make that clear by separating out a `Child` type with fewer fields.

---

<div class="post-metadata">

**Author:** ![matklad](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matklad/32/12266_2.png) [@matklad](https://internals.rust-lang.org/u/matklad)\
**Post date:** [May 9, 2016, 10:42am UTC](https://internals.rust-lang.org/t/rustcs-json-output-format/3446/2 "2016-05-09T10:42:20Z")

</div>

Two tips:

- There is [`RUSTFLAGS`](https://github.com/rust-lang/cargo/blob/master/src/doc/environment-variables.md#environment-variables-cargo-reads) environmental variable which should help with passing `--error-format`
- “chose to simply ignore all output lines not starting with a” \<-- this hopefully will become unnecessary when [`#1473`](https://github.com/rust-lang/cargo/issues/1473) is fixed

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [May 9, 2016, 12:21pm UTC](https://internals.rust-lang.org/t/rustcs-json-output-format/3446/3 "2016-05-09T12:21:59Z")

</div>

So this is roughly the format that I would [like to see](https://gist.github.com/nikomatsakis/3ad1306ace259cb22404e8d8abbd73a8). I can’t see to copy-and-paste here so this is a link to a gist. But the high-level idea is to include roughly the same logical information that we include today, along with _presentation_ information. The presentation information would be literally the same output that rustc emits, but augmented with formatting info (like "this should be styled as the “main message”, or “this is the filename/line-number” or “this is a line from the source text”). The goal of the presentation information is to make it easy for tools to reproduce rustc’s output and formatting, which will presumably evolve and improve, without having to reproduce all of our internal logic for extracting snippets and rendering annotations.

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [May 9, 2016, 12:24pm UTC](https://internals.rust-lang.org/t/rustcs-json-output-format/3446/4 "2016-05-09T12:24:31Z")

</div>

> [@matklad](#):
>
> There is RUSTFLAGS environmental variable which should help with passing --error-format

I see two problems with RUSTFLAGS to convey a request for JSON:

- rustc itself doesn't respect it, only cargo (we could change this)
- I see RUSTFLAGS as being more for humans to inject flags than tools, but I guess that's a relatively minor point; specifically, I expect people to do things like `make foo RUSTFLAGS="-g"` which would then ignore any RUSTFLAGS settings installed by the editor.

But this will depend a lot on the environment. I am assuming a tool like emacs, where users may wish to specify their own build command, but we would like to silently control the output format. But this particular aspect of the discussion (how to select json output) feels like it belongs more to [the original thread](https://internals.rust-lang.org/t/editor-compatibility-and-the-new-error-format/3435/)

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [May 9, 2016, 12:25pm UTC](https://internals.rust-lang.org/t/rustcs-json-output-format/3446/5 "2016-05-09T12:25:06Z")

</div>

> [@ker](#):
>
> In the Atom plugin build-cargo I chose to simply ignore all output lines not starting with a { (so any cargo output)

Yeah, cargo outputting as json would be great.

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [May 9, 2016, 12:25pm UTC](https://internals.rust-lang.org/t/rustcs-json-output-format/3446/6 "2016-05-09T12:25:33Z")

</div>

> [@ker](#):
>
> I'm quite happy with the current format.

This is indeed cool. It seems to me that you too _might_ benefit from the "presentation" info I have been describing, but maybe not.

---

<div class="post-metadata">

**Author:** ![oli-obk](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/oli-obk/32/3168_2.png) [@oli-obk](https://internals.rust-lang.org/u/oli-obk)\
**Post date:** [May 9, 2016, 1:13pm UTC](https://internals.rust-lang.org/t/rustcs-json-output-format/3446/7 "2016-05-09T13:13:43Z")

</div>

> [@nikomatsakis](#):
>
> The presentation information would be literally the same output that rustc emits, but augmented with formatting info (like "this should be styled as the "main message", or "this is the filename/line-number" or "this is a line from the source text").

So basically it could be html with style attributes. Then end users can choose their css style or simply strip the html.

> Diagnostic -\> logical -\> suggestions (`Vec<(Span, String)>`)?

What if there are multiple possible suggestions?

> Diagnostic -\> logical -\> error code

There are also errors due to deny'd lints, these don't have an error code, but they have a lint name. Clippy goes as far as giving a url to the lint documentation, but the explanation is probably enough.

> [@nikomatsakis](#):
>
> It seems to me that you too might benefit from the "presentation" info I have been describing, but maybe not.

I don't think so, the logical format is great to process, and I'm not creating the tooltip, I'm utilizing an existing framework.

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [May 9, 2016, 1:17pm UTC](https://internals.rust-lang.org/t/rustcs-json-output-format/3446/8 "2016-05-09T13:17:14Z")

</div>

> [@ker](#):
>
> So basically it could be html with style attributes. Then end users can choose their css style or simply strip the html.

Yeah. We could even use HTML I guess.

> [@ker](#):
>
> What if there are multiple possible suggestions?

I'm not sure I follow. Currently, though, we produce _a_ suggested edit. I guess you are saying what if we made multiple suggested edits?

> [@ker](#):
>
> There are also errors due to deny'd lints, these don't have an error code, but they have a lint name. Clippy goes as far as giving a url to the lint documentation, but the explanation is probably enough.

Yeah, it'd be good to expose the lint name in the JSON I imagine.

> [@ker](#):
>
> I don't think so, the logical format is great to process, and I'm not creating the tooltip, I'm utilizing an existing framework.

Seems fine. I figured that the more "inline" the presentation, the less useful rustc's output would be. I could imagine though that you might want to explain borrow check errors this way (for example) -- but maybe not. Maybe you can render it inline.

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [May 14, 2016, 1:38am UTC](https://internals.rust-lang.org/t/rustcs-json-output-format/3446/9 "2016-05-14T01:38:27Z")

</div>

> [@ker](#):
>
> It allowed me to create error messages of the following look:

By the way, is this some publicly available Atom plugin?

---

<div class="post-metadata">

**Author:** ![oli-obk](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/oli-obk/32/3168_2.png) [@oli-obk](https://internals.rust-lang.org/u/oli-obk)\
**Post date:** [May 14, 2016, 11:22am UTC](https://internals.rust-lang.org/t/rustcs-json-output-format/3446/10 "2016-05-14T11:22:21Z")

</div>

It hasn’t been merged yet, but to get the same behaviour, you can install the `build` package (version 0.63.0), install the `linter` package (search for `linter base`) and create an `.atom-build.js` in your project root with the following content:

```rust
module.exports = {
  cmd: "cargo",
  args: ["build"],
  env: {
    "RUSTFLAGS": "-Z unstable-options --error-format=json"
  },
  functionMatch: function(output) {
    var array = [];
    function level2severity(level) {
      switch (level) {
        case 'warning': return 'warning';
        case 'error': return 'error';
        case 'note': return 'info';
        default: return 'error';
      }
    }
    output.split(/\n/).forEach(line => {
      if (line[0] != '{') {
          return;
      }
      const json = JSON.parse(line);
      var trace = [];
      json.children.forEach(child => {
        child.spans.forEach(span => {
          trace.push({
            message: child.message,
            file: span.file_name,
            line: span.line_start,
            line_end: span.line_end,
            col: span.column_start,
            col_end: span.column_end,
            type: 'Trace', // FIXME: change to `child.level` after https://github.com/steelbrain/linter/issues/1149 is fixed
            severity: level2severity(json.level),
          });
        });
      });
      if (json.code) {
        trace.push({
          message: json.code.explanation,
          type: "Explanation",
          severity: 'info',
        });
      }
      json.spans.forEach(span => {
        array.push({
          message: json.message,
          file: span.file_name,
          line: span.line_start,
          line_end: span.line_end,
          col: span.column_start,
          col_end: span.column_end,
          type: json.level, // FIXME: change to `json.code ? json.code : json.level` after https://github.com/steelbrain/linter/issues/1149 is fixed
          severity: level2severity(json.level),
          trace: trace,
        });
      });
    });
    return array;
  }
};

```

Adding the `.atom-build.js` file from within atom might require an atom restart (Ctrl + Alt + R). Then you should be able to press Ctrl + Alt + B to trigger a build. The exact keys may vary between operating systems (F6 seems to work, too).

---

<div class="post-metadata">

**Author:** ![oli-obk](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/oli-obk/32/3168_2.png) [@oli-obk](https://internals.rust-lang.org/u/oli-obk)\
**Post date:** [May 17, 2016, 4:29pm UTC](https://internals.rust-lang.org/t/rustcs-json-output-format/3446/11 "2016-05-17T16:29:22Z")

</div>

So, here's my current report on the usability of the json output:

# "expected X, got Y" errors

These are split into two `children` without spans. There's a few ways that they could be improved.

1. for types, the error could give the span of the reason for the `expected`. So if it's a function argument, give a span for that argument's declaration.
2. these are so common in rustc that there's [special code](https://github.com/rust-lang/rust/pull/19870/files) processing this kind of text into multiple lines

- json should profit from this, too, maybe an `expected` field?

1. these should not be split up, but I'm not sure how to do this better, other than 2.

 ![](https://us1.discourse-cdn.com/flex002/uploads/rustlang/original/2X/8/816396d0bdd8307bf271e67b534f8a948c2f31e6.png)

# multiple suggested imports

To automate future 1-click-solutions, instead of listing them in the current note manner, the `suggested_replacement` could be used to offer inserting a new line on the top of the file with `use xyz;`.

 ![](https://us1.discourse-cdn.com/flex002/uploads/rustlang/original/2X/6/69d7d31afbfb4325d8572eae574c8b30219ec14d.png)

# suggestions for suggestions

1. remove the `suggested_replacement` field, and instead add a new "error `level`".
2. generally use suggestions more often. E.g. in `unresolved name` errors ![](https://us1.discourse-cdn.com/flex002/uploads/rustlang/original/2X/7/7d75ce815fd318583b6b870b947d043f3f3b976c.png)

# the `label` field

I've so far ignored it. Many errors do not set it, and with those that do set it, I've found that I can't replace the main `message`, and that it's partially redundant with the `note`s. An example is a type-mismatch. `let _: () = 5;` gives `"type mismatch"` for the message, `expected type '()'` and `got type '_'` for the notes, and then `"expected (), found integral variable"` for the `label`. The label is nicer than the notes, but still needs the message.

I could simply show it when it's there, but I don't want to clutter the error popups with redundancy.

#Macro Expansion

I'm not sure how to improve on this yet. An alternative would be to repeat the error at every expansion location. Or just show something at the location of the expansion.

 ![](https://us1.discourse-cdn.com/flex002/uploads/rustlang/original/2X/f/f0dbfbc6c1fcfe7ccd5e3d99dd1c1fa1203e8207.png)

#WIP

Anyway, this is a work in progress. If anyone has ideas what to try out, I'll check how it works and post some screenshots.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:26am UTC](https://internals.rust-lang.org/t/rustcs-json-output-format/3446/12 "2019-03-25T08:26:09Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
