Cheating to learn Rust by converting JavaScript to Rust, now I want to improve the code

I'm interested in learning Rust. I cheated a little to start off. I used this CodeConvert AI - Convert code with a click of a button online conversion tool to convert JavaScript to Rust.

It's an algorithm from here Permutations without recursive function call.

The online tool spit this out

use std::collections::HashMap;

fn main() {
    if !global::has_console() {
        global::set_console();
    }

    for prop in global::get_properties() {
        console_log(&prop);
    }

    // const input = [0,1,2,3,4], lex = 5;
    let _ = array_nth_permutation(vec![0, 1, 2, 3, 4], 5);
}

mod global {
    use std::collections::HashMap;

    pub fn has_console() -> bool {
        // Check if console exists in global context
        false // Placeholder for actual implementation
    }

    pub fn set_console() {
        // Set up console logging
    }

    pub fn get_properties() -> Vec<String> {
        // Return properties of global context
        vec![] // Placeholder for actual implementation
    }
}

fn console_log(args: &str) {
    println!("{}", args);
}
// https://stackoverflow.com/a/34238979
fn array_nth_permutation(a: Vec<i32>, n: usize) -> i32 {
    let mut lex = n;
    let mut b: Vec<i32> = a.clone();
    let len = a.len();
    let mut res: Vec<i32> = Vec::new();
    let mut f = (1..=len).product::<usize>();

    if n >= 0 && n < f {
        let mut n = n;
        let mut len = len;

        while len > 0 {
            f /= len;
            let i = (n - n % f) / f;
            res.push(b.remove(i));
            n %= f;
            len -= 1;
        }
        console_log(&format!("[{}] {:?}", lex, res));
    } else {
        console_log(&format!("{} >= 0 && {} < {}: {}", n, n, f, n >= 0 && n < f));
    }
    0
}

I manually edited the code to this

#![feature(str_split_whitespace_remainder)]
use std::io::{self, BufRead};

// https://stackoverflow.com/a/34238979
fn array_nth_permutation(t: usize, n: usize) -> usize {
  if t < 2 || n == usize::MAX {
    println!("Expected n > 2, m >= 0, got {}, {}", t, n);
    return 1;
  }
  
  let a: Vec<usize> = (0..t).collect();
  let lex = n;
  let mut b: Vec<usize> = a.clone(); // copy of the set
  let mut len = a.len(); // length of the set
  let mut res: Vec<usize> = Vec::new(); // return value, undefined
  let mut f = 1;
  let mut m = n;
  // compute f = factorial(len)
  for i in 1..=len {
    f *= i;
  }
  let fac = f;
  // if the permutation number is within range
  if m < f {
    // start with the empty set, loop for len elements
    for _ in 0..len {
      // determine the next element:
      // there are f/len subsets for each possible element,
      f /= len;
      // a simple division gives the leading element index
      let i = (m - m % f) / f; // Math.floor(n / f);
      res.push(b.remove(i));
      // reduce n for the remaining subset:
      // compute the remainder of the above division
      m %= f;
      len -= 1;
    }
    println!(
      "{} of {} (0-indexed, factorial {}) => {:?}",
      lex,
      fac - 1,
      fac,
      res
    );
  } else {
    println!("{} >= 0 && {} < {}: {}", n, n, f, n < f);
  }

  // return the permutated set or undefined if n is out of range
  0
}

fn main() {
  let stdin = io::stdin();
  let mut iterator = stdin.lock().lines();
  let line = iterator.next().unwrap().unwrap();
  let mut split = line.split_whitespace();
  let a: usize = split
    .next()
    .unwrap()
    .trim()
    .parse()
    .expect("Input not an integer");
  let n: usize = split
    .next()
    .unwrap()
    .trim()
    .parse()
    .expect("Input not an integer");
  array_nth_permutation(a, n);
}

This works up to a point

CARGO_HOME=/media/user/123/rust/.cargo RUSTUP_HOME=/media/user/123/rust/.rustup rustc permutations.rs -o permutations
echo '12 9' | ./permutations
9 of 479001599 (0-indexed, factorial 479001600) => [0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 8]
CARGO_HOME=/media/user/123/.cargo RUSTUP_HOME=/media/user/123/rust/.rustup rustc --target wasm32-wasip1 permutations.rs -o permutations-rust.wasm
echo '4 5' | wasmtime permutations-rust.wasm
5 of 23 (0-indexed, factorial 24) => [0, 3, 2, 1]

