Skip to content

Compiler hang with incomplete struct literal at end of file #103451

Description

@jruderman

This malformed code (playground) hangs the compiler:

struct R { }

struct S {
    x: [u8; R

Found by fuzzing with a modified fuzz-rustc.

The bug's edges

  • R must be defined as a named-field struct (not a tuple struct or unit struct), although it can have 0 fields.
  • R must be the last token to produce the hang:
    • No opening brace (note that braces are required for literals of named-field structs)
    • No closing delimiters
    • Not even a comment

Where it hangs

If I understand mj.sample.txt correctly, the hang occurs in LateResolutionVisitor, with try_lookup_name_relaxed never finishing (while calling various functions such as smart_resolve_context_dependent_help and span_to_snippet)

Additional example

This also hangs. I'm guessing it's the same bug.

struct R { }

fn f() {
    R

Version

rustc --version --verbose:

rustc 1.66.0-nightly (6e95b6da8 2022-10-22)
binary: rustc
commit-hash: 6e95b6da885f42a4e1314595089fa4295e329d11
commit-date: 2022-10-22
host: x86_64-apple-darwin
release: 1.66.0-nightly
LLVM version: 15.0.2

Regression

Bisected with:

cargo-bisect-rustc --start=2022-10-03 --end=nightly-2022-10-23 --preserve --script=./timeout.sh
timeout.sh

#!/bin/bash

# This script is wrong in several ways:
# - It will try to kill processes that might no longer exist
# - It may leave an orphan rustc process after the bisect (because it only kills the shell, not rustc)
# But it seems to be good enough for bisection to work

killall rustc
outershell=$$
(sleep 5; kill $outershell) &
rustc src/main.rs
true

@rustbot label +regression-from-stable-to-nightly +I-hang

Activity

  1. added
    I-hangIssue: The compiler never terminates, due to infinite loops, deadlock, livelock, etc.
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Oct 23, 2022
  2. chenyukang commented on Oct 24, 2022

    @chenyukang
    Member

    @rustbot claim

  3. chenyukang commented on Oct 24, 2022

    @chenyukang
    Member

    I can not reproduce it with latest code, did I missed anything?

    cat@LAPTOP-V6U0QKD4:~/code/rust$ cat hang.rs
    struct R { }
    
    struct S {
        x: [u8; R
    cat@LAPTOP-V6U0QKD4:~/code/rust$ rustc -vV
    rustc 1.66.0-nightly (7fcf850d7 2022-10-23)
    binary: rustc
    commit-hash: 7fcf850d7942804990a1d2e3fe036622a0fe4c74
    commit-date: 2022-10-23
    host: x86_64-unknown-linux-gnu
    release: 1.66.0-nightly
    LLVM version: 15.0.2
    cat@LAPTOP-V6U0QKD4:~/code/rust$ rustc hang.rs
    error: this file contains an unclosed delimiter
     --> hang.rs:4:15
      |
    3 | struct S {
      |          - unclosed delimiter
    4 |     x: [u8; R
      |        -      ^
      |        |
      |        unclosed delimiter
    
    error[E0423]: expected value, found struct `R`
     --> hang.rs:4:13
      |
    1 | struct R { }
      | ------------ `R` defined here
    ...
    4 |     x: [u8; R
      |             ^ help: use struct literal syntax instead: `R {}`
    
    error: aborting due to 2 previous errors
    
    For more information about this error, try `rustc --explain E0423`.
  4. chenyukang commented on Oct 24, 2022

    @chenyukang
    Member

    Great cactch @jruderman

    Confirmed the error is only triggered by commit: 6e95b6da885f42a4e1314595089fa4295e329d11

    The root cause is I changed the edge corner case in find_width_of_character_at_span:

            // Ensure indexes are also not malformed.
            if start_index > end_index || end_index > source_len - 1 {
                debug!("find_width_of_character_at_span: source indexes are malformed");
                return 0;  // Previous version is  `return 1`
            }

    We think next_point won't return a span which outside of source file, so 0 is a valid one, then next_point will always return a valid span, and we get Ok("") from sm.span_to_snippet when reaching the end of source.

    So, there is a loop in previous followed_by_brace, which will run infinitely loop:

    sp = sm.next_point(sp);

    Lucky, my another PR #101908 merged at last day, this PR refactored this function:
    518d5eb#diff-2c81e6d8048a31a3ce43f30181aaa037e0ad0076e7aee67792ca993f28c75ac3L1108

  5. jruderman commented on Oct 24, 2022

    @jruderman
    ContributorAuthor

    Verif, I no longer get a hang after rollup 9be2f35

    Do you want to add one or two of these as tests?

  6. chenyukang commented on Oct 24, 2022

    @chenyukang
    Member

    Yes, we'd better add a testcase for it.

    I'm thinking whether we sould return 1 in find_width_of_character_at_span when reaching to the end of source, so that sm.span_to_snippet may get an error.

  7. chenyukang commented on Oct 24, 2022

    @chenyukang
    Member

    This testcase seems not easy to be added:

    struct R { }
    
    struct S {
        x: [u8; R //~ ERROR this file contains an unclosed delimiter
        //~| ERROR expected value

    If so, the trigger point will do not exist, 😂

  8. jruderman commented on Oct 24, 2022

    @jruderman
    ContributorAuthor

    @rustbot label -I-prioritize

  9. removed
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Oct 24, 2022
  10. estebank commented on Oct 24, 2022

    @estebank
    Contributor

    If so, the trigger point will do not exist

    There's an alternative kind of annotation for patterns that should work for this case: // error-pattern:this file contains an unclosed delimiter

  11. added 5 commits that reference this issue on Nov 7, 2022
    976973f
    948e7e7
    b782619
    f058639
    2541408
  12. added 4 commits that reference this issue on Nov 8, 2022
    71b8f42
    e0f5315
    3779222
    75c2394
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.I-hangIssue: The compiler never terminates, due to infinite loops, deadlock, livelock, etc.regression-from-stable-to-nightlyPerformance or correctness regression from stable to nightly.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions