Repository: nexus-xyz/nexus-zkvm
File: runtime/macros/src/io.rs (Rust)

Code before:
                            attr_args.get(0).unwrap().to_token_stream()
                        ),
                    );
                }
            } else if let Path(id) = attr_args.get(0).unwrap() {
                let mut p: Punctuated<Expr, Comma> = Punctuated::new();
                p.insert(0, Path(id.clone()));
                (Some(name), p)
            } else {
                return stream_error(
                    &attr_args,
                    format!(
                        "Expected a tuple of input types, got type {:?}.",
                        attr_args.get(0).unwrap().to_token_stream()
                    ),
                );
            }
        }
        InputType::Public | InputType::Private => (None, attr_args.clone()),
    };

    // Check that the set of input variables is non-empty.
    let input_type_label = match input_type {
        InputType::Public => "public input",
        InputType::Private => "private input",
        InputType::Custom => "input",
    };
    if attr_inputs.is_empty() {
        return stream_error(
            &attr_args,
            format!("Expected at least one {}.", input_type_label),
        );
    }

    // Parse the input variables.
    let mut public_inputs: HashSet<Ident> = HashSet::new();
    for x in attr_inputs.iter() {
        if let Path(id) = x {
            if id.path.segments.len() != 1 {
                return stream_error(id, "Expected an identifier.");
            }
            let name = id.path.segments.get(0).unwrap().ident.clone();
            if public_inputs.contains(&name) {
                return stream_error(
                    &attr_args,
                    format!("Duplicate {}: {:?}.", input_type_label, name),
                );
            }
            public_inputs.insert(name);
        } else {
            return stream_error(x, "Expected an identifier.");

Review comment (suggestion):
This one is a good fix, but the label matching can now be moved inline so it won't be used elsewhere.

Code after:
                }
            } else if let Path(id) = attr_args.get(0).unwrap() {
                let mut p: Punctuated<Expr, Comma> = Punctuated::new();
                p.insert(0, Path(id.clone()));
                (Some(name), p)
            } else {
                let got = attr_args.get(0).unwrap().to_token_stream().to_string();
                return stream_error(
                    &attr_args,
                    format!("Expected a tuple of input types, got type {}.", got),
                );
            }
        }
        InputType::Public | InputType::Private => (None, attr_args.clone()),
    };

    // Check that the set of input variables is non-empty.
    if attr_inputs.is_empty() {
        let input_type_label = match input_type {
            InputType::Public => "public input",
            InputType::Private => "private input",
            InputType::Custom => "input",
        };
        return stream_error(
            &attr_args,
            format!("Expected at least one {}.", input_type_label),
        );
    }

    // Parse the input variables.
    let mut public_inputs: HashSet<Ident> = HashSet::new();
    for x in attr_inputs.iter() {
        if let Path(id) = x {
            if id.path.segments.len() != 1 {
                return stream_error(id, "Expected an identifier.");
            }
            let name = id.path.segments.get(0).unwrap().ident.clone();
            if public_inputs.contains(&name) {
                return stream_error(&attr_args, format!("Duplicate public input: {}.", name));
            }
            public_inputs.insert(name);
        } else {
            return stream_error(x, "Expected an identifier.");
        }
    }

    // Extract the function signature and body.
    let ItemFn {
        attrs, sig, block, ..
    } = parse_macro_input!(item as ItemFn);
    let fn_name = sig.ident.clone();