However, the WASM version of the code code panics when factorial 13! is input.

echo '13 2' | wasmtime permutations-rust.wasm
thread 'main' panicked at permutations.rs:21:5:
attempt to multiply with overflow
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Error: failed to run main module `permutations-rust.wasm`

Caused by:
    0: failed to invoke command default
    1: error while executing at wasm backtrace:
           0: 0xe918 - permutations-rust.wasm!__rust_start_panic
           1: 0xe83f - permutations-rust.wasm!rust_panic
           2: 0xe812 - permutations-rust.wasm!std::panicking::rust_panic_with_hook::h1ead75d7eace2784
           3: 0xdbd4 - permutations-rust.wasm!std::panicking::begin_panic_handler::{{closure}}::he44d57a6b952509a
           4: 0xdb0e - permutations-rust.wasm!std::sys::backtrace::__rust_end_short_backtrace::h0b4e9296dec8b10d
           5: 0xe1a6 - permutations-rust.wasm!rust_begin_unwind
           6: 0x132f5 - permutations-rust.wasm!core::panicking::panic_fmt::h9cf85a86c30a3523
           7: 0x1732c - permutations-rust.wasm!core::panicking::panic_const::panic_const_mul_overflow::hf20ebbd79badb656
           8: 0x5b4d - permutations-rust.wasm!permutations::array_nth_permutation::h93f1f81f912c4943
           9: 0x5fe2 - permutations-rust.wasm!permutations::main::h52e0aee3e982e29f
          10: 0x664e - permutations-rust.wasm!core::ops::function::FnOnce::call_once::hb243900555505583
          11: 0x6625 - permutations-rust.wasm!std::sys::backtrace::__rust_begin_short_backtrace::h87e777f30e6a49a0
          12:  0xd1b - permutations-rust.wasm!std::rt::lang_start::{{closure}}::h3dd0c64a3ec98083
          13: 0xb9de - permutations-rust.wasm!std::rt::lang_start_internal::h1b3a8c98b33cbfb4
          14:  0xce1 - permutations-rust.wasm!std::rt::lang_start::hce049f2007367618
          15: 0x6049 - permutations-rust.wasm!__main_void
          16:  0x3e4 - permutations-rust.wasm!_start
       note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information
    2: wasm trap: wasm `unreachable` instruction executed

From experimenting with AssemblyScript I think this has to do with usize usage, instead of i64.

What changes need to be made to use i64, and otherwise improve the code so the same output is produced executing the native executable and the Rust source code compiled to WASM with WASI support?

Might be worth showing your original JS code to verify the behavior of the Rust code.

From experimenting with AssemblyScript I think this has to do with usize usage, instead of i64.

I think you are correct. However, using i64 will also only bring you a limited distance, as factorial(len) will grow excessively fast.

Here's your algorithm modified so it uses u128 as its n value:

use std::io::{self, BufRead};

// https://stackoverflow.com/a/34238979
fn array_nth_permutation(t: usize, n: u128) -> usize {
    if t < 2 || n == u128::MAX {
        println!("Expected n > 2, m >= 0, got {}, {}", t, n);
        return 1;
    }

    let a: Vec<usize> = (0..t).collect();
    let lex = n;
    let mut b: Vec<usize> = a.clone(); // copy of the set
    let mut len = a.len() as u128; // length of the set
    let mut res: Vec<usize> = Vec::new(); // return value, undefined
    let mut f = 1;
    let mut m = n;
    // compute f = factorial(len)
    for i in 1..=len {
        f *= i;
    }
    let fac = f;
    // if the permutation number is within range
    if m < f {
        // start with the empty set, loop for len elements
        for _ in 0..len {
            // determine the next element:
            // there are f/len subsets for each possible element,
            f /= len;
            // a simple division gives the leading element index
            let i = (m - m % f) / f; // Math.floor(n / f);
            res.push(b.remove(i as usize));
            // reduce n for the remaining subset:
            // compute the remainder of the above division
            m %= f;
            len -= 1;
        }
        println!(
            "{} of {} (0-indexed, factorial {}) => {:?}",
            lex,
            fac - 1,
            fac,
            res
        );
    } else {
        println!("{} >= 0 && {} < {}: {}", n, n, f, n < f);
    }

    // return the permutated set or undefined if n is out of range
    0
}

fn main() {
    let stdin = io::stdin();
    let mut iterator = stdin.lock().lines();
    let line = iterator.next().unwrap().unwrap();
    let mut split = line.split_whitespace();
    let a: usize = split
        .next()
        .unwrap()
        .trim()
        .parse()
        .expect("Input not an integer");
    let n: u128 = split
        .next()
        .unwrap()
        .trim()
        .parse()
        .expect("Input not an integer");
    array_nth_permutation(a, n);
}

It now seems to work a little further; it now breaks at a = 35.

FYI I'm using the following command line for building and running, in case somebody wants a cargo version for trying:
cargo build --target wasm32-wasip1 && (echo '34 0' | wasmtime target/wasm32-wasip1/debug/rust-playground.wasm)

1 Like

Some more beautifications:

let mut f = 1;
for i in 1..=len {
    f *= i;
}

can be written as:

let mut f = (1..=len).product();

// Math.floor(n / f);
let i = (m - m % f) / f;

is quite pointless. Positive integer divisions in Rust are already floored.

let i = m / f;

should be equivalent.

1 Like

Part of the problem is that all WASM targets currently have a 32-bit address space limitation, making usize::MAX == u32::MAX.

Another part of the problem is that factorials grow extremely rapidly and require storage in an arbitrary precision number (like bigdecimal) for input values more than 2 decimal digits.

Another problem is that the default release profile doesn't enable integer overflow checks. Getting a panic from overflow in the WASM suggests you are compiling without the --release argument. (In turn, your build will run glacially slow.) Always remember to build with --release. If you need to also keep overflow panics in release builds, consider adding this to your Cargo.toml:

[profile.release]
overflow-checks = true

I think many of the other suggestions are good, too.

2 Likes

I'm using nightly profile.

Per this wasm64-unknown-unknown - The rustc book Rust supports 64-bit memories.

Sure, I'm pretty sure I used this

'show source';
  function array_nth_permutation(z = "4", y = "5") {
    const args = [z, y];
    let [length, n] = args.map(Number);
    let lex = n;
    if (length < 2 || lex < 0) {
      return `Expected n > 2, m >= 0, got ${length}, ${lex}\n`; // eval(input)
    }

    let a = Array.from({ length }, (_, i) => i);

    let b = Array(); // copy of the set a.slice()
    for (let x = 0; x < a.length; x++) {
      b[x] = a[x];
    }
    let len = a.length; // length of the set
    const res = Array(); // return value, undefined
    let i = 1;
    let f = 1;

    // compute f = factorial(len)
    for (; i <= len; i++) {
      f *= i;
    }

    let fac = f;
    // if the permutation number is within range
    if (n >= 0 && n < f) {
      // start with the empty set, loop for len elements
      // let result_len = 0;
      for (; len > 0; len--) {
        // determine the next element:
        // there are f/len subsets for each possible element,
        f /= len;
        // a simple division gives the leading element index
        i = (n - n % f) / f; // Math.floor(n / f);
        // alternately: i = (n - n % f) / f;
        // res[(result_len)++] = b[i];
        // for (let j = i; j < len; j++) {
        //   b[j] = b[j + 1]; // shift elements left
        // }
        res.push(b.splice(i, 1)[0]);
        // reduce n for the remaining subset:
        // compute the remainder of the above division
        n %= f;
        // extract the i-th element from b and push it at the end of res
      }
      return `${lex} of ${fac - 1} (0-indexed, factorial ${fac}) => ${
        JSON.stringify(res)
      }`;
    } else {
      if (n === 0) {
        return `${JSON.stringify(res)}\n`;
      }
      return `${n} >= 0 && ${n} < ${f}: ${n >= 0 && n < f}`;
    }
  }

I've done this before using Bytecode Alliance's Javy, which depends on the Rust QuickJS crate. This issue doesn't show there

