From a9dfca6633e7376b762d6ceb39e6a036dba68e95 Mon Sep 17 00:00:00 2001 From: vasilito Date: Mon, 3 Aug 2026 09:09:56 +0300 Subject: [PATCH] fix: verify-fork-functions compares bare function names The extractor matched '(?:pub )?(?:async )?(?:unsafe )?fn \w+' and then stripped only the 'fn ', leaving the visibility modifier inside the key. So 'fn foo' and 'pub fn foo' were different keys, and 'pub(crate) fn' was not matched at all. Merely changing a function's visibility made it look deleted: base was reported as missing remove_dentry, which the fork demonstrably still has, and the report printed nonsense like 'fn pub socket'. The exclude files had accumulated duplicate entries ('foo' and 'pub foo') to work around this. Compare bare names on both sides, and normalize the function half of each exclude entry so existing files keep matching. --- local/scripts/verify-fork-functions.sh | 31 +++++++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/local/scripts/verify-fork-functions.sh b/local/scripts/verify-fork-functions.sh index b1e8caed6b..65fb1cb10c 100755 --- a/local/scripts/verify-fork-functions.sh +++ b/local/scripts/verify-fork-functions.sh @@ -113,16 +113,26 @@ for fork in "${TARGET_FORKS[@]}"; do declare -a missing_details=() for f in "${shared_files[@]}"; do - # Extract function names from upstream version of the file + # Extract BARE function names (no visibility/async/unsafe/const + # modifiers) from the upstream version of the file. + # + # The key must be the bare name. The previous pattern kept whatever + # modifier it happened to match as part of the key ('pub foo' vs + # 'foo'), so merely changing a function's visibility in the fork — + # or upstream using 'pub(crate)', which the old pattern did not + # match at all — made an existing function look deleted. That is + # what produced report lines like "fn pub socket" and flagged + # functions the fork demonstrably still has. Visibility changes are + # not dropped code; only the name's presence is what this gate is + # meant to assert. upstream_fns=$(cd "$fork_dir" && git show "${upstream_ref}:${f}" 2>/dev/null | \ - grep -oP '(?:pub )?(?:async )?(?:unsafe )?fn \w+' | \ - sed 's/fn //' | sed 's/ *$//' | sort -u) + grep -oP '\bfn\s+\w+' | sed -E 's/^fn[[:space:]]+//' | sort -u) [[ -z "$upstream_fns" ]] && continue # Extract function names from our version of the file - local_fns=$(cd "$fork_dir" && grep -oP '(?:pub )?(?:async )?(?:unsafe )?fn \w+' "$f" 2>/dev/null | \ - sed 's/fn //' | sed 's/ *$//' | sort -u) + local_fns=$(cd "$fork_dir" && grep -oP '\bfn\s+\w+' "$f" 2>/dev/null | \ + sed -E 's/^fn[[:space:]]+//' | sort -u) # Load per-fork exclusion list for intentionally removed/replaced functions exclude_file="${fork_dir}/.verify-fork-functions.exclude" @@ -131,7 +141,16 @@ for fork in "${TARGET_FORKS[@]}"; do while IFS= read -r line; do [[ "$line" =~ ^# ]] && continue [[ -z "$line" ]] && continue - excluded["$line"]=1 + # Existing exclude files were written against the old + # modifier-carrying key format (and often list the same + # function twice, e.g. 'foo' and 'pub foo', to work around + # it). Normalize the function half to the bare name so both + # spellings keep matching now that keys are bare. + ex_path="${line%%:*}" + ex_fn="${line#*:}" + ex_fn="$(printf '%s' "$ex_fn" | \ + sed -E 's/^(pub(\([^)]*\))?[[:space:]]+|async[[:space:]]+|unsafe[[:space:]]+|const[[:space:]]+)+//')" + excluded["${ex_path}:${ex_fn}"]=1 done < "$exclude_file" fi