Commit c5f1925bc8

Andrew Kelley <superjoe30@gmail.com>
2018-08-03 23:59:11
when decls don't change, don't regenerate them
1 parent 5dfcd09
Changed files (4)
src-self-hosted/compilation.zig
@@ -876,13 +876,25 @@ pub const Compilation = struct {
 
                     if (existing_decls.remove(name)) |entry| {
                         // compare new code to existing
-                        const existing_decl = entry.value;
-                        // Just compare the old bytes to the new bytes of the top level decl.
-                        // Even if the AST is technically the same, we want error messages to display
-                        // from the most recent source.
-                        @panic("TODO handle decl comparison");
-                        // Add the new thing before dereferencing the old thing. This way we don't end
-                        // up pointlessly re-creating things we end up using in the new thing.
+                        if (entry.value.cast(Decl.Fn)) |existing_fn_decl| {
+                            // Just compare the old bytes to the new bytes of the top level decl.
+                            // Even if the AST is technically the same, we want error messages to display
+                            // from the most recent source.
+                            const old_decl_src = existing_fn_decl.base.tree_scope.tree.getNodeSource(
+                                &existing_fn_decl.fn_proto.base,
+                            );
+                            const new_decl_src = tree_scope.tree.getNodeSource(&fn_proto.base);
+                            if (mem.eql(u8, old_decl_src, new_decl_src)) {
+                                // it's the same, we can skip this decl
+                                continue;
+                            } else {
+                                @panic("TODO decl changed implementation");
+                                // Add the new thing before dereferencing the old thing. This way we don't end
+                                // up pointlessly re-creating things we end up using in the new thing.
+                            }
+                        } else {
+                            @panic("TODO decl changed kind");
+                        }
                     } else {
                         // add new decl
                         const fn_decl = try self.gpa().create(Decl.Fn{
src-self-hosted/decl.zig
@@ -22,6 +22,11 @@ pub const Decl = struct {
 
     pub const Table = std.HashMap([]const u8, *Decl, mem.hash_slice_u8, mem.eql_slice_u8);
 
+    pub fn cast(base: *Decl, comptime T: type) ?*T {
+        if (base.id != @field(Id, @typeName(T))) return null;
+        return @fieldParentPtr(T, "base", base);
+    }
+
     pub fn isExported(base: *const Decl, tree: *ast.Tree) bool {
         switch (base.id) {
             Id.Fn => {
@@ -98,4 +103,3 @@ pub const Decl = struct {
         base: Decl,
     };
 };
-
std/zig/ast.zig
@@ -32,6 +32,12 @@ pub const Tree = struct {
         return self.source[token.start..token.end];
     }
 
+    pub fn getNodeSource(self: *const Tree, node: *const Node) []const u8 {
+        const first_token = self.tokens.at(node.firstToken());
+        const last_token = self.tokens.at(node.lastToken());
+        return self.source[first_token.start..last_token.end];
+    }
+
     pub const Location = struct {
         line: usize,
         column: usize,
@@ -338,7 +344,7 @@ pub const Node = struct {
         unreachable;
     }
 
-    pub fn firstToken(base: *Node) TokenIndex {
+    pub fn firstToken(base: *const Node) TokenIndex {
         comptime var i = 0;
         inline while (i < @memberCount(Id)) : (i += 1) {
             if (base.id == @field(Id, @memberName(Id, i))) {
@@ -349,7 +355,7 @@ pub const Node = struct {
         unreachable;
     }
 
-    pub fn lastToken(base: *Node) TokenIndex {
+    pub fn lastToken(base: *const Node) TokenIndex {
         comptime var i = 0;
         inline while (i < @memberCount(Id)) : (i += 1) {
             if (base.id == @field(Id, @memberName(Id, i))) {
@@ -473,11 +479,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *Root) TokenIndex {
+        pub fn firstToken(self: *const Root) TokenIndex {
             return if (self.decls.len == 0) self.eof_token else (self.decls.at(0).*).firstToken();
         }
 
-        pub fn lastToken(self: *Root) TokenIndex {
+        pub fn lastToken(self: *const Root) TokenIndex {
             return if (self.decls.len == 0) self.eof_token else (self.decls.at(self.decls.len - 1).*).lastToken();
         }
     };
@@ -518,7 +524,7 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *VarDecl) TokenIndex {
+        pub fn firstToken(self: *const VarDecl) TokenIndex {
             if (self.visib_token) |visib_token| return visib_token;
             if (self.comptime_token) |comptime_token| return comptime_token;
             if (self.extern_export_token) |extern_export_token| return extern_export_token;
@@ -526,7 +532,7 @@ pub const Node = struct {
             return self.mut_token;
         }
 
-        pub fn lastToken(self: *VarDecl) TokenIndex {
+        pub fn lastToken(self: *const VarDecl) TokenIndex {
             return self.semicolon_token;
         }
     };
@@ -548,12 +554,12 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *Use) TokenIndex {
+        pub fn firstToken(self: *const Use) TokenIndex {
             if (self.visib_token) |visib_token| return visib_token;
             return self.use_token;
         }
 
-        pub fn lastToken(self: *Use) TokenIndex {
+        pub fn lastToken(self: *const Use) TokenIndex {
             return self.semicolon_token;
         }
     };
@@ -575,11 +581,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *ErrorSetDecl) TokenIndex {
+        pub fn firstToken(self: *const ErrorSetDecl) TokenIndex {
             return self.error_token;
         }
 
-        pub fn lastToken(self: *ErrorSetDecl) TokenIndex {
+        pub fn lastToken(self: *const ErrorSetDecl) TokenIndex {
             return self.rbrace_token;
         }
     };
@@ -618,14 +624,14 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *ContainerDecl) TokenIndex {
+        pub fn firstToken(self: *const ContainerDecl) TokenIndex {
             if (self.layout_token) |layout_token| {
                 return layout_token;
             }
             return self.kind_token;
         }
 
-        pub fn lastToken(self: *ContainerDecl) TokenIndex {
+        pub fn lastToken(self: *const ContainerDecl) TokenIndex {
             return self.rbrace_token;
         }
     };
@@ -646,12 +652,12 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *StructField) TokenIndex {
+        pub fn firstToken(self: *const StructField) TokenIndex {
             if (self.visib_token) |visib_token| return visib_token;
             return self.name_token;
         }
 
-        pub fn lastToken(self: *StructField) TokenIndex {
+        pub fn lastToken(self: *const StructField) TokenIndex {
             return self.type_expr.lastToken();
         }
     };
@@ -679,11 +685,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *UnionTag) TokenIndex {
+        pub fn firstToken(self: *const UnionTag) TokenIndex {
             return self.name_token;
         }
 
-        pub fn lastToken(self: *UnionTag) TokenIndex {
+        pub fn lastToken(self: *const UnionTag) TokenIndex {
             if (self.value_expr) |value_expr| {
                 return value_expr.lastToken();
             }
@@ -712,11 +718,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *EnumTag) TokenIndex {
+        pub fn firstToken(self: *const EnumTag) TokenIndex {
             return self.name_token;
         }
 
-        pub fn lastToken(self: *EnumTag) TokenIndex {
+        pub fn lastToken(self: *const EnumTag) TokenIndex {
             if (self.value) |value| {
                 return value.lastToken();
             }
@@ -741,11 +747,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *ErrorTag) TokenIndex {
+        pub fn firstToken(self: *const ErrorTag) TokenIndex {
             return self.name_token;
         }
 
-        pub fn lastToken(self: *ErrorTag) TokenIndex {
+        pub fn lastToken(self: *const ErrorTag) TokenIndex {
             return self.name_token;
         }
     };
@@ -758,11 +764,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *Identifier) TokenIndex {
+        pub fn firstToken(self: *const Identifier) TokenIndex {
             return self.token;
         }
 
-        pub fn lastToken(self: *Identifier) TokenIndex {
+        pub fn lastToken(self: *const Identifier) TokenIndex {
             return self.token;
         }
     };
@@ -784,11 +790,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *AsyncAttribute) TokenIndex {
+        pub fn firstToken(self: *const AsyncAttribute) TokenIndex {
             return self.async_token;
         }
 
-        pub fn lastToken(self: *AsyncAttribute) TokenIndex {
+        pub fn lastToken(self: *const AsyncAttribute) TokenIndex {
             if (self.rangle_bracket) |rangle_bracket| {
                 return rangle_bracket;
             }
@@ -856,7 +862,7 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *FnProto) TokenIndex {
+        pub fn firstToken(self: *const FnProto) TokenIndex {
             if (self.visib_token) |visib_token| return visib_token;
             if (self.async_attr) |async_attr| return async_attr.firstToken();
             if (self.extern_export_inline_token) |extern_export_inline_token| return extern_export_inline_token;
@@ -865,7 +871,7 @@ pub const Node = struct {
             return self.fn_token;
         }
 
-        pub fn lastToken(self: *FnProto) TokenIndex {
+        pub fn lastToken(self: *const FnProto) TokenIndex {
             if (self.body_node) |body_node| return body_node.lastToken();
             switch (self.return_type) {
                 // TODO allow this and next prong to share bodies since the types are the same
@@ -896,11 +902,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *PromiseType) TokenIndex {
+        pub fn firstToken(self: *const PromiseType) TokenIndex {
             return self.promise_token;
         }
 
-        pub fn lastToken(self: *PromiseType) TokenIndex {
+        pub fn lastToken(self: *const PromiseType) TokenIndex {
             if (self.result) |result| return result.return_type.lastToken();
             return self.promise_token;
         }
@@ -923,14 +929,14 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *ParamDecl) TokenIndex {
+        pub fn firstToken(self: *const ParamDecl) TokenIndex {
             if (self.comptime_token) |comptime_token| return comptime_token;
             if (self.noalias_token) |noalias_token| return noalias_token;
             if (self.name_token) |name_token| return name_token;
             return self.type_node.firstToken();
         }
 
-        pub fn lastToken(self: *ParamDecl) TokenIndex {
+        pub fn lastToken(self: *const ParamDecl) TokenIndex {
             if (self.var_args_token) |var_args_token| return var_args_token;
             return self.type_node.lastToken();
         }
@@ -954,7 +960,7 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *Block) TokenIndex {
+        pub fn firstToken(self: *const Block) TokenIndex {
             if (self.label) |label| {
                 return label;
             }
@@ -962,7 +968,7 @@ pub const Node = struct {
             return self.lbrace;
         }
 
-        pub fn lastToken(self: *Block) TokenIndex {
+        pub fn lastToken(self: *const Block) TokenIndex {
             return self.rbrace;
         }
     };
@@ -981,11 +987,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *Defer) TokenIndex {
+        pub fn firstToken(self: *const Defer) TokenIndex {
             return self.defer_token;
         }
 
-        pub fn lastToken(self: *Defer) TokenIndex {
+        pub fn lastToken(self: *const Defer) TokenIndex {
             return self.expr.lastToken();
         }
     };
@@ -1005,11 +1011,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *Comptime) TokenIndex {
+        pub fn firstToken(self: *const Comptime) TokenIndex {
             return self.comptime_token;
         }
 
-        pub fn lastToken(self: *Comptime) TokenIndex {
+        pub fn lastToken(self: *const Comptime) TokenIndex {
             return self.expr.lastToken();
         }
     };
@@ -1029,11 +1035,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *Payload) TokenIndex {
+        pub fn firstToken(self: *const Payload) TokenIndex {
             return self.lpipe;
         }
 
-        pub fn lastToken(self: *Payload) TokenIndex {
+        pub fn lastToken(self: *const Payload) TokenIndex {
             return self.rpipe;
         }
     };
@@ -1054,11 +1060,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *PointerPayload) TokenIndex {
+        pub fn firstToken(self: *const PointerPayload) TokenIndex {
             return self.lpipe;
         }
 
-        pub fn lastToken(self: *PointerPayload) TokenIndex {
+        pub fn lastToken(self: *const PointerPayload) TokenIndex {
             return self.rpipe;
         }
     };
@@ -1085,11 +1091,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *PointerIndexPayload) TokenIndex {
+        pub fn firstToken(self: *const PointerIndexPayload) TokenIndex {
             return self.lpipe;
         }
 
-        pub fn lastToken(self: *PointerIndexPayload) TokenIndex {
+        pub fn lastToken(self: *const PointerIndexPayload) TokenIndex {
             return self.rpipe;
         }
     };
@@ -1114,11 +1120,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *Else) TokenIndex {
+        pub fn firstToken(self: *const Else) TokenIndex {
             return self.else_token;
         }
 
-        pub fn lastToken(self: *Else) TokenIndex {
+        pub fn lastToken(self: *const Else) TokenIndex {
             return self.body.lastToken();
         }
     };
@@ -1146,11 +1152,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *Switch) TokenIndex {
+        pub fn firstToken(self: *const Switch) TokenIndex {
             return self.switch_token;
         }
 
-        pub fn lastToken(self: *Switch) TokenIndex {
+        pub fn lastToken(self: *const Switch) TokenIndex {
             return self.rbrace;
         }
     };
@@ -1181,11 +1187,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *SwitchCase) TokenIndex {
+        pub fn firstToken(self: *const SwitchCase) TokenIndex {
             return (self.items.at(0).*).firstToken();
         }
 
-        pub fn lastToken(self: *SwitchCase) TokenIndex {
+        pub fn lastToken(self: *const SwitchCase) TokenIndex {
             return self.expr.lastToken();
         }
     };
@@ -1198,11 +1204,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *SwitchElse) TokenIndex {
+        pub fn firstToken(self: *const SwitchElse) TokenIndex {
             return self.token;
         }
 
-        pub fn lastToken(self: *SwitchElse) TokenIndex {
+        pub fn lastToken(self: *const SwitchElse) TokenIndex {
             return self.token;
         }
     };
@@ -1245,7 +1251,7 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *While) TokenIndex {
+        pub fn firstToken(self: *const While) TokenIndex {
             if (self.label) |label| {
                 return label;
             }
@@ -1257,7 +1263,7 @@ pub const Node = struct {
             return self.while_token;
         }
 
-        pub fn lastToken(self: *While) TokenIndex {
+        pub fn lastToken(self: *const While) TokenIndex {
             if (self.@"else") |@"else"| {
                 return @"else".body.lastToken();
             }
@@ -1298,7 +1304,7 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *For) TokenIndex {
+        pub fn firstToken(self: *const For) TokenIndex {
             if (self.label) |label| {
                 return label;
             }
@@ -1310,7 +1316,7 @@ pub const Node = struct {
             return self.for_token;
         }
 
-        pub fn lastToken(self: *For) TokenIndex {
+        pub fn lastToken(self: *const For) TokenIndex {
             if (self.@"else") |@"else"| {
                 return @"else".body.lastToken();
             }
@@ -1349,11 +1355,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *If) TokenIndex {
+        pub fn firstToken(self: *const If) TokenIndex {
             return self.if_token;
         }
 
-        pub fn lastToken(self: *If) TokenIndex {
+        pub fn lastToken(self: *const If) TokenIndex {
             if (self.@"else") |@"else"| {
                 return @"else".body.lastToken();
             }
@@ -1480,11 +1486,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *InfixOp) TokenIndex {
+        pub fn firstToken(self: *const InfixOp) TokenIndex {
             return self.lhs.firstToken();
         }
 
-        pub fn lastToken(self: *InfixOp) TokenIndex {
+        pub fn lastToken(self: *const InfixOp) TokenIndex {
             return self.rhs.lastToken();
         }
     };
@@ -1570,11 +1576,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *PrefixOp) TokenIndex {
+        pub fn firstToken(self: *const PrefixOp) TokenIndex {
             return self.op_token;
         }
 
-        pub fn lastToken(self: *PrefixOp) TokenIndex {
+        pub fn lastToken(self: *const PrefixOp) TokenIndex {
             return self.rhs.lastToken();
         }
     };
@@ -1594,11 +1600,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *FieldInitializer) TokenIndex {
+        pub fn firstToken(self: *const FieldInitializer) TokenIndex {
             return self.period_token;
         }
 
-        pub fn lastToken(self: *FieldInitializer) TokenIndex {
+        pub fn lastToken(self: *const FieldInitializer) TokenIndex {
             return self.expr.lastToken();
         }
     };
@@ -1673,7 +1679,7 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *SuffixOp) TokenIndex {
+        pub fn firstToken(self: *const SuffixOp) TokenIndex {
             switch (self.op) {
                 @TagType(Op).Call => |*call_info| if (call_info.async_attr) |async_attr| return async_attr.firstToken(),
                 else => {},
@@ -1681,7 +1687,7 @@ pub const Node = struct {
             return self.lhs.firstToken();
         }
 
-        pub fn lastToken(self: *SuffixOp) TokenIndex {
+        pub fn lastToken(self: *const SuffixOp) TokenIndex {
             return self.rtoken;
         }
     };
@@ -1701,11 +1707,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *GroupedExpression) TokenIndex {
+        pub fn firstToken(self: *const GroupedExpression) TokenIndex {
             return self.lparen;
         }
 
-        pub fn lastToken(self: *GroupedExpression) TokenIndex {
+        pub fn lastToken(self: *const GroupedExpression) TokenIndex {
             return self.rparen;
         }
     };
@@ -1749,11 +1755,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *ControlFlowExpression) TokenIndex {
+        pub fn firstToken(self: *const ControlFlowExpression) TokenIndex {
             return self.ltoken;
         }
 
-        pub fn lastToken(self: *ControlFlowExpression) TokenIndex {
+        pub fn lastToken(self: *const ControlFlowExpression) TokenIndex {
             if (self.rhs) |rhs| {
                 return rhs.lastToken();
             }
@@ -1792,11 +1798,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *Suspend) TokenIndex {
+        pub fn firstToken(self: *const Suspend) TokenIndex {
             return self.suspend_token;
         }
 
-        pub fn lastToken(self: *Suspend) TokenIndex {
+        pub fn lastToken(self: *const Suspend) TokenIndex {
             if (self.body) |body| {
                 return body.lastToken();
             }
@@ -1813,11 +1819,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *IntegerLiteral) TokenIndex {
+        pub fn firstToken(self: *const IntegerLiteral) TokenIndex {
             return self.token;
         }
 
-        pub fn lastToken(self: *IntegerLiteral) TokenIndex {
+        pub fn lastToken(self: *const IntegerLiteral) TokenIndex {
             return self.token;
         }
     };
@@ -1830,11 +1836,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *FloatLiteral) TokenIndex {
+        pub fn firstToken(self: *const FloatLiteral) TokenIndex {
             return self.token;
         }
 
-        pub fn lastToken(self: *FloatLiteral) TokenIndex {
+        pub fn lastToken(self: *const FloatLiteral) TokenIndex {
             return self.token;
         }
     };
@@ -1856,11 +1862,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *BuiltinCall) TokenIndex {
+        pub fn firstToken(self: *const BuiltinCall) TokenIndex {
             return self.builtin_token;
         }
 
-        pub fn lastToken(self: *BuiltinCall) TokenIndex {
+        pub fn lastToken(self: *const BuiltinCall) TokenIndex {
             return self.rparen_token;
         }
     };
@@ -1873,11 +1879,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *StringLiteral) TokenIndex {
+        pub fn firstToken(self: *const StringLiteral) TokenIndex {
             return self.token;
         }
 
-        pub fn lastToken(self: *StringLiteral) TokenIndex {
+        pub fn lastToken(self: *const StringLiteral) TokenIndex {
             return self.token;
         }
     };
@@ -1892,11 +1898,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *MultilineStringLiteral) TokenIndex {
+        pub fn firstToken(self: *const MultilineStringLiteral) TokenIndex {
             return self.lines.at(0).*;
         }
 
-        pub fn lastToken(self: *MultilineStringLiteral) TokenIndex {
+        pub fn lastToken(self: *const MultilineStringLiteral) TokenIndex {
             return self.lines.at(self.lines.len - 1).*;
         }
     };
@@ -1909,11 +1915,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *CharLiteral) TokenIndex {
+        pub fn firstToken(self: *const CharLiteral) TokenIndex {
             return self.token;
         }
 
-        pub fn lastToken(self: *CharLiteral) TokenIndex {
+        pub fn lastToken(self: *const CharLiteral) TokenIndex {
             return self.token;
         }
     };
@@ -1926,11 +1932,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *BoolLiteral) TokenIndex {
+        pub fn firstToken(self: *const BoolLiteral) TokenIndex {
             return self.token;
         }
 
-        pub fn lastToken(self: *BoolLiteral) TokenIndex {
+        pub fn lastToken(self: *const BoolLiteral) TokenIndex {
             return self.token;
         }
     };
@@ -1943,11 +1949,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *NullLiteral) TokenIndex {
+        pub fn firstToken(self: *const NullLiteral) TokenIndex {
             return self.token;
         }
 
-        pub fn lastToken(self: *NullLiteral) TokenIndex {
+        pub fn lastToken(self: *const NullLiteral) TokenIndex {
             return self.token;
         }
     };
@@ -1960,11 +1966,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *UndefinedLiteral) TokenIndex {
+        pub fn firstToken(self: *const UndefinedLiteral) TokenIndex {
             return self.token;
         }
 
-        pub fn lastToken(self: *UndefinedLiteral) TokenIndex {
+        pub fn lastToken(self: *const UndefinedLiteral) TokenIndex {
             return self.token;
         }
     };
@@ -1977,11 +1983,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *ThisLiteral) TokenIndex {
+        pub fn firstToken(self: *const ThisLiteral) TokenIndex {
             return self.token;
         }
 
-        pub fn lastToken(self: *ThisLiteral) TokenIndex {
+        pub fn lastToken(self: *const ThisLiteral) TokenIndex {
             return self.token;
         }
     };
@@ -2022,11 +2028,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *AsmOutput) TokenIndex {
+        pub fn firstToken(self: *const AsmOutput) TokenIndex {
             return self.lbracket;
         }
 
-        pub fn lastToken(self: *AsmOutput) TokenIndex {
+        pub fn lastToken(self: *const AsmOutput) TokenIndex {
             return self.rparen;
         }
     };
@@ -2054,11 +2060,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *AsmInput) TokenIndex {
+        pub fn firstToken(self: *const AsmInput) TokenIndex {
             return self.lbracket;
         }
 
-        pub fn lastToken(self: *AsmInput) TokenIndex {
+        pub fn lastToken(self: *const AsmInput) TokenIndex {
             return self.rparen;
         }
     };
@@ -2089,11 +2095,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *Asm) TokenIndex {
+        pub fn firstToken(self: *const Asm) TokenIndex {
             return self.asm_token;
         }
 
-        pub fn lastToken(self: *Asm) TokenIndex {
+        pub fn lastToken(self: *const Asm) TokenIndex {
             return self.rparen;
         }
     };
@@ -2106,11 +2112,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *Unreachable) TokenIndex {
+        pub fn firstToken(self: *const Unreachable) TokenIndex {
             return self.token;
         }
 
-        pub fn lastToken(self: *Unreachable) TokenIndex {
+        pub fn lastToken(self: *const Unreachable) TokenIndex {
             return self.token;
         }
     };
@@ -2123,11 +2129,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *ErrorType) TokenIndex {
+        pub fn firstToken(self: *const ErrorType) TokenIndex {
             return self.token;
         }
 
-        pub fn lastToken(self: *ErrorType) TokenIndex {
+        pub fn lastToken(self: *const ErrorType) TokenIndex {
             return self.token;
         }
     };
@@ -2140,11 +2146,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *VarType) TokenIndex {
+        pub fn firstToken(self: *const VarType) TokenIndex {
             return self.token;
         }
 
-        pub fn lastToken(self: *VarType) TokenIndex {
+        pub fn lastToken(self: *const VarType) TokenIndex {
             return self.token;
         }
     };
@@ -2159,11 +2165,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *DocComment) TokenIndex {
+        pub fn firstToken(self: *const DocComment) TokenIndex {
             return self.lines.at(0).*;
         }
 
-        pub fn lastToken(self: *DocComment) TokenIndex {
+        pub fn lastToken(self: *const DocComment) TokenIndex {
             return self.lines.at(self.lines.len - 1).*;
         }
     };
@@ -2184,11 +2190,11 @@ pub const Node = struct {
             return null;
         }
 
-        pub fn firstToken(self: *TestDecl) TokenIndex {
+        pub fn firstToken(self: *const TestDecl) TokenIndex {
             return self.test_token;
         }
 
-        pub fn lastToken(self: *TestDecl) TokenIndex {
+        pub fn lastToken(self: *const TestDecl) TokenIndex {
             return self.body_node.lastToken();
         }
     };
std/segmented_list.zig
@@ -2,7 +2,7 @@ const std = @import("index.zig");
 const assert = std.debug.assert;
 const Allocator = std.mem.Allocator;
 
-// Imagine that `fn at(self: &Self, index: usize) &T` is a customer asking for a box
+// Imagine that `fn at(self: *Self, index: usize) &T` is a customer asking for a box
 // from a warehouse, based on a flat array, boxes ordered from 0 to N - 1.
 // But the warehouse actually stores boxes in shelves of increasing powers of 2 sizes.
 // So when the customer requests a box index, we have to translate it to shelf index
@@ -93,6 +93,14 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
 
         pub const prealloc_count = prealloc_item_count;
 
+        fn AtType(comptime SelfType: type) type {
+            if (@typeInfo(SelfType).Pointer.is_const) {
+                return *const T;
+            } else {
+                return *T;
+            }
+        }
+
         /// Deinitialize with `deinit`
         pub fn init(allocator: *Allocator) Self {
             return Self{
@@ -109,7 +117,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
             self.* = undefined;
         }
 
-        pub fn at(self: *Self, i: usize) *T {
+        pub fn at(self: var, i: usize) AtType(@typeOf(self)) {
             assert(i < self.len);
             return self.uncheckedAt(i);
         }
@@ -133,7 +141,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
             if (self.len == 0) return null;
 
             const index = self.len - 1;
-            const result = self.uncheckedAt(index).*;
+            const result = uncheckedAt(self, index).*;
             self.len = index;
             return result;
         }
@@ -141,7 +149,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
         pub fn addOne(self: *Self) !*T {
             const new_length = self.len + 1;
             try self.growCapacity(new_length);
-            const result = self.uncheckedAt(self.len);
+            const result = uncheckedAt(self, self.len);
             self.len = new_length;
             return result;
         }
@@ -193,7 +201,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
             self.dynamic_segments = self.allocator.shrink([*]T, self.dynamic_segments, new_cap_shelf_count);
         }
 
-        pub fn uncheckedAt(self: *Self, index: usize) *T {
+        pub fn uncheckedAt(self: var, index: usize) AtType(@typeOf(self)) {
             if (index < prealloc_item_count) {
                 return &self.prealloc_segment[index];
             }