function main() {
  const stdin = 0;
  const stdout = 1;
  const stderr = 2;

  const decoder = new TextDecoder();
  const encoder = new TextEncoder();

  let offset = 0;

  const message = new Uint8Array(65536);

  function array_nth_permutation(a, n) {
    let lex = n;
    let b = []; // copy of the set a.slice()
    for (let x = 0; x < a.length; x++) {
      b[x] = a[x];
    }
    let len = a.length; // length of the set
    const res = []; // return value, undefined
    let i = 1;
    let f = 1;

    // compute f = factorial(len)
    for (; i <= len; i++) {
      f *= i;
    }
    //console.log(f);
    let fac = f;
    // if the permutation number is within range
    if (n >= 0 && n < f) {
      // start with the empty set, loop for len elements
      //let result_len = 0;
      for (; len > 0; len--) {
        // determine the next element:
        // there are f/len subsets for each possible element,
        f /= len;
        // a simple division gives the leading element index
        i = (n - n % f) / f; // Math.floor(n / f);
        //console.log(i);
        // alternately: i = (n - n % f) / f;
        //res[(result_len)++] = b[i];
        //for (let j = i; j < len; j++) {
        //          b[j] = b[j + 1]; // shift elements left
        //      }
        res.push(b.splice(i, 1)echo '13 2' | wasmtime ../nm_javy_permutations_standalone.wasm
2 of 6227020799 (0-indexed, factorial 6227020800) => [0,1,2,3,4,5,6,7,8,9,11,10,12][0]);
        // reduce n for the remaining subset:
        // compute the remainder of the above division
        n %= f;
        // extract the i-th element from b and push it at the end of res
      }
      return `${lex} of ${fac - 1} (0-indexed, factorial ${fac}) => ${
        JSON.stringify(res)
      }\n`;
    } else {
      if (n === 0) {
        return `${JSON.stringify(res)}\n`;
      }
      return `${n} >= 0 && ${n} < ${f}: ${n >= 0 && n < f}\n`;
    }
    //console.log("[" + lex + "]", JSON.stringify(res));
    // return the permutated set or undefined if n is out of range
    // return 0;
  }

  // const input = [0,1,2,3,4], lex = 5;

  while (1) {
    const buffer = new Uint8Array(1);
    const bytesRead = Javy.IO.readSync(stdin, buffer);
    message.set(buffer, offset);
    offset += bytesRead;
    if (bytesRead === 0) {
      break;
    }
  }

  const data = decoder.decode(message.subarray(0, offset));

  const [input, lex] = data.split(" ").map(Math.floor); // JSON.parse(data);
  /*
  if (input >= 2 && lex >= 0) {
    Javy.IO.writeSync(
      stdout,
      encoder.encode(`Expected n > 2, m >= 0`), // eval(input)
    );
    return 1;
  }
  */
  if (input < 2 || lex < 0) {
    //throw new Error(`Expected n > 2, m >= 0, got ${input}, ${lex}`);
    Javy.IO.writeSync(
      stderr,
      encoder.encode(`Expected n > 2, m >= 0, got ${input}, ${lex}\n`), // eval(input)
    );
    return 1;
  } else {
    Javy.IO.writeSync(
      stdout,
      encoder.encode(
        array_nth_permutation([...new Array(input).keys()].map(Number), lex),
      ), // eval(input)
    );
    return 0;
  }
}

main();
echo '13 2' | wasmtime ../nm_javy_permutations_standalone.wasm
2 of 6227020799 (0-indexed, factorial 6227020800) => [0,1,2,3,4,5,6,7,8,9,11,10,12]

Unfortunately Binaryen's wasm2js doesn't appear to be able to handle the case. The output is mangled around the 10th index of the output stringified array

../binaryen/bin/wasm2js module.wasm --enable-bulk-memory --enable-nontrapping-float-to-int --sign-ext -o module-rust.js
echo '13 2' | node module-rust.js 
2 of 6227020799 (0-indexed, factorial 6227020800) => [0,1,2,3,4,5,6,7,8,9,1110,12]

nightly is a channel (different version of the compiler, more or less), which is a completely separate thing from the build profile. Using nightly does not affect whether optimizations or overflow checks are enabled.

This is true, but irrelevant unless you are actually compiling to the wasm64-unknown-unknown target. As long as you are using wasm32-wasip1, usize will be 32 bits.

I managed to get Rust to install on a USB and stay on the USB without creating $HOME/.cargo as such Installing Rust on an external USB and keeping the installation there · GitHub. There was no real roadmap for how to do that that I could locate in one documentation.

wget https://static.rust-lang.org/rustup/dist/x86_64-unknown-linux-gnu/rustup-init > rustup-init
CARGO_HOME=$PWD/rust/.cargo RUSTUP_HOME=$PWD/rust/.rustup ./rustup-init.1 --profile minimal --default-toolchain nightly

This is true, but irrelevant unless you are actually compiling to the wasm64-unknown-unknown target. As long as you are using wasm32-wasip1 , usize will be 32 bits.

I think the answers above improve the Rust code I started with. Thanks.

I'm not saying you have to change your toolchain. I'm saying that “nightly” is not a profile, and whether you are using nightly is irrelevant to whether optimizations and debug assertions are enabled. You can read this page to see what the defaults are when using rustc without cargo (profiles are a Cargo thing only):

If not specified, debug assertions are automatically enabled only if the opt-level is 0.

The default [opt-level] is 0.

Are you suggesting I try compiling with and without debug assertions?

I'm trying to avoid cargo writing crates to $HOME/.cargo. That's why I'm not building with cargo.

Are you suggesting I try compiling with and without debug assertions?

No, I'm trying to remove confusions. @parasyte was talking about changing optimization and debug assertions, and you responded to that with “I'm using nightly profile.”. Whether you are using nightly is irrelevant to whether you are compiling with optimization or debug assertions enabled.

Not using Cargo is a very impractical way to write any non-trivial Rust code. You can have Cargo use whatever location you like for its caches by setting the environment variable CARGO_HOME.

Not using Cargo is a very impractical way to write any non-trivial Rust code. You can have Cargo use whatever location you like for its caches by setting the environment variable CARGO_HOME .

I have not observed that to work in practice.

I'm using a Linux live USB, a temporary file system running on RAM. Rust uses a lot of space for crates. I start out with less than 1 GB, ordinarily. I've run out of disk space more than once trying to build with cargo. That's how and why I cobbled together the steps in the linked gist.

I can pass opt-level directly to rustc, right?

Right now I'm just comparing various approaches to compiling JavaScript to WASM, and/or compiling C, C++, Rust to JavaScript. WASM, from that vantage, is a viable intermediary to achieve that goal.

I can compile JavaScript to WASM using Bytecode Alliance Javy, Facebook's Static Hermes, and AssemblyScript.

Facebook's Static Hermes emits C from JavaScript source, which can be compiled to WASM with WASI support using WASI-SDK, clang and clang++.

Essentially using JavaScript as source code for cross-compilation to native executable, WASM, other programming languages; comparable to Rust.

I think I've got the Rust code to work as expected for what I'm doing presently. Specially, Rust to WASM, back to JavaScript with Binaryen's wasm2js

 ../binaryen/bin/wasm2js permutations-rust.wasm --enable-bulk-memory -o module-rust.js
echo '13 2' | deno -A module-rust.js
2 of 6227020799 (0-indexed, factorial 6227020800) => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 10, 12]
echo '13 2' | bun permutations-rust.wasm
2 of 6227020799 (0-indexed, factorial 6227020800) => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 10, 12]

I can execute WASM directly using bun. I can execute AssemblyScript directly using bun and deno, and compile AssemblyScript to JavaScript with each.

Right now I'm trying to figure out why Binaryen's wasm2js is mangling the output of the same algorithm compiled to WASM with AssemblyScript source, consistently, at the 10th index of the output.

AssemblyScript is typed.

export function array_nth_permutation(len: i64, n: i64): void { //Array<f64>
  let lex = n; // length of the set
  let b: i64[] = []; // copy of the set a.slice()
  for (let x: i64 = 0; x < len; x++) {
    b.push(x);
  }
  const res: i64[] = []; // return value, undefined
  let i: i64 = 1;
  let f: i64 = 1;

  // compute f = factorial(len)
  for (; i <= len; i++) {
    f *= i;
  }

  let fac = f;
  // if the permutation number is within range
  if (n >= 0 && n < f) {
    // start with the empty set, loop for len elements
    // let result_len = 0;
    for (; len > 0; len--) {
      // determine the next element:
      // there are f/len subsets for each possible element,
      f /= len;
      // a simple division gives the leading element index
      i = (n - n % f) / f; // Math.floor(n / f);
      //process.stdout.write(`i: ${i} `);
      // alternately: i = (n - n % f) / f;
      // res[(result_len)++] = b[i];
      // for (let j = i; j < len; j++) {
      //   b[j] = b[j + 1]; // shift elements left
      // }
      res.push(<i64>b.splice(<i32>i, 1)[0]);
      // reduce n for the remaining subset:
      // compute the remainder of the above division
      n %= f;
      //process.stdout.write(`n: ${n} `);
      // extract the i-th element from b and push it at the end of res
    }

    // let result: string = `[${res}]`;
    /*
    "[";
    for (let x: i32 = 0; x < res.length; x++) {
      let m: string = res[x].toString();
      let i: i32 = 0;
      do {
        result += m[i];
        i++;
      } while (m[i] !== ".");
      if (x < res.length -1) {
        result += ",";
      }
    }
    result += "]";
    */
    process.stdout.write(
      `${lex} of ${fac - 1} (0-indexed, factorial ${fac}) => [${res.join(",")}]\n`,
    );

    process.exit(0);
  } else {
    if (n === 0) {
      process.stdout.write(`${n} = 0`);
    }
    process.stdout.write(`${n} >= 0 && ${n} < ${f}: ${n >= 0 && n < f}`);
    process.exit(1);
  }
}

let input: string = "0";
let lex: string = "0";

if (process.argv.length > 1) {
  input = process.argv.at(-2);
  lex = process.argv.at(-1);
} else {
  let stdin = process.stdin;
  let buffer = new ArrayBuffer(64);
  // @ts-ignore
  let n: number = stdin.read(buffer);
  if (n > 0) {
    // @ts-ignore
    let data = String.UTF8.decode(buffer);
    input = data.slice(0, data.indexOf(" "));
    lex = data.slice(data.indexOf(" "), data.length);
  }
}

input = input.trim();
lex = lex.trim();

if (<i32> parseInt(input) < 2 || <i32> parseInt(lex) < 0) {
  process.stdout.write(`Expected n > 2, m >= 0, got ${input}, ${lex}`); // eval(input)
  process.exit(1);
}

array_nth_permutation(<i32> parseInt(input), <i32> parseInt(lex));
../binaryen/bin/wasm2js module.wasm --llvm-memory-copy-fill-lowering  --llvm-nontrapping-fptoint-lowering --signext-lowering --enable-mutable-globals --enable-bulk-memory  --signext-lowering  --enable-nontrapping-float-to-int -o module.js
echo '13 2' | node  module.js
2 of 6227020799 (0-indexed, factorial 6227020800) => [0,1,2,3,4,5,6,7,8,9,1110,12]

Just for completeness, how do I build with cargo when I don't have a Cargo.toml file, just pointing to the .rs file itself?

Cargo needs a manifest file (Cargo.toml) for every package; but there’s actually an in-development / unstable feature to offer a way of working without a Cargo.toml.

1 Like

Thanks. Yes, I've used -Zscript previously NativeMessagingHosts/nm_rust.rs at main · guest271314/NativeMessagingHosts · GitHub

#!/usr/bin/env -S /home/user/.cargo/bin/cargo -Zscript

Is the below really different than using -C opt-level 3 directly?

echo '13 2' | CARGO_HOME=/media/user/1234/rust/.cargo RUSTUP_HOME=/media/user/1234/rust/.rustup /media/user/1234/rust/.cargo/bin/cargo +nightly -Zscript permutations.rs --target wasm32-wasip1 -C opt-level 3 -o permutations-rust.wasm
warning: `package.edition` is unspecified, defaulting to `2024`
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.03s
     Running `/media/user/1234/rust/.cargo/target/e2/faac113191d70d/debug/permutations --target wasm32-wasip1 -C opt-level 3 -o permutations-rust.wasm`
2 of 6227020799 (0-indexed, factorial 6227020800) => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 10, 12]
 CARGO_HOME=/media/user/1234/rust/.cargo RUSTUP_HOME=/media/user/1234/rust/.rustup /media/user/1234/rust/.cargo/bin/rustc permutations.rs --target wasm32-wasip1 -C opt-level=3 -o permutations-rust.wasm 

Doesn't look like cargo build has that option.

Cargo sets things like optimization level via profiles.

The default dev and release profiles set optimiation to level 0 and 3, respectively by default, but also influence other things, e. g. overflow checks.

You choose the release profile with the --release flag.

Right, which can be done directly with rustc, which cargoultimately executes with arguments passed tocargo`, correct?

Or am I missing something?

-C opt-level=3 is a rustc option. You only use it when using rustc directly. If you are using Cargo, you would use the --release option to select the release profile which includes opt-level=3.

But the options you are passing with cargo -Zscript after the program file path are not doing anything. When you use cargo -Zscript <path to .rs>, following arguments are taken as arguments to the program you are running via Cargo, not to Cargo. If they were used as options for Cargo, you'd have gotten errors for -C and -o because Cargo doesn't take the same options rustc does.

1 Like