Skip to content

Shebang feature incompatible with upcoming cargo script feature #14146

@PaulGrandperrin

Description

@PaulGrandperrin

To launch rust sources files as a script, we can currently use rust-script. And even more powerful, we can combine it with nix's shebang syntax which works with both the old and the new command-line interfaces of nix:

Old:

#!/usr/bin/env nix-shell
//! ```cargo
//! [dependencies]
//! time = "0.1.25"
//! ```
/*
#!nix-shell -i rust-script -p rustc -p rust-script -p cargo
*/
fn main() {
    for argument in std::env::args().skip(1) {
        println!("{}", argument);
    };
    println!("{}", std::env::var("HOME").expect(""));
    println!("{}", time::now().rfc822z());
}

(from https://nixos.wiki/wiki/Nix-shell_shebang#With_dependencies, doc: https://nix.dev/manual/nix/2.18/command-ref/nix-shell#use-as-a--interpreter)

New:

#!/usr/bin/env nix
//! ```cargo
//! [dependencies]
//! time = "0.1.25"
//! ```
/*
#!nix shell nixpkgs#rustc nixpkgs#rust-script nixpkgs#cargo --command rust-script
*/
fn main() {
    for argument in std::env::args().skip(1) {
        println!("{}", argument);
    };
    println!("{}", std::env::var("HOME").expect(""));
    println!("{}", time::now().rfc822z());
}

(https://hydra.nixos.org/build/308646369/download/1/manual/command-ref/new-cli/nix.html?highlight=shebang#shebang-interpreter)

However, this rust-as-a-script feature is now being integrated directly into the official cargo and the syntax to integrate the content of Cargo.toml is different, which makes it incompatible with nix's shebang:

#!/usr/bin/env nix
---cargo
[dependencies]
time = "0.1.25"
---
/*
#! nix shell github:oxalica/rust-overlay#rust-nightly --command sh -c ``cargo -Zscript $0``
*/

fn main() {
    for argument in std::env::args().skip(1) {
        println!("{}", argument);
    };
    println!("{}", std::env::var("HOME").expect(""));
    println!("{}", time::now().rfc822z());
}

results in:

error: './test.rs' is not a recognised command

This is because nix's multiline shebang can't really be placed anywhere in the file like the documentation suggests:

or with cascading interpreters. Note that the `#! nix` lines don't need to follow after the first line, to accommodate other interpreters.

Nix uses a hardcoded list of characters that should be at the beginning of a line to know if this line can be inserted between multiple nix shebang lines:

static const std::string commentChars("#/\\%@*-(");

An easy solution would be to allow nix shebang lines to be anywhere in the file but I don't know if there's an issue with this or not.

Conversely, cargo could be changed to allow comments to be inserted before the cargo file content. Their syntax RFC had already been merged but the feature has not be stabilized yet: rust-lang/cargo#12207

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions