JSON 输出

本章介绍 rustc 发出的 JSON 结构。可以使用 --error-format=json 标志启用 JSON。可以使用 --json 标志指定其他选项,该选项可以更改生成的消息以及消息的格式。

JSON 消息每行一个地发送到 stderr。

如果使用 Rust 解析输出,则 cargo_metadata crate 提供了一些解析消息的支持。

每种类型的消息都有一个 $message_type 字段,可用于区分不同的格式。解析时,应注意与将来对格式的更改保持向前兼容。可选值可能为 null。可能会添加新字段。"level" 或 "suggestion_applicability" 等枚举字段可能会添加新值。

诊断信息

诊断消息提供编译期间生成的错误或可能的关注点。 rustc 提供有关诊断信息来源的详细信息,以及提示和建议。

诊断信息以父/子关系排列,其中父诊断值是诊断信息的核心,附加的子诊断信息提供额外的上下文、帮助和信息。

诊断信息具有以下格式

{
    /* Type of this message */
    "$message_type": "diagnostic",
    /* The primary message. */
    "message": "unused variable: `x`",
    /* The diagnostic code.
       Some messages may set this value to null.
    */
    "code": {
        /* A unique string identifying which diagnostic triggered. */
        "code": "unused_variables",
        /* An optional string explaining more detail about the diagnostic code. */
        "explanation": null
    },
    /* The severity of the diagnostic.
       Values may be:
       - "error": A fatal error that prevents compilation.
       - "warning": A possible error or concern.
       - "note": Additional information or context about the diagnostic.
       - "help": A suggestion on how to resolve the diagnostic.
       - "failure-note": A note attached to the message for further information.
       - "error: internal compiler error": Indicates a bug within the compiler.
    */
    "level": "warning",
    /* An array of source code locations to point out specific details about
       where the diagnostic originates from. This may be empty, for example
       for some global messages, or child messages attached to a parent.

       Character offsets are offsets of Unicode Scalar Values.
    */
    "spans": [
        {
            /* The file where the span is located.
               Note that this path may not exist. For example, if the path
               points to the standard library, and the rust src is not
               available in the sysroot, then it may point to a nonexistent
               file. Beware that this may also point to the source of an
               external crate.
            */
            "file_name": "lib.rs",
            /* The byte offset where the span starts (0-based, inclusive). */
            "byte_start": 21,
            /* The byte offset where the span ends (0-based, exclusive). */
            "byte_end": 22,
            /* The first line number of the span (1-based, inclusive). */
            "line_start": 2,
            /* The last line number of the span (1-based, inclusive). */
            "line_end": 2,
            /* The first character offset of the line_start (1-based, inclusive). */
            "column_start": 9,
            /* The last character offset of the line_end (1-based, exclusive). */
            "column_end": 10,
            /* Whether or not this is the "primary" span.

               This indicates that this span is the focal point of the
               diagnostic.

               There are rare cases where multiple spans may be marked as
               primary. For example, "immutable borrow occurs here" and
               "mutable borrow ends here" can be two separate primary spans.

               The top (parent) message should always have at least one
               primary span, unless it has zero spans. Child messages may have
               zero or more primary spans.
            */
            "is_primary": true,
            /* An array of objects showing the original source code for this
               span. This shows the entire lines of text where the span is
               located. A span across multiple lines will have a separate
               value for each line.
            */
            "text": [
                {
                    /* The entire line of the original source code. */
                    "text": "    let x = 123;",
                    /* The first character offset of the line of
                       where the span covers this line (1-based, inclusive). */
                    "highlight_start": 9,
                    /* The last character offset of the line of
                       where the span covers this line (1-based, exclusive). */
                    "highlight_end": 10
                }
            ],
            /* An optional message to display at this span location.
               This is typically null for primary spans.
            */
            "label": null,
            /* An optional string of a suggested replacement for this span to
               solve the issue. Tools may try to replace the contents of the
               span with this text.
            */
            "suggested_replacement": null,
            /* An optional string that indicates the confidence of the
               "suggested_replacement". Tools may use this value to determine
               whether or not suggestions should be automatically applied.

               Possible values may be:
               - "MachineApplicable": The suggestion is definitely what the
                 user intended. This suggestion should be automatically
                 applied.
               - "MaybeIncorrect": The suggestion may be what the user
                 intended, but it is uncertain. The suggestion should result
                 in valid Rust code if it is applied.
               - "HasPlaceholders": The suggestion contains placeholders like
                 `(...)`. The suggestion cannot be applied automatically
                 because it will not result in valid Rust code. The user will
                 need to fill in the placeholders.
               - "Unspecified": The applicability of the suggestion is unknown.
            */
            "suggestion_applicability": null,
            /* An optional object indicating the expansion of a macro within
               this span.

               If a message occurs within a macro invocation, this object will
               provide details of where within the macro expansion the message
               is located.
            */
            "expansion": {
                /* The span of the macro invocation.
                   Uses the same span definition as the "spans" array.
                */
                "span": {/*...*/}
                /* Name of the macro, such as "foo!" or "#[derive(Eq)]". */
                "macro_decl_name": "some_macro!",
                /* Optional span where the relevant part of the macro is
                  defined. */
                "def_site_span": {/*...*/},
            }
        }
    ],
    /* Array of attached diagnostic messages.
       This is an array of objects using the same format as the parent
       message. Children are not nested (children do not themselves
       contain "children" definitions).
    */
    "children": [
        {
            "message": "`#[warn(unused_variables)]` on by default",
            "code": null,
            "level": "note",
            "spans": [],
            "children": [],
            "rendered": null
        },
        {
            "message": "if this is intentional, prefix it with an underscore",
            "code": null,
            "level": "help",
            "spans": [
                {
                    "file_name": "lib.rs",
                    "byte_start": 21,
                    "byte_end": 22,
                    "line_start": 2,
                    "line_end": 2,
                    "column_start": 9,
                    "column_end": 10,
                    "is_primary": true,
                    "text": [
                        {
                            "text": "    let x = 123;",
                            "highlight_start": 9,
                            "highlight_end": 10
                        }
                    ],
                    "label": null,
                    "suggested_replacement": "_x",
                    "suggestion_applicability": "MachineApplicable",
                    "expansion": null
                }
            ],
            "children": [],
            "rendered": null
        }
    ],
    /* Optional string of the rendered version of the diagnostic as displayed
       by rustc. Note that this may be influenced by the `--json` flag.
    */
    "rendered": "warning: unused variable: `x`\n --> lib.rs:2:9\n  |\n2 |     let x = 123;\n  |         ^ help: if this is intentional, prefix it with an underscore: `_x`\n  |\n  = note: `#[warn(unused_variables)]` on by default\n\n"
}

工件通知

当使用 --json=artifacts 标志时,会发出工件通知。它们指示文件工件已保存到磁盘。有关发出类型的更多信息,请参见 --emit 标志文档。每个类型可以包含多个文件,例如当使用多个代码生成单元时。

{
    /* Type of this message */
    "$message_type": "artifact",
    /* The filename that was generated. */
    "artifact": "libfoo.rlib",
    /* The kind of artifact that was generated. Possible values:
       - "link": The generated crate as specified by the crate-type.
       - "dep-info": The `.d` file with dependency information in a Makefile-like syntax.
       - "metadata": The Rust `.rmeta` file containing metadata about the crate.
       - "asm": The `.s` file with generated assembly
       - "llvm-ir": The `.ll` file with generated textual LLVM IR
       - "llvm-bc": The `.bc` file with generated LLVM bitcode
       - "mir": The `.mir` file with rustc's mid-level intermediate representation.
       - "obj": The `.o` file with generated native object code
    */
    "emit": "link"
}

未来不兼容的报告

如果使用 --json=future-incompat 标志,则如果 crate 将来可能停止编译,则会发出一个单独的 JSON 结构。其中包含有关将来可能转变为硬错误的特定警告的诊断信息。这将包括诊断信息,即使诊断信息已被抑制(例如使用 #[allow] 属性或 --cap-lints 选项)。

{
    /* Type of this message */
    "$message_type": "future_incompat",
    /* An array of objects describing a warning that will become a hard error
       in the future.
    */
    "future_incompat_report":
    [
        {
            /* A diagnostic structure as defined in
               https://doc.rust-lang.net.cn/rustc/json.html#diagnostics
            */
            "diagnostic": {...},
        }
    ]
}

未使用依赖项通知

选项 --json=unused-externs--json=unused-externs-silentunused-crate-dependencies lint 结合使用时,将发出 JSON 结构,报告任何未引用任何符号的 crate 依赖项(使用 --extern 指定)。 这些旨在由构建系统使用,然后构建系统可以发出诊断信息,告诉用户从 Cargo.toml (或任何定义依赖项的构建系统文件)中删除未使用的依赖项。

JSON 结构是

{
    "lint_level": "deny", /* Level of the warning */
    "unused_names": [
        "foo"  /* Names of unused crates, as specified with --extern foo=libfoo.rlib */
    ],
}

在 JSON 中,警告/拒绝/禁止 lint 级别(如在命令行或源代码中定义的)决定 lint_level。使用 unused-externs 时,denyforbid 级别诊断还会导致 rustc 以失败退出代码退出。

unused-externs-silent 将以相同的方式报告诊断信息,但不会导致 rustc 以失败退出 - 由使用者适当地标记失败。(Cargo 需要此功能,因为它在多个构建目标之间共享相同的依赖项,因此只有在任何目标都没有使用某个依赖项时,才应报告该依赖项未使用。)