Commit 1d808d0dd2

Andrew Kelley <andrew@ziglang.org>
2021-05-18 04:11:11
stage2: fix crash in switch compile error
when the AST for the switch has never been loaded
1 parent 67f5a28
Changed files (3)
src/Module.zig
@@ -4419,13 +4419,20 @@ pub const SwitchProngSrc = union(enum) {
     /// the LazySrcLoc in order to emit a compile error.
     pub fn resolve(
         prong_src: SwitchProngSrc,
+        gpa: *Allocator,
         decl: *Decl,
         switch_node_offset: i32,
         range_expand: RangeExpand,
     ) LazySrcLoc {
         @setCold(true);
+        const tree = decl.namespace.file_scope.getTree(gpa) catch |err| {
+            // In this case we emit a warning + a less precise source location.
+            log.warn("unable to load {s}: {s}", .{
+                decl.namespace.file_scope.sub_file_path, @errorName(err),
+            });
+            return LazySrcLoc{ .node_offset = 0};
+        };
         const switch_node = decl.relativeToNodeIndex(switch_node_offset);
-        const tree = decl.namespace.file_scope.tree;
         const main_tokens = tree.nodes.items(.main_token);
         const node_datas = tree.nodes.items(.data);
         const node_tags = tree.nodes.items(.tag);
src/Sema.zig
@@ -4229,18 +4229,19 @@ fn resolveSwitchItemVal(
     switch_prong_src: Module.SwitchProngSrc,
     range_expand: Module.SwitchProngSrc.RangeExpand,
 ) InnerError!TypedValue {
+    const mod = sema.mod;
     const item = try sema.resolveInst(item_ref);
     // We have to avoid the other helper functions here because we cannot construct a LazySrcLoc
     // because we only have the switch AST node. Only if we know for sure we need to report
     // a compile error do we resolve the full source locations.
     if (item.value()) |val| {
         if (val.isUndef()) {
-            const src = switch_prong_src.resolve(block.src_decl, switch_node_offset, range_expand);
+            const src = switch_prong_src.resolve(mod, block.src_decl, switch_node_offset, range_expand);
             return sema.failWithUseOfUndef(block, src);
         }
         return TypedValue{ .ty = item.ty, .val = val };
     }
-    const src = switch_prong_src.resolve(block.src_decl, switch_node_offset, range_expand);
+    const src = switch_prong_src.resolve(mod, block.src_decl, switch_node_offset, range_expand);
     return sema.failWithNeededComptime(block, src);
 }
 
@@ -4284,7 +4285,7 @@ fn validateSwitchItemEnum(
     const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
     const field_index = item_tv.ty.enumTagFieldIndex(item_tv.val) orelse {
         const msg = msg: {
-            const src = switch_prong_src.resolve(block.src_decl, src_node_offset, .none);
+            const src = switch_prong_src.resolve(mod, block.src_decl, src_node_offset, .none);
             const msg = try mod.errMsg(
                 &block.base,
                 src,
@@ -4316,8 +4317,8 @@ fn validateSwitchDupe(
 ) InnerError!void {
     const prev_prong_src = maybe_prev_src orelse return;
     const mod = sema.mod;
-    const src = switch_prong_src.resolve(block.src_decl, src_node_offset, .none);
-    const prev_src = prev_prong_src.resolve(block.src_decl, src_node_offset, .none);
+    const src = switch_prong_src.resolve(mod, block.src_decl, src_node_offset, .none);
+    const prev_src = prev_prong_src.resolve(mod, block.src_decl, src_node_offset, .none);
     const msg = msg: {
         const msg = try mod.errMsg(
             &block.base,
@@ -4354,7 +4355,7 @@ fn validateSwitchItemBool(
         false_count.* += 1;
     }
     if (true_count.* + false_count.* > 2) {
-        const src = switch_prong_src.resolve(block.src_decl, src_node_offset, .none);
+        const src = switch_prong_src.resolve(mod, block.src_decl, src_node_offset, .none);
         return sema.mod.fail(&block.base, src, "duplicate switch value", .{});
     }
 }
BRANCH_TODO
@@ -1,3 +0,0 @@
- * in SwitchProng resolve, make sure AST tree gets loaded.
-   It will be unloaded if using cached ZIR.
-