| ... | @@ -1463,11 +1463,7 @@ pub const File = struct { | ... | @@ -1463,11 +1463,7 @@ pub const File = struct { |
| 1463 | /// Whether this is populated depends on `source_loaded`. | 1463 | /// Whether this is populated depends on `source_loaded`. |
| 1464 | source: [:0]const u8, | 1464 | source: [:0]const u8, |
| 1465 | /// Whether this is populated depends on `status`. | 1465 | /// Whether this is populated depends on `status`. |
| 1466 | stat_size: u64, | 1466 | stat: Cache.File.Stat, |
| 1467 | /// Whether this is populated depends on `status`. | | |
| 1468 | stat_inode: std.fs.File.INode, | | |
| 1469 | /// Whether this is populated depends on `status`. | | |
| 1470 | stat_mtime: i128, | | |
| 1471 | /// Whether this is populated or not depends on `tree_loaded`. | 1467 | /// Whether this is populated or not depends on `tree_loaded`. |
| 1472 | tree: Ast, | 1468 | tree: Ast, |
| 1473 | /// Whether this is populated or not depends on `zir_loaded`. | 1469 | /// Whether this is populated or not depends on `zir_loaded`. |
| ... | @@ -1535,8 +1531,16 @@ pub const File = struct { | ... | @@ -1535,8 +1531,16 @@ pub const File = struct { |
| 1535 | file.* = undefined; | 1531 | file.* = undefined; |
| 1536 | } | 1532 | } |
| 1537 | | 1533 | |
| 1538 | pub fn getSource(file: *File, gpa: Allocator) ![:0]const u8 { | 1534 | pub const Source = struct { |
| 1539 | if (file.source_loaded) return file.source; | 1535 | bytes: [:0]const u8, |
| | 1536 | stat: Cache.File.Stat, |
| | 1537 | }; |
| | 1538 | |
| | 1539 | pub fn getSource(file: *File, gpa: Allocator) !Source { |
| | 1540 | if (file.source_loaded) return Source{ |
| | 1541 | .bytes = file.source, |
| | 1542 | .stat = file.stat, |
| | 1543 | }; |
| 1540 | | 1544 | |
| 1541 | const root_dir_path = file.pkg.root_src_directory.path orelse "."; | 1545 | const root_dir_path = file.pkg.root_src_directory.path orelse "."; |
| 1542 | log.debug("File.getSource, not cached. pkgdir={s} sub_file_path={s}", .{ | 1546 | log.debug("File.getSource, not cached. pkgdir={s} sub_file_path={s}", .{ |
| ... | @@ -1565,14 +1569,21 @@ pub const File = struct { | ... | @@ -1565,14 +1569,21 @@ pub const File = struct { |
| 1565 | | 1569 | |
| 1566 | file.source = source; | 1570 | file.source = source; |
| 1567 | file.source_loaded = true; | 1571 | file.source_loaded = true; |
| 1568 | return source; | 1572 | return Source{ |
| | 1573 | .bytes = source, |
| | 1574 | .stat = .{ |
| | 1575 | .size = stat.size, |
| | 1576 | .inode = stat.inode, |
| | 1577 | .mtime = stat.mtime, |
| | 1578 | }, |
| | 1579 | }; |
| 1569 | } | 1580 | } |
| 1570 | | 1581 | |
| 1571 | pub fn getTree(file: *File, gpa: Allocator) !*const Ast { | 1582 | pub fn getTree(file: *File, gpa: Allocator) !*const Ast { |
| 1572 | if (file.tree_loaded) return &file.tree; | 1583 | if (file.tree_loaded) return &file.tree; |
| 1573 | | 1584 | |
| 1574 | const source = try file.getSource(gpa); | 1585 | const source = try file.getSource(gpa); |
| 1575 | file.tree = try std.zig.parse(gpa, source); | 1586 | file.tree = try std.zig.parse(gpa, source.bytes); |
| 1576 | file.tree_loaded = true; | 1587 | file.tree_loaded = true; |
| 1577 | return &file.tree; | 1588 | return &file.tree; |
| 1578 | } | 1589 | } |
| ... | @@ -1631,9 +1642,7 @@ pub const EmbedFile = struct { | ... | @@ -1631,9 +1642,7 @@ pub const EmbedFile = struct { |
| 1631 | /// Memory is stored in gpa, owned by EmbedFile. | 1642 | /// Memory is stored in gpa, owned by EmbedFile. |
| 1632 | sub_file_path: []const u8, | 1643 | sub_file_path: []const u8, |
| 1633 | bytes: [:0]const u8, | 1644 | bytes: [:0]const u8, |
| 1634 | stat_size: u64, | 1645 | stat: Cache.File.Stat, |
| 1635 | stat_inode: std.fs.File.INode, | | |
| 1636 | stat_mtime: i128, | | |
| 1637 | /// Package that this file is a part of, managed externally. | 1646 | /// Package that this file is a part of, managed externally. |
| 1638 | pkg: *Package, | 1647 | pkg: *Package, |
| 1639 | /// The Decl that was created from the `@embedFile` to own this resource. | 1648 | /// The Decl that was created from the `@embedFile` to own this resource. |
| ... | @@ -2704,9 +2713,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void { | ... | @@ -2704,9 +2713,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void { |
| 2704 | keep_zir = true; | 2713 | keep_zir = true; |
| 2705 | file.zir = zir; | 2714 | file.zir = zir; |
| 2706 | file.zir_loaded = true; | 2715 | file.zir_loaded = true; |
| 2707 | file.stat_size = header.stat_size; | 2716 | file.stat = .{ |
| 2708 | file.stat_inode = header.stat_inode; | 2717 | .size = header.stat_size, |
| 2709 | file.stat_mtime = header.stat_mtime; | 2718 | .inode = header.stat_inode, |
| | 2719 | .mtime = header.stat_mtime, |
| | 2720 | }; |
| 2710 | file.status = .success_zir; | 2721 | file.status = .success_zir; |
| 2711 | log.debug("AstGen cached success: {s}", .{file.sub_file_path}); | 2722 | log.debug("AstGen cached success: {s}", .{file.sub_file_path}); |
| 2712 | | 2723 | |
| ... | @@ -2724,9 +2735,9 @@ pub fn astGenFile(mod: *Module, file: *File) !void { | ... | @@ -2724,9 +2735,9 @@ pub fn astGenFile(mod: *Module, file: *File) !void { |
| 2724 | }, | 2735 | }, |
| 2725 | .parse_failure, .astgen_failure, .success_zir => { | 2736 | .parse_failure, .astgen_failure, .success_zir => { |
| 2726 | const unchanged_metadata = | 2737 | const unchanged_metadata = |
| 2727 | stat.size == file.stat_size and | 2738 | stat.size == file.stat.size and |
| 2728 | stat.mtime == file.stat_mtime and | 2739 | stat.mtime == file.stat.mtime and |
| 2729 | stat.inode == file.stat_inode; | 2740 | stat.inode == file.stat.inode; |
| 2730 | | 2741 | |
| 2731 | if (unchanged_metadata) { | 2742 | if (unchanged_metadata) { |
| 2732 | log.debug("unmodified metadata of file: {s}", .{file.sub_file_path}); | 2743 | log.debug("unmodified metadata of file: {s}", .{file.sub_file_path}); |
| ... | @@ -2787,9 +2798,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void { | ... | @@ -2787,9 +2798,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void { |
| 2787 | if (amt != stat.size) | 2798 | if (amt != stat.size) |
| 2788 | return error.UnexpectedEndOfFile; | 2799 | return error.UnexpectedEndOfFile; |
| 2789 | | 2800 | |
| 2790 | file.stat_size = stat.size; | 2801 | file.stat = .{ |
| 2791 | file.stat_inode = stat.inode; | 2802 | .size = stat.size, |
| 2792 | file.stat_mtime = stat.mtime; | 2803 | .inode = stat.inode, |
| | 2804 | .mtime = stat.mtime, |
| | 2805 | }; |
| 2793 | file.source = source; | 2806 | file.source = source; |
| 2794 | file.source_loaded = true; | 2807 | file.source_loaded = true; |
| 2795 | | 2808 | |
| ... | @@ -3069,9 +3082,11 @@ pub fn populateBuiltinFile(mod: *Module) !void { | ... | @@ -3069,9 +3082,11 @@ pub fn populateBuiltinFile(mod: *Module) !void { |
| 3069 | | 3082 | |
| 3070 | try writeBuiltinFile(file, builtin_pkg); | 3083 | try writeBuiltinFile(file, builtin_pkg); |
| 3071 | } else { | 3084 | } else { |
| 3072 | file.stat_size = stat.size; | 3085 | file.stat = .{ |
| 3073 | file.stat_inode = stat.inode; | 3086 | .size = stat.size, |
| 3074 | file.stat_mtime = stat.mtime; | 3087 | .inode = stat.inode, |
| | 3088 | .mtime = stat.mtime, |
| | 3089 | }; |
| 3075 | } | 3090 | } |
| 3076 | } else |err| switch (err) { | 3091 | } else |err| switch (err) { |
| 3077 | error.BadPathName => unreachable, // it's always "builtin.zig" | 3092 | error.BadPathName => unreachable, // it's always "builtin.zig" |
| ... | @@ -3099,9 +3114,11 @@ pub fn writeBuiltinFile(file: *File, builtin_pkg: *Package) !void { | ... | @@ -3099,9 +3114,11 @@ pub fn writeBuiltinFile(file: *File, builtin_pkg: *Package) !void { |
| 3099 | try af.file.writeAll(file.source); | 3114 | try af.file.writeAll(file.source); |
| 3100 | try af.finish(); | 3115 | try af.finish(); |
| 3101 | | 3116 | |
| 3102 | file.stat_size = file.source.len; | 3117 | file.stat = .{ |
| 3103 | file.stat_inode = 0; // dummy value | 3118 | .size = file.source.len, |
| 3104 | file.stat_mtime = 0; // dummy value | 3119 | .inode = 0, // dummy value |
| | 3120 | .mtime = 0, // dummy value |
| | 3121 | }; |
| 3105 | } | 3122 | } |
| 3106 | | 3123 | |
| 3107 | pub fn mapOldZirToNew( | 3124 | pub fn mapOldZirToNew( |
| ... | @@ -3382,16 +3399,16 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { | ... | @@ -3382,16 +3399,16 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 3382 | } | 3399 | } |
| 3383 | | 3400 | |
| 3384 | if (mod.comp.whole_cache_manifest) |man| { | 3401 | if (mod.comp.whole_cache_manifest) |man| { |
| 3385 | assert(file.source_loaded); | 3402 | const source = file.getSource(gpa) catch |err| { |
| | 3403 | try reportRetryableFileError(mod, file, "unable to load source: {s}", .{@errorName(err)}); |
| | 3404 | return error.AnalysisFail; |
| | 3405 | }; |
| 3386 | const resolved_path = try file.pkg.root_src_directory.join(gpa, &.{ | 3406 | const resolved_path = try file.pkg.root_src_directory.join(gpa, &.{ |
| 3387 | file.sub_file_path, | 3407 | file.sub_file_path, |
| 3388 | }); | 3408 | }); |
| 3389 | errdefer gpa.free(resolved_path); | 3409 | errdefer gpa.free(resolved_path); |
| 3390 | try man.addFilePostContents(resolved_path, file.source, .{ | 3410 | |
| 3391 | .size = file.stat_size, | 3411 | try man.addFilePostContents(resolved_path, source.bytes, source.stat); |
| 3392 | .inode = file.stat_inode, | | |
| 3393 | .mtime = file.stat_mtime, | | |
| 3394 | }); | | |
| 3395 | } | 3412 | } |
| 3396 | } else { | 3413 | } else { |
| 3397 | new_decl.analysis = .file_failure; | 3414 | new_decl.analysis = .file_failure; |
| ... | @@ -3723,9 +3740,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult { | ... | @@ -3723,9 +3740,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult { |
| 3723 | .source_loaded = false, | 3740 | .source_loaded = false, |
| 3724 | .tree_loaded = false, | 3741 | .tree_loaded = false, |
| 3725 | .zir_loaded = false, | 3742 | .zir_loaded = false, |
| 3726 | .stat_size = undefined, | 3743 | .stat = undefined, |
| 3727 | .stat_inode = undefined, | | |
| 3728 | .stat_mtime = undefined, | | |
| 3729 | .tree = undefined, | 3744 | .tree = undefined, |
| 3730 | .zir = undefined, | 3745 | .zir = undefined, |
| 3731 | .status = .never_loaded, | 3746 | .status = .never_loaded, |
| ... | @@ -3793,9 +3808,7 @@ pub fn importFile( | ... | @@ -3793,9 +3808,7 @@ pub fn importFile( |
| 3793 | .source_loaded = false, | 3808 | .source_loaded = false, |
| 3794 | .tree_loaded = false, | 3809 | .tree_loaded = false, |
| 3795 | .zir_loaded = false, | 3810 | .zir_loaded = false, |
| 3796 | .stat_size = undefined, | 3811 | .stat = undefined, |
| 3797 | .stat_inode = undefined, | | |
| 3798 | .stat_mtime = undefined, | | |
| 3799 | .tree = undefined, | 3812 | .tree = undefined, |
| 3800 | .zir = undefined, | 3813 | .zir = undefined, |
| 3801 | .status = .never_loaded, | 3814 | .status = .never_loaded, |
| ... | @@ -3840,8 +3853,13 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb | ... | @@ -3840,8 +3853,13 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb |
| 3840 | var file = try cur_file.pkg.root_src_directory.handle.openFile(sub_file_path, .{}); | 3853 | var file = try cur_file.pkg.root_src_directory.handle.openFile(sub_file_path, .{}); |
| 3841 | defer file.close(); | 3854 | defer file.close(); |
| 3842 | | 3855 | |
| 3843 | const stat = try file.stat(); | 3856 | const actual_stat = try file.stat(); |
| 3844 | const size_usize = try std.math.cast(usize, stat.size); | 3857 | const stat: Cache.File.Stat = .{ |
| | 3858 | .size = actual_stat.size, |
| | 3859 | .inode = actual_stat.inode, |
| | 3860 | .mtime = actual_stat.mtime, |
| | 3861 | }; |
| | 3862 | const size_usize = try std.math.cast(usize, actual_stat.size); |
| 3845 | const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0); | 3863 | const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0); |
| 3846 | errdefer gpa.free(bytes); | 3864 | errdefer gpa.free(bytes); |
| 3847 | | 3865 | |
| ... | @@ -3852,11 +3870,7 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb | ... | @@ -3852,11 +3870,7 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb |
| 3852 | if (mod.comp.whole_cache_manifest) |man| { | 3870 | if (mod.comp.whole_cache_manifest) |man| { |
| 3853 | const copied_resolved_path = try gpa.dupe(u8, resolved_path); | 3871 | const copied_resolved_path = try gpa.dupe(u8, resolved_path); |
| 3854 | errdefer gpa.free(copied_resolved_path); | 3872 | errdefer gpa.free(copied_resolved_path); |
| 3855 | try man.addFilePostContents(copied_resolved_path, bytes, .{ | 3873 | try man.addFilePostContents(copied_resolved_path, bytes, stat); |
| 3856 | .size = stat.size, | | |
| 3857 | .inode = stat.inode, | | |
| 3858 | .mtime = stat.mtime, | | |
| 3859 | }); | | |
| 3860 | } | 3874 | } |
| 3861 | | 3875 | |
| 3862 | keep_resolved_path = true; // It's now owned by embed_table. | 3876 | keep_resolved_path = true; // It's now owned by embed_table. |
| ... | @@ -3864,9 +3878,7 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb | ... | @@ -3864,9 +3878,7 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb |
| 3864 | new_file.* = .{ | 3878 | new_file.* = .{ |
| 3865 | .sub_file_path = sub_file_path, | 3879 | .sub_file_path = sub_file_path, |
| 3866 | .bytes = bytes, | 3880 | .bytes = bytes, |
| 3867 | .stat_size = stat.size, | 3881 | .stat = stat, |
| 3868 | .stat_inode = stat.inode, | | |
| 3869 | .stat_mtime = stat.mtime, | | |
| 3870 | .pkg = cur_file.pkg, | 3882 | .pkg = cur_file.pkg, |
| 3871 | .owner_decl = undefined, // Set by Sema immediately after this function returns. | 3883 | .owner_decl = undefined, // Set by Sema immediately after this function returns. |
| 3872 | }; | 3884 | }; |
| ... | @@ -3880,9 +3892,9 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void { | ... | @@ -3880,9 +3892,9 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void { |
| 3880 | const stat = try file.stat(); | 3892 | const stat = try file.stat(); |
| 3881 | | 3893 | |
| 3882 | const unchanged_metadata = | 3894 | const unchanged_metadata = |
| 3883 | stat.size == embed_file.stat_size and | 3895 | stat.size == embed_file.stat.size and |
| 3884 | stat.mtime == embed_file.stat_mtime and | 3896 | stat.mtime == embed_file.stat.mtime and |
| 3885 | stat.inode == embed_file.stat_inode; | 3897 | stat.inode == embed_file.stat.inode; |
| 3886 | | 3898 | |
| 3887 | if (unchanged_metadata) return; | 3899 | if (unchanged_metadata) return; |
| 3888 | | 3900 | |
| ... | @@ -3891,9 +3903,11 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void { | ... | @@ -3891,9 +3903,11 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void { |
| 3891 | const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0); | 3903 | const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0); |
| 3892 | gpa.free(embed_file.bytes); | 3904 | gpa.free(embed_file.bytes); |
| 3893 | embed_file.bytes = bytes; | 3905 | embed_file.bytes = bytes; |
| 3894 | embed_file.stat_size = stat.size; | 3906 | embed_file.stat = .{ |
| 3895 | embed_file.stat_mtime = stat.mtime; | 3907 | .size = stat.size, |
| 3896 | embed_file.stat_inode = stat.inode; | 3908 | .mtime = stat.mtime, |
| | 3909 | .inode = stat.inode, |
| | 3910 | }; |
| 3897 | | 3911 | |
| 3898 | mod.comp.mutex.lock(); | 3912 | mod.comp.mutex.lock(); |
| 3899 | defer mod.comp.mutex.unlock(); | 3913 | defer mod.comp.mutex.unlock(); |
| ... | @@ -5024,3 +5038,35 @@ pub fn linkerUpdateDecl(mod: *Module, decl: *Decl) !void { | ... | @@ -5024,3 +5038,35 @@ pub fn linkerUpdateDecl(mod: *Module, decl: *Decl) !void { |
| 5024 | }, | 5038 | }, |
| 5025 | }; | 5039 | }; |
| 5026 | } | 5040 | } |
| | 5041 | |
| | 5042 | fn reportRetryableFileError( |
| | 5043 | mod: *Module, |
| | 5044 | file: *File, |
| | 5045 | comptime format: []const u8, |
| | 5046 | args: anytype, |
| | 5047 | ) error{OutOfMemory}!void { |
| | 5048 | file.status = .retryable_failure; |
| | 5049 | |
| | 5050 | const err_msg = try ErrorMsg.create( |
| | 5051 | mod.gpa, |
| | 5052 | .{ |
| | 5053 | .file_scope = file, |
| | 5054 | .parent_decl_node = 0, |
| | 5055 | .lazy = .entire_file, |
| | 5056 | }, |
| | 5057 | format, |
| | 5058 | args, |
| | 5059 | ); |
| | 5060 | errdefer err_msg.destroy(mod.gpa); |
| | 5061 | |
| | 5062 | mod.comp.mutex.lock(); |
| | 5063 | defer mod.comp.mutex.unlock(); |
| | 5064 | |
| | 5065 | const gop = try mod.failed_files.getOrPut(mod.gpa, file); |
| | 5066 | if (gop.found_existing) { |
| | 5067 | if (gop.value_ptr.*) |old_err_msg| { |
| | 5068 | old_err_msg.destroy(mod.gpa); |
| | 5069 | } |
| | 5070 | } |
| | 5071 | gop.value_ptr.* = err_msg; |
| | 5072 | } |