Commit 3eb90a110f

Loris Cro <kappaloris@gmail.com>
2022-03-08 19:57:22
autodoc: add support for pointers and comptime expressions in decl paths
1 parent 03d3929
Changed files (2)
lib
docs
src
lib/docs/main.js
@@ -144,13 +144,33 @@
         return typeKind === typeKinds.ErrorSet || typeKindIsContainer(typeKind);
     }
 
+    function findCteInDeclPath(path) {
+        for (var i = path.length - 1; i >= 0; i -= 1) {
+            const decl = zigAnalysis.decls[path[i]];
+            if ("comptimeExpr" in decl.value) {
+                return decl;
+            }
+
+            if ("declPath" in decl.value) {
+                const res = findCteInDeclPath(decl.value.declPath);
+                if (res !== null) {
+                    return res;
+                }
+            }
+        }
+
+        return null;
+    }
+
     function resolveValue(value) {
         var i = 0;
         while(i < 1000) {
             i += 1;
 
             if ("declPath" in value) {
-                console.assert(value.declPath.length == 1); // only support declRefs for now
+                if (value.hasCte) {
+                    return findCteInDeclPath(value.declPath).value;
+                }
                 value = zigAnalysis.decls[value.declPath[0]].value;
                 continue;
             }
@@ -171,30 +191,34 @@
             }
 
             if ("declPath" in decl.value) {
-                console.assert(decl.value.declPath.length == 1); // only support declRefs for now
-                decl = zigAnalysis.decls[decl.value.declPath[0]];
+                if (decl.value.hasCte) {
+                    decl = findCteInDeclPath(decl.value.declPath);
+                } else {
+                    decl = zigAnalysis.decls[decl.value.declPath[0]];
+                }
+
                 continue;
             }
 
             if ("int" in decl.value) {
-                return resolveTypeRefToTypeId(decl.value.int.typeRef);
+                return decl.value.int.typeRef;
             }
 
             if ("float" in decl.value) {
-                return resolveTypeRefToTypeId(decl.value.float.typeRef);
+                return decl.value.float.typeRef;
             }
 
             if ("array" in decl.value) {
-                return resolveTypeRefToTypeId(decl.value.array.typeRef);
+                return decl.value.array.typeRef;
             }
 
             if ("struct" in decl.value) {
-                return resolveTypeRefToTypeId(decl.value.struct.typeRef);
+                return decl.value.struct.typeRef;
             }
 
             if ("comptimeExpr" in decl.value) {
                 const cte = zigAnalysis.comptimeExprs[decl.value.comptimeExpr];
-                return resolveTypeRefToTypeId(cte.typeRef);
+                return cte.typeRef;
             }
 
             if ("call" in decl.value) {
@@ -205,7 +229,7 @@
                 console.assert("type" in fn_decl_value); //TODO handle comptimeExpr
                 const fn_type = zigAnalysis.types[fn_decl_value.type];
                 console.assert(fn_type.kind === typeKinds.Fn);
-                return resolveTypeRefToTypeId(fn_type.ret);
+                return fn_type.ret;
             }
 
             console.log("TODO: handle in `typeOfDecl` more cases: ", decl);
@@ -215,23 +239,6 @@
         console.assert(false);
     }
 
