@@ -12,6 +12,7 @@ module main
1212// the way. The `macos_v3_` name is kept for continuity with the original macOS
1313// rollout even though the behavior now also covers Linux.
1414import os
15+ import crypto.sha256
1516import v.pref
1617import v.util
1718import v.builder
@@ -44,6 +45,13 @@ const macos_v3_c_error_kind_file = 'kind'
4445// the receiver's c_error_string parser stores a nonempty, groupable diagnostic).
4546const macos_v3_compiler_error_message_base = 'error: the experimental V3 compiler hit an internal compiler error building this program'
4647
48+ struct MacosV3InputSnapshot {
49+ path string
50+ digest string
51+ v_file string
52+ v_source string
53+ }
54+
4755fn macos_v3_compiler_error_message (stage string ) string {
4856 stage_suffix := if stage == '' { '' } else { ' during ${stage }' }
4957 return '${macos_v3_compiler_error_message_base }${stage_suffix } (the stable V compiler built it successfully)'
@@ -217,13 +225,14 @@ fn launch_macos_v3_compiler(prefs &pref.Preferences, raw_args []string) ?MacosV3
217225 }
218226 replace_macos_v3_process_environment (environment)
219227 is_verbose := prefs.is_verbose
220- // The input path is captured before V3 runs so the compatibility fallback can
221- // stage it for a bug report if V3 fails with an internal compiler error.
222- input_path := prefs.path
228+ // Capture and bound the source before V3 runs. If an editor or build watcher rewrites
229+ // the input while V3 is compiling, the fallback will detect the changed digest and
230+ // submit metadata only instead of reading/uploading bytes V3 never parsed.
231+ input_snapshot := macos_v3_compiler_error_input_snapshot (prefs.path)
223232 retry_args := os.args[1 ..].clone ()
224- at_exit (fn [caller_environment, fallback_file, c_error_dir, retry_args, is_verbose, input_path ] () {
233+ at_exit (fn [caller_environment, fallback_file, c_error_dir, retry_args, is_verbose, input_snapshot ] () {
225234 retry_macos_v3_with_old_compiler (caller_environment, fallback_file, c_error_dir,
226- retry_args, is_verbose, input_path )
235+ retry_args, is_verbose, input_snapshot )
227236 }) or {
228237 eprintln ('cannot register the V3 compatibility fallback: ${err }' )
229238 exit (1 )
@@ -246,7 +255,7 @@ fn replace_macos_v3_process_environment(environment map[string]string) {
246255 }
247256}
248257
249- fn retry_macos_v3_with_old_compiler (caller_environment map [string ]string , fallback_file string , c_error_dir string , retry_args []string , is_verbose bool , input_path string ) {
258+ fn retry_macos_v3_with_old_compiler (caller_environment map [string ]string , fallback_file string , c_error_dir string , retry_args []string , is_verbose bool , input_snapshot MacosV 3 InputSnapshot ) {
250259 fallback_payload := os.read_file (fallback_file) or { return }
251260 fallback_reason , fallback_stage := macos_v3_fallback_reason_and_stage (fallback_payload)
252261 os.rm (fallback_file) or {}
@@ -289,14 +298,13 @@ fn retry_macos_v3_with_old_compiler(caller_environment map[string]string, fallba
289298 }
290299 } else if fallback_reason == macos_v3_ compiler_error_fallback {
291300 // V3 hit an internal compiler error (parser/checker/codegen) that V1 may still
292- // handle. Bound the input V source HERE (trusted) and forward it to the retry as
293- // content, so once the retry's build succeeds it prints the fallback notice and
294- // (for a single-file build) files a bug with the source. A directory build (`v .`)
295- // or non-V input yields no source, so the report stays metadata-only but the
296- // fallback is never silent.
297- export_macos_v3_report_content (macos_v3_ compiler_error_fallback, 'v3' ,
298- macos_v3_compiler_error_message (fallback_stage),
299- macos_v3_compiler_error_input_source (input_path), [])
301+ // handle. Forward the pre-V3 source snapshot only if the input still has the same
302+ // digest; otherwise send metadata only, never bytes that V3 did not parse. Once the
303+ // retry succeeds it prints the fallback notice and files the report. A directory
304+ // build (`v .`) or non-V input also remains metadata-only, but never silent.
305+ v_file , v_source := input_snapshot.current_report_source ()
306+ export_macos_v3_bounded_report_content (macos_v3_ compiler_error_fallback, 'v3' ,
307+ macos_v3_compiler_error_message (fallback_stage), v_file, v_source)
300308 os.rmdir_all (c_error_dir) or {}
301309 if should_report {
302310 eprintln ('V3 compilation failed; retrying with `-old-compiler`.' )
@@ -343,6 +351,10 @@ fn take_macos_v3_report_content() ?MacosV3CErrorReport {
343351// retry through the environment.
344352fn export_macos_v3_report_content (kind string , ccompiler string , c_output string , c_file string , v_sources []string ) {
345353 v_file , v_source := builder.bounded_v3_fallback_source (kind, c_output, c_file, v_sources)
354+ export_macos_v3_bounded_report_content (kind, ccompiler, c_output, v_file, v_source)
355+ }
356+
357+ fn export_macos_v3_bounded_report_content (kind string , ccompiler string , c_output string , v_file string , v_source string ) {
346358 builder.export_external_v3_report_to_env (builder.ExternalCErrorBugReport{
347359 kind: kind
348360 ccompiler: ccompiler
@@ -354,6 +366,35 @@ fn export_macos_v3_report_content(kind string, ccompiler string, c_output string
354366 })
355367}
356368
369+ fn macos_v3_compiler_error_input_snapshot (input_path string ) MacosV3 InputSnapshot {
370+ candidate := macos_v3_compiler_error_input_source (input_path)
371+ if candidate == '' {
372+ return MacosV3 InputSnapshot{}
373+ }
374+ // Preserve the caller's symlink semantics while making the path independent of any
375+ // working-directory changes inside V3.
376+ v_path := os.abs_path (candidate)
377+ source := os.read_file (v_path) or { return MacosV3 InputSnapshot{} }
378+ v_file , v_source := builder.bounded_v3_internal_fallback_source (v_path, source)
379+ return MacosV3 InputSnapshot{
380+ path: v_path
381+ digest: sha256 .hexhash (source)
382+ v_file: v_file
383+ v_source: v_source
384+ }
385+ }
386+
387+ fn (snapshot MacosV3InputSnapshot) current_report_source () (string , string ) {
388+ if snapshot.path == '' || snapshot.digest == '' {
389+ return '' , ''
390+ }
391+ current := os.read_file (snapshot.path) or { return '' , '' }
392+ if sha256 .hexhash (current) != snapshot.digest {
393+ return '' , ''
394+ }
395+ return snapshot.v_file, snapshot.v_source
396+ }
397+
357398// macos_v3_compiler_error_input_source returns `input_path` when it is a single V source
358399// file whose bounded contents can be uploaded, or '' for a directory / non-V input (which
359400// keeps the internal-error report metadata-only).
0 commit comments