Skip to content

rustc_on_unimplemented is not std-agnostic #112923

Open
@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

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions