rust-lang / rust-lang/rustfmt

Formatting causes syntax error when indexing into return value of long unsafe block within a closure

Open
#4,965 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-closures C-bug
Dominant language
Rust
Stars
7k
Forks
1.1k
Avg merge
2d 13h
Merged PRs (30d)
24

Description

In rare cases, inserting braces around the body of a closure containing an unsafe block followed by indexing seems to cause a syntax error.
Here is a minimal example for reproducing this behavior:

unsafe fn very_long_unsafe_function(vec: &Vec<usize>) -> &Vec<usize> {
    vec
}

fn long_outer_function<'a, F>(index: usize, function: F) -> &'a usize
where
    F: Fn(usize) -> &'a usize,
{
    function(index)
}

fn main() {
    let vec = vec![1, 2, 3, 4];
    // Line which will be split up and reformatted by rust-fmt - compiles and runs without issues
    let output: Vec<_> = vec![0, 0, 1, 1, 2, 2].iter().map(|&index| long_outer_function(index, |index| &unsafe { very_long_unsafe_function(&vec) }[index])).collect();
    println!("{:?}", output);
}

Here is the formatted output using version 1.4.37-nightly (2021-08-25 0afc208)

unsafe fn very_long_unsafe_function(vec: &Vec<usize>) -> &Vec<usize> {
    vec
}

fn long_outer_function<'a, F>(index: usize, function: F) -> &'a usize
where
    F: Fn(usize) -> &'a usize,
{
    function(index)
}

fn main() {
    let vec = vec![1, 2, 3, 4];
    let output: Vec<_> = vec![0, 0, 1, 1, 2, 2]
        .iter()
        // Rust format inserts braces around the bodies of both closures, breaking the inner closure
        .map(|&index| {
            long_outer_function(index, |index| {
                &unsafe { very_long_unsafe_function(&vec) }[index]
            })
        })
        .collect();
    println!("{:?}", output);
}

This results in the following syntax error:

error: expected one of `.`, `;`, `?`, `}`, or an operator, found `[`
  --> src/main.rs:18:60
   |
18 |                 &unsafe { very_long_unsafe_function(&vec) }[index]
   |                                                            ^ expected one of `.`, `;`, `?`, `}`, or an operator

Example code on the playground for reference: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=46a316d108e9686e425ee72b8bb4957e

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

Start by running the minimal Rust example from the issue through rustfmt and compiling the formatted output to reproduce the syntax error. Trace the formatter's handling of closures containing unsafe blocks followed by indexing, then add a regression test showing that the formatted example still compiles and runs without the syntax error.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
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.