Skip to content

rustc_on_unimplemented is not std-agnostic #112923

@WaffleLapkin

Description

@WaffleLapkin

If rustc_on_unimplemented contains a path mentioning std::, it won't work in #![no_std] crates, even if the type exists in the core. Similarly if you use core:: path instead, the diagnostic will only work in #![no_std] crates.

As an example take this annotation for ? desugaring:

on(
all(
from_desugaring = "QuestionMark",
_Self = "std::option::Option<T>",
R = "std::result::Result<T, E>",
),
message = "the `?` operator can only be used on `Option`s, not `Result`s, \
in {ItemContext} that returns `Option`",
label = "use `.ok()?` if you want to discard the `{R}` error information",
parent_label = "this function returns an `Option`"
),

It should (and does) trigger for the following code:

fn f() -> Option<()> {
    Err::<(), _>(())?;
    None
}
error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
 --> src/lib.rs:2:21
  |
1 | fn f() -> Option<()> {
  | -------------------- this function returns an `Option`
2 |     Err::<(), _>(())?;
  |                     ^ use `.ok()?` if you want to discard the `Result<Infallible, ()>` error information
  |
  = help: the trait `FromResidual<Result<Infallible, ()>>` is not implemented for `Option<()>`
  = help: the following other types implement trait `FromResidual<R>`:
            <Option<T> as FromResidual<Yeet<()>>>
            <Option<T> as FromResidual>

(play;note the use .ok()? label)

However, if you add #![no_std] the label disappears:

#![no_std]

fn f() -> Option<()> {
    Err::<(), _>(())?;
    None
}
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
 --> src/lib.rs:4:21
  |
3 | fn f() -> Option<()> {
  | -------------------- this function should return `Result` or `Option` to accept `?`
4 |     Err::<(), _>(())?;
  |                     ^ cannot use the `?` operator in a function that returns `Option<()>`
  |
  = help: the trait `FromResidual<Result<Infallible, ()>>` is not implemented for `Option<()>`
  = help: the following other types implement trait `FromResidual<R>`:
            <Option<T> as FromResidual<Yeet<()>>>
            <Option<T> as FromResidual>

(play; the error message is also misleading, the function does return option)


rustc in general is not great at being std-agnostic in diagnostics, and this is just another annoying example of that.

Meta

rustc --version --verbose:

rustc 1.70.0 (90c541806 2023-05-31)
binary: rustc
commit-hash: 90c541806f23a127002de5b4038be731ba1458ca
commit-date: 2023-05-31
host: aarch64-unknown-linux-gnu
release: 1.70.0
LLVM version: 16.0.2

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsC-bugCategory: This is a bug.D-confusingDiagnostics: Confusing error or lint that should be reworked.D-diagnostic-infraDiagnostics: Issues that affect all diagnostics, or relate to the diagnostic machinery itself.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions