cranpose-macros 0.1.168

Procedural macros for Cranpose
Documentation
use quote::{ToTokens, quote};

use super::*;

fn nested_fn_tokens(stmt: &Stmt) -> Option<String> {
    match stmt {
        Stmt::Item(syn::Item::Fn(item)) => Some(item.to_token_stream().to_string()),
        _ => None,
    }
}

#[test]
fn a_naked_nested_fn_stays_untouched() {
    let mut block: Block = syn::parse_quote!({
        #[unsafe(naked)]
        unsafe extern "C" fn trampoline() {
            core::arch::naked_asm!("ret");
        }
        #[naked]
        unsafe extern "C" fn older_spelling() {
            core::arch::naked_asm!("ret");
        }
        let _ = trampoline as unsafe extern "C" fn();
    });
    let reference = block.clone();
    let core_path = quote!(::cranpose_core);
    inject_branch_groups(&core_path, &mut block);

    let before: Vec<String> = reference
        .stmts
        .iter()
        .filter_map(nested_fn_tokens)
        .collect();
    let after: Vec<String> = block.stmts.iter().filter_map(nested_fn_tokens).collect();
    assert_eq!(before.len(), 2, "the probe declares both naked spellings");
    assert_eq!(
        before, after,
        "a naked body must stay a single naked_asm! call; instrumentation \
         inside it is a compile error for the user"
    );
    assert!(
        block.stmts.len() > reference.stmts.len(),
        "the sibling statements around the naked items are still instrumented"
    );
}

#[test]
fn branch_keys_do_not_monomorphise_the_once_lock_initializer() {
    let mut block: Block = syn::parse_quote!({
        if flag {
            first();
        } else {
            second();
        }
    });
    let core_path = quote!(::cranpose_core);
    inject_branch_groups(&core_path, &mut block);
    let tokens = block.to_token_stream().to_string();

    assert!(
        tokens.contains("cached_branch_location_key"),
        "branch keys must be latched through the outlined core helper, \
         got: {tokens}"
    );
    assert!(
        !tokens.contains("get_or_init"),
        "no initializer closure may reach the expansion site, got: {tokens}"
    );
}