-    function resolveTypeRefToTypeId(ref) {
-        if ("unspecified" in ref) {
-            console.log("found an unspecified type!")
-            return -1;
-        }
-
-        if ("declRef" in ref) {
-            return typeOfDecl(ref.declRef);
-        }
-
-        if ("type" in ref) {
-            return ref.type;
-        }
-
-        console.assert(false);
-    }
-
     function render() {
         domStatus.classList.add("hidden");
         domFnProto.classList.add("hidden");
@@ -369,7 +376,7 @@
         console.assert("type" in value);
         var typeObj = zigAnalysis.types[value.type];
 
-        domFnProtoCode.innerHTML = typeIndexName(value.type, true, true, fnDecl);
+        domFnProtoCode.innerHTML = typeValueName(value, true, true, fnDecl);
 
         var docsSource = null;
         var srcNode = zigAnalysis.astNodes[fnDecl.src];
@@ -462,9 +469,6 @@
 
 
             var value = typeObj.params[i];
-            var valueType = resolveValue(value);
-            console.assert("type" in valueType);
-            var argTypeIndex = valueType.type;
             var html = '<pre>' + escapeHtml(fieldNode.name) + ": ";
             if (isVarArgs && i === typeObj.params.length - 1) {
                 html += '...';
@@ -482,8 +486,6 @@
             } else if ("type" in value) {
                 var name = zigAnalysis.types[value.type].name;
                 html += '<span class="tok-kw">' + escapeHtml(name) + '</span>';
-            } else if (argTypeIndex != null) {
-                html += typeIndexName(argTypeIndex, true, true);
             } else {
                 html += '<span class="tok-kw">var</span>';
             }
@@ -654,13 +656,16 @@
         }
     }
 
-    function typeIndexName(typeIndex, wantHtml, wantLink, fnDecl, linkFnNameDecl) {
-        return typeValueName({ type: typeIndex }, wantHtml, wantLink, fnDecl, linkFnNameDecl);
-    }
-
     function typeValueName(typeValue, wantHtml, wantLink, fnDecl, linkFnNameDecl) {
         if ("declPath" in typeValue) {
-            console.assert(typeValue.declPath.length == 1);
+            if (typeValue.hasCte) {
+                // TODO: find the cte, print it nicely
+                if (wantLink) {
+                    return '<a href=""># CTE TODO #</a>';
+                } else {
+                    return "# CTE TODO #";
+                }
+            }
             var declIndex = typeValue.declPath[0];
             var name = zigAnalysis.decls[declIndex].name;
             var declPath = getCanonDeclPath(declIndex);
@@ -695,12 +700,17 @@
         }
     }
 
-    function shouldSkipParamName(typeIndex, paramName) {
-        var typeObj = zigAnalysis.types[typeIndex];
-        if (typeObj.kind === typeKinds.Pointer && getPtrSize(typeObj) === pointerSizeEnum.One) {
-            typeIndex = typeObj.child;
+    function shouldSkipParamName(typeRef, paramName) {
+        var resolvedTypeRef = resolveValue(typeRef);
+        if ("type" in resolvedTypeRef) {
+            var typeObj = zigAnalysis.types[resolvedTypeRef.type];
+            if (typeObj.kind === typeKinds.Pointer &&
+                  getPtrSize(typeObj) === pointerSizeEnum.One) {
+                const value = resolveValue(typeObj.child);
+                return typeValueName(value, false, true).toLowerCase() === paramName;
+            }
         }
-        return typeIndexName(typeIndex, false, true).toLowerCase() === paramName;
+        return false;
     }
 
     function getPtrSize(typeObj) {
@@ -716,20 +726,25 @@
                 for (var arg_i = 0; arg_i < callObj.args.length; arg_i += 1) {
                     if (arg_i !== 0) html += ', ';
                     var argObj = callObj.args[arg_i];
-                    html += getValueText(argObj.type, argObj.value, true, true);
+                    html += getValueText(argObj, argObj.value, true, true);
                 }
                 html += ')';
             return html;
         }
 
-    function getValueText(typeIndex, value, wantHtml, wantLink) {
-        var typeObj = zigAnalysis.types[typeIndex];
+    function getValueText(typeRef, value, wantHtml, wantLink) {
+        var resolvedTypeRef = resolveValue(typeRef);
+        if ("comptimeExpr" in resolvedTypeRef) {
+            return "# CTE TODO #";
+        }
+        console.assert("type" in resolvedTypeRef);
+        var typeObj = zigAnalysis.types[typeRef.type];
         switch (typeObj.kind) {
             case typeKinds.Type:
                 return typeIndexName(value, wantHtml, wantLink);
             case typeKinds.Fn:
                 var fnObj = zigAnalysis.fns[value];
-                return typeIndexName(fnObj.type, wantHtml, wantLink);
+                return typeValueName(fnObj, wantHtml, wantLink);
             case typeKinds.Int:
                 if (wantHtml) {
                     return '<span class="tok-number">' + value + '</span>';
@@ -923,11 +938,10 @@
                             if (i != 0) {
                                 payloadHtml += ', ';
                             }
+
                             var value = typeObj.params[i];
                             var paramValue = resolveValue(value);
-                            console.assert("type" in paramValue);
-                            var argTypeIndex = paramValue.type;
-
+                            var isCte = "comptimeExpr" in paramValue;
 
                             if (fields != null) {
                                 var paramNode = zigAnalysis.astNodes[fields[i]];
@@ -956,7 +970,7 @@
                                 var paramName = paramNode.name;
                                 if (paramName != null) {
                                     // skip if it matches the type name
-                                    if (argTypeIndex == null || !shouldSkipParamName(argTypeIndex, paramName)) {
+                                    if (!shouldSkipParamName(paramValue, paramName)) {
                                         payloadHtml += paramName + ': ';
                                     }
                                 }
@@ -975,10 +989,10 @@
                                 payloadHtml += '<span class="tok-kw" style="color:lightblue;">' + escapeHtml(decl.name) + '</span>';
                                 payloadHtml += '</a>';
                             } else if ("type" in value) {
-                                var name = zigAnalysis.types[value.type].name;
+                                var name = typeValueName(value, false);
                                 payloadHtml += '<span class="tok-kw">' + escapeHtml(name) + '</span>';
-                            } else if (argTypeIndex != null) {
-                                payloadHtml += typeIndexName(argTypeIndex, wantHtml, wantSubLink);
+                            } else if ("comptimeExpr" in value) {
+                                payloadHtml += '<span class="tok-kw"> # CTE TODO #</span>';
                             } else if (wantHtml) {
                                 payloadHtml += '<span class="tok-kw">var</span>';
                             } else {
@@ -1152,7 +1166,7 @@
 
     function renderValue(decl) {
 
-        var declTypeId = typeOfDecl(decl);
+        var declTypeRef = typeOfDecl(decl);
         var declValueText = "";
         switch(Object.keys(decl.value)[0]) {
             case "int":
@@ -1170,7 +1184,7 @@
         }
 
         domFnProtoCode.innerHTML = '<span class="tok-kw">const</span> ' +
-            escapeHtml(decl.name) + ': ' + typeIndexName(declTypeId, true, true) +
+            escapeHtml(decl.name) + ': ' + typeValueName(declTypeRef, true, true) +
             " = " + declValueText;
 
         var docs = zigAnalysis.astNodes[decl.src].docs;
@@ -1183,9 +1197,9 @@
     }
 
     function renderVar(decl) {
-        var declTypeId = typeOfDecl(decl);
+        var declTypeRef = typeOfDecl(decl);
         domFnProtoCode.innerHTML = '<span class="tok-kw">var</span> ' +
-            escapeHtml(decl.name) + ': ' + typeIndexName(declTypeId, true, true);
+            escapeHtml(decl.name) + ': ' + typeValueName(declTypeRef, true, true);
 
         var docs = zigAnalysis.astNodes[decl.src].docs;
         if (docs != null) {
@@ -1221,8 +1235,9 @@
                     var value = zigAnalysis.types[declValue.type];
                     var kind = value.kind;
                     if (kind === typeKinds.Fn) {
-                        //if (allCompTimeFnCallsHaveTypeResult(decl.type, declTypeId)) {
-                        if (resolveTypeRefToTypeId(value.ret) == typeTypeId) {
+                        // TODO: handle CTE return types when we know their type.
+                        const resVal = resolveValue(value.ret);
+                        if ("type" in resVal && resVal.type == typeTypeId) {
                             typesList.push(decl);
                         } else {
                             fnsList.push(decl);
@@ -1300,7 +1315,7 @@
                 var declType = resolveValue(decl.value);
                 console.assert("type" in declType);
 
-                tdFnCode.innerHTML = typeIndexName(declType.type, true, true, decl, navLinkDecl(decl.name));
+                tdFnCode.innerHTML = typeValueName(declType, true, true, decl, navLinkDecl(decl.name));
 
                 var docs = zigAnalysis.astNodes[decl.src].docs;
                 if (docs != null) {
@@ -1327,35 +1342,37 @@
                 } else {
                     var field = container.fields[i];
                     html += ": ";
-                    if (typeof(field) === 'object') {
-                        if (field.failure === true) {
-                            html += '<span class="tok-kw" style="color:red;">#FAILURE#</span>';
-                        } else if ("declPath" in field) {
-                            for (var j = field.declPath.length - 1; j >= 0; j--) {
-                                var decl = zigAnalysis.decls[field.declPath[j]];
-
-                                html += '<a href="'+navLinkDecl(decl.name)+'">';
-                                html += '<span class="tok-kw" style="color:lightblue;">' +
-                                    escapeHtml(decl.name) + '</span>';
-                                html += '</a>';
-                                if (j != 0) html += ".";
+                    if (field.failure === true) {
+                        html += '<span class="tok-kw" style="color:red;">#FAILURE#</span>';
+                    } else if ("declPath" in field) {
+                        for (var j = field.declPath.length - 1; j >= 0; j--) {
+                            var decl = zigAnalysis.decls[field.declPath[j]];
+
+                            // TODO: handle nested decl paths properly!
+                            if (field.hasCte) {
+                                html += "<a href=\"\"># CTE TODO #</a>";
+                                break;
                             }
-                            // at the end of the for loop this is the value of `decl`
-                            //decl = zigAnalysis.decls[field.declPath[0]];
-
-                            var val = resolveValue(decl.value);
-                            console.assert("type" in val);
-                            var valType = zigAnalysis.types[val.type];
-                            var valTypeName = typeShorthandName(valType);
-                            html += ' ('+ valTypeName +')';
-                        } else if ("type" in field) {
-                            var name = zigAnalysis.types[field.type].name;
-                            html += '<span class="tok-kw">' + escapeHtml(name) + '</span>';
-                        } else {
-                            html += '<span class="tok-kw">var</span>';
+
+                            html += '<a href="'+navLinkDecl(decl.name)+'">';
+                            html += '<span class="tok-kw" style="color:lightblue;">' +
+                                escapeHtml(decl.name) + '</span>';
+                            html += '</a>';
+                            if (j != 0) html += ".";
                         }
+                        // at the end of the for loop this is the value of `decl`
+                        //decl = zigAnalysis.decls[field.declPath[0]];
+
+                        var val = resolveValue(decl.value);
+                        console.assert("type" in val);
+                        var valType = zigAnalysis.types[val.type];
+                        var valTypeName = typeShorthandName(valType);
+                        html += ' ('+ valTypeName +')';
+                    } else if ("type" in field) {
+                        var name = zigAnalysis.types[field.type].name;
+                        html += '<span class="tok-kw">' + escapeHtml(name) + '</span>';
                     } else {
-                        html += typeIndexName(field, true, true);
+                        html += '<span class="tok-kw">var</span>';
                     }
                 }
 
@@ -1385,7 +1402,7 @@
                 tdNameA.setAttribute('href', navLinkDecl(decl.name));
                 tdNameA.textContent = decl.name;
 
-                tdType.innerHTML = typeIndexName(typeOfDecl(decl), true, true);
+                tdType.innerHTML = typeValueName(typeOfDecl(decl), true, true);
 
                 var docs = zigAnalysis.astNodes[decl.src].docs;
                 if (docs != null) {
@@ -1412,7 +1429,7 @@
                 tdNameA.setAttribute('href', navLinkDecl(decl.name));
                 tdNameA.textContent = decl.name;
 
-                tdType.innerHTML = typeIndexName(typeOfDecl(decl), true, true);
+                tdType.innerHTML = typeValueName(typeOfDecl(decl), true, true);
 
                 var docs = zigAnalysis.astNodes[decl.src].docs;
                 if (docs != null) {
src/Autodoc.zig
@@ -30,7 +30,7 @@ decl_paths_pending_on_types: std.AutoHashMapUnmanaged(
 
 const DeclPathResumeInfo = struct {
     file: *File,
-    path: []usize,
+    decl_path: DocData.DeclPath,
 };
 
 var arena_allocator: std.heap.ArenaAllocator = undefined;
@@ -347,7 +347,7 @@ const DocData = struct {
         Int: struct { name: []const u8 },
         Float: struct { name: []const u8 },
         Pointer: struct {
-            name: []const u8,
+            size: std.builtin.TypeInfo.Pointer.Size,
             child: TypeRef,
         },
         Array: struct {
@@ -427,6 +427,20 @@ const DocData = struct {
                 .Int => |v| try printTypeBody(v, options, w),
                 .Float => |v| try printTypeBody(v, options, w),
                 .Type => |v| try printTypeBody(v, options, w),
+                .Pointer => |v| {
+                    if (options.whitespace) |ws| try ws.outputIndent(w);
+                    try w.print(
+                        \\"size": {},
+                        \\
+                    , .{@enumToInt(v.size)});
+                    if (options.whitespace) |ws| try ws.outputIndent(w);
+                    try w.print(
+                        \\"child":
+                    , .{});
+
+                    if (options.whitespace) |*ws| ws.indent_level += 1;
+                    try v.child.jsonStringify(options, w);
+                },
                 else => {
                     std.debug.print(
                         "TODO: add {s} to `DocData.Type.jsonStringify`\n",
@@ -458,9 +472,14 @@ const DocData = struct {
         }
     };
 
+    const DeclPath = struct {
+        path: []usize, // indexes in `decls`
+        hasCte: bool = false, // a prefix of this path could not be resolved
+    };
+
     const TypeRef = union(enum) {
         unspecified,
-        declPath: []usize, // indexes in `decls`
+        declPath: DeclPath,
         type: usize, // index in `types`
         comptimeExpr: usize, // index in `comptimeExprs`
 
@@ -490,9 +509,9 @@ const DocData = struct {
                     , .{ @tagName(self), v });
                 },
                 .declPath => |v| {
-                    try w.print("{{ \"declPath\": [", .{});
-                    for (v) |d, i| {
-                        const comma = if (i == v.len - 1) "]}" else ",";
+                    try w.print("{{ \"hasCte\": {}, \"declPath\": [", .{v.hasCte});
+                    for (v.path) |d, i| {
+                        const comma = if (i == v.path.len - 1) "]}" else ",";
                         try w.print("{d}{s}", .{ d, comma });
                     }
                 },
@@ -509,7 +528,7 @@ const DocData = struct {
         @"struct": Struct,
         bool: bool,
         type: usize, // index in `types`
-        declPath: []usize, // indices in `decl`
+        declPath: DeclPath,
         int: struct {
             typeRef: TypeRef,
             value: usize, // direct value
@@ -584,9 +603,9 @@ const DocData = struct {
                     w,
                 ),
                 .declPath => |v| {
-                    try w.print("{{ \"declPath\": [", .{});
-                    for (v) |d, i| {
-                        const comma = if (i == v.len - 1) "]}" else ",";
+                    try w.print("{{ \"hasCte\": {}, \"declPath\": [", .{v.hasCte});
+                    for (v.path) |d, i| {
+                        const comma = if (i == v.path.len - 1) "]}" else ",";
                         try w.print("{d}{s}", .{ d, comma });
                     }
                 },
@@ -676,6 +695,19 @@ fn walkInstruction(
                 },
             };
         },
+        .ptr_type_simple => {
+            const ptr = data[inst_index].ptr_type_simple;
+            const type_slot_index = self.types.items.len;
+            const elem_type_ref = try self.walkRef(file, parent_scope, ptr.elem_type);
+            try self.types.append(self.arena, .{
+                .Pointer = .{
+                    .size = ptr.size,
+                    .child = walkResultToTypeRef(elem_type_ref),
+                },
+            });
+
+            return DocData.WalkResult{ .type = type_slot_index };
+        },
         .array_init => {
             const pl_node = data[inst_index].pl_node;
             const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index);
@@ -770,7 +802,7 @@ fn walkInstruction(
             const decls_slot_index = parent_scope.resolveDeclName(str_tok.start);
             var path = try self.arena.alloc(usize, 1);
             path[0] = decls_slot_index;
-            return DocData.WalkResult{ .declPath = path };
+            return DocData.WalkResult{ .declPath = .{ .path = path } };
         },
         .field_val, .field_call_bind, .field_ptr => {
             const pl_node = data[inst_index].pl_node;
@@ -844,8 +876,9 @@ fn walkInstruction(
             // the analyzed data corresponding to the top-most decl of this path.
             // We are now going to reverse loop over `path` to resolve each name
             // to its corresponding index in `decls`.
-            try self.tryResolveDeclPath(file, path.items);
-            return DocData.WalkResult{ .declPath = path.items };
+            var decl_path: DocData.DeclPath = .{ .path = path.items };
+            try self.tryResolveDeclPath(file, &decl_path);
+            return DocData.WalkResult{ .declPath = decl_path };
         },
         .int_type => {
             const int_type = data[inst_index].int_type;
@@ -893,7 +926,7 @@ fn walkInstruction(
 
             return DocData.WalkResult{ .call = call_slot_index };
         },
-        .func => {
+        .func, .func_inferred => {
             const fn_info = file.zir.getFnInfo(@intCast(u32, inst_index));
 
             try self.ast_nodes.ensureUnusedCapacity(self.arena, fn_info.total_params_len);
@@ -960,18 +993,18 @@ fn walkInstruction(
             return DocData.WalkResult{ .type = self.types.items.len - 1 };
         },
         .extended => {
-            // TODO: this assumes that we always return a type when analyzing
-            //       an extended instruction. Also we willingfully not reserve
-            //       a slot for functions (handled right above) despite them
-            //       being stored in `types`. The reason why we reserve a slot
-            //       in here, is for decl paths and their resolution system.
+            // NOTE: this code + the subsequent defer block are working towards
+            // solving pending decl paths that depend on a type to be analyzed.
+            // When we don't find a type, the defer will run anyway but shouldn't
+            // ever be able to find a match inside `decl_paths_pending_on_types`
+            // TODO: extract this logic into a function and only call it when appropriate.
             const type_slot_index = self.types.items.len;
             try self.types.append(self.arena, .{ .Unanalyzed = {} });
 
             defer {
                 if (self.decl_paths_pending_on_types.get(type_slot_index)) |paths| {
-                    for (paths.items) |resume_info| {
-                        self.tryResolveDeclPath(resume_info.file, resume_info.path) catch {
+                    for (paths.items) |*resume_info| {
+                        self.tryResolveDeclPath(resume_info.file, &resume_info.decl_path) catch {
                             @panic("Out of memory");
                         };
                     }
@@ -1537,8 +1570,8 @@ fn walkDecls(
 
         // Unblock any pending decl path that was waiting for this decl.
         if (self.decl_paths_pending_on_decls.get(decls_slot_index)) |paths| {
-            for (paths.items) |resume_info| {
-                try self.tryResolveDeclPath(resume_info.file, resume_info.path);
+            for (paths.items) |*resume_info| {
+                try self.tryResolveDeclPath(resume_info.file, &resume_info.decl_path);
             }
 
             _ = self.decl_paths_pending_on_decls.remove(decls_slot_index);
@@ -1560,10 +1593,12 @@ fn tryResolveDeclPath(
     self: *Autodoc,
     /// File from which the decl path originates.
     file: *File,
-    path: []usize,
+    decl_path: *DocData.DeclPath,
 ) error{OutOfMemory}!void {
+    const path: []usize = decl_path.path;
+
     var i: usize = path.len;
-    while (i > 1) {
+    outer: while (i > 1) {
         i -= 1;
         const decl_index = path[i];
         const string_index = path[i - 1];
@@ -1580,7 +1615,7 @@ fn tryResolveDeclPath(
             if (!res.found_existing) res.value_ptr.* = .{};
             try res.value_ptr.*.append(self.arena, .{
                 .file = file,
-                .path = path[0 .. i + 1],
+                .decl_path = .{ .path = path[0 .. i + 1] },
             });
 
             return;
@@ -1590,15 +1625,25 @@ fn tryResolveDeclPath(
         switch (parent.value) {
             else => {
                 std.debug.panic(
-                    "TODO: handle `{s}`in walkInstruction.field_val\n \"{s}\":{}",
+                    "TODO: handle `{s}`in tryResolveDecl.field_val\n \"{s}\":{}",
                     .{ @tagName(parent.value), parent.name, parent.value },
                 );
             },
+            .comptimeExpr => {
+                // Since we hit a cte, we leave the remaining strings unresolved
+                // and completely give up on resolving this decl path.
+                decl_path.hasCte = true;
+                break :outer;
+            },
             .declPath => |dp| {
-                if (self.pending_decl_paths.getPtr(&dp[0])) |waiter_list| {
+                if (dp.hasCte) {
+                    decl_path.hasCte = true;
+                    break :outer;
+                }
+                if (self.pending_decl_paths.getPtr(&dp.path[0])) |waiter_list| {
                     try waiter_list.append(self.arena, .{
                         .file = file,
-                        .path = path[0 .. i + 1],
+                        .decl_path = .{ .path = path[0 .. i + 1] },
                     });
 
                     // This decl path is pending completion
@@ -1610,7 +1655,7 @@ fn tryResolveDeclPath(
                     return;
                 }
 
-                const final_decl_index = dp[0];
+                const final_decl_index = dp.path[0];
                 // For the purpose of being able to call tryResolveDeclPath again,
                 // we momentarily replace the decl index present in `path[i]`
                 // with the final decl in `dp`.
@@ -1619,7 +1664,7 @@ fn tryResolveDeclPath(
                 // will not get fully resolved (also in the case that final_decl is
                 // not resolved yet).
                 path[i] = final_decl_index;
-                try self.tryResolveDeclPath(file, path);
+                try self.tryResolveDeclPath(file, decl_path);
                 path[i] = decl_index;
             },
             .type => |t_index| switch (self.types.items[t_index]) {
@@ -1643,7 +1688,7 @@ fn tryResolveDeclPath(
                     if (!res.found_existing) res.value_ptr.* = .{};
                     try res.value_ptr.*.append(self.arena, .{
                         .file = file,
-                        .path = path[0 .. i + 1],
+                        .decl_path = .{ .path = path[0 .. i + 1] },
                     });
 
                     return;
@@ -1677,8 +1722,8 @@ fn tryResolveDeclPath(
         // attempting to resolve any other decl.
         _ = self.pending_decl_paths.remove(&path[0]);
 
-        for (waiter_list.items) |resume_info| {
-            try self.tryResolveDeclPath(resume_info.file, resume_info.path);
+        for (waiter_list.items) |*resume_info| {
+            try self.tryResolveDeclPath(resume_info.file, &resume_info.decl_path);
         }
         // TODO: this is where we should free waiter_list, but its in the arena
         //       that said, we might want to store it elsewhere and reclaim memory asap