2

Is it possible to take any Rust code and make it work in only one line (without any line breaks)? In particular, it should work exactly like the "normal" multi line code:

  • if it's an executable, the runtime behavior should be the same.
  • if it's a library, the documentation and .rlib file should be the same.

This is a purely theoretical question and I don't plan on actually writing my Rust code like this :P

I know that most typical Rust code can be written in one line. Hello world is easy-peasy:

fn main() { println!("Hello, world"); }

Are there any Rust constructs that can't be written in one line? I thought of a few candidates already:

  • Doc comments. I usually see them written as /// or //! and they include everything until the end of the line.
  • Macros, especially procedural ones, can do some strange unexpected things. Maybe it is possible to construct macros that only work on multiple lines?
  • String literals can be written over multiple lines in which case they will include the linebreaks. I know that those line breaks can also be written as \n, but maybe there is something about multi-line strings that does not work in a single line? Maybe something something about raw string literals?
  • Maybe some planned future extensions of Rust?
  • Probably many other things I didn't think of...
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Lukas Kalbertodt
  • 79,749
  • 26
  • 255
  • 305
  • 3
    doc-comments can [be an attribute](https://stackoverflow.com/q/33999341/155423). – Shepmaster Nov 19 '19 at 19:05
  • Doc comments can also use `/*! */` or `/** */` – mcarton Nov 19 '19 at 20:42
  • Doc comments are Markdown, which does require line breaks for some features (eg. paragraphs(!)), even with the `/*! */` or `/** */` or attribute syntax. Other than that, I believe everything could be written in one line. – Jmb Nov 20 '19 at 07:56
  • @Shepmaster but attributes are applied to next item(?), `#[attrib] item;` is perfectly valid syntax, for example `fn main(){#[cfg(debug_assertions)] println!("dbg");}` –  Nov 21 '19 at 14:19
  • 1
    @Sahsahae yes, that’s my point. Because doc comments can be attributes, they don’t require multiple lines. It’s a refutal of that bullet point. – Shepmaster Nov 21 '19 at 14:24
  • 2
    @Jmb if you write it as an attribute, can’t you use `\n` in the string literal? – Shepmaster Nov 21 '19 at 14:25
  • @Shepmaster good point, it should work with attributes – Jmb Nov 25 '19 at 08:09
  • 1
    Another thing I just thought of: in proc macros you can (on nightly) get the line number of a specific span. With that, you can artificially enforce a syntax that requires multiple lines. That's a unusual exception tho. I guess now someone just has to summarize it all and write an answer? ^_^ – Lukas Kalbertodt Nov 25 '19 at 08:19
  • @LukasKalbertodt not really. The question is a ["prove a negative"](https://en.wikipedia.org/wiki/Burden_of_proof_(philosophy)#Proving_a_negative) which means it's hard to answer authoritatively. – Shepmaster Nov 25 '19 at 14:43

1 Answers1

1

Out of curiosity, I did a quick read through of Rust's Lexer Code and there is only one case (that I noticed) which requires a newline and can not be rewritten any other way. As people have pointed out, there are directly equivalent ways to write doc comments, string literals, and macros which can be done on a single line.

That being said, this is technically not considered Rust syntax. However, it has been part of rustc since the creation of rustc_lexer (4 years ago) and likely long before that so I'm going to count it. Plus if we squint really hard then it kind of looks like it might just fit the restriction of "if it's an executable, the runtime behavior should be the same".

Rust files allow the inclusion of a shebang on the first line. Since shebang's are a Unix convention, Rust needs to follow the existing standard (which requires a line break before the rest of the file contents). For example, it is not possible to write this Rust file without any newline characters in a way that preserves the behavior when run (cough on systems that support shebangs cough):

#!/usr/bin/rustrun

fn main() {
    println!("Hello World!");
}

Rust Playground (You won't be able to try using the shebang on Rust Playground, but at least you can see it compiles and can not be reduced to a single line)

For anyone who is curious, here is how it is described in the lexer code:

/// `rustc` allows files to have a shebang, e.g. "#!/usr/bin/rustrun",
/// but shebang isn't a part of rust syntax.
pub fn strip_shebang(input: &str) -> Option<usize> {
    // Shebang must start with `#!` literally, without any preceding whitespace.
    // For simplicity we consider any line starting with `#!` a shebang,
    // regardless of restrictions put on shebangs by specific platforms.
    if let Some(input_tail) = input.strip_prefix("#!") {
        // Ok, this is a shebang but if the next non-whitespace token is `[`,
        // then it may be valid Rust code, so consider it Rust code.
        let next_non_whitespace_token = tokenize(input_tail).map(|tok| tok.kind).find(|tok| {
            !matches!(
                tok,
                TokenKind::Whitespace
                    | TokenKind::LineComment { doc_style: None }
                    | TokenKind::BlockComment { doc_style: None, .. }
            )
        });
        if next_non_whitespace_token != Some(TokenKind::OpenBracket) {
            // No other choice than to consider this a shebang.
            return Some(2 + input_tail.lines().next().unwrap_or_default().len());
        }
    }
    None
}

https://github.com/rust-lang/rust/blob/e1c91213ff80af5b87a197b784b40bcbc8cf3add/compiler/rustc_lexer/src/lib.rs#L221-L244

Locke
  • 7,626
  • 2
  • 21
  • 41