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

Invalid syntax and crash on unit struct with where-clause #3194

Closed
dtolnay opened this issue Nov 11, 2018 · 4 comments · Fixed by #3200
Closed

Invalid syntax and crash on unit struct with where-clause #3194

dtolnay opened this issue Nov 11, 2018 · 4 comments · Fixed by #3200
Labels
bug Panic, non-idempotency, invalid code, etc.

Comments

@dtolnay
Copy link
Member

dtolnay commented Nov 11, 2018

Against the current master branch, 4e2f741:

$ echo "mod m { struct S where A: B; }" | cargo run --bin rustfmt

mod m {
    struct S
    mod m { struct S
    where
        A: B;
}

The output is not valid Rust syntax.

If the input is in two files, rustfmt crashes. I am hitting this in dtolnay/syn#536.

src/lib.rs

mod m;

src/m.rs

struct A where B: C;
$ RUST_BACKTRACE=1 cargo run --bin rustfmt -- ../path/to/src/lib.rs 

thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', libcore/option.rs:355:21
stack backtrace:
   9: <core::option::Option<T>>::unwrap
  10: rustfmt_nightly::rewrite::RewriteContext::snippet
             at src/rewrite.rs:56
  11: rustfmt_nightly::comment::rewrite_missing_comment
             at src/comment.rs:823
  12: rustfmt_nightly::items::rewrite_comments_before_after_where
             at src/items.rs:2731
  13: rustfmt_nightly::items::rewrite_where_clause_rfc_style
             at src/items.rs:2528
  14: rustfmt_nightly::items::rewrite_where_clause
             at src/items.rs:2630
  15: rustfmt_nightly::items::format_generics
             at src/items.rs:2786
  16: rustfmt_nightly::items::format_unit_struct
             at src/items.rs:1183
  17: rustfmt_nightly::items::format_struct
             at src/items.rs:991
  18: rustfmt_nightly::items::<impl rustfmt_nightly::visitor::FmtVisitor<'a>>::visit_struct
             at src/items.rs:438
  19: rustfmt_nightly::visitor::FmtVisitor::visit_item
             at src/visitor.rs:399
  20: rustfmt_nightly::reorder::<impl rustfmt_nightly::visitor::FmtVisitor<'a>>::visit_items_with_reordering
             at src/reorder.rs:281
  21: rustfmt_nightly::visitor::FmtVisitor::walk_mod_items
             at src/visitor.rs:697
  22: rustfmt_nightly::visitor::FmtVisitor::format_separate_mod
             at src/visitor.rs:781
  23: <rustfmt_nightly::formatting::FormatContext<'a, T>>::format_file
             at ./src/formatting.rs:150
  24: rustfmt_nightly::formatting::format_project
             at ./src/formatting.rs:92
  25: rustfmt_nightly::formatting::<impl rustfmt_nightly::Session<'b, T>>::format_input_inner::{{closure}}
             at ./src/formatting.rs:47
  26: <scoped_tls::ScopedKey<T>>::set
             at scoped-tls-0.1.2/src/lib.rs:155
  27: syntax::with_globals::{{closure}}
             at rustc-ap-syntax-290.0.0/lib.rs:123
  28: <scoped_tls::ScopedKey<T>>::set
             at scoped-tls-0.1.2/src/lib.rs:155
  29: syntax::with_globals
             at rustc-ap-syntax-290.0.0/lib.rs:122
  30: rustfmt_nightly::formatting::<impl rustfmt_nightly::Session<'b, T>>::format_input_inner
             at ./src/formatting.rs:31
  31: <rustfmt_nightly::Session<'b, T>>::format
             at ./src/lib.rs:531
  32: rustfmt::format_and_emit_report
             at src/bin/main.rs:300
  33: rustfmt::format::{{closure}}
             at src/bin/main.rs:272
  34: <rustfmt_nightly::Session<'b, T>>::override_config
             at ./src/lib.rs:539
  35: rustfmt::format
             at src/bin/main.rs:271
  36: rustfmt::execute
             at src/bin/main.rs:199
  37: rustfmt::main
             at src/bin/main.rs:36
@nrc nrc added the bug Panic, non-idempotency, invalid code, etc. label Nov 11, 2018
@scampi
Copy link
Contributor

scampi commented Nov 13, 2018

With regards to the bad output, here's what I gathered.

Because there is no parameter, the span before the where clause is defined with the logic below, where span.lo() == BytePos (0). This is the start of the file I think, although from the comment (also below) it should just after struct S.

https://github.com/rust-lang-nursery/rustfmt/blob/34333bad20c89e9f6f96c5428924cd4c2f9c1315/src/items.rs#L2779-L2785

Then, comments before the where clause are extracted as follows; however, because of the wrong span earlier, the code mod m { struct S is considered to be a comment.

https://github.com/rust-lang-nursery/rustfmt/blob/34333bad20c89e9f6f96c5428924cd4c2f9c1315/src/items.rs#L2525-L2528

@dtolnay just to better understand your example, I was wondering if it is normal that the struct S is not parameterised with A, i.e., struct S<A> where A: B;. If I add it, then there is no issue. Is it intentional ?
If it is, then it seems there is something wrong with the span value of generics, isn't it ?

@dtolnay
Copy link
Member Author

dtolnay commented Nov 13, 2018

It is intentional that there is no generic parameter. This is legal and useful Rust syntax.

@scampi
Copy link
Contributor

scampi commented Nov 13, 2018

I was not aware! What is the use ? I'd appreciate any pointers ;o)
I tried this in the playground but it fails with error[E0412]: cannot find type B in this scope
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=fa1205ba785feec0af7f6d8828b2895b

@dtolnay
Copy link
Member Author

dtolnay commented Nov 13, 2018

For example:

pub struct Error {
    /* ... */
}

#[cfg(test)]
struct _Test where Error: Send + Sync;

This is a test that proves the Error type is Send and Sync. If you put a std::rc::Rc<()> inside the error, the test will catch that it is no longer Send and Sync.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Panic, non-idempotency, invalid code, etc.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants