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

Add suggestions for unsafe impl error codes #103283

Merged
merged 1 commit into from
Oct 28, 2022

Conversation

nbarrios1337
Copy link
Contributor

@nbarrios1337 nbarrios1337 commented Oct 20, 2022

Adds suggestions for users to add unsafe to trait impls that should be unsafe, and remove unsafe from trait impls that do not require unsafe

With the folllowing code:

struct Foo {}

struct Bar {}

trait Safe {}

unsafe trait Unsafe {}

impl Safe for Foo {} // ok

impl Unsafe for Foo {} // E0200

unsafe impl Safe for Bar {} // E0199

unsafe impl Unsafe for Bar {} // ok

// omitted empty main fn

The current rustc output is:

error[E0199]: implementing the trait `Safe` is not unsafe
  --> e0200.rs:13:1
   |
13 | unsafe impl Safe for Bar {} // E0199
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0200]: the trait `Unsafe` requires an `unsafe impl` declaration
  --> e0200.rs:11:1
   |
11 | impl Unsafe for Foo {} // E0200
   | ^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0199, E0200.
For more information about an error, try `rustc --explain E0199`.

With this PR, the future rustc output would be:

error[E0199]: implementing the trait `Safe` is not unsafe
  --> ../../temp/e0200.rs:13:1
   |
13 | unsafe impl Safe for Bar {} // E0199
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
help: remove `unsafe` from this trait implementation
   |
13 - unsafe impl Safe for Bar {} // E0199
13 + impl Safe for Bar {} // E0199
   |

error[E0200]: the trait `Unsafe` requires an `unsafe impl` declaration
  --> ../../temp/e0200.rs:11:1
   |
11 | impl Unsafe for Foo {} // E0200
   | ^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: the trait `Unsafe` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
   |
11 | unsafe impl Unsafe for Foo {} // E0200
   | ++++++

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0199, E0200.
For more information about an error, try `rustc --explain E0199`.

@rustbot label +T-compiler +A-diagnostics +A-suggestion-diagnostics

@rustbot rustbot added A-testsuite Area: The testsuite used to check the correctness of rustc T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 20, 2022
@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @cjgillot (or someone else) soon.

Please see the contribution instructions for more information.

@rustbot rustbot added A-diagnostics Area: Messages for errors, warnings, and lints A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` labels Oct 20, 2022
@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Oct 20, 2022
@inquisitivecrystal
Copy link
Contributor

inquisitivecrystal commented Oct 20, 2022

Telling people to remove unnecessary unsafe is probably fine. For telling them to add it, should we add a note to tell them to make sure they're fulfilling the safety invariants of the trait? When rustc gives me a suggestion, I sometimes follow it without too much thought, but unsafe traits document invariants that the compiler can't check, so we shouldn't be telling them to implement one if they're not sure they're fulfilled those invariants.

It might even be worth writing it out explicitly, as in "note: this trait has safety invariants that the compiler can't check, so check the documentation to make sure you're fulfilling them". (I wouldn't suggest going with that exact phrasing: I'm exhausted and not thinking or writing very clearly at the moment.)

@compiler-errors
Copy link
Member

compiler-errors commented Oct 20, 2022

I was about to comment approximately the same feedback as @inquisitivecrystal -- these should probably be a bit more careful around adding unsafe, maybe they shouldn't be MachineApplicable and/or maybe they should have some more descriptive wording about the implication of adding unsafe.

Removing unsafe seems fine, though.

@nbarrios1337
Copy link
Contributor Author

This is what I was worried about (in a good way!); I had focused a bit more on the implementation and less on the implications.

How about: "the trait {} has some invariant that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the unsafe keyword" as the warning?

I'll replace the Applicability with MaybeIncorrect or Unspecified.

@compiler-errors
Copy link
Member

maybe a bit stronger wording: "the trait {} enforces some invariant", but otherwise sounds good.

@nbarrios1337 nbarrios1337 force-pushed the unsafe-impl-suggestions branch 2 times, most recently from 594b700 to b1a6131 Compare October 20, 2022 19:52
Copy link
Contributor

@inquisitivecrystal inquisitivecrystal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty good!

I left some minor suggestions that might help the sentences flow a bit better. You could also go the other direction and make everything plural (change to enforces invariants and then leave those invariants in place). Not sure whether that's better.

@nbarrios1337
Copy link
Contributor Author

I think it best if it is pluralized; To my knowledge, there's no restriction against an unsafe trait having more than one manually-checked invariant

@nbarrios1337 nbarrios1337 force-pushed the unsafe-impl-suggestions branch 2 times, most recently from 93338d2 to 4d5aff2 Compare October 20, 2022 23:28
@cjgillot
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Oct 27, 2022

📌 Commit 770538e has been approved by cjgillot

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 27, 2022
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Oct 28, 2022
…ns, r=cjgillot

Add suggestions for unsafe impl error codes

Adds suggestions for users to add `unsafe` to trait impls that should be `unsafe`, and remove `unsafe` from trait impls that do not require `unsafe`

With the folllowing code:

```rust
struct Foo {}

struct Bar {}

trait Safe {}

unsafe trait Unsafe {}

impl Safe for Foo {} // ok

impl Unsafe for Foo {} // E0200

unsafe impl Safe for Bar {} // E0199

unsafe impl Unsafe for Bar {} // ok

// omitted empty main fn
```

The current rustc output is:
```
error[E0199]: implementing the trait `Safe` is not unsafe
  --> e0200.rs:13:1
   |
13 | unsafe impl Safe for Bar {} // E0199
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0200]: the trait `Unsafe` requires an `unsafe impl` declaration
  --> e0200.rs:11:1
   |
11 | impl Unsafe for Foo {} // E0200
   | ^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0199, E0200.
For more information about an error, try `rustc --explain E0199`.
```

With this PR, the future rustc output would be:
```
error[E0199]: implementing the trait `Safe` is not unsafe
  --> ../../temp/e0200.rs:13:1
   |
13 | unsafe impl Safe for Bar {} // E0199
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
help: remove `unsafe` from this trait implementation
   |
13 - unsafe impl Safe for Bar {} // E0199
13 + impl Safe for Bar {} // E0199
   |

error[E0200]: the trait `Unsafe` requires an `unsafe impl` declaration
  --> ../../temp/e0200.rs:11:1
   |
11 | impl Unsafe for Foo {} // E0200
   | ^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: the trait `Unsafe` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
   |
11 | unsafe impl Unsafe for Foo {} // E0200
   | ++++++

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0199, E0200.
For more information about an error, try `rustc --explain E0199`.
```

`@rustbot` label +T-compiler +A-diagnostics +A-suggestion-diagnostics
bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 28, 2022
…iaskrgr

Rollup of 5 pull requests

Successful merges:

 - rust-lang#102642 (Add tests for static async functions in traits)
 - rust-lang#103283 (Add suggestions for unsafe impl error codes)
 - rust-lang#103523 (Fix unwanted merge of inline doc comments for impl blocks)
 - rust-lang#103550 (diagnostics: do not suggest static candidates as traits to import)
 - rust-lang#103641 (Don't carry MIR location in `ConstraintCategory::CallArgument`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 270e0c5 into rust-lang:master Oct 28, 2022
@rustbot rustbot added this to the 1.66.0 milestone Oct 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` A-testsuite Area: The testsuite used to check the correctness of rustc S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants