rust-lang / rust-lang/rust

Bad parse error on token sequences `safe unsafe` and `unsafe safe`

Open
#134,580 18 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-diagnostics A-parser D-confusing D-incorrect D-invalid-suggestion D-terse T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Code
// #1
unsafe extern {
    safe unsafe fn foo();
    unsafe safe fn bar();
}
// #2
unsafe safe fn baz() {}
safe unsafe fn qux() {}
// #3
unsafe safe extern "C" fn ham() {}
safe unsafe extern "C" fn egg() {}
Current output
# example #1:
`safe` must come before `unsafe`: `safe unsafe`
`unsafe` must come before `safe`: `unsafe safe`
# Example #2
items outside an `unsafe extern {...} block may not be annotated with `safe``
`safe` must come before `unsafe`: `safe unsafe`
`unsafe` must come before `safe`: `unsafe safe`
# example #3 is the same as #2
Desired output
# Example #1
error: `safe` and `unsafe` are incompatible
note: extern functions are unsafe by default
help: if you want to make this function safe, remove `unsafe`
# Example #2
error: items outside an `unsafe extern {...}` block may not be annotated with `safe`
help: remove `safe`
# example #3
error: items outside an `unsafe extern {...}` block may not be annotated with `safe`
note: extern functions are safe by default
help: remove `safe`
Rationale and extra context

look at the errors for #2 and #3:

`safe` must come before `unsafe`: `safe unsafe`
`unsafe` must come before `safe`: `unsafe safe`

this means that it thinks that the order is incorrect

which is likely because they are both included in the check for order

Other cases
// #1
unsafe safe static FOO: i32 = 42;
unsafe safe const BAR: i32 = 42;
unsafe safe trait Baz {}
unsafe trait _X {}
unsafe safe impl _X for i32 {}
// #2 
unsafe extern {
    unsafe safe static QUX: usize = 42;
    // the rest of the examples just copy pasted
}

Output:

# #1 
items outside an `unsafe extern` blocks cannot be `safe`
# shuffle safe and unsafe like usual
# #2 
# same as 1 but without the 'items outside `unsafe extern` ...'
Rust Version
$ rustc --version --verbose
rustc 1.83.0 (90b35a623 2024-11-26)
binary: rustc
commit-hash: 90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf
commit-date: 2024-11-26
host: x86_64-unknown-linux-gnu
release: 1.83.0
LLVM version: 19.1.1
Anything else?

This is a follow up to #133586 and #133631

#133586 has the PR #133618
(all of the above are closed)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the Rust code examples with rustc 1.83.0 and compare the current diagnostics with the desired output. No source file or test is named; trace the compiler diagnostics for safe/unsafe ordering and add coverage for the extern-block and standalone-item cases, with completion defined by matching the requested errors, notes, and help messages.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.