diff --git a/build.zig b/build.zig index 63bccaae41..a9a93fbdb7 100644 --- a/build.zig +++ b/build.zig @@ -631,24 +631,24 @@ fn discoverBuiltinRocFiles(b: *std.Build) ![]const []const u8 { var builtin_roc_dir = try std.fs.openDirAbsolute(builtin_roc_path, .{ .iterate = true }); defer builtin_roc_dir.close(); - var roc_files = std.array_list.Managed([]const u8).init(b.allocator); - errdefer roc_files.deinit(); + var roc_files = std.ArrayList([]const u8).empty; + errdefer roc_files.deinit(b.allocator); var iter = builtin_roc_dir.iterate(); while (try iter.next()) |entry| { if (entry.kind == .file and std.mem.endsWith(u8, entry.name, ".roc")) { const full_path = b.fmt("src/build/roc/{s}", .{entry.name}); - try roc_files.append(full_path); + try roc_files.append(b.allocator, full_path); } } - return roc_files.toOwnedSlice(); + return roc_files.toOwnedSlice(b.allocator); } fn generateCompiledBuiltinsSource(b: *std.Build, roc_files: []const []const u8) ![]const u8 { - var builtins_source = std.array_list.Managed(u8).init(b.allocator); - errdefer builtins_source.deinit(); - const writer = builtins_source.writer(); + var builtins_source = std.ArrayList(u8).empty; + errdefer builtins_source.deinit(b.allocator); + const writer = builtins_source.writer(b.allocator); for (roc_files) |roc_path| { const roc_basename = std.fs.path.basename(roc_path); @@ -671,7 +671,7 @@ fn generateCompiledBuiltinsSource(b: *std.Build, roc_files: []const []const u8) // Also embed builtin_indices.bin try writer.writeAll("pub const builtin_indices_bin = @embedFile(\"builtin_indices.bin\");\n"); - return builtins_source.toOwnedSlice(); + return builtins_source.toOwnedSlice(b.allocator); } fn add_fuzz_target( @@ -770,7 +770,7 @@ fn addMainExe( .root_source_file = b.path("test/str/platform/host.zig"), .target = target, .optimize = optimize, - .strip = true, + .strip = optimize != .Debug, .pic = true, // Enable Position Independent Code for PIE compatibility }), }); @@ -794,7 +794,7 @@ fn addMainExe( .root_source_file = b.path("test/int/platform/host.zig"), .target = target, .optimize = optimize, - .strip = true, + .strip = optimize != .Debug, .pic = true, // Enable Position Independent Code for PIE compatibility }), }); @@ -827,7 +827,7 @@ fn addMainExe( .root_source_file = b.path("test/int/platform/host.zig"), .target = cross_resolved_target, .optimize = optimize, - .strip = true, + .strip = optimize != .Debug, .pic = true, }), .linkage = .static, @@ -872,7 +872,7 @@ fn addMainExe( .root_source_file = b.path("src/interpreter_shim/main.zig"), .target = target, .optimize = optimize, - .strip = true, + .strip = optimize != .Debug, .pic = true, // Enable Position Independent Code for PIE compatibility }), .linkage = .static, @@ -953,13 +953,13 @@ const ParsedBuildArgs = struct { }; fn appendFilter( - list: *std.array_list.Managed([]const u8), + list: *std.ArrayList([]const u8), b: *std.Build, value: []const u8, ) void { const trimmed = std.mem.trim(u8, value, " \t\n\r"); if (trimmed.len == 0) return; - list.append(b.dupe(trimmed)) catch @panic("OOM while parsing --test-filter value"); + list.append(b.allocator, b.dupe(trimmed)) catch @panic("OOM while parsing --test-filter value"); } fn parseBuildArgs(b: *std.Build) ParsedBuildArgs { @@ -968,8 +968,8 @@ fn parseBuildArgs(b: *std.Build) ParsedBuildArgs { .test_filters = &.{}, }; - var run_args_list = std.array_list.Managed([]const u8).init(b.allocator); - var filter_list = std.array_list.Managed([]const u8).init(b.allocator); + var run_args_list = std.ArrayList([]const u8).empty; + var filter_list = std.ArrayList([]const u8).empty; var i: usize = 0; while (i < raw_args.len) { @@ -994,12 +994,12 @@ fn parseBuildArgs(b: *std.Build) ParsedBuildArgs { continue; } - run_args_list.append(arg) catch @panic("OOM while recording build arguments"); + run_args_list.append(b.allocator, arg) catch @panic("OOM while recording build arguments"); i += 1; } - const run_args = run_args_list.toOwnedSlice() catch @panic("OOM while finalizing build arguments"); - const test_filters = filter_list.toOwnedSlice() catch @panic("OOM while finalizing test filters"); + const run_args = run_args_list.toOwnedSlice(b.allocator) catch @panic("OOM while finalizing build arguments"); + const test_filters = filter_list.toOwnedSlice(b.allocator) catch @panic("OOM while finalizing test filters"); return .{ .run_args = run_args, .test_filters = test_filters }; } @@ -1423,10 +1423,10 @@ fn getCompilerVersion(b: *std.Build, optimize: OptimizeMode) []const u8 { fn generateGlibcStub(b: *std.Build, target: ResolvedTarget, target_name: []const u8) ?*Step.UpdateSourceFiles { // Generate assembly stub with comprehensive symbols using the new build module - var assembly_buf = std.array_list.Managed(u8).init(b.allocator); - defer assembly_buf.deinit(); + var assembly_buf = std.ArrayList(u8).empty; + defer assembly_buf.deinit(b.allocator); - const writer = assembly_buf.writer(); + const writer = assembly_buf.writer(b.allocator); const target_arch = target.result.cpu.arch; const target_abi = target.result.abi; diff --git a/src/base/Ident.zig b/src/base/Ident.zig index 5c5cf031a3..44c52c387d 100644 --- a/src/base/Ident.zig +++ b/src/base/Ident.zig @@ -602,13 +602,13 @@ test "Ident.Store comprehensive CompactWriter roundtrip" { .{ .text = "hello", .expected_idx = 1 }, // duplicate, should reuse }; - var indices = std.array_list.Managed(Ident.Idx).init(gpa); - defer indices.deinit(); + var indices = std.ArrayList(Ident.Idx).empty; + defer indices.deinit(gpa); for (test_idents) |test_ident| { const ident = Ident.for_text(test_ident.text); const idx = try original.insert(gpa, ident); - try indices.append(idx); + try indices.append(gpa, idx); // Verify the index matches expectation try std.testing.expectEqual(test_ident.expected_idx, idx.idx); } diff --git a/src/base/Scratch.zig b/src/base/Scratch.zig index c448ee62d9..a1b9e530bc 100644 --- a/src/base/Scratch.zig +++ b/src/base/Scratch.zig @@ -24,10 +24,20 @@ pub fn Scratch(comptime T: type) type { } /// Returns the start position for a new Span of indexes in scratch - pub fn top(self: *Self) u32 { + pub fn top(self: *const Self) u32 { return @as(u32, @intCast(self.items.items.len)); } + /// Check if a value is in the array + pub fn contains(self: *const Self, val: T) bool { + for (self.items.items) |item| { + if (item == val) { + return true; + } + } + return false; + } + /// Places a new index of type `T` in the scratch pub fn append(self: *Self, idx: T) std.mem.Allocator.Error!void { try self.items.append(idx); @@ -48,6 +58,25 @@ pub fn Scratch(comptime T: type) type { return self.items.items[@intCast(start)..]; } + /// Creates slice from the provided start index + pub fn sliceFromSpan(self: *Self, span: DataSpan) []T { + const start: usize = @intCast(span.start); + const end: usize = @intCast(span.start + span.len); + + std.debug.assert(start <= end); + std.debug.assert(end <= self.items.items.len); + + return self.items.items[start..end]; + } + + /// Creates span from the provided start index to the end of the list + pub fn spanFrom(self: *Self, start: u32) DataSpan { + return DataSpan{ + .start = start, + .len = @as(u32, @intCast(self.items.items.len)) - start, + }; + } + /// Creates a new span starting at start. Moves the items from scratch /// to extra_data as appropriate. pub fn spanFromStart(self: *Self, start: u32, data: *std.array_list.Managed(u32)) std.mem.Allocator.Error!DataSpan { diff --git a/src/base/SmallStringInterner.zig b/src/base/SmallStringInterner.zig index 74d47fcdd5..89ee36e2ed 100644 --- a/src/base/SmallStringInterner.zig +++ b/src/base/SmallStringInterner.zig @@ -305,12 +305,12 @@ test "SmallStringInterner basic CompactWriter roundtrip" { "duplicate", // Should reuse the same index }; - var indices = std.array_list.Managed(SmallStringInterner.Idx).init(gpa); - defer indices.deinit(); + var indices = std.ArrayList(SmallStringInterner.Idx).empty; + defer indices.deinit(gpa); for (test_strings) |str| { const idx = try original.insert(gpa, str); - try indices.append(idx); + try indices.append(gpa, idx); } // Verify duplicate detection worked @@ -507,12 +507,12 @@ test "SmallStringInterner edge cases CompactWriter roundtrip" { " start_with_space", }; - var indices = std.array_list.Managed(SmallStringInterner.Idx).init(gpa); - defer indices.deinit(); + var indices = std.ArrayList(SmallStringInterner.Idx).empty; + defer indices.deinit(gpa); for (edge_cases) |str| { const idx = try original.insert(gpa, str); - try indices.append(idx); + try indices.append(gpa, idx); } // Create a temp file diff --git a/src/base/StringLiteral.zig b/src/base/StringLiteral.zig index aca045c8f5..c5cfec86ba 100644 --- a/src/base/StringLiteral.zig +++ b/src/base/StringLiteral.zig @@ -257,12 +257,12 @@ test "Store comprehensive CompactWriter roundtrip" { "very long string " ** 50, // long string }; - var indices = std.array_list.Managed(Idx).init(gpa); - defer indices.deinit(); + var indices = std.ArrayList(Idx).empty; + defer indices.deinit(gpa); for (test_strings) |str| { const idx = try original.insert(gpa, str); - try indices.append(idx); + try indices.append(gpa, idx); } // Create a temp file diff --git a/src/build/builtin_compiler/main.zig b/src/build/builtin_compiler/main.zig index 156954ed2c..9b055507d2 100644 --- a/src/build/builtin_compiler/main.zig +++ b/src/build/builtin_compiler/main.zig @@ -336,12 +336,12 @@ fn compileModule( // 6. Type check // Build the list of other modules for type checking - var imported_envs = std.array_list.Managed(*const ModuleEnv).init(gpa); - defer imported_envs.deinit(); + var imported_envs = std.ArrayList(*const ModuleEnv).empty; + defer imported_envs.deinit(gpa); // Add dependencies for (deps) |dep| { - try imported_envs.append(dep.env); + try imported_envs.append(gpa, dep.env); } var checker = try Check.init( diff --git a/src/build/modules.zig b/src/build/modules.zig index 48e94ff0c6..84efc573c9 100644 --- a/src/build/modules.zig +++ b/src/build/modules.zig @@ -41,16 +41,16 @@ fn extendWithAggregatorFilters( const extras = aggregatorFilters(module_type); if (extras.len == 0) return base; - var list = std.array_list.Managed([]const u8).init(b.allocator); - list.ensureTotalCapacity(base.len + extras.len) catch @panic("OOM while extending module test filters"); - list.appendSlice(base) catch @panic("OOM while extending module test filters"); + var list = std.ArrayList([]const u8).empty; + list.ensureTotalCapacity(b.allocator, base.len + extras.len) catch @panic("OOM while extending module test filters"); + list.appendSlice(b.allocator, base) catch @panic("OOM while extending module test filters"); for (extras) |extra| { if (filtersContain(base, extra)) continue; - list.append(b.dupe(extra)) catch @panic("OOM while extending module test filters"); + list.append(b.allocator, b.dupe(extra)) catch @panic("OOM while extending module test filters"); } - return list.toOwnedSlice() catch @panic("OOM while finalizing module test filters"); + return list.toOwnedSlice(b.allocator) catch @panic("OOM while finalizing module test filters"); } /// Represents a test module with its compilation and execution steps. diff --git a/src/bundle/test_bundle.zig b/src/bundle/test_bundle.zig index 7f56f6e69c..5226c0dfff 100644 --- a/src/bundle/test_bundle.zig +++ b/src/bundle/test_bundle.zig @@ -1067,10 +1067,10 @@ test "double roundtrip bundle -> unbundle -> bundle -> unbundle" { var first_bundle_writer: std.Io.Writer.Allocating = .init(allocator); defer first_bundle_writer.deinit(); - var paths1 = std.array_list.Managed([]const u8).init(allocator); - defer paths1.deinit(); + var paths1 = std.ArrayList([]const u8).empty; + defer paths1.deinit(allocator); for (test_files) |test_file| { - try paths1.append(test_file.path); + try paths1.append(allocator, test_file.path); } var iter1 = FilePathIterator{ .paths = paths1.items }; @@ -1106,10 +1106,10 @@ test "double roundtrip bundle -> unbundle -> bundle -> unbundle" { var second_bundle_writer: std.Io.Writer.Allocating = .init(allocator); defer second_bundle_writer.deinit(); - var paths2 = std.array_list.Managed([]const u8).init(allocator); - defer paths2.deinit(); + var paths2 = std.ArrayList([]const u8).empty; + defer paths2.deinit(allocator); for (test_files) |test_file| { - try paths2.append(test_file.path); + try paths2.append(allocator, test_file.path); } var iter2 = FilePathIterator{ .paths = paths2.items }; @@ -1216,13 +1216,13 @@ test "CLI unbundle with no args defaults to all .tar.zst files" { var cwd = try tmp_dir.openDir(".", .{ .iterate = true }); defer cwd.close(); - var found_archives = std.array_list.Managed([]const u8).init(allocator); - defer found_archives.deinit(); + var found_archives = std.ArrayList([]const u8).empty; + defer found_archives.deinit(allocator); var iter = cwd.iterate(); while (try iter.next()) |entry| { if (entry.kind == .file and std.mem.endsWith(u8, entry.name, ".tar.zst")) { - try found_archives.append(entry.name); + try found_archives.append(allocator, entry.name); } } diff --git a/src/bundle/test_streaming.zig b/src/bundle/test_streaming.zig index 55742d0963..307b518ad3 100644 --- a/src/bundle/test_streaming.zig +++ b/src/bundle/test_streaming.zig @@ -218,14 +218,14 @@ test "different compression levels" { ); defer reader.deinit(); - var decompressed = std.array_list.Managed(u8).init(allocator); - defer decompressed.deinit(); + var decompressed = std.ArrayList(u8).empty; + defer decompressed.deinit(allocator); var buffer: [1024]u8 = undefined; while (true) { const n = try reader.read(&buffer); if (n == 0) break; - try decompressed.appendSlice(buffer[0..n]); + try decompressed.appendSlice(allocator, buffer[0..n]); } try std.testing.expectEqualStrings(test_data, decompressed.items); diff --git a/src/canonicalize/Can.zig b/src/canonicalize/Can.zig index 7c441e255d..4c32cdfffb 100644 --- a/src/canonicalize/Can.zig +++ b/src/canonicalize/Can.zig @@ -24,39 +24,6 @@ const DataSpan = base.DataSpan; const ModuleEnv = @import("ModuleEnv.zig"); const Node = @import("Node.zig"); -/// Both the canonicalized expression and any free variables -/// -/// We keep track of the free variables as we go so we can union these -/// in our Lambda's in a single forward pass during canonicalization. -pub const CanonicalizedExpr = struct { - idx: Expr.Idx, - free_vars: ?[]Pattern.Idx, - - pub fn get_idx(self: @This()) Expr.Idx { - return self.idx; - } - - pub fn maybe_expr_get_idx(self: ?@This()) ?Expr.Idx { - if (self != null) { - return self.?.idx; - } else { - return null; - } - } -}; - -const TypeVarProblemKind = enum { - unused_type_var, - type_var_marked_unused, - type_var_ending_in_underscore, -}; - -const TypeVarProblem = struct { - ident: Ident.Idx, - problem: TypeVarProblemKind, - ast_anno: AST.TypeAnno.Idx, -}; - /// Information about an auto-imported module type pub const AutoImportedType = struct { env: *const ModuleEnv, @@ -64,7 +31,7 @@ pub const AutoImportedType = struct { env: *ModuleEnv, parse_ir: *AST, -scopes: std.ArrayListUnmanaged(Scope) = .{}, +scopes: std.ArrayList(Scope) = .{}, /// Special scope for rigid type variables in annotations type_vars_scope: base.Scratch(TypeVarScope), /// Special scope for tracking exposed items from module header @@ -103,6 +70,8 @@ scratch_seen_record_fields: base.Scratch(SeenRecordField), scratch_tags: base.Scratch(types.Tag), /// Scratch free variables scratch_free_vars: base.Scratch(Pattern.Idx), +/// Scratch free variables +scratch_captures: base.Scratch(Pattern.Idx), const Ident = base.Ident; const Region = base.Region; @@ -137,6 +106,39 @@ const RecordField = CIR.RecordField; /// Struct to track fields that have been seen before during canonicalization const SeenRecordField = struct { ident: base.Ident.Idx, region: base.Region }; +/// Both the canonicalized expression and any free variables +/// +/// We keep track of the free variables as we go so we can union these +/// in our Lambda's in a single forward pass during canonicalization. +pub const CanonicalizedExpr = struct { + idx: Expr.Idx, + free_vars: ?DataSpan, // This is a span into scratch_free_vars + + pub fn get_idx(self: @This()) Expr.Idx { + return self.idx; + } + + pub fn maybe_expr_get_idx(self: ?@This()) ?Expr.Idx { + if (self != null) { + return self.?.idx; + } else { + return null; + } + } +}; + +const TypeVarProblemKind = enum { + unused_type_var, + type_var_marked_unused, + type_var_ending_in_underscore, +}; + +const TypeVarProblem = struct { + ident: Ident.Idx, + problem: TypeVarProblemKind, + ast_anno: AST.TypeAnno.Idx, +}; + /// Deinitialize canonicalizer resources pub fn deinit( self: *Self, @@ -169,6 +171,7 @@ pub fn deinit( self.import_indices.deinit(gpa); self.scratch_tags.deinit(); self.scratch_free_vars.deinit(); + self.scratch_captures.deinit(); } /// Options for initializing the canonicalizer. @@ -201,6 +204,7 @@ pub fn init( .scratch_tags = try base.Scratch(types.Tag).init(gpa), .unqualified_nominal_tags = std.StringHashMapUnmanaged(Statement.Idx){}, .scratch_free_vars = try base.Scratch(Pattern.Idx).init(gpa), + .scratch_captures = try base.Scratch(Pattern.Idx).init(gpa), }; // Top-level scope is not a function boundary @@ -1520,7 +1524,7 @@ fn bringImportIntoScope( // const res = self.env.imports.getOrInsert(gpa, import_name, shorthand); // if (res.was_present) { - // _ = self.env.problems.append(gpa, Problem.Canonicalize.make(.{ .DuplicateImport = .{ + // _ = self.env.problems.append(Problem.Canonicalize.make(.{ .DuplicateImport = .{ // .duplicate_import_region = region, // } })); // } @@ -1947,19 +1951,7 @@ fn canonicalizeDeclWithAnnotation( const trace = tracy.trace(@src()); defer trace.end(); - const pattern_region = self.parse_ir.tokenizedRegionToRegion(self.parse_ir.store.getPattern(decl.pattern).to_tokenized_region()); - - const pattern_idx = blk: { - if (try self.canonicalizePattern(decl.pattern)) |idx| { - break :blk idx; - } else { - const malformed_idx = try self.env.pushMalformed(Pattern.Idx, Diagnostic{ .pattern_not_canonicalized = .{ - .region = pattern_region, - } }); - break :blk malformed_idx; - } - }; - + const pattern_idx = try self.canonicalizePatternOrMalformed(decl.pattern); const can_expr = try self.canonicalizeExprOrMalformed(decl.body); // Create the def entry and set def type variable to a flex var @@ -2066,8 +2058,8 @@ fn canonicalizeStringLike( .span = can_str_span, } }, region); - const free_vars_slice = self.scratch_free_vars.slice(free_vars_start, self.scratch_free_vars.top()); - return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null }; + const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); + return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_span.len > 0) free_vars_span else null }; } fn canonicalizeSingleQuote( @@ -2218,8 +2210,8 @@ pub fn canonicalizeExpr( }, }, region); - const free_vars_slice = self.scratch_free_vars.slice(free_vars_start, self.scratch_free_vars.top()); - return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null }; + const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); + return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_span.len > 0) free_vars_span else null }; }, .ident => |e| { const region = self.parse_ir.tokenizedRegionToRegion(e.region); @@ -2250,8 +2242,7 @@ pub fn canonicalizeExpr( const free_vars_start = self.scratch_free_vars.top(); try self.scratch_free_vars.append(found_pattern_idx); - const free_vars_slice = self.scratch_free_vars.slice(free_vars_start, self.scratch_free_vars.top()); - return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null }; + return CanonicalizedExpr{ .idx = expr_idx, .free_vars = DataSpan.init(free_vars_start, 1) }; }, .not_found => { // Not a local qualified identifier, try module-qualified lookup @@ -2387,8 +2378,8 @@ pub fn canonicalizeExpr( const free_vars_start = self.scratch_free_vars.top(); try self.scratch_free_vars.append(found_pattern_idx); - const free_vars_slice = self.scratch_free_vars.slice(free_vars_start, self.scratch_free_vars.top()); - return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null }; + const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); + return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_span.len > 0) free_vars_span else null }; }, .not_found => { // Check if this identifier is an exposed item from an import @@ -2781,8 +2772,8 @@ pub fn canonicalizeExpr( .e_list = .{ .elems = elems_span }, }, region); - const free_vars_slice = self.scratch_free_vars.slice(free_vars_start, self.scratch_free_vars.top()); - return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null }; + const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); + return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_span.len > 0) free_vars_span else null }; }, .tag => |e| { const region = self.parse_ir.tokenizedRegionToRegion(e.region); @@ -2853,8 +2844,8 @@ pub fn canonicalizeExpr( }, }, region); - const free_vars_slice = self.scratch_free_vars.slice(free_vars_start, self.scratch_free_vars.top()); - return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null }; + const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); + return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_span.len > 0) free_vars_span else null }; } }, .record => |e| { @@ -2946,8 +2937,8 @@ pub fn canonicalizeExpr( }, }, region); - const free_vars_slice = self.scratch_free_vars.slice(free_vars_start, self.scratch_free_vars.top()); - return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null }; + const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); + return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_span.len > 0) free_vars_span else null }; }, .lambda => |e| { const region = self.parse_ir.tokenizedRegionToRegion(e.region); @@ -2960,7 +2951,7 @@ pub fn canonicalizeExpr( try self.scopeEnter(self.env.gpa, true); // true = is_function_boundary defer self.scopeExit(self.env.gpa) catch {}; - // args + // Canonicalize the lambda args const args_start = self.env.store.scratch.?.patterns.top(); for (self.parse_ir.store.patternSlice(e.args)) |arg_pattern_idx| { if (try self.canonicalizePattern(arg_pattern_idx)) |pattern_idx| { @@ -2976,61 +2967,67 @@ pub fn canonicalizeExpr( } const args_span = try self.env.store.patternSpanFrom(args_start); - // body (this will detect and record captures) - const body_free_vars_start = self.scratch_free_vars.top(); - const can_body = try self.canonicalizeExpr(e.body) orelse { - self.scratch_free_vars.clearFrom(body_free_vars_start); - const ast_body = self.parse_ir.store.getExpr(e.body); - const body_region = self.parse_ir.tokenizedRegionToRegion(ast_body.to_tokenized_region()); - const malformed_idx = try self.env.pushMalformed(Expr.Idx, Diagnostic{ - .lambda_body_not_canonicalized = .{ .region = body_region }, - }); - return CanonicalizedExpr{ .idx = malformed_idx, .free_vars = null }; - }; + // Define the set of captures + const captures_top = self.scratch_captures.top(); + defer self.scratch_captures.clearFrom(captures_top); - // Determine captures: free variables in body minus variables bound by args - var bound_vars = std.AutoHashMapUnmanaged(Pattern.Idx, void){}; - defer bound_vars.deinit(self.env.gpa); - for (self.env.store.slicePatterns(args_span)) |arg_pat_idx| { - try self.collectBoundVars(arg_pat_idx, &bound_vars); - } + // Canonicalize the lambda body + const body_idx = blk: { + const body_free_vars_start = self.scratch_free_vars.top(); + defer self.scratch_free_vars.clearFrom(body_free_vars_start); - var captures_set = std.AutoHashMapUnmanaged(Pattern.Idx, void){}; - defer captures_set.deinit(self.env.gpa); + const can_body = try self.canonicalizeExpr(e.body) orelse { + const ast_body = self.parse_ir.store.getExpr(e.body); + const body_region = self.parse_ir.tokenizedRegionToRegion(ast_body.to_tokenized_region()); + const malformed_idx = try self.env.pushMalformed(Expr.Idx, Diagnostic{ + .lambda_body_not_canonicalized = .{ .region = body_region }, + }); + return CanonicalizedExpr{ .idx = malformed_idx, .free_vars = null }; + }; - const body_free_vars_slice = can_body.free_vars orelse &.{}; - for (body_free_vars_slice) |fv| { - if (!bound_vars.contains(fv)) { - try captures_set.put(self.env.gpa, fv, {}); + // Determine captures: free variables in body minus variables bound by args + var bound_vars = std.AutoHashMapUnmanaged(Pattern.Idx, void){}; + defer bound_vars.deinit(self.env.gpa); + + for (self.env.store.slicePatterns(args_span)) |arg_pat_idx| { + try self.collectBoundVars(arg_pat_idx, &bound_vars); } - } - // Now that we have the captures, we can clear the free variables from the body - // from the scratch buffer. - self.scratch_free_vars.clearFrom(body_free_vars_start); + const body_free_vars_slice = self.scratch_free_vars.sliceFromSpan(can_body.free_vars orelse DataSpan.empty()); + for (body_free_vars_slice) |fv| { + if (!self.scratch_captures.contains(fv) and !bound_vars.contains(fv)) { + try self.scratch_captures.append(fv); + } + } + + break :blk can_body.idx; + }; // Create the pure lambda expression first const lambda_expr = Expr{ .e_lambda = .{ .args = args_span, - .body = can_body.idx, + .body = body_idx, }, }; const lambda_idx = try self.env.addExpr(lambda_expr, region); + // Get a slice of the captured vars in the body + const captures_slice = self.scratch_captures.sliceFromStart(captures_top); + // If there are no captures, this is a pure lambda. - // Otherwise, it's a closure. - if (captures_set.count() == 0) { - // A pure lambda has no free variables. + // A pure lambda has no free variables. + if (captures_slice.len == 0) { return CanonicalizedExpr{ .idx = lambda_idx, .free_vars = null }; } + // Otherwise, it's a closure. + + // Copy the captures into the store const capture_info: Expr.Capture.Span = blk: { const scratch_start = self.env.store.scratch.?.captures.top(); - var cap_it = captures_set.iterator(); - while (cap_it.next()) |entry| { - const pattern_idx = entry.key_ptr.*; + for (captures_slice) |pattern_idx| { const pattern = self.env.store.getPattern(pattern_idx); const name = switch (pattern) { .assign => |a| a.ident, @@ -3055,19 +3052,17 @@ pub fn canonicalizeExpr( .captures = capture_info, }, }; - // The type of the closure is the same as the type of the pure lambda const expr_idx = try self.env.addExpr(closure_expr, region); // The free variables of the lambda are its captures. - // I need to add them to the global list and return a span. + // Copy the contiguous list to the backing array const lambda_free_vars_start = self.scratch_free_vars.top(); - var cap_it = captures_set.iterator(); - while (cap_it.next()) |entry| { - try self.scratch_free_vars.append(entry.key_ptr.*); + for (captures_slice) |pattern_idx| { + try self.scratch_free_vars.append(pattern_idx); } - const free_vars_slice = self.scratch_free_vars.slice(lambda_free_vars_start, self.scratch_free_vars.top()); - return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null }; + const free_vars_span = self.scratch_free_vars.spanFrom(lambda_free_vars_start); + return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_span.len > 0) free_vars_span else null }; }, .record_updater => |_| { const feature = try self.env.insertString("canonicalize record_updater expression"); @@ -3141,8 +3136,8 @@ pub fn canonicalizeExpr( .e_binop = Expr.Binop.init(op, can_lhs.idx, can_rhs.idx), }, region); - const free_vars_slice = self.scratch_free_vars.slice(free_vars_start, self.scratch_free_vars.top()); - return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null }; + const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); + return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_span.len > 0) free_vars_span else null }; }, .suffix_single_question => |_| { const feature = try self.env.insertString("canonicalize suffix_single_question expression"); @@ -3262,8 +3257,8 @@ pub fn canonicalizeExpr( }, }, region); - const free_vars_slice = self.scratch_free_vars.slice(free_vars_start, self.scratch_free_vars.top()); - return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null }; + const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); + return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_span.len > 0) free_vars_span else null }; }, .match => |m| { const region = self.parse_ir.tokenizedRegionToRegion(m.region); @@ -3384,8 +3379,8 @@ pub fn canonicalizeExpr( }; const expr_idx = try self.env.addExpr(CIR.Expr{ .e_match = match_expr }, region); - const free_vars_slice = self.scratch_free_vars.slice(free_vars_start, self.scratch_free_vars.top()); - return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null }; + const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); + return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_span.len > 0) free_vars_span else null }; }, .dbg => |d| { // Debug expression - canonicalize the inner expression @@ -3513,10 +3508,10 @@ fn canonicalizeTagExpr(self: *Self, e: AST.TagExpr, mb_args: ?AST.Expr.Span, reg }, }, region); - const free_vars_slice = self.scratch_free_vars.slice(free_vars_start, self.scratch_free_vars.top()); + const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); return CanonicalizedExpr{ .idx = expr_idx, - .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null, + .free_vars = free_vars_span, }; }, .s_alias_decl => { @@ -3563,10 +3558,10 @@ fn canonicalizeTagExpr(self: *Self, e: AST.TagExpr, mb_args: ?AST.Expr.Span, reg }, }, region); - const free_vars_slice = self.scratch_free_vars.slice(free_vars_start, self.scratch_free_vars.top()); + const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); return CanonicalizedExpr{ .idx = expr_idx, - .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null, + .free_vars = if (free_vars_span.len > 0) free_vars_span else null, }; } } @@ -3635,10 +3630,10 @@ fn canonicalizeTagExpr(self: *Self, e: AST.TagExpr, mb_args: ?AST.Expr.Span, reg }, }, region); - const free_vars_slice = self.scratch_free_vars.slice(free_vars_start, self.scratch_free_vars.top()); + const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); return CanonicalizedExpr{ .idx = expr_idx, - .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null, + .free_vars = free_vars_span, }; } @@ -3703,10 +3698,10 @@ fn canonicalizeTagExpr(self: *Self, e: AST.TagExpr, mb_args: ?AST.Expr.Span, reg }, }, region); - const free_vars_slice = self.scratch_free_vars.slice(free_vars_start, self.scratch_free_vars.top()); + const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); return CanonicalizedExpr{ .idx = expr_idx, - .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null, + .free_vars = free_vars_span, }; }, .s_alias_decl => { @@ -3806,10 +3801,10 @@ fn canonicalizeTagExpr(self: *Self, e: AST.TagExpr, mb_args: ?AST.Expr.Span, reg }, }, region); - const free_vars_slice = self.scratch_free_vars.slice(free_vars_start, self.scratch_free_vars.top()); + const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); return CanonicalizedExpr{ .idx = expr_idx, - .free_vars = if (free_vars_slice.len > 0) free_vars_slice else null, + .free_vars = if (free_vars_span.len > 0) free_vars_span else null, }; } } @@ -3895,6 +3890,21 @@ fn extractMultilineStringSegments(self: *Self, parts: []const AST.Expr.Idx) std. return try self.env.store.exprSpanFrom(start); } +fn canonicalizePatternOrMalformed( + self: *Self, + ast_pattern_idx: AST.Pattern.Idx, +) std.mem.Allocator.Error!Pattern.Idx { + if (try self.canonicalizePattern(ast_pattern_idx)) |idx| { + return idx; + } else { + const pattern_region = self.parse_ir.tokenizedRegionToRegion(self.parse_ir.store.getPattern(ast_pattern_idx).to_tokenized_region()); + const malformed_idx = try self.env.pushMalformed(Pattern.Idx, Diagnostic{ .pattern_not_canonicalized = .{ + .region = pattern_region, + } }); + return malformed_idx; + } +} + fn canonicalizePattern( self: *Self, ast_pattern_idx: AST.Pattern.Idx, @@ -6009,8 +6019,8 @@ fn canonicalizeBlock(self: *Self, e: AST.Block) std.mem.Allocator.Error!Canonica var bound_vars = std.AutoHashMapUnmanaged(Pattern.Idx, void){}; defer bound_vars.deinit(self.env.gpa); - var captures = std.AutoHashMapUnmanaged(Pattern.Idx, void){}; - defer captures.deinit(self.env.gpa); + const captures_top = self.scratch_captures.top(); + defer self.scratch_captures.clearFrom(captures_top); // Canonicalize all statements in the block const ast_stmt_idxs = self.parse_ir.store.statementSlice(e.statements); @@ -6105,11 +6115,10 @@ fn canonicalizeBlock(self: *Self, e: AST.Block) std.mem.Allocator.Error!Canonica } // Collect free vars from the statement into the block's scratch space - if (canonicailzed_stmt.free_vars) |fvs| { - for (fvs) |fv| { - if (!bound_vars.contains(fv)) { - try captures.put(self.env.gpa, fv, {}); - } + const stmt_free_vars_slice = self.scratch_free_vars.sliceFromSpan(canonicailzed_stmt.free_vars orelse DataSpan.empty()); + for (stmt_free_vars_slice) |fv| { + if (!self.scratch_captures.contains(fv) and !bound_vars.contains(fv)) { + try self.scratch_captures.append(fv); } } } @@ -6136,21 +6145,22 @@ fn canonicalizeBlock(self: *Self, e: AST.Block) std.mem.Allocator.Error!Canonica }; // Add free vars from the final expression to the block's scratch space - if (final_expr.free_vars) |fvs| { - for (fvs) |fv| { - if (!bound_vars.contains(fv)) { - try captures.put(self.env.gpa, fv, {}); - } + const final_expr_free_vars_slice = self.scratch_free_vars.sliceFromSpan(final_expr.free_vars orelse DataSpan.empty()); + for (final_expr_free_vars_slice) |fv| { + if (!self.scratch_captures.contains(fv) and !bound_vars.contains(fv)) { + try self.scratch_captures.append(fv); } } + // Get a slice of the captured vars in the block + const captures_slice = self.scratch_captures.sliceFromStart(captures_top); + // Add the actual free variables (captures) to the parent's scratch space - const captures_start = self.scratch_free_vars.top(); - var cap_it = captures.iterator(); - while (cap_it.next()) |entry| { - try self.scratch_free_vars.append(entry.key_ptr.*); + const block_captures_start = self.scratch_free_vars.top(); + for (captures_slice) |ptrn_idx| { + try self.scratch_free_vars.append(ptrn_idx); } - const captures_slice = self.scratch_free_vars.slice(captures_start, self.scratch_free_vars.top()); + const block_free_vars = self.scratch_free_vars.spanFrom(block_captures_start); // Create statement span const stmt_span = try self.env.store.statementSpanFrom(stmt_start); @@ -6164,7 +6174,7 @@ fn canonicalizeBlock(self: *Self, e: AST.Block) std.mem.Allocator.Error!Canonica }; const block_idx = try self.env.addExpr(block_expr, block_region); - return CanonicalizedExpr{ .idx = block_idx, .free_vars = if (captures_slice.len > 0) captures_slice else null }; + return CanonicalizedExpr{ .idx = block_idx, .free_vars = if (block_free_vars.len > 0) block_free_vars else null }; } const StatementResult = struct { @@ -6313,6 +6323,13 @@ pub fn canonicalizeBlockStatement(self: *Self, ast_stmt: AST.Statement, ast_stmt mb_canonicailzed_stmt = CanonicalizedStatement{ .idx = stmt_idx, .free_vars = expr.free_vars }; }, .@"return" => |r| { + // To implement early returns and make them usable, we need to: + // 1. Update the parse to allow for if statements (as opposed to if expressions) + // 2. Track function scope in czer and capture the function for this return in `s_return` + // 3. When type checking a lambda, capture all early returns + // a. Unify all early returns together + // b. Unify early returns with func return type + const region = self.parse_ir.tokenizedRegionToRegion(r.region); // Canonicalize the return expression @@ -6433,14 +6450,90 @@ pub fn canonicalizeBlockStatement(self: *Self, ast_stmt: AST.Statement, ast_stmt // then in the canonicalize IR _ = try self.canonicalizeImportStatement(import_stmt); }, - else => { - // Other statement types not yet implemented - const feature = try self.env.insertString("statement type in block"); - const malformed_idx = try self.env.pushMalformed(Statement.Idx, Diagnostic{ .not_implemented = .{ - .feature = feature, - .region = Region.zero(), - } }); - mb_canonicailzed_stmt = CanonicalizedStatement{ .idx = malformed_idx, .free_vars = null }; + .@"for" => |for_stmt| { + // Tmp state to capture free vars from both expr & body + // + // This is stored as a map, so we can avoid adding duplicate captures + // if both the expr and the body reference the same var + var captures = std.AutoHashMapUnmanaged(Pattern.Idx, void){}; + defer captures.deinit(self.env.gpa); + + // Canoncalize the list expr + // for item in [1,2,3] { + // ^^^^^^^ + const expr = blk: { + const body_free_vars_start = self.scratch_free_vars.top(); + defer self.scratch_free_vars.clearFrom(body_free_vars_start); + + const czerd_expr = try self.canonicalizeExprOrMalformed(for_stmt.expr); + + // Copy free vars into scratch array + const free_vars_slice = self.scratch_free_vars.sliceFromSpan(czerd_expr.free_vars orelse DataSpan.empty()); + for (free_vars_slice) |fv| { + try captures.put(self.env.gpa, fv, {}); + } + + break :blk czerd_expr; + }; + + // Canoncalize the pattern + // for item in [1,2,3] { + // ^^^^ + const ptrn = try self.canonicalizePatternOrMalformed(for_stmt.patt); + + // Collect bound vars from pattern + var for_bound_vars = std.AutoHashMapUnmanaged(Pattern.Idx, void){}; + defer for_bound_vars.deinit(self.env.gpa); + try self.collectBoundVars(ptrn, &for_bound_vars); + + // Canoncalize the body + // for item in [1,2,3] { + // print!(item.toStr()) <<<< + // } + // Canonicalize body with scoping + const body = blk: { + const body_free_vars_start = self.scratch_free_vars.top(); + defer self.scratch_free_vars.clearFrom(body_free_vars_start); + + const body_expr = try self.canonicalizeExprOrMalformed(for_stmt.body); + + // Copy free vars into scratch array + const body_free_vars_slice = self.scratch_free_vars.sliceFromSpan(body_expr.free_vars orelse DataSpan.empty()); + for (body_free_vars_slice) |fv| { + if (!for_bound_vars.contains(fv)) { + try captures.put(self.env.gpa, fv, {}); + } + } + + break :blk body_expr; + }; + + // Get captures and copy to free_vars for parent + const free_vars_start = self.scratch_free_vars.top(); + var captures_iter = captures.keyIterator(); + while (captures_iter.next()) |capture| { + try self.scratch_free_vars.append(capture.*); + } + const free_vars = if (self.scratch_free_vars.top() > free_vars_start) + self.scratch_free_vars.spanFrom(free_vars_start) + else + null; + + // Insert into store + const region = self.parse_ir.tokenizedRegionToRegion(for_stmt.region); + const stmt_idx = try self.env.addStatement(Statement{ + .s_for = .{ + .patt = ptrn, + .expr = expr.idx, + .body = body.idx, + }, + }, region); + + mb_canonicailzed_stmt = CanonicalizedStatement{ .idx = stmt_idx, .free_vars = free_vars }; + }, + .malformed => |_| { + // Stmt was malformed, parse reports this error, so do nothing here + mb_canonicailzed_stmt = null; }, } @@ -6544,7 +6637,7 @@ pub fn canonicalizeBlockDecl(self: *Self, d: AST.Statement.Decl, mb_last_anno: ? // A canonicalized statement const CanonicalizedStatement = struct { idx: Statement.Idx, - free_vars: ?[]Pattern.Idx, + free_vars: ?DataSpan, // This is a span into scratch_free_vars }; // special type var scope // @@ -6964,8 +7057,8 @@ fn checkScopeForUnusedVariables(self: *Self, scope: *const Scope) std.mem.Alloca const UnusedVar = struct { ident: base.Ident.Idx, region: Region }; // Collect all unused variables first so we can sort them - var unused_vars = std.array_list.Managed(UnusedVar).init(self.env.gpa); - defer unused_vars.deinit(); + var unused_vars = std.ArrayList(UnusedVar).empty; + defer unused_vars.deinit(self.env.gpa); // Iterate through all identifiers in this scope var iterator = scope.idents.iterator(); @@ -7010,7 +7103,7 @@ fn checkScopeForUnusedVariables(self: *Self, scope: *const Scope) std.mem.Alloca const region = self.env.store.getPatternRegion(pattern_idx); // Collect unused variable for sorting - try unused_vars.append(.{ + try unused_vars.append(self.env.gpa, .{ .ident = ident_idx, .region = region, }); diff --git a/src/canonicalize/DependencyGraph.zig b/src/canonicalize/DependencyGraph.zig index e42ef6f9ec..cd78c87c7f 100644 --- a/src/canonicalize/DependencyGraph.zig +++ b/src/canonicalize/DependencyGraph.zig @@ -20,7 +20,7 @@ const ModuleEnv = @import("ModuleEnv.zig"); /// Edges point from dependent to dependency (A -> B means A depends on B). pub const DependencyGraph = struct { /// Map from def_idx to list of def_idx it depends on - edges: std.AutoHashMapUnmanaged(CIR.Def.Idx, std.ArrayListUnmanaged(CIR.Def.Idx)), + edges: std.AutoHashMapUnmanaged(CIR.Def.Idx, std.ArrayList(CIR.Def.Idx)), /// All defs in the graph nodes: []const CIR.Def.Idx, @@ -354,13 +354,13 @@ const TarjanState = struct { visited: std.AutoHashMapUnmanaged(CIR.Def.Idx, void), /// Stack for Tarjan's algorithm - stack: std.ArrayListUnmanaged(CIR.Def.Idx), + stack: std.ArrayList(CIR.Def.Idx), /// Set of nodes currently on stack on_stack: std.AutoHashMapUnmanaged(CIR.Def.Idx, void), /// Resulting SCCs (in reverse topological order during construction) - sccs: std.ArrayListUnmanaged(SCC), + sccs: std.ArrayList(SCC), allocator: std.mem.Allocator, @@ -422,7 +422,7 @@ const TarjanState = struct { const v_lowlink = self.lowlinks.get(v).?; const v_index = self.indices.get(v).?; if (v_lowlink == v_index) { - var scc_defs = std.ArrayListUnmanaged(CIR.Def.Idx){}; + var scc_defs = std.ArrayList(CIR.Def.Idx){}; while (true) { const w = self.stack.pop() orelse unreachable; // Stack should not be empty diff --git a/src/canonicalize/test/node_store_test.zig b/src/canonicalize/test/node_store_test.zig index 9271aa8b61..f75fb206f2 100644 --- a/src/canonicalize/test/node_store_test.zig +++ b/src/canonicalize/test/node_store_test.zig @@ -58,10 +58,10 @@ test "NodeStore round trip - Statements" { var store = try NodeStore.init(gpa); defer store.deinit(); - var statements = std.array_list.Managed(CIR.Statement).init(gpa); - defer statements.deinit(); + var statements = std.ArrayList(CIR.Statement).empty; + defer statements.deinit(gpa); - try statements.append(CIR.Statement{ + try statements.append(gpa, CIR.Statement{ .s_decl = .{ .pattern = rand_idx(CIR.Pattern.Idx), .expr = rand_idx(CIR.Expr.Idx), @@ -69,45 +69,45 @@ test "NodeStore round trip - Statements" { }, }); - try statements.append(CIR.Statement{ + try statements.append(gpa, CIR.Statement{ .s_var = .{ .pattern_idx = rand_idx(CIR.Pattern.Idx), .expr = rand_idx(CIR.Expr.Idx), }, }); - try statements.append(CIR.Statement{ + try statements.append(gpa, CIR.Statement{ .s_reassign = .{ .pattern_idx = rand_idx(CIR.Pattern.Idx), .expr = rand_idx(CIR.Expr.Idx), }, }); - try statements.append(CIR.Statement{ + try statements.append(gpa, CIR.Statement{ .s_expr = .{ .expr = rand_idx(CIR.Expr.Idx), }, }); - try statements.append(CIR.Statement{ + try statements.append(gpa, CIR.Statement{ .s_crash = .{ .msg = rand_idx(StringLiteral.Idx), }, }); - try statements.append(CIR.Statement{ + try statements.append(gpa, CIR.Statement{ .s_dbg = .{ .expr = rand_idx(CIR.Expr.Idx), }, }); - try statements.append(CIR.Statement{ + try statements.append(gpa, CIR.Statement{ .s_expect = .{ .body = rand_idx(CIR.Expr.Idx), }, }); - try statements.append(CIR.Statement{ + try statements.append(gpa, CIR.Statement{ .s_for = .{ .patt = rand_idx(CIR.Pattern.Idx), .expr = rand_idx(CIR.Expr.Idx), @@ -115,13 +115,13 @@ test "NodeStore round trip - Statements" { }, }); - try statements.append(CIR.Statement{ + try statements.append(gpa, CIR.Statement{ .s_return = .{ .expr = rand_idx(CIR.Expr.Idx), }, }); - try statements.append(CIR.Statement{ + try statements.append(gpa, CIR.Statement{ .s_import = .{ .module_name_tok = rand_ident_idx(), .qualifier_tok = rand_ident_idx(), @@ -130,27 +130,27 @@ test "NodeStore round trip - Statements" { }, }); - try statements.append(CIR.Statement{ + try statements.append(gpa, CIR.Statement{ .s_alias_decl = .{ .header = rand_idx(CIR.TypeHeader.Idx), .anno = rand_idx(CIR.TypeAnno.Idx), }, }); - try statements.append(CIR.Statement{ + try statements.append(gpa, CIR.Statement{ .s_nominal_decl = .{ .header = rand_idx(CIR.TypeHeader.Idx), .anno = rand_idx(CIR.TypeAnno.Idx), }, }); - try statements.append(CIR.Statement{ .s_type_anno = .{ + try statements.append(gpa, CIR.Statement{ .s_type_anno = .{ .name = rand_ident_idx(), .anno = rand_idx(CIR.TypeAnno.Idx), .where = null, } }); - try statements.append(CIR.Statement{ .s_runtime_error = .{ + try statements.append(gpa, CIR.Statement{ .s_runtime_error = .{ .diagnostic = rand_idx(CIR.Diagnostic.Idx), } }); @@ -180,28 +180,28 @@ test "NodeStore round trip - Expressions" { var store = try NodeStore.init(gpa); defer store.deinit(); - var expressions = std.array_list.Managed(CIR.Expr).init(gpa); - defer expressions.deinit(); + var expressions = std.ArrayList(CIR.Expr).empty; + defer expressions.deinit(gpa); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_num = .{ .value = .{ .bytes = @bitCast(@as(i128, 42)), .kind = .i128 }, .kind = .i128, }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_frac_f32 = .{ .value = rand.random().float(f32), .has_suffix = false }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_frac_f64 = .{ .value = rand.random().float(f64), .has_suffix = false }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_dec = .{ .value = RocDec{ .num = 314 }, .has_suffix = false, }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_dec_small = .{ .value = .{ .numerator = rand.random().int(i16), @@ -210,87 +210,87 @@ test "NodeStore round trip - Expressions" { .has_suffix = false, }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_str_segment = .{ .literal = rand_idx(StringLiteral.Idx), }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_str = .{ .span = CIR.Expr.Span{ .span = rand_span() }, }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_lookup_local = .{ .pattern_idx = rand_idx(CIR.Pattern.Idx), }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_lookup_external = .{ .module_idx = rand_idx_u16(CIR.Import.Idx), .target_node_idx = rand.random().int(u16), .region = rand_region(), }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_list = .{ .elems = CIR.Expr.Span{ .span = rand_span() }, }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_tuple = .{ .elems = CIR.Expr.Span{ .span = rand_span() }, }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_match = CIR.Expr.Match{ .cond = rand_idx(CIR.Expr.Idx), .branches = CIR.Expr.Match.Branch.Span{ .span = rand_span() }, .exhaustive = rand_idx(TypeVar), }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_if = .{ .branches = CIR.Expr.IfBranch.Span{ .span = rand_span() }, .final_else = rand_idx(CIR.Expr.Idx), }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_call = .{ .func = rand_idx(CIR.Expr.Idx), .args = CIR.Expr.Span{ .span = rand_span() }, .called_via = CalledVia.apply, }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_record = .{ .fields = CIR.RecordField.Span{ .span = rand_span() }, .ext = null, }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_empty_list = .{}, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_block = .{ .stmts = CIR.Statement.Span{ .span = rand_span() }, .final_expr = rand_idx(CIR.Expr.Idx), }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_tag = .{ .name = rand_ident_idx(), .args = CIR.Expr.Span{ .span = rand_span() }, }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_nominal = .{ .nominal_type_decl = rand_idx(CIR.Statement.Idx), .backing_expr = rand_idx(CIR.Expr.Idx), .backing_type = .tag, }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_zero_argument_tag = .{ .closure_name = rand_ident_idx(), .variant_var = rand_idx(TypeVar), @@ -298,68 +298,68 @@ test "NodeStore round trip - Expressions" { .name = rand_ident_idx(), }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_closure = .{ .lambda_idx = rand_idx(CIR.Expr.Idx), .captures = CIR.Expr.Capture.Span{ .span = rand_span() }, }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_lambda = .{ .args = CIR.Pattern.Span{ .span = rand_span() }, .body = rand_idx(CIR.Expr.Idx), }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_binop = CIR.Expr.Binop.init( .add, rand_idx(CIR.Expr.Idx), rand_idx(CIR.Expr.Idx), ), }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_unary_minus = CIR.Expr.UnaryMinus.init(rand_idx(CIR.Expr.Idx)), }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_unary_not = CIR.Expr.UnaryNot.init(rand_idx(CIR.Expr.Idx)), }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_dot_access = .{ .receiver = rand_idx(CIR.Expr.Idx), .field_name = rand_ident_idx(), .args = null, }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_runtime_error = .{ .diagnostic = rand_idx(CIR.Diagnostic.Idx), }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_crash = .{ .msg = rand_idx(StringLiteral.Idx), }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_dbg = .{ .expr = rand_idx(CIR.Expr.Idx), }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_empty_record = .{}, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_expect = .{ .body = rand_idx(CIR.Expr.Idx), }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_dec = .{ .value = RocDec{ .num = 123456789 }, .has_suffix = false, }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_nominal_external = .{ .module_idx = rand_idx_u16(CIR.Import.Idx), .target_node_idx = rand.random().int(u16), @@ -367,7 +367,7 @@ test "NodeStore round trip - Expressions" { .backing_type = .tag, }, }); - try expressions.append(CIR.Expr{ + try expressions.append(gpa, CIR.Expr{ .e_ellipsis = .{}, }); @@ -397,118 +397,118 @@ test "NodeStore round trip - Diagnostics" { var store = try NodeStore.init(gpa); defer store.deinit(); - var diagnostics = std.array_list.Managed(CIR.Diagnostic).init(gpa); - defer diagnostics.deinit(); + var diagnostics = std.ArrayList(CIR.Diagnostic).empty; + defer diagnostics.deinit(gpa); // Test all diagnostic types to ensure complete coverage - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .not_implemented = .{ .feature = rand_idx(StringLiteral.Idx), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .invalid_num_literal = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .ident_already_in_scope = .{ .ident = rand_ident_idx(), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .crash_expects_string = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .ident_not_in_scope = .{ .ident = rand_ident_idx(), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .qualified_ident_does_not_exist = .{ .ident = rand_ident_idx(), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .invalid_top_level_statement = .{ .stmt = rand_idx(StringLiteral.Idx), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .expr_not_canonicalized = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .invalid_string_interpolation = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .pattern_arg_invalid = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .pattern_not_canonicalized = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .can_lambda_not_implemented = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .lambda_body_not_canonicalized = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .if_condition_not_canonicalized = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .if_then_not_canonicalized = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .if_else_not_canonicalized = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .var_across_function_boundary = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .shadowing_warning = .{ .ident = rand_ident_idx(), .region = rand_region(), @@ -516,7 +516,7 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .type_redeclared = .{ .name = rand_ident_idx(), .redeclared_region = rand_region(), @@ -524,80 +524,80 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .undeclared_type = .{ .name = rand_ident_idx(), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .undeclared_type_var = .{ .name = rand_ident_idx(), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .type_alias_but_needed_nominal = .{ .name = rand_ident_idx(), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .malformed_type_annotation = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .malformed_where_clause = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .where_clause_not_allowed_in_type_decl = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .type_module_missing_matching_type = .{ .module_name = rand_ident_idx(), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .default_app_missing_main = .{ .module_name = rand_ident_idx(), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .default_app_wrong_arity = .{ .arity = 2, .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .cannot_import_default_app = .{ .module_name = rand_ident_idx(), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .execution_requires_app_or_default_app = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .type_name_case_mismatch = .{ .module_name = rand_ident_idx(), .type_name = rand_ident_idx(), @@ -605,13 +605,13 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .module_header_deprecated = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .redundant_expose_main_type = .{ .type_name = rand_ident_idx(), .module_name = rand_ident_idx(), @@ -619,7 +619,7 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .invalid_main_type_rename_in_exposing = .{ .type_name = rand_ident_idx(), .alias = rand_ident_idx(), @@ -627,21 +627,21 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .unused_variable = .{ .ident = rand_ident_idx(), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .used_underscore_variable = .{ .ident = rand_ident_idx(), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .type_alias_redeclared = .{ .name = rand_ident_idx(), .original_region = rand_region(), @@ -649,7 +649,7 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .nominal_type_redeclared = .{ .name = rand_ident_idx(), .original_region = rand_region(), @@ -657,7 +657,7 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .type_shadowed_warning = .{ .name = rand_ident_idx(), .region = rand_region(), @@ -666,7 +666,7 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .type_parameter_conflict = .{ .name = rand_ident_idx(), .parameter_name = rand_ident_idx(), @@ -675,7 +675,7 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .duplicate_record_field = .{ .field_name = rand_ident_idx(), .duplicate_region = rand_region(), @@ -683,19 +683,19 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .invalid_single_quote = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .f64_pattern_literal = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .unused_type_var_name = .{ .name = rand_ident_idx(), .suggested_name = rand_ident_idx(), @@ -703,7 +703,7 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .type_var_marked_unused = .{ .name = rand_ident_idx(), .suggested_name = rand_ident_idx(), @@ -711,7 +711,7 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .type_var_ending_in_underscore = .{ .name = rand_ident_idx(), .suggested_name = rand_ident_idx(), @@ -719,33 +719,33 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .underscore_in_type_declaration = .{ .is_alias = rand.random().boolean(), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .tuple_elem_not_canonicalized = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .empty_tuple = .{ .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .exposed_but_not_implemented = .{ .ident = rand_ident_idx(), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .redundant_exposed = .{ .ident = rand_ident_idx(), .region = rand_region(), @@ -753,14 +753,14 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .module_not_found = .{ .module_name = rand_ident_idx(), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .value_not_exposed = .{ .module_name = rand_ident_idx(), .value_name = rand_ident_idx(), @@ -768,7 +768,7 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .type_not_exposed = .{ .module_name = rand_ident_idx(), .type_name = rand_ident_idx(), @@ -776,14 +776,14 @@ test "NodeStore round trip - Diagnostics" { }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .module_not_imported = .{ .module_name = rand_ident_idx(), .region = rand_region(), }, }); - try diagnostics.append(CIR.Diagnostic{ + try diagnostics.append(gpa, CIR.Diagnostic{ .too_many_exports = .{ .count = rand.random().int(u32), .region = rand_region(), @@ -816,25 +816,25 @@ test "NodeStore round trip - TypeAnno" { var store = try NodeStore.init(gpa); defer store.deinit(); - var type_annos = std.array_list.Managed(CIR.TypeAnno).init(gpa); - defer type_annos.deinit(); + var type_annos = std.ArrayList(CIR.TypeAnno).empty; + defer type_annos.deinit(gpa); // Test all TypeAnno variants to ensure complete coverage - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .apply = .{ .name = rand_ident_idx(), .base = .{ .builtin = .dec }, .args = CIR.TypeAnno.Span{ .span = rand_span() }, }, }); - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .apply = .{ .name = rand_ident_idx(), .base = .{ .local = .{ .decl_idx = @enumFromInt(10) } }, .args = CIR.TypeAnno.Span{ .span = rand_span() }, }, }); - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .apply = .{ .name = rand_ident_idx(), .base = .{ .external = .{ @@ -845,34 +845,34 @@ test "NodeStore round trip - TypeAnno" { }, }); - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .rigid_var = .{ .name = rand_ident_idx(), }, }); - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .rigid_var_lookup = .{ .ref = rand_idx(CIR.TypeAnno.Idx), }, }); - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .underscore = {}, }); - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .lookup = .{ .name = rand_ident_idx(), .base = .{ .builtin = .dec }, }, }); - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .lookup = .{ .name = rand_ident_idx(), .base = .{ .local = .{ .decl_idx = @enumFromInt(10) } }, }, }); - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .lookup = .{ .name = rand_ident_idx(), .base = .{ .external = .{ @@ -882,33 +882,33 @@ test "NodeStore round trip - TypeAnno" { }, }); - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .tag_union = .{ .tags = CIR.TypeAnno.Span{ .span = rand_span() }, .ext = rand_idx(CIR.TypeAnno.Idx), }, }); - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .tag = .{ .name = rand_ident_idx(), .args = CIR.TypeAnno.Span{ .span = rand_span() }, }, }); - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .tuple = .{ .elems = CIR.TypeAnno.Span{ .span = rand_span() }, }, }); - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .record = .{ .fields = CIR.TypeAnno.RecordField.Span{ .span = rand_span() }, }, }); - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .@"fn" = .{ .args = CIR.TypeAnno.Span{ .span = rand_span() }, .ret = rand_idx(CIR.TypeAnno.Idx), @@ -916,13 +916,13 @@ test "NodeStore round trip - TypeAnno" { }, }); - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .parens = .{ .anno = rand_idx(CIR.TypeAnno.Idx), }, }); - try type_annos.append(CIR.TypeAnno{ + try type_annos.append(gpa, CIR.TypeAnno{ .malformed = .{ .diagnostic = rand_idx(CIR.Diagnostic.Idx), }, @@ -960,35 +960,35 @@ test "NodeStore round trip - Pattern" { var store = try NodeStore.init(gpa); defer store.deinit(); - var patterns = std.array_list.Managed(CIR.Pattern).init(gpa); - defer patterns.deinit(); + var patterns = std.ArrayList(CIR.Pattern).empty; + defer patterns.deinit(gpa); // Test all Pattern variants to ensure complete coverage - try patterns.append(CIR.Pattern{ + try patterns.append(gpa, CIR.Pattern{ .assign = .{ .ident = rand_ident_idx(), }, }); - try patterns.append(CIR.Pattern{ + try patterns.append(gpa, CIR.Pattern{ .as = .{ .pattern = rand_idx(CIR.Pattern.Idx), .ident = rand_ident_idx(), }, }); - try patterns.append(CIR.Pattern{ + try patterns.append(gpa, CIR.Pattern{ .applied_tag = .{ .name = rand_ident_idx(), .args = CIR.Pattern.Span{ .span = rand_span() }, }, }); - try patterns.append(CIR.Pattern{ + try patterns.append(gpa, CIR.Pattern{ .nominal = .{ .nominal_type_decl = rand_idx(CIR.Statement.Idx), .backing_pattern = rand_idx(CIR.Pattern.Idx), .backing_type = .tag, }, }); - try patterns.append(CIR.Pattern{ + try patterns.append(gpa, CIR.Pattern{ .nominal_external = .{ .module_idx = rand_idx_u16(CIR.Import.Idx), .target_node_idx = rand.random().int(u16), @@ -996,23 +996,23 @@ test "NodeStore round trip - Pattern" { .backing_type = .tag, }, }); - try patterns.append(CIR.Pattern{ + try patterns.append(gpa, CIR.Pattern{ .record_destructure = .{ .destructs = CIR.Pattern.RecordDestruct.Span{ .span = rand_span() }, }, }); - try patterns.append(CIR.Pattern{ + try patterns.append(gpa, CIR.Pattern{ .list = .{ .patterns = CIR.Pattern.Span{ .span = rand_span() }, .rest_info = .{ .index = rand.random().int(u32), .pattern = rand_idx(CIR.Pattern.Idx) }, }, }); - try patterns.append(CIR.Pattern{ + try patterns.append(gpa, CIR.Pattern{ .tuple = .{ .patterns = CIR.Pattern.Span{ .span = rand_span() }, }, }); - try patterns.append(CIR.Pattern{ + try patterns.append(gpa, CIR.Pattern{ .num_literal = .{ .value = CIR.IntValue{ .bytes = @bitCast(rand.random().int(i128)), @@ -1021,7 +1021,7 @@ test "NodeStore round trip - Pattern" { .kind = .int_unbound, }, }); - try patterns.append(CIR.Pattern{ + try patterns.append(gpa, CIR.Pattern{ .small_dec_literal = .{ .value = .{ .numerator = rand.random().int(i16), @@ -1030,29 +1030,29 @@ test "NodeStore round trip - Pattern" { .has_suffix = true, }, }); - try patterns.append(CIR.Pattern{ + try patterns.append(gpa, CIR.Pattern{ .dec_literal = .{ .value = RocDec.fromU64(rand.random().int(u64)), .has_suffix = false, }, }); - try patterns.append(CIR.Pattern{ + try patterns.append(gpa, CIR.Pattern{ .str_literal = .{ .literal = rand_idx(StringLiteral.Idx), }, }); - try patterns.append(CIR.Pattern{ + try patterns.append(gpa, CIR.Pattern{ .frac_f32_literal = .{ .value = rand.random().float(f32), }, }); - try patterns.append(CIR.Pattern{ + try patterns.append(gpa, CIR.Pattern{ .frac_f64_literal = .{ .value = rand.random().float(f64), }, }); - try patterns.append(CIR.Pattern{ .underscore = {} }); - try patterns.append(CIR.Pattern{ + try patterns.append(gpa, CIR.Pattern{ .underscore = {} }); + try patterns.append(gpa, CIR.Pattern{ .runtime_error = .{ .diagnostic = rand_idx(CIR.Diagnostic.Idx), }, diff --git a/src/check/Check.zig b/src/check/Check.zig index 7c8fb89fd3..4be73fb003 100644 --- a/src/check/Check.zig +++ b/src/check/Check.zig @@ -1589,6 +1589,13 @@ fn generateBuiltinTypeInstance( } } +// types // + +const Expected = union(enum) { + no_expectation, + expected: struct { var_: Var, from_annotation: bool }, +}; + // pattern // /// Check the types for the provided pattern, saving the type in-place @@ -2036,11 +2043,6 @@ fn checkPatternHelp( // expr // -const Expected = union(enum) { - no_expectation, - expected: struct { var_: Var, from_annotation: bool }, -}; - fn checkExpr(self: *Self, expr_idx: CIR.Expr.Idx, rank: types_mod.Rank, expected: Expected) std.mem.Allocator.Error!bool { const trace = tracy.trace(@src()); defer trace.end(); @@ -2474,110 +2476,7 @@ fn checkExpr(self: *Self, expr_idx: CIR.Expr.Idx, rank: types_mod.Rank, expected // Check all statements in the block const statements = self.cir.store.sliceStatements(block.stmts); - for (statements) |stmt_idx| { - const stmt = self.cir.store.getStatement(stmt_idx); - switch (stmt) { - .s_decl => |decl_stmt| { - // Check the pattern - try self.checkPattern(decl_stmt.pattern, rank, .no_expectation); - const decl_pattern_var: Var = ModuleEnv.varFrom(decl_stmt.pattern); - - // Check the annotation, if it exists - const check_mode = blk: { - if (decl_stmt.anno) |annotation_idx| { - // Generate the annotation type var in-place - try self.generateAnnotationType(annotation_idx); - const annotation_var = ModuleEnv.varFrom(annotation_idx); - - // Return the expectation - break :blk Expected{ - .expected = .{ .var_ = annotation_var, .from_annotation = true }, - }; - } else { - break :blk Expected.no_expectation; - } - }; - - { - // Enter a new rank - try self.var_pool.pushRank(); - defer self.var_pool.popRank(); - - const next_rank = rank.next(); - std.debug.assert(next_rank == self.var_pool.current_rank); - - does_fx = try self.checkExpr(decl_stmt.expr, next_rank, check_mode) or does_fx; - - // Now that we are existing the scope, we must generalize then pop this rank - try self.generalizer.generalize(&self.var_pool, next_rank); - } - - // Unify the pattern with the expression - const decl_expr_var: Var = ModuleEnv.varFrom(decl_stmt.expr); - _ = try self.unify(decl_pattern_var, decl_expr_var, rank); - }, - .s_reassign => |reassign| { - // Check the pattern - try self.checkPattern(reassign.pattern_idx, rank, .no_expectation); - const reassign_pattern_var: Var = ModuleEnv.varFrom(reassign.pattern_idx); - - { - // Enter a new rank - try self.var_pool.pushRank(); - defer self.var_pool.popRank(); - - const next_rank = rank.next(); - std.debug.assert(next_rank == self.var_pool.current_rank); - - does_fx = try self.checkExpr(reassign.expr, next_rank, .no_expectation) or does_fx; - - // Now that we are existing the scope, we must generalize then pop this rank - try self.generalizer.generalize(&self.var_pool, next_rank); - } - - // Unify the pattern with the expression - const reassign_expr_var: Var = ModuleEnv.varFrom(reassign.expr); - _ = try self.unify(reassign_pattern_var, reassign_expr_var, rank); - }, - .s_expr => |expr_stmt| { - does_fx = try self.checkExpr(expr_stmt.expr, rank, .no_expectation) or does_fx; - }, - .s_expect => |expr_stmt| { - does_fx = try self.checkExpr(expr_stmt.body, rank, .no_expectation) or does_fx; - const stmt_expr: Var = ModuleEnv.varFrom(expr_stmt.body); - - const bool_var = try self.freshBool(rank, expr_region); - _ = try self.unify(bool_var, stmt_expr, rank); - }, - .s_var => |var_stmt| { - - // Check the pattern - try self.checkPattern(var_stmt.pattern_idx, rank, .no_expectation); - const var_pattern_var: Var = ModuleEnv.varFrom(var_stmt.pattern_idx); - - { - // Enter a new rank - try self.var_pool.pushRank(); - defer self.var_pool.popRank(); - - const next_rank = rank.next(); - std.debug.assert(next_rank == self.var_pool.current_rank); - - does_fx = try self.checkExpr(var_stmt.expr, next_rank, Expected.no_expectation) or does_fx; - - // Now that we are existing the scope, we must generalize then pop this rank - try self.generalizer.generalize(&self.var_pool, next_rank); - } - - // Unify the pattern with the expression - const var_expr_var: Var = ModuleEnv.varFrom(var_stmt.expr); - _ = try self.unify(var_pattern_var, var_expr_var, rank); - }, - else => { - // TODO - }, - } - } + does_fx = try self.checkBlockStatements(statements, rank, expr_region) or does_fx; // Check the final expression does_fx = try self.checkExpr(block.final_expr, rank, expected) or does_fx; @@ -3093,6 +2992,199 @@ fn checkExpr(self: *Self, expr_idx: CIR.Expr.Idx, rank: types_mod.Rank, expected return does_fx; } +// stmts // + +/// Given a slice of stmts, type check each one +fn checkBlockStatements(self: *Self, statements: []const CIR.Statement.Idx, rank: types_mod.Rank, _: Region) std.mem.Allocator.Error!bool { + var does_fx = false; + for (statements) |stmt_idx| { + const stmt = self.cir.store.getStatement(stmt_idx); + const stmt_var = ModuleEnv.varFrom(stmt_idx); + const stmt_region = self.cir.store.getNodeRegion(ModuleEnv.nodeIdxFrom(stmt_idx)); + + switch (stmt) { + .s_decl => |decl_stmt| { + // Check the pattern + try self.checkPattern(decl_stmt.pattern, rank, .no_expectation); + const decl_pattern_var: Var = ModuleEnv.varFrom(decl_stmt.pattern); + + // Check the annotation, if it exists + const expectation = blk: { + if (decl_stmt.anno) |annotation_idx| { + // Generate the annotation type var in-place + try self.generateAnnotationType(annotation_idx); + const annotation_var = ModuleEnv.varFrom(annotation_idx); + + // Return the expectation + break :blk Expected{ + .expected = .{ .var_ = annotation_var, .from_annotation = true }, + }; + } else { + break :blk Expected.no_expectation; + } + }; + + // Evaluate the rhs of the expression + { + // Enter a new rank + try self.var_pool.pushRank(); + defer self.var_pool.popRank(); + + const next_rank = rank.next(); + std.debug.assert(next_rank == self.var_pool.current_rank); + + does_fx = try self.checkExpr(decl_stmt.expr, next_rank, expectation) or does_fx; + + // Now that we are existing the scope, we must generalize then pop this rank + try self.generalizer.generalize(&self.var_pool, next_rank); + } + + // Unify the pattern with the expression + const decl_expr_var: Var = ModuleEnv.varFrom(decl_stmt.expr); + _ = try self.unify(decl_pattern_var, decl_expr_var, rank); + + try self.types.setVarRedirect(stmt_var, decl_expr_var); + }, + .s_var => |var_stmt| { + // Check the pattern + try self.checkPattern(var_stmt.pattern_idx, rank, .no_expectation); + const reassign_pattern_var: Var = ModuleEnv.varFrom(var_stmt.pattern_idx); + + // Evaluate the rhs of the expression + { + // Enter a new rank + try self.var_pool.pushRank(); + defer self.var_pool.popRank(); + + const next_rank = rank.next(); + std.debug.assert(next_rank == self.var_pool.current_rank); + + does_fx = try self.checkExpr(var_stmt.expr, next_rank, .no_expectation) or does_fx; + + // Now that we are existing the scope, we must generalize then pop this rank + try self.generalizer.generalize(&self.var_pool, next_rank); + } + + // Unify the pattern with the expression + const var_expr: Var = ModuleEnv.varFrom(var_stmt.expr); + _ = try self.unify(reassign_pattern_var, var_expr, rank); + + try self.types.setVarRedirect(stmt_var, var_expr); + }, + .s_reassign => |reassign| { + // Check the pattern + try self.checkPattern(reassign.pattern_idx, rank, .no_expectation); + const reassign_pattern_var: Var = ModuleEnv.varFrom(reassign.pattern_idx); + + // Evaluate the rhs of the expression + { + // Enter a new rank + try self.var_pool.pushRank(); + defer self.var_pool.popRank(); + + const next_rank = rank.next(); + std.debug.assert(next_rank == self.var_pool.current_rank); + + does_fx = try self.checkExpr(reassign.expr, next_rank, .no_expectation) or does_fx; + + // Now that we are existing the scope, we must generalize then pop this rank + try self.generalizer.generalize(&self.var_pool, next_rank); + } + + // Unify the pattern with the expression + const reassign_expr_var: Var = ModuleEnv.varFrom(reassign.expr); + _ = try self.unify(reassign_pattern_var, reassign_expr_var, rank); + + try self.types.setVarRedirect(stmt_var, reassign_expr_var); + }, + .s_for => |for_stmt| { + // Check the pattern + // for item in [1,2,3] { + // ^^^^ + try self.checkPattern(for_stmt.patt, rank, .no_expectation); + const for_ptrn_var: Var = ModuleEnv.varFrom(for_stmt.patt); + + // Check the expr + // for item in [1,2,3] { + // ^^^^^^^ + does_fx = try self.checkExpr(for_stmt.expr, rank, .no_expectation) or does_fx; + const for_expr_region = self.cir.store.getNodeRegion(ModuleEnv.nodeIdxFrom(for_stmt.expr)); + const for_expr_var: Var = ModuleEnv.varFrom(for_stmt.expr); + + // Check that the expr is list of the ptrn + const list_var = try self.freshFromContent(.{ .structure = .{ .list = for_ptrn_var } }, rank, for_expr_region); + _ = try self.unify(list_var, for_expr_var, rank); + + // Check the body + // for item in [1,2,3] { + // print!(item.toStr()) <<<< + // } + does_fx = try self.checkExpr(for_stmt.body, rank, .no_expectation) or does_fx; + const for_body_var: Var = ModuleEnv.varFrom(for_stmt.body); + + // Check that the for body evaluates to {} + const body_ret = try self.freshFromContent(.{ .structure = .empty_record }, rank, for_expr_region); + _ = try self.unify(body_ret, for_body_var, rank); + + try self.types.setVarRedirect(stmt_var, for_body_var); + }, + .s_expr => |expr| { + does_fx = try self.checkExpr(expr.expr, rank, .no_expectation) or does_fx; + const expr_var: Var = ModuleEnv.varFrom(expr.expr); + + const resolved = self.types.resolveVar(expr_var).desc.content; + if (resolved == .err or (resolved == .structure and resolved.structure == .empty_record)) { + // If this type resolves to an empty record, then we are good! + } else { + const snapshot = try self.snapshots.deepCopyVar(self.types, expr_var); + _ = try self.problems.appendProblem(self.cir.gpa, .{ .unused_value = .{ + .var_ = expr_var, + .snapshot = snapshot, + } }); + } + + try self.types.setVarRedirect(stmt_var, expr_var); + }, + .s_dbg => |expr| { + does_fx = try self.checkExpr(expr.expr, rank, .no_expectation) or does_fx; + const expr_var: Var = ModuleEnv.varFrom(expr.expr); + + try self.types.setVarRedirect(stmt_var, expr_var); + }, + .s_expect => |expr_stmt| { + does_fx = try self.checkExpr(expr_stmt.body, rank, .no_expectation) or does_fx; + const body_var: Var = ModuleEnv.varFrom(expr_stmt.body); + + const bool_var = try self.freshBool(rank, stmt_region); + _ = try self.unify(bool_var, body_var, rank); + + try self.types.setVarRedirect(stmt_var, body_var); + }, + .s_crash => |_| { + try self.updateVar(stmt_var, .{ .flex = Flex.init() }, rank); + }, + .s_return => |_| { + // To implement early returns and make them usable, we need to: + // 1. Update the parse to allow for if statements (as opposed to if expressions) + // 2. Track function scope in czer and capture the function for this return in `s_return` + // 3. When type checking a lambda, capture all early returns + // a. Unify all early returns together + // b. Unify early returns with func return type + + try self.updateVar(stmt_var, .{ .structure = .empty_record }, rank); + }, + .s_import, .s_alias_decl, .s_nominal_decl, .s_type_anno => { + // These are only valid at the top level, czer reports error + try self.updateVar(stmt_var, .err, rank); + }, + .s_runtime_error => { + try self.updateVar(stmt_var, .err, rank); + }, + } + } + return does_fx; +} + // if-else // /// Check the types for an if-else expr diff --git a/src/check/copy_import.zig b/src/check/copy_import.zig index 70a2218ee7..b589983924 100644 --- a/src/check/copy_import.zig +++ b/src/check/copy_import.zig @@ -165,17 +165,17 @@ fn copyAlias( const type_name_str = source_idents.getText(source_alias.ident.ident_idx); const translated_ident = try dest_idents.insert(allocator, base.Ident.for_text(type_name_str)); - var dest_args = std.array_list.Managed(Var).init(dest_store.gpa); - defer dest_args.deinit(); + var dest_args = std.ArrayList(Var).empty; + defer dest_args.deinit(dest_store.gpa); const origin_backing = source_store.getAliasBackingVar(source_alias); const dest_backing = try copyVar(source_store, dest_store, origin_backing, var_mapping, source_idents, dest_idents, allocator); - try dest_args.append(dest_backing); + try dest_args.append(dest_store.gpa, dest_backing); const origin_args = source_store.sliceAliasArgs(source_alias); for (origin_args) |arg_var| { const dest_arg = try copyVar(source_store, dest_store, arg_var, var_mapping, source_idents, dest_idents, allocator); - try dest_args.append(dest_arg); + try dest_args.append(dest_store.gpa, dest_arg); } const dest_vars_span = try dest_store.appendVars(dest_args.items); @@ -225,12 +225,12 @@ fn copyTuple( ) std.mem.Allocator.Error!types_mod.Tuple { const elems_slice = source_store.sliceVars(tuple.elems); - var dest_elems = std.array_list.Managed(Var).init(dest_store.gpa); - defer dest_elems.deinit(); + var dest_elems = std.ArrayList(Var).empty; + defer dest_elems.deinit(dest_store.gpa); for (elems_slice) |elem_var| { const dest_elem = try copyVar(source_store, dest_store, elem_var, var_mapping, source_idents, dest_idents, allocator); - try dest_elems.append(dest_elem); + try dest_elems.append(dest_store.gpa, dest_elem); } const dest_range = try dest_store.appendVars(dest_elems.items); @@ -270,12 +270,12 @@ fn copyFunc( ) std.mem.Allocator.Error!Func { const args_slice = source_store.sliceVars(func.args); - var dest_args = std.array_list.Managed(Var).init(dest_store.gpa); - defer dest_args.deinit(); + var dest_args = std.ArrayList(Var).empty; + defer dest_args.deinit(dest_store.gpa); for (args_slice) |arg_var| { const dest_arg = try copyVar(source_store, dest_store, arg_var, var_mapping, source_idents, dest_idents, allocator); - try dest_args.append(dest_arg); + try dest_args.append(dest_store.gpa, dest_arg); } const dest_ret = try copyVar(source_store, dest_store, func.ret, var_mapping, source_idents, dest_idents, allocator); @@ -299,13 +299,13 @@ fn copyRecordFields( ) std.mem.Allocator.Error!types_mod.RecordField.SafeMultiList.Range { const source_fields = source_store.getRecordFieldsSlice(fields_range); - var fresh_fields = std.array_list.Managed(RecordField).init(allocator); - defer fresh_fields.deinit(); + var fresh_fields = std.ArrayList(RecordField).empty; + defer fresh_fields.deinit(allocator); for (source_fields.items(.name), source_fields.items(.var_)) |name, var_| { const name_str = source_idents.getText(name); const translated_name = try dest_idents.insert(allocator, base.Ident.for_text(name_str)); - _ = try fresh_fields.append(.{ + _ = try fresh_fields.append(allocator, .{ .name = translated_name, // Field names are local to the record type .var_ = try copyVar(source_store, dest_store, var_, var_mapping, source_idents, dest_idents, allocator), }); @@ -350,18 +350,18 @@ fn copyTagUnion( ) std.mem.Allocator.Error!TagUnion { const tags_slice = source_store.getTagsSlice(tag_union.tags); - var fresh_tags = std.array_list.Managed(Tag).init(allocator); - defer fresh_tags.deinit(); + var fresh_tags = std.ArrayList(Tag).empty; + defer fresh_tags.deinit(allocator); for (tags_slice.items(.name), tags_slice.items(.args)) |name, args_range| { const args_slice = source_store.sliceVars(args_range); - var dest_args = std.array_list.Managed(Var).init(dest_store.gpa); - defer dest_args.deinit(); + var dest_args = std.ArrayList(Var).empty; + defer dest_args.deinit(dest_store.gpa); for (args_slice) |arg_var| { const dest_arg = try copyVar(source_store, dest_store, arg_var, var_mapping, source_idents, dest_idents, allocator); - try dest_args.append(dest_arg); + try dest_args.append(dest_store.gpa, dest_arg); } const dest_args_range = try dest_store.appendVars(dest_args.items); @@ -369,7 +369,7 @@ fn copyTagUnion( const name_str = source_idents.getText(name); const translated_name = try dest_idents.insert(allocator, base.Ident.for_text(name_str)); - _ = try fresh_tags.append(.{ + _ = try fresh_tags.append(allocator, .{ .name = translated_name, // Tag names are local to the union type .args = dest_args_range, }); @@ -400,17 +400,17 @@ fn copyNominalType( const origin_str = source_idents.getText(source_nominal.origin_module); const translated_origin = try dest_idents.insert(allocator, base.Ident.for_text(origin_str)); - var dest_args = std.array_list.Managed(Var).init(dest_store.gpa); - defer dest_args.deinit(); + var dest_args = std.ArrayList(Var).empty; + defer dest_args.deinit(dest_store.gpa); const origin_backing = source_store.getNominalBackingVar(source_nominal); const dest_backing = try copyVar(source_store, dest_store, origin_backing, var_mapping, source_idents, dest_idents, allocator); - try dest_args.append(dest_backing); + try dest_args.append(dest_store.gpa, dest_backing); const origin_args = source_store.sliceNominalArgs(source_nominal); for (origin_args) |arg_var| { const dest_arg = try copyVar(source_store, dest_store, arg_var, var_mapping, source_idents, dest_idents, allocator); - try dest_args.append(dest_arg); + try dest_args.append(dest_store.gpa, dest_arg); } const dest_vars_span = try dest_store.appendVars(dest_args.items); diff --git a/src/check/problem.zig b/src/check/problem.zig index a7ad5fb28b..39ca342088 100644 --- a/src/check/problem.zig +++ b/src/check/problem.zig @@ -39,6 +39,7 @@ pub const Problem = union(enum) { static_dispach: StaticDispatch, number_does_not_fit: NumberDoesNotFit, negative_unsigned_int: NegativeUnsignedInt, + unused_value: UnusedValue, infinite_recursion: struct { var_: Var }, anonymous_recursion: struct { var_: Var }, invalid_number_type: VarProblem1, @@ -91,6 +92,12 @@ pub const NegativeUnsignedInt = struct { expected_type: SnapshotContentIdx, }; +/// Error when a stmt expression returns a non-empty record value +pub const UnusedValue = struct { + var_: Var, + snapshot: SnapshotContentIdx, +}; + // type mismatch // /// These two variables mismatch. This should usually be cast into a more @@ -351,6 +358,9 @@ pub const ReportBuilder = struct { .negative_unsigned_int => |data| { return self.buildNegativeUnsignedIntReport(data); }, + .unused_value => |data| { + return self.buildUnusedValueReport(data); + }, .infinite_recursion => |_| return self.buildUnimplementedReport("infinite_recursion"), .anonymous_recursion => |_| return self.buildUnimplementedReport("anonymous_recursion"), .invalid_number_type => |_| return self.buildUnimplementedReport("invalid_number_type"), @@ -1778,6 +1788,38 @@ pub const ReportBuilder = struct { return report; } + /// Build a report for "negative unsigned integer" diagnostic + fn buildUnusedValueReport(self: *Self, data: UnusedValue) !Report { + var report = Report.init(self.gpa, "UNUSED VALUE", .runtime_error); + errdefer report.deinit(); + + self.snapshot_writer.resetContext(); + try self.snapshot_writer.write(data.snapshot); + const owned_expected = try report.addOwnedString(self.snapshot_writer.get()); + + const region = self.can_ir.store.regions.get(@enumFromInt(@intFromEnum(data.var_))); + const region_info = self.module_env.calcRegionInfo(region.*); + + try report.document.addReflowingText("This expression produces a value, but it's not being used:"); + try report.document.addLineBreak(); + + try report.document.addSourceRegion( + region_info, + .error_highlight, + self.filename, + self.source, + self.module_env.getLineStarts(), + ); + try report.document.addLineBreak(); + + try report.document.addReflowingText("It has the type:"); + try report.document.addLineBreak(); + try report.document.addText(" "); + try report.document.addAnnotated(owned_expected, .type_variable); + + return report; + } + // cross-module import // /// Build a report for cross-module import type mismatch @@ -2054,11 +2096,11 @@ pub const Store = struct { const Self = @This(); const ALIGNMENT = std.mem.Alignment.@"16"; - problems: std.ArrayListAlignedUnmanaged(Problem, ALIGNMENT) = .{}, + problems: std.ArrayListAligned(Problem, ALIGNMENT) = .{}, pub fn initCapacity(gpa: Allocator, capacity: usize) std.mem.Allocator.Error!Self { return .{ - .problems = try std.ArrayListAlignedUnmanaged(Problem, ALIGNMENT).initCapacity(gpa, capacity), + .problems = try std.ArrayListAligned(Problem, ALIGNMENT).initCapacity(gpa, capacity), }; } diff --git a/src/check/test/compiled_builtins_test.zig b/src/check/test/compiled_builtins_test.zig index 59a3bc3e8b..a0b0ca2bea 100644 --- a/src/check/test/compiled_builtins_test.zig +++ b/src/check/test/compiled_builtins_test.zig @@ -227,10 +227,10 @@ test "compiled builtins - use Set and Dict together" { try can_result.validateForChecking(); // Type check - var imported_envs = std.array_list.Managed(*const ModuleEnv).init(gpa); - defer imported_envs.deinit(); - try imported_envs.append(set_loaded.env); - try imported_envs.append(dict_loaded.env); + var imported_envs = std.ArrayList(*const ModuleEnv).empty; + defer imported_envs.deinit(gpa); + try imported_envs.append(gpa, set_loaded.env); + try imported_envs.append(gpa, dict_loaded.env); var checker = try Check.init( gpa, diff --git a/src/check/test/nominal_type_origin_test.zig b/src/check/test/nominal_type_origin_test.zig index 615a9149ff..70ccba9689 100644 --- a/src/check/test/nominal_type_origin_test.zig +++ b/src/check/test/nominal_type_origin_test.zig @@ -83,8 +83,8 @@ test "nominal type origin - displays origin in snapshot writer" { // Test 3: Origin shown with type arguments { - var buf = std.array_list.Managed(u8).init(test_allocator); - defer buf.deinit(); + var buf = std.ArrayList(u8).empty; + defer buf.deinit(test_allocator); // Create type arguments const str_content = snapshot.SnapshotContent{ .structure = .{ .str = {} } }; diff --git a/src/check/test/type_checking_integration.zig b/src/check/test/type_checking_integration.zig index 9fe02de47a..5ae3be5469 100644 --- a/src/check/test/type_checking_integration.zig +++ b/src/check/test/type_checking_integration.zig @@ -947,7 +947,7 @@ test "check type - patterns record field mismatch" { try checkTypesExpr(source, .fail, "INCOMPATIBLE MATCH PATTERNS"); } -// vars +// vars + reassignment // test "check type - var ressignment" { const source = @@ -960,7 +960,7 @@ test "check type - var ressignment" { try checkTypesModule(source, .{ .pass = .last_def }, "Num(_size)"); } -// expect +// expect // test "check type - expect" { const source = @@ -984,6 +984,92 @@ test "check type - expect not bool" { try checkTypesModule(source, .fail, "TYPE MISMATCH"); } +// crash // + +test "check type - crash" { + const source = + \\module [] + \\ + \\y : U64 + \\y = { + \\ crash "bug" + \\} + \\ + \\main = { + \\ x = 1 + \\ x + y + \\} + ; + try checkTypesModule( + source, + .{ .pass = .{ .def = "main" } }, + "Num(Int(Unsigned64))", + ); +} + +// debug // + +test "check type - debug" { + const source = + \\module [] + \\ + \\y : U64 + \\y = { + \\ debug 2 + \\} + \\ + \\main = { + \\ x = 1 + \\ x + y + \\} + ; + try checkTypesModule( + source, + .{ .pass = .{ .def = "main" } }, + "Num(Int(Unsigned64))", + ); +} + +// for // + +test "check type - for" { + const source = + \\module [] + \\ + \\main = { + \\ var result = 0 + \\ for x in [1, 2, 3] { + \\ result = result + x + \\ } + \\ result + \\} + ; + try checkTypesModule( + source, + .{ .pass = .{ .def = "main" } }, + "Num(_size)", + ); +} + +test "check type - for mismatch" { + const source = + \\module [] + \\ + \\main = { + \\ var result = 0 + \\ for x in ["a", "b", "c"] { + \\ result = result + x + \\ } + \\ result + \\} + ; + try checkTypesModule( + source, + .fail, + "TYPE MISMATCH", + ); +} + // static dispatch // test "check type - static dispatch - polymorphic - annotation" { diff --git a/src/cli/main.zig b/src/cli/main.zig index 4985622217..2bdc5ea7db 100644 --- a/src/cli/main.zig +++ b/src/cli/main.zig @@ -1886,8 +1886,8 @@ pub fn rocBundle(allocs: *Allocators, args: cli_args.BundleArgs) !void { } // Collect all files to bundle - var file_paths = std.array_list.Managed([]const u8).init(allocs.arena); - defer file_paths.deinit(); + var file_paths = std.ArrayList([]const u8).empty; + defer file_paths.deinit(allocs.arena); var uncompressed_size: u64 = 0; @@ -1908,7 +1908,7 @@ pub fn rocBundle(allocs: *Allocators, args: cli_args.BundleArgs) !void { const stat = try file.stat(); uncompressed_size += stat.size; - try file_paths.append(path); + try file_paths.append(allocs.arena, path); } // Sort and deduplicate paths @@ -2623,14 +2623,14 @@ fn rocFormat(allocs: *Allocators, args: cli_args.FormatArgs) !void { var exit_code: u8 = 0; if (args.check) { - var unformatted_files = std.array_list.Managed([]const u8).init(allocs.gpa); - defer unformatted_files.deinit(); + var unformatted_files = std.ArrayList([]const u8).empty; + defer unformatted_files.deinit(allocs.gpa); for (args.paths) |path| { var result = try fmt.formatPath(allocs.gpa, allocs.arena, std.fs.cwd(), path, true); defer result.deinit(); if (result.unformatted_files) |files| { - try unformatted_files.appendSlice(files.items); + try unformatted_files.appendSlice(allocs.gpa, files.items); } failure_count += result.failure; } @@ -2695,6 +2695,10 @@ fn handleProcessFileError(err: anytype, stderr: anytype, path: []const u8) noret // Catch-all for any other errors else => stderr.print("{s}", .{@errorName(err)}) catch {}, } + stderr.print("\n", .{}) catch {}; + + // Flush stderr before exit to ensure error message is visible + stderr_writer.interface.flush() catch {}; std.process.exit(1); } @@ -3695,11 +3699,11 @@ fn generateAppDocs( } // Convert map to sorted list - var modules_list = std.array_list.Managed(ModuleInfo).init(allocs.gpa); - defer modules_list.deinit(); + var modules_list = std.ArrayList(ModuleInfo).empty; + defer modules_list.deinit(allocs.gpa); var map_iter = modules_map.iterator(); while (map_iter.next()) |entry| { - try modules_list.append(entry.value_ptr.*); + try modules_list.append(allocs.gpa, entry.value_ptr.*); } // Collect package shorthands diff --git a/src/cli/test_bundle_logic.zig b/src/cli/test_bundle_logic.zig index d5ca904f5e..03a89224b4 100644 --- a/src/cli/test_bundle_logic.zig +++ b/src/cli/test_bundle_logic.zig @@ -14,10 +14,10 @@ test "bundle paths - empty list defaults to main.roc" { test "bundle paths - single file unchanged" { const allocator = testing.allocator; - var file_paths = std.array_list.Managed([]const u8).init(allocator); - defer file_paths.deinit(); + var file_paths = std.ArrayList([]const u8).empty; + defer file_paths.deinit(allocator); - try file_paths.append("app.roc"); + try file_paths.append(allocator, "app.roc"); try testing.expectEqual(@as(usize, 1), file_paths.items.len); try testing.expectEqualStrings("app.roc", file_paths.items[0]); @@ -26,14 +26,14 @@ test "bundle paths - single file unchanged" { test "bundle paths - sorting and deduplication" { const allocator = testing.allocator; - var file_paths = std.array_list.Managed([]const u8).init(allocator); - defer file_paths.deinit(); + var file_paths = std.ArrayList([]const u8).empty; + defer file_paths.deinit(allocator); // Add paths in non-sorted order with duplicates - try file_paths.append("zebra.roc"); - try file_paths.append("apple.roc"); - try file_paths.append("banana.roc"); - try file_paths.append("apple.roc"); + try file_paths.append(allocator, "zebra.roc"); + try file_paths.append(allocator, "apple.roc"); + try file_paths.append(allocator, "banana.roc"); + try file_paths.append(allocator, "apple.roc"); const first_cli_path = file_paths.items[0]; // "zebra.roc" @@ -85,18 +85,18 @@ test "bundle paths - sorting and deduplication" { test "bundle paths - preserves first CLI arg with many files" { const allocator = testing.allocator; - var file_paths = std.array_list.Managed([]const u8).init(allocator); - defer file_paths.deinit(); + var file_paths = std.ArrayList([]const u8).empty; + defer file_paths.deinit(allocator); // Add 8 paths with specific first - try file_paths.append("tests/test2.roc"); - try file_paths.append("main.roc"); - try file_paths.append("src/app.roc"); - try file_paths.append("src/lib.roc"); - try file_paths.append("src/utils/helper.roc"); - try file_paths.append("tests/test1.roc"); - try file_paths.append("docs/readme.md"); - try file_paths.append("config.roc"); + try file_paths.append(allocator, "tests/test2.roc"); + try file_paths.append(allocator, "main.roc"); + try file_paths.append(allocator, "src/app.roc"); + try file_paths.append(allocator, "src/lib.roc"); + try file_paths.append(allocator, "src/utils/helper.roc"); + try file_paths.append(allocator, "tests/test1.roc"); + try file_paths.append(allocator, "docs/readme.md"); + try file_paths.append(allocator, "config.roc"); const first_cli_path = file_paths.items[0]; // "tests/test2.roc" diff --git a/src/collections/safe_list.zig b/src/collections/safe_list.zig index e66dba3c84..84307d400d 100644 --- a/src/collections/safe_list.zig +++ b/src/collections/safe_list.zig @@ -1218,8 +1218,8 @@ test "SafeList CompactWriter interleaved pattern with alignment tracking" { defer writer.deinit(gpa); // Track offsets as we go - var offsets = std.array_list.Managed(usize).init(gpa); - defer offsets.deinit(); + var offsets = std.ArrayList(usize).empty; + defer offsets.deinit(gpa); // Create temp file var tmp_dir = testing.tmpDir(.{}); @@ -1238,7 +1238,7 @@ test "SafeList CompactWriter interleaved pattern with alignment tracking" { _ = try list1.append(gpa, 3); const start1 = writer.total_bytes; - try offsets.append(start1); // Serialized struct is placed at current position + try offsets.append(gpa, start1); // Serialized struct is placed at current position const serialized1 = try writer.appendAlloc(gpa, SafeList(u8).Serialized); try serialized1.serialize(&list1, gpa, &writer); @@ -1249,7 +1249,7 @@ test "SafeList CompactWriter interleaved pattern with alignment tracking" { _ = try list2.append(gpa, 2_000_000); const start2 = writer.total_bytes; - try offsets.append(start2); // Serialized struct is placed at current position + try offsets.append(gpa, start2); // Serialized struct is placed at current position const serialized2 = try writer.appendAlloc(gpa, SafeList(u64).Serialized); try serialized2.serialize(&list2, gpa, &writer); @@ -1266,7 +1266,7 @@ test "SafeList CompactWriter interleaved pattern with alignment tracking" { _ = try list3.append(gpa, 400); const start3 = writer.total_bytes; - try offsets.append(start3); // Serialized struct is placed at current position + try offsets.append(gpa, start3); // Serialized struct is placed at current position const serialized3 = try writer.appendAlloc(gpa, SafeList(u16).Serialized); try serialized3.serialize(&list3, gpa, &writer); @@ -1276,7 +1276,7 @@ test "SafeList CompactWriter interleaved pattern with alignment tracking" { _ = try list4.append(gpa, 42); const start4 = writer.total_bytes; - try offsets.append(start4); // Serialized struct is placed at current position + try offsets.append(gpa, start4); // Serialized struct is placed at current position const serialized4 = try writer.appendAlloc(gpa, SafeList(u32).Serialized); try serialized4.serialize(&list4, gpa, &writer); diff --git a/src/compile/compile_build.zig b/src/compile/compile_build.zig index e5fe83d0b4..20e6c1c5e9 100644 --- a/src/compile/compile_build.zig +++ b/src/compile/compile_build.zig @@ -715,9 +715,9 @@ pub const BuildEnv = struct { // Simple DFS walk on shorthand edges to detect if to_pkg reaches from_pkg if (std.mem.eql(u8, from_pkg, to_pkg)) return true; - var stack = std.array_list.Managed([]const u8).init(self.gpa); - defer stack.deinit(); - stack.append(to_pkg) catch { + var stack = std.ArrayList([]const u8).empty; + defer stack.deinit(self.gpa); + stack.append(self.gpa, to_pkg) catch { return false; }; @@ -739,7 +739,7 @@ pub const BuildEnv = struct { var it = pkg.shorthands.iterator(); while (it.next()) |e| { const next = e.value_ptr.name; - stack.append(next) catch { + stack.append(self.gpa, next) catch { return false; }; } @@ -906,8 +906,8 @@ pub const BuildEnv = struct { const e = ast.store.getExpr(expr_idx); return switch (e) { .string => |s| blk: { - var buf = std.array_list.Managed(u8).init(self.gpa); - errdefer buf.deinit(); + var buf = std.ArrayList(u8).empty; + errdefer buf.deinit(self.gpa); // Use exprSlice to properly iterate through string parts for (ast.store.exprSlice(s.parts)) |part_idx| { @@ -915,11 +915,11 @@ pub const BuildEnv = struct { if (part == .string_part) { const tok = part.string_part.token; const slice = ast.resolve(tok); - try buf.appendSlice(slice); + try buf.appendSlice(self.gpa, slice); } } - const result = try buf.toOwnedSlice(); + const result = try buf.toOwnedSlice(self.gpa); // Check for null bytes in the string, which are invalid in file paths if (std.mem.indexOfScalar(u8, result, 0) != null) { @@ -944,13 +944,13 @@ pub const BuildEnv = struct { fn dottedToPath(self: *BuildEnv, root_dir: []const u8, dotted: []const u8) ![]const u8 { var parts = std.mem.splitScalar(u8, dotted, '.'); - var segs = std.array_list.Managed([]const u8).init(self.gpa); - defer segs.deinit(); + var segs = std.ArrayList([]const u8).empty; + defer segs.deinit(self.gpa); - try segs.append(root_dir); + try segs.append(self.gpa, root_dir); while (parts.next()) |p| { if (p.len == 0) continue; - try segs.append(p); + try segs.append(self.gpa, p); } const joined = try std.fs.path.join(self.gpa, segs.items); @@ -1154,12 +1154,12 @@ pub const BuildEnv = struct { // sort by (min dependency depth from root app, then package and module names). fn emitDeterministic(self: *BuildEnv) !void { // Build arrays of package names, module names, and depths - var pkg_names = std.array_list.Managed([]const u8).init(self.gpa); - defer pkg_names.deinit(); - var module_names = std.array_list.Managed([]const u8).init(self.gpa); - defer module_names.deinit(); - var depths = std.array_list.Managed(u32).init(self.gpa); - defer depths.deinit(); + var pkg_names = std.ArrayList([]const u8).empty; + defer pkg_names.deinit(self.gpa); + var module_names = std.ArrayList([]const u8).empty; + defer module_names.deinit(self.gpa); + var depths = std.ArrayList(u32).empty; + defer depths.deinit(self.gpa); var it = self.schedulers.iterator(); while (it.next()) |e| { @@ -1171,9 +1171,9 @@ pub const BuildEnv = struct { const mod = me.key_ptr.*; const depth = sched.getModuleDepth(mod) orelse @as(u32, std.math.maxInt(u32)); - try pkg_names.append(pkg_name); - try module_names.append(mod); - try depths.append(depth); + try pkg_names.append(self.gpa, pkg_name); + try module_names.append(self.gpa, mod); + try depths.append(self.gpa, depth); } } diff --git a/src/compile/compile_package.zig b/src/compile/compile_package.zig index 517d5a7845..243f19b87f 100644 --- a/src/compile/compile_package.zig +++ b/src/compile/compile_package.zig @@ -100,11 +100,11 @@ const ModuleState = struct { path: []const u8, env: ?ModuleEnv = null, phase: Phase = .Parse, - imports: std.array_list.Managed(ModuleId), + imports: std.ArrayList(ModuleId), /// External imports qualified via package shorthand (e.g. "cli.Stdout") - still strings as they reference other packages - external_imports: std.array_list.Managed([]const u8), - dependents: std.array_list.Managed(ModuleId), - reports: std.array_list.Managed(Report), + external_imports: std.ArrayList([]const u8), + dependents: std.ArrayList(ModuleId), + reports: std.ArrayList(Report), depth: u32 = std.math.maxInt(u32), // min depth from root /// DFS visitation color for cycle detection: 0=white (unvisited), 1=gray (visiting), 2=black (finished) visit_color: u8 = 0, @@ -116,24 +116,24 @@ const ModuleState = struct { const source = if (self.env) |*e| e.common.source else null; if (self.env) |*e| e.deinit(); if (source) |s| gpa.free(s); - self.imports.deinit(); - self.external_imports.deinit(); - self.dependents.deinit(); + self.imports.deinit(gpa); + self.external_imports.deinit(gpa); + self.dependents.deinit(gpa); // NOTE: Do NOT deinit reports here! Ownership has been transferred to OrderedSink // when reports were emitted via sink.emitFn. The OrderedSink is responsible for // deinitiating the reports after they've been drained and rendered. - self.reports.deinit(); + self.reports.deinit(gpa); gpa.free(self.path); } - fn init(gpa: Allocator, name: []const u8, path: []const u8) ModuleState { + fn init(name: []const u8, path: []const u8) ModuleState { return .{ .name = name, .path = path, - .imports = std.array_list.Managed(ModuleId).init(gpa), - .external_imports = std.array_list.Managed([]const u8).init(gpa), - .dependents = std.array_list.Managed(ModuleId).init(gpa), - .reports = std.array_list.Managed(Report).init(gpa), + .imports = std.ArrayList(ModuleId).empty, + .external_imports = std.ArrayList([]const u8).empty, + .dependents = std.ArrayList(ModuleId).empty, + .reports = std.ArrayList(Report).empty, }; } }; @@ -160,10 +160,10 @@ pub const PackageEnv = struct { cond: Condition = .{}, // Work queue - injector: std.array_list.Managed(Task), + injector: std.ArrayList(Task), // Module storage - modules: std.array_list.Managed(ModuleState), + modules: std.ArrayList(ModuleState), // String intern table: module name -> module ID module_names: std.StringHashMapUnmanaged(ModuleId) = .{}, @@ -171,7 +171,7 @@ pub const PackageEnv = struct { remaining_modules: usize = 0, // Track module discovery order and which modules have had their reports emitted - discovered: std.array_list.Managed(ModuleId), + discovered: std.ArrayList(ModuleId), emitted: std.bit_set.DynamicBitSetUnmanaged = .{}, // Timing collection (accumulated across all modules) @@ -192,9 +192,9 @@ pub const PackageEnv = struct { .schedule_hook = schedule_hook, .compiler_version = compiler_version, .builtin_modules = builtin_modules, - .injector = std.array_list.Managed(Task).init(gpa), - .modules = std.array_list.Managed(ModuleState).init(gpa), - .discovered = std.array_list.Managed(ModuleId).init(gpa), + .injector = std.ArrayList(Task).empty, + .modules = std.ArrayList(ModuleState).empty, + .discovered = std.ArrayList(ModuleId).empty, }; } @@ -221,9 +221,9 @@ pub const PackageEnv = struct { .schedule_hook = schedule_hook, .compiler_version = compiler_version, .builtin_modules = builtin_modules, - .injector = std.array_list.Managed(Task).init(gpa), - .modules = std.array_list.Managed(ModuleState).init(gpa), - .discovered = std.array_list.Managed(ModuleId).init(gpa), + .injector = std.ArrayList(Task).empty, + .modules = std.ArrayList(ModuleState).empty, + .discovered = std.ArrayList(ModuleId).empty, }; } @@ -234,7 +234,7 @@ pub const PackageEnv = struct { for (self.modules.items) |*ms| { ms.deinit(self.gpa); } - self.modules.deinit(); + self.modules.deinit(self.gpa); // Free interned strings var it = self.module_names.iterator(); @@ -243,8 +243,8 @@ pub const PackageEnv = struct { } self.module_names.deinit(self.gpa); - self.injector.deinit(); - self.discovered.deinit(); + self.injector.deinit(self.gpa); + self.discovered.deinit(self.gpa); self.emitted.deinit(self.gpa); } @@ -357,8 +357,8 @@ pub const PackageEnv = struct { // This is a new module const owned_path = try self.gpa.dupe(u8, path); const owned_name = self.module_names.getKey(name).?; // We just interned it - try self.modules.append(ModuleState.init(self.gpa, owned_name, owned_path)); - try self.discovered.append(module_id); + try self.modules.append(self.gpa, ModuleState.init(owned_name, owned_path)); + try self.discovered.append(self.gpa, module_id); // Invoke scheduling hook for new module discovery/scheduling self.schedule_hook.onSchedule(self.schedule_hook.ctx, self.package_name, owned_name, owned_path, 0); @@ -403,7 +403,7 @@ pub const PackageEnv = struct { self.schedule_hook.onSchedule(self.schedule_hook.ctx, self.package_name, st.name, st.path, st.depth); } else { // Default behavior: use internal injector - try self.injector.append(.{ .module_id = module_id }); + try self.injector.append(self.gpa, .{ .module_id = module_id }); if (@import("builtin").target.cpu.arch != .wasm32) self.cond.signal(); } } @@ -571,11 +571,11 @@ pub const PackageEnv = struct { // Convert parse diagnostics to reports for (parse_ast.tokenize_diagnostics.items) |diagnostic| { const report = try parse_ast.tokenizeDiagnosticToReport(diagnostic, self.gpa); - try st.reports.append(report); + try st.reports.append(self.gpa, report); } for (parse_ast.parse_diagnostics.items) |diagnostic| { const report = try parse_ast.parseDiagnosticToReport(&env.common, diagnostic, self.gpa, st.path); - try st.reports.append(report); + try st.reports.append(self.gpa, report); } // canonicalize using the AST @@ -609,7 +609,7 @@ pub const PackageEnv = struct { defer self.gpa.free(diags); for (diags) |d| { const report = try env.diagnosticToReport(d, self.gpa, st.path); - try st.reports.append(report); + try st.reports.append(self.gpa, report); } const canon_diag_end = if (@import("builtin").target.cpu.arch != .wasm32) std.time.nanoTimestamp() else 0; if (@import("builtin").target.cpu.arch != .wasm32) { @@ -629,7 +629,7 @@ pub const PackageEnv = struct { if (qualified) { // Qualified imports refer to external packages; track and schedule externally - try st.external_imports.append(mod_name); + try st.external_imports.append(self.gpa, mod_name); if (self.resolver) |r| r.scheduleExternal(r.ctx, self.package_name, mod_name); // External dependencies are resolved by the workspace; skip local scheduling/cycle detection continue; @@ -642,13 +642,13 @@ pub const PackageEnv = struct { st = &self.modules.items[module_id]; env = &st.env.?; const existed = child_id < self.modules.items.len - 1; - try st.imports.append(child_id); + try st.imports.append(self.gpa, child_id); // parent depth + 1 try self.setDepthIfSmaller(child_id, st.depth + 1); // Cycle detection for local deps var child = &self.modules.items[child_id]; - try child.dependents.append(module_id); + try child.dependents.append(self.gpa, module_id); if (child.visit_color == 1 or child_id == module_id) { // Build a report on the current module describing the cycle @@ -680,7 +680,7 @@ pub const PackageEnv = struct { } // Store the report on both modules for clarity - try st.reports.append(rep); + try st.reports.append(self.gpa, rep); // Duplicate for child as well so it gets emitted too var rep_child = Report.init(self.gpa, "Import cycle detected", .runtime_error); const child_msg = try rep_child.addOwnedString("This module participates in an import cycle. Cycles between modules are not allowed."); @@ -691,7 +691,7 @@ pub const PackageEnv = struct { try rep_child.document.addText(" -> "); try rep_child.document.addAnnotated(mod_name, .emphasized); try rep_child.document.addLineBreak(); - try child.reports.append(rep_child); + try child.reports.append(self.gpa, rep_child); // Mark both Done and adjust counters if (st.phase != .Done) { @@ -780,7 +780,7 @@ pub const PackageEnv = struct { // Build other_modules array according to env.imports order const import_count = env.imports.imports.items.items.len; - var imported_envs = try std.array_list.Managed(*ModuleEnv).initCapacity(self.gpa, import_count); + var imported_envs = try std.ArrayList(*ModuleEnv).initCapacity(self.gpa, import_count); // NOTE: Don't deinit 'imported_envs' yet - comptime_evaluator holds a reference to imported_envs.items for (env.imports.imports.items.items[0..import_count]) |str_idx| { const import_name = env.getString(str_idx); @@ -791,7 +791,7 @@ pub const PackageEnv = struct { if (self.resolver) |r| { if (r.getEnv(r.ctx, self.package_name, import_name)) |ext_env_ptr| { // External env is already a pointer, use it directly - try imported_envs.append(ext_env_ptr); + try imported_envs.append(self.gpa, ext_env_ptr); } else { // External env not ready; skip (tryUnblock should have prevented this) } @@ -802,7 +802,7 @@ pub const PackageEnv = struct { // Get a pointer to the child's env (stored in the modules ArrayList) // This is safe because we don't modify the modules ArrayList during type checking const child_env_ptr = &child.env.?; - try imported_envs.append(child_env_ptr); + try imported_envs.append(self.gpa, child_env_ptr); } } @@ -846,7 +846,7 @@ pub const PackageEnv = struct { defer rb.deinit(); for (checker.problems.problems.items) |prob| { const rep = rb.build(prob) catch continue; - try st.reports.append(rep); + try st.reports.append(self.gpa, rep); } const check_diag_end = if (@import("builtin").target.cpu.arch != .wasm32) std.time.nanoTimestamp() else 0; if (@import("builtin").target.cpu.arch != .wasm32) { @@ -857,7 +857,7 @@ pub const PackageEnv = struct { comptime_evaluator.deinit(); // Now we can safely deinit the 'imported_envs' ArrayList - imported_envs.deinit(); + imported_envs.deinit(self.gpa); // Note: We no longer need to free the 'imported_envs' items because they now point directly // to ModuleEnv instances stored in the modules ArrayList, not to heap-allocated copies. @@ -878,16 +878,16 @@ pub const PackageEnv = struct { } // Default: convert dotted module name to path under root_dir - var buffer = std.array_list.Managed(u8).init(self.gpa); - defer buffer.deinit(); + var buffer = std.ArrayList(u8).empty; + defer buffer.deinit(self.gpa); var it = std.mem.splitScalar(u8, mod_name, '.'); var first = true; while (it.next()) |part| { - if (!first) try buffer.appendSlice(std.fs.path.sep_str) else first = false; - try buffer.appendSlice(part); + if (!first) try buffer.appendSlice(self.gpa, std.fs.path.sep_str) else first = false; + try buffer.appendSlice(self.gpa, part); } - try buffer.appendSlice(".roc"); - const rel = try buffer.toOwnedSlice(); + try buffer.appendSlice(self.gpa, ".roc"); + const rel = try buffer.toOwnedSlice(self.gpa); const full = try std.fs.path.join(self.gpa, &.{ self.root_dir, rel }); self.gpa.free(rel); return full; @@ -920,15 +920,15 @@ pub const PackageEnv = struct { try visited.resize(self.gpa, self.modules.items.len, false); const Frame = struct { id: ModuleId, next_idx: usize }; - var frames = std.array_list.Managed(Frame).init(self.gpa); - defer frames.deinit(); + var frames = std.ArrayList(Frame).empty; + defer frames.deinit(self.gpa); - var stack_ids = std.array_list.Managed(ModuleId).init(self.gpa); - defer stack_ids.deinit(); + var stack_ids = std.ArrayList(ModuleId).empty; + defer stack_ids.deinit(self.gpa); visited.set(start); - try frames.append(.{ .id = start, .next_idx = 0 }); - try stack_ids.append(start); + try frames.append(self.gpa, .{ .id = start, .next_idx = 0 }); + try stack_ids.append(self.gpa, start); while (frames.items.len > 0) { var top = &frames.items[frames.items.len - 1]; @@ -951,8 +951,8 @@ pub const PackageEnv = struct { if (!visited.isSet(child)) { visited.set(child); - try frames.append(.{ .id = child, .next_idx = 0 }); - try stack_ids.append(child); + try frames.append(self.gpa, .{ .id = child, .next_idx = 0 }); + try stack_ids.append(self.gpa, child); } } return null; diff --git a/src/compile/test/cache_test.zig b/src/compile/test/cache_test.zig index 5d67fe1cd7..6428919d38 100644 --- a/src/compile/test/cache_test.zig +++ b/src/compile/test/cache_test.zig @@ -344,9 +344,9 @@ // defer original_tree.deinit(); // try module_env.pushToSExprTree(null, &original_tree); -// var original_sexpr = std.array_list.Managed(u8).init(gpa); -// defer original_sexpr.deinit(); -// try original_tree.toStringPretty(original_sexpr.writer().any()); +// var original_sexpr = std.ArrayList(u8).empty; +// defer original_sexpr.deinit(gpa); +// try original_tree.toStringPretty(original_sexpr.writer(gpa).any()); // // Create arena for serialization // var arena = std.heap.ArenaAllocator.init(gpa); @@ -373,8 +373,8 @@ // try restored_env.pushToSExprTree(null, &restored_tree); -// var restored_sexpr = std.array_list.Managed(u8).init(gpa); -// defer restored_sexpr.deinit(); +// var restored_sexpr = std.ArrayList(u8).empty; +// defer restored_sexpr.deinit(gpa); // try restored_tree.toStringPretty(restored_sexpr.writer().any()); @@ -420,9 +420,9 @@ // // defer original_tree.deinit(); // // try module_env.pushToSExprTree(null, &original_tree); -// // var original_sexpr = std.array_list.Managed(u8).init(gpa); -// // defer original_sexpr.deinit(); -// // try original_tree.toStringPretty(original_sexpr.writer().any()); +// // var original_sexpr = std.ArrayList(u8).empty; +// // defer original_sexpr.deinit(gpa); +// // try original_tree.toStringPretty(original_sexpr.writer(gpa).any()); // // // Create arena for serialization // // var arena = std.heap.ArenaAllocator.init(gpa); @@ -515,8 +515,8 @@ // // try restored_env.pushToSExprTree(null, &restored_tree); -// // var restored_sexpr = std.array_list.Managed(u8).init(gpa); -// // defer restored_sexpr.deinit(); +// // var restored_sexpr = std.ArrayList(u8).empty; +// // defer restored_sexpr.deinit(gpa); // // try restored_tree.toStringPretty(restored_sexpr.writer().any()); diff --git a/src/compile/test/module_env_test.zig b/src/compile/test/module_env_test.zig index e78a55ea9d..65414c269b 100644 --- a/src/compile/test/module_env_test.zig +++ b/src/compile/test/module_env_test.zig @@ -410,9 +410,9 @@ test "ModuleEnv pushExprTypesToSExprTree extracts and formats types" { try env.pushTypesToSExprTree(expr_idx, &tree); // Convert tree to string - var result = std.array_list.Managed(u8).init(gpa); - defer result.deinit(); - try tree.toStringPretty(result.writer().any(), .include_linecol); + var result = std.ArrayList(u8).empty; + defer result.deinit(gpa); + try tree.toStringPretty(result.writer(gpa).any(), .include_linecol); // Verify the output contains the type information const result_str = result.items; diff --git a/src/compile/test/stderr_reporting_test.zig b/src/compile/test/stderr_reporting_test.zig index 7cbf80c193..c555ba872c 100644 --- a/src/compile/test/stderr_reporting_test.zig +++ b/src/compile/test/stderr_reporting_test.zig @@ -19,8 +19,8 @@ test "roc check writes parse errors to stderr" { return error.SkipZigTest; }; - // Use the existing test/str/app.roc file which has type errors - const test_file = try std.fs.path.join(gpa, &.{ cwd_path, "test", "str", "app.roc" }); + // Use a test file that intentionally has a parse error + const test_file = try std.fs.path.join(gpa, &.{ cwd_path, "test", "compile", "has_parse_error.roc" }); defer gpa.free(test_file); // Run roc check and capture stderr @@ -40,9 +40,9 @@ test "roc check writes parse errors to stderr" { // 2. Stderr contains error information (THIS IS THE KEY TEST - without flush, this will be empty) try testing.expect(result.stderr.len > 0); - // 3. Stderr contains error reporting (look for UNDECLARED TYPE error) - const has_error = std.mem.indexOf(u8, result.stderr, "UNDECLARED TYPE") != null or + // 3. Stderr contains error reporting + const has_error = std.mem.indexOf(u8, result.stderr, "Failed to check") != null or std.mem.indexOf(u8, result.stderr, "error") != null or - std.mem.indexOf(u8, result.stderr, "Found") != null; + std.mem.indexOf(u8, result.stderr, "Unsupported") != null; try testing.expect(has_error); } diff --git a/src/compile/test/test_build_env.zig b/src/compile/test/test_build_env.zig index 5c2d8c543b..cf12832a2b 100644 --- a/src/compile/test/test_build_env.zig +++ b/src/compile/test/test_build_env.zig @@ -516,16 +516,16 @@ // const mod_name = try std.fmt.allocPrint(gpa, "Mod{}", .{i}); // defer gpa.free(mod_name); -// var imports = std.array_list.Managed(u8).init(gpa); -// defer imports.deinit(); +// var imports = std.ArrayList(u8).empty; +// defer imports.deinit(gpa); // // Each module imports the next two modules (circular style) // var j: usize = 1; // while (j <= 2) : (j += 1) { // const import_idx = (i + j) % module_count; -// try imports.appendSlice("import Mod"); +// try imports.appendSlice(gpa, "import Mod"); // try std.fmt.formatInt(import_idx, 10, .lower, .{}, imports.writer()); -// try imports.append('\n'); +// try imports.append(gpa, '\n'); // } // const content = try std.fmt.allocPrint(gpa, diff --git a/src/compile/test/test_package_env.zig b/src/compile/test/test_package_env.zig index 11f83a6337..0aa8568136 100644 --- a/src/compile/test/test_package_env.zig +++ b/src/compile/test/test_package_env.zig @@ -206,11 +206,11 @@ // const TestSink = struct { // gpa: std.mem.Allocator, -// reports: std.array_list.Managed(Report), -// modules: std.array_list.Managed([]const u8), +// reports: std.ArrayList(Report), +// modules: std.ArrayList([]const u8), // fn init(gpa: std.mem.Allocator) TestSink { -// return .{ .gpa = gpa, .reports = std.array_list.Managed(Report).init(gpa), .modules = std.array_list.Managed([]const u8).init(gpa) }; +// return .{ .gpa = gpa, .reports = std.ArrayList.empty }; // } // fn deinit(self: *TestSink) void { diff --git a/src/eval/interpreter.zig b/src/eval/interpreter.zig index 462a2f3154..38a71432e4 100644 --- a/src/eval/interpreter.zig +++ b/src/eval/interpreter.zig @@ -137,8 +137,8 @@ pub const Interpreter = struct { pub fn init(allocator: std.mem.Allocator, env: *can.ModuleEnv, builtin_types: BuiltinTypes, imported_modules_map: ?*const std.AutoHashMap(base_pkg.Ident.Idx, can.Can.AutoImportedType)) !Interpreter { // Convert imported modules map to other_envs slice // IMPORTANT: The order must match Import.Idx order (not hash map iteration order!) - var other_envs_list = std.array_list.Managed(*const can.ModuleEnv).init(allocator); - errdefer other_envs_list.deinit(); + var other_envs_list = std.ArrayList(*const can.ModuleEnv).empty; + errdefer other_envs_list.deinit(allocator); if (imported_modules_map) |modules_map| { // Iterate through imports in Import.Idx order (0, 1, 2, ...) @@ -156,7 +156,7 @@ pub const Interpreter = struct { // Look up the module env in the map if (modules_map.get(module_ident)) |auto_imported| { - try other_envs_list.append(auto_imported.env); + try other_envs_list.append(allocator, auto_imported.env); } else { // Import exists in env.imports but not in the map we were given. // This shouldn't happen in practice if the map is properly constructed. @@ -167,7 +167,7 @@ pub const Interpreter = struct { // Transfer ownership of the slice to the Interpreter // Note: The caller is responsible for freeing this via deinitAndFreeOtherEnvs() - const other_envs = try other_envs_list.toOwnedSlice(); + const other_envs = try other_envs_list.toOwnedSlice(allocator); return initWithOtherEnvs(allocator, env, other_envs, builtin_types); } @@ -3566,7 +3566,7 @@ pub const Interpreter = struct { break :blk try self.runtime_types.freshFromContent(.{ .structure = .{ .num = .{ .num_compact = compact_num } } }); }, .tag_union => |tu| { - var rt_tag_args = try std.ArrayListUnmanaged(types.Var).initCapacity(self.allocator, 8); + var rt_tag_args = try std.ArrayList(types.Var).initCapacity(self.allocator, 8); defer rt_tag_args.deinit(self.allocator); var rt_tags = try self.gatherTags(module, tu); @@ -3746,8 +3746,8 @@ pub const Interpreter = struct { ctx: *const Interpreter, module: *can.ModuleEnv, tag_union: types.TagUnion, - ) std.mem.Allocator.Error!std.ArrayListUnmanaged(types.Tag) { - var scratch_tags = try std.ArrayListUnmanaged(types.Tag).initCapacity(ctx.allocator, 8); + ) std.mem.Allocator.Error!std.ArrayList(types.Tag) { + var scratch_tags = try std.ArrayList(types.Tag).initCapacity(ctx.allocator, 8); const tag_slice = module.types.getTagsSlice(tag_union.tags); for (tag_slice.items(.name), tag_slice.items(.args)) |name, args| { diff --git a/src/eval/test/comptime_eval_test.zig b/src/eval/test/comptime_eval_test.zig index a92b8fdcca..0b985d68b4 100644 --- a/src/eval/test/comptime_eval_test.zig +++ b/src/eval/test/comptime_eval_test.zig @@ -170,12 +170,12 @@ fn parseCheckAndEvalModuleWithImport(src: []const u8, import_name: []const u8, i try czer.canonicalizeFile(); // Set up other_envs for type checking (include Bool, Result, and Str modules) - var imported_envs = std.array_list.Managed(*const ModuleEnv).init(gpa); - defer imported_envs.deinit(); - try imported_envs.append(imported_module); - try imported_envs.append(bool_module.env); - try imported_envs.append(result_module.env); - try imported_envs.append(str_module.env); + var imported_envs = std.ArrayList(*const ModuleEnv).empty; + defer imported_envs.deinit(gpa); + try imported_envs.append(gpa, imported_module); + try imported_envs.append(gpa, bool_module.env); + try imported_envs.append(gpa, result_module.env); + try imported_envs.append(gpa, str_module.env); // Type check the module var checker = try Check.init(gpa, &module_env.types, module_env, imported_envs.items, &module_envs, &module_env.store.regions, common_idents); diff --git a/src/fs/Filesystem.zig b/src/fs/Filesystem.zig index 79e0b2eb91..76c26a62b1 100644 --- a/src/fs/Filesystem.zig +++ b/src/fs/Filesystem.zig @@ -155,14 +155,14 @@ pub const Dir = struct { /// Find all filepaths in this directory recursively. /// /// The text of the relative paths are stored in the `string_arena` - /// and the slices over said paths are returned in an `ArrayListUnmanaged` + /// and the slices over said paths are returned in an `ArrayList` /// that must be `deinit`ed by the caller. pub fn findAllFilesRecursively( dir: *Dir, gpa: std.mem.Allocator, string_arena: *std.heap.ArenaAllocator, - ) !std.array_list.Managed([]const u8) { - var files = std.array_list.Managed([]const u8){}; + ) !std.ArrayList([]const u8) { + var files = std.ArrayList([]const u8){}; errdefer files.deinit(gpa); var walker = try dir.dir.walk(gpa); diff --git a/src/layout/store.zig b/src/layout/store.zig index aebfa26da1..bd06b9d2c3 100644 --- a/src/layout/store.zig +++ b/src/layout/store.zig @@ -189,12 +189,12 @@ pub const Store = struct { field_layouts: []const Layout, field_names: []const Ident.Idx, ) std.mem.Allocator.Error!Idx { - var temp_fields = std.array_list.Managed(RecordField).init(self.env.gpa); - defer temp_fields.deinit(); + var temp_fields = std.ArrayList(RecordField).empty; + defer temp_fields.deinit(self.env.gpa); for (field_layouts, field_names) |field_layout, field_name| { const field_layout_idx = try self.insertLayout(field_layout); - try temp_fields.append(.{ + try temp_fields.append(self.env.gpa, .{ .name = field_name, .layout = field_layout_idx, }); @@ -263,12 +263,12 @@ pub const Store = struct { /// Insert a tuple layout from concrete element layouts pub fn putTuple(self: *Self, element_layouts: []const Layout) std.mem.Allocator.Error!Idx { // Collect fields - var temp_fields = std.array_list.Managed(TupleField).init(self.env.gpa); - defer temp_fields.deinit(); + var temp_fields = std.ArrayList(TupleField).empty; + defer temp_fields.deinit(self.env.gpa); for (element_layouts, 0..) |elem_layout, i| { const elem_idx = try self.insertLayout(elem_layout); - try temp_fields.append(.{ .index = @intCast(i), .layout = elem_idx }); + try temp_fields.append(self.env.gpa, .{ .index = @intCast(i), .layout = elem_idx }); } // Sort by alignment desc, then by original index asc @@ -620,11 +620,11 @@ pub const Store = struct { const field_idxs = self.work.resolved_record_fields.items(.field_idx); // First, collect the fields into a temporary array so we can sort them - var temp_fields = std.array_list.Managed(RecordField).init(self.env.gpa); - defer temp_fields.deinit(); + var temp_fields = std.ArrayList(RecordField).empty; + defer temp_fields.deinit(self.env.gpa); for (updated_record.resolved_fields_start..resolved_fields_end) |i| { - try temp_fields.append(.{ + try temp_fields.append(self.env.gpa, .{ .name = field_names[i], .layout = field_idxs[i], }); @@ -721,11 +721,11 @@ pub const Store = struct { const field_idxs = self.work.resolved_tuple_fields.items(.field_idx); // First, collect the fields into a temporary array so we can sort them - var temp_fields = std.array_list.Managed(TupleField).init(self.env.gpa); - defer temp_fields.deinit(); + var temp_fields = std.ArrayList(TupleField).empty; + defer temp_fields.deinit(self.env.gpa); for (updated_tuple.resolved_fields_start..resolved_fields_end) |i| { - try temp_fields.append(.{ + try temp_fields.append(self.env.gpa, .{ .index = field_indices[i], .layout = field_idxs[i], }); diff --git a/src/parse/AST.zig b/src/parse/AST.zig index b67c03647c..a316d7f92b 100644 --- a/src/parse/AST.zig +++ b/src/parse/AST.zig @@ -35,8 +35,8 @@ env: *CommonEnv, tokens: TokenizedBuffer, store: NodeStore, root_node_idx: u32 = 0, -tokenize_diagnostics: std.ArrayListUnmanaged(tokenize.Diagnostic), -parse_diagnostics: std.ArrayListUnmanaged(AST.Diagnostic), +tokenize_diagnostics: std.ArrayList(tokenize.Diagnostic), +parse_diagnostics: std.ArrayList(AST.Diagnostic), /// Calculate whether this region is - or will be - multiline pub fn regionIsMultiline(self: *AST, region: TokenizedRegion) bool { diff --git a/src/parse/NodeStore.zig b/src/parse/NodeStore.zig index 437a835e4e..45542722a7 100644 --- a/src/parse/NodeStore.zig +++ b/src/parse/NodeStore.zig @@ -20,7 +20,7 @@ const NodeStore = @This(); gpa: std.mem.Allocator, nodes: Node.List, -extra_data: std.array_list.Managed(u32), +extra_data: std.ArrayList(u32), scratch_statements: base.Scratch(AST.Statement.Idx), scratch_tokens: base.Scratch(Token.Idx), scratch_exprs: base.Scratch(AST.Expr.Idx), @@ -54,7 +54,7 @@ pub fn initCapacity(gpa: std.mem.Allocator, capacity: usize) std.mem.Allocator.E var store: NodeStore = .{ .gpa = gpa, .nodes = try Node.List.initCapacity(gpa, capacity), - .extra_data = try std.array_list.Managed(u32).initCapacity(gpa, capacity / 2), + .extra_data = try std.ArrayList(u32).initCapacity(gpa, capacity / 2), .scratch_statements = try base.Scratch(AST.Statement.Idx).init(gpa), .scratch_tokens = try base.Scratch(Token.Idx).init(gpa), .scratch_exprs = try base.Scratch(AST.Expr.Idx).init(gpa), @@ -88,7 +88,7 @@ const scratch_90th_percentile_capacity = std.math.ceilPowerOfTwoAssert(usize, 64 /// method. pub fn deinit(store: *NodeStore) void { store.nodes.deinit(store.gpa); - store.extra_data.deinit(); + store.extra_data.deinit(store.gpa); store.scratch_statements.deinit(); store.scratch_tokens.deinit(); store.scratch_exprs.deinit(); @@ -160,7 +160,7 @@ pub fn addMalformed(store: *NodeStore, comptime T: type, reason: Diagnostic.Tag, /// Adds a file node to the store. pub fn addFile(store: *NodeStore, file: AST.File) std.mem.Allocator.Error!void { - try store.extra_data.append(@intFromEnum(file.header)); + try store.extra_data.append(store.gpa, @intFromEnum(file.header)); store.nodes.set(@enumFromInt(0), .{ .tag = .root, .main_token = 0, @@ -204,7 +204,7 @@ pub fn addHeader(store: *NodeStore, header: AST.Header) std.mem.Allocator.Error! node.data.rhs = @intFromEnum(app.packages); node.region = app.region; - try store.extra_data.append(@intFromEnum(app.platform_idx)); + try store.extra_data.append(store.gpa, @intFromEnum(app.platform_idx)); }, .module => |mod| { node.tag = .module_header; @@ -227,11 +227,11 @@ pub fn addHeader(store: *NodeStore, header: AST.Header) std.mem.Allocator.Error! node.main_token = platform.name; const ed_start = store.extra_data.items.len; - try store.extra_data.append(@intFromEnum(platform.requires_rigids)); - try store.extra_data.append(@intFromEnum(platform.requires_signatures)); - try store.extra_data.append(@intFromEnum(platform.exposes)); - try store.extra_data.append(@intFromEnum(platform.packages)); - try store.extra_data.append(@intFromEnum(platform.provides)); + try store.extra_data.append(store.gpa, @intFromEnum(platform.requires_rigids)); + try store.extra_data.append(store.gpa, @intFromEnum(platform.requires_signatures)); + try store.extra_data.append(store.gpa, @intFromEnum(platform.exposes)); + try store.extra_data.append(store.gpa, @intFromEnum(platform.packages)); + try store.extra_data.append(store.gpa, @intFromEnum(platform.provides)); const ed_len = store.extra_data.items.len - ed_start; node.data.lhs = @intCast(ed_start); @@ -376,16 +376,16 @@ pub fn addStatement(store: *NodeStore, statement: AST.Statement) std.mem.Allocat // Store all import data in a flat format: // [exposes.span.start, exposes.span.len, qualifier_tok?, alias_tok?] const data_start = @as(u32, @intCast(store.extra_data.items.len)); - try store.extra_data.append(i.exposes.span.start); - try store.extra_data.append(i.exposes.span.len); + try store.extra_data.append(store.gpa, i.exposes.span.start); + try store.extra_data.append(store.gpa, i.exposes.span.len); if (i.qualifier_tok) |tok| { rhs.qualified = 1; - try store.extra_data.append(tok); + try store.extra_data.append(store.gpa, tok); } if (i.alias_tok) |tok| { rhs.aliased = 1; - try store.extra_data.append(tok); + try store.extra_data.append(store.gpa, tok); } node.data.rhs = @as(u32, @bitCast(rhs)); @@ -410,17 +410,17 @@ pub fn addStatement(store: *NodeStore, statement: AST.Statement) std.mem.Allocat // Store where clause index (0 if null) const where_idx = if (d.where) |w| @intFromEnum(w) else 0; - try store.extra_data.append(where_idx); + try store.extra_data.append(store.gpa, where_idx); // Store associated data if present if (d.associated) |assoc| { - try store.extra_data.append(1); // has_associated = 1 - try store.extra_data.append(assoc.statements.span.start); - try store.extra_data.append(assoc.statements.span.len); - try store.extra_data.append(assoc.region.start); - try store.extra_data.append(assoc.region.end); + try store.extra_data.append(store.gpa, 1); // has_associated = 1 + try store.extra_data.append(store.gpa, assoc.statements.span.start); + try store.extra_data.append(store.gpa, assoc.statements.span.len); + try store.extra_data.append(store.gpa, assoc.region.start); + try store.extra_data.append(store.gpa, assoc.region.end); } else { - try store.extra_data.append(0); // has_associated = 0 + try store.extra_data.append(store.gpa, 0); // has_associated = 0 } node.main_token = extra_start; @@ -464,9 +464,9 @@ pub fn addPattern(store: *NodeStore, pattern: AST.Pattern) std.mem.Allocator.Err }, .tag => |t| { const data_start = @as(u32, @intCast(store.extra_data.items.len)); - try store.extra_data.append(t.args.span.len); - try store.extra_data.append(t.qualifiers.span.start); - try store.extra_data.append(t.qualifiers.span.len); + try store.extra_data.append(store.gpa, t.args.span.len); + try store.extra_data.append(store.gpa, t.qualifiers.span.start); + try store.extra_data.append(store.gpa, t.qualifiers.span.len); node.tag = .tag_patt; node.region = t.region; @@ -617,12 +617,12 @@ pub fn addExpr(store: *NodeStore, expr: AST.Expr) std.mem.Allocator.Error!AST.Ex // Store all record data in flat format: // [fields.span.start, fields.span.len, ext_or_zero] const data_start = @as(u32, @intCast(store.extra_data.items.len)); - try store.extra_data.append(r.fields.span.start); - try store.extra_data.append(r.fields.span.len); + try store.extra_data.append(store.gpa, r.fields.span.start); + try store.extra_data.append(store.gpa, r.fields.span.len); // Store ext value or 0 for null const ext_value = if (r.ext) |ext| @intFromEnum(ext) else 0; - try store.extra_data.append(ext_value); + try store.extra_data.append(store.gpa, ext_value); node.data.lhs = data_start; node.data.rhs = 0; // Not used @@ -633,7 +633,7 @@ pub fn addExpr(store: *NodeStore, expr: AST.Expr) std.mem.Allocator.Error!AST.Ex node.data.lhs = l.args.span.start; node.data.rhs = l.args.span.len; const body_idx = store.extra_data.items.len; - try store.extra_data.append(@intFromEnum(l.body)); + try store.extra_data.append(store.gpa, @intFromEnum(l.body)); node.main_token = @as(u32, @intCast(body_idx)); }, .apply => |app| { @@ -642,7 +642,7 @@ pub fn addExpr(store: *NodeStore, expr: AST.Expr) std.mem.Allocator.Error!AST.Ex node.data.lhs = app.args.span.start; node.data.rhs = app.args.span.len; const fn_ed_idx = store.extra_data.items.len; - try store.extra_data.append(@intFromEnum(app.@"fn")); + try store.extra_data.append(store.gpa, @intFromEnum(app.@"fn")); node.main_token = @as(u32, @intCast(fn_ed_idx)); }, .record_updater => |_| {}, @@ -684,8 +684,8 @@ pub fn addExpr(store: *NodeStore, expr: AST.Expr) std.mem.Allocator.Error!AST.Ex node.region = i.region; node.data.lhs = @intFromEnum(i.condition); node.data.rhs = @as(u32, @intCast(store.extra_data.items.len)); - try store.extra_data.append(@intFromEnum(i.then)); - try store.extra_data.append(@intFromEnum(i.@"else")); + try store.extra_data.append(store.gpa, @intFromEnum(i.then)); + try store.extra_data.append(store.gpa, @intFromEnum(i.@"else")); }, .match => |m| { node.tag = .match; @@ -693,7 +693,7 @@ pub fn addExpr(store: *NodeStore, expr: AST.Expr) std.mem.Allocator.Error!AST.Ex node.data.lhs = m.branches.span.start; node.data.rhs = m.branches.span.len; const expr_idx = store.extra_data.items.len; - try store.extra_data.append(@intFromEnum(m.expr)); + try store.extra_data.append(store.gpa, @intFromEnum(m.expr)); node.main_token = @as(u32, @intCast(expr_idx)); }, .ident => |id| { @@ -854,9 +854,9 @@ pub fn addWhereClause(store: *NodeStore, clause: AST.WhereClause) std.mem.Alloca node.region = c.region; node.main_token = c.var_tok; const ed_start = store.extra_data.items.len; - try store.extra_data.append(c.name_tok); - try store.extra_data.append(@intFromEnum(c.args)); - try store.extra_data.append(@intFromEnum(c.ret_anno)); + try store.extra_data.append(store.gpa, c.name_tok); + try store.extra_data.append(store.gpa, @intFromEnum(c.args)); + try store.extra_data.append(store.gpa, @intFromEnum(c.ret_anno)); node.data.lhs = @intCast(ed_start); }, .mod_alias => |c| { @@ -921,8 +921,8 @@ pub fn addTypeAnno(store: *NodeStore, anno: AST.TypeAnno) std.mem.Allocator.Erro // Store all tag_union data in flat format: // [tags.span.start, tags.span.len, open_anno?] const data_start = @as(u32, @intCast(store.extra_data.items.len)); - try store.extra_data.append(tu.tags.span.start); - try store.extra_data.append(tu.tags.span.len); + try store.extra_data.append(store.gpa, tu.tags.span.start); + try store.extra_data.append(store.gpa, tu.tags.span.len); var rhs = AST.TypeAnno.TagUnionRhs{ .open = 0, @@ -930,7 +930,7 @@ pub fn addTypeAnno(store: *NodeStore, anno: AST.TypeAnno) std.mem.Allocator.Erro }; if (tu.open_anno) |a| { rhs.open = 1; - try store.extra_data.append(@intFromEnum(a)); + try store.extra_data.append(store.gpa, @intFromEnum(a)); } node.data.lhs = data_start; @@ -957,7 +957,7 @@ pub fn addTypeAnno(store: *NodeStore, anno: AST.TypeAnno) std.mem.Allocator.Erro .args_len = @intCast(f.args.span.len), // We hope a function has less than 2.147b args }); const ret_idx = store.extra_data.items.len; - try store.extra_data.append(@intFromEnum(f.ret)); + try store.extra_data.append(store.gpa, @intFromEnum(f.ret)); node.main_token = @intCast(ret_idx); }, .parens => |p| { @@ -1874,7 +1874,7 @@ pub fn exprSpanFrom(store: *NodeStore, start: u32) std.mem.Allocator.Error!AST.E const ed_start = @as(u32, @intCast(store.extra_data.items.len)); std.debug.assert(end >= i); while (i < end) { - try store.extra_data.append(@intFromEnum(store.scratch_exprs.items.items[i])); + try store.extra_data.append(store.gpa, @intFromEnum(store.scratch_exprs.items.items[i])); i += 1; } return .{ .span = .{ .start = ed_start, .len = @as(u32, @intCast(end)) - start } }; @@ -1912,7 +1912,7 @@ pub fn statementSpanFrom(store: *NodeStore, start: u32) std.mem.Allocator.Error! const ed_start = @as(u32, @intCast(store.extra_data.items.len)); std.debug.assert(end >= i); while (i < end) { - try store.extra_data.append(@intFromEnum(store.scratch_statements.items.items[i])); + try store.extra_data.append(store.gpa, @intFromEnum(store.scratch_statements.items.items[i])); i += 1; } return .{ .span = .{ .start = ed_start, .len = @as(u32, @intCast(end)) - start } }; @@ -1950,7 +1950,7 @@ pub fn patternSpanFrom(store: *NodeStore, start: u32) std.mem.Allocator.Error!AS const ed_start = @as(u32, @intCast(store.extra_data.items.len)); std.debug.assert(end >= i); while (i < end) { - try store.extra_data.append(@intFromEnum(store.scratch_patterns.items.items[i])); + try store.extra_data.append(store.gpa, @intFromEnum(store.scratch_patterns.items.items[i])); i += 1; } return .{ .span = .{ .start = ed_start, .len = @as(u32, @intCast(end)) - start } }; @@ -1997,7 +1997,7 @@ pub fn patternRecordFieldSpanFrom(store: *NodeStore, start: u32) std.mem.Allocat var i = @as(usize, @intCast(start)); const ed_start = @as(u32, @intCast(store.extra_data.items.len)); while (i < end) { - try store.extra_data.append(@intFromEnum(store.scratch_pattern_record_fields.items.items[i])); + try store.extra_data.append(store.gpa, @intFromEnum(store.scratch_pattern_record_fields.items.items[i])); i += 1; } return .{ .span = .{ .start = ed_start, .len = @as(u32, @intCast(end)) - start } }; @@ -2033,7 +2033,7 @@ pub fn recordFieldSpanFrom(store: *NodeStore, start: u32) std.mem.Allocator.Erro var i = @as(usize, @intCast(start)); const ed_start = @as(u32, @intCast(store.extra_data.items.len)); while (i < end) { - try store.extra_data.append(@intFromEnum(store.scratch_record_fields.items.items[i])); + try store.extra_data.append(store.gpa, @intFromEnum(store.scratch_record_fields.items.items[i])); i += 1; } return .{ .span = .{ .start = ed_start, .len = @as(u32, @intCast(end)) - start } }; @@ -2064,7 +2064,7 @@ pub fn matchBranchSpanFrom(store: *NodeStore, start: u32) std.mem.Allocator.Erro var i = @as(usize, @intCast(start)); const ed_start = @as(u32, @intCast(store.extra_data.items.len)); while (i < end) { - try store.extra_data.append(@intFromEnum(store.scratch_match_branches.items.items[i])); + try store.extra_data.append(store.gpa, @intFromEnum(store.scratch_match_branches.items.items[i])); i += 1; } return .{ .span = .{ .start = ed_start, .len = @as(u32, @intCast(end)) - start } }; @@ -2101,7 +2101,7 @@ pub fn typeAnnoSpanFrom(store: *NodeStore, start: u32) std.mem.Allocator.Error!A var i = @as(usize, @intCast(start)); const ed_start = @as(u32, @intCast(store.extra_data.items.len)); while (i < end) { - try store.extra_data.append(@intFromEnum(store.scratch_type_annos.items.items[i])); + try store.extra_data.append(store.gpa, @intFromEnum(store.scratch_type_annos.items.items[i])); i += 1; } return .{ .span = .{ .start = ed_start, .len = @as(u32, @intCast(end)) - start } }; @@ -2138,7 +2138,7 @@ pub fn annoRecordFieldSpanFrom(store: *NodeStore, start: u32) std.mem.Allocator. var i = @as(usize, @intCast(start)); const ed_start = @as(u32, @intCast(store.extra_data.items.len)); while (i < end) { - try store.extra_data.append(@intFromEnum(store.scratch_anno_record_fields.items.items[i])); + try store.extra_data.append(store.gpa, @intFromEnum(store.scratch_anno_record_fields.items.items[i])); i += 1; } return .{ .span = .{ .start = ed_start, .len = @as(u32, @intCast(end)) - start } }; @@ -2175,7 +2175,7 @@ pub fn tokenSpanFrom(store: *NodeStore, start: u32) std.mem.Allocator.Error!Toke var i = @as(usize, @intCast(start)); const ed_start = @as(u32, @intCast(store.extra_data.items.len)); while (i < end) { - try store.extra_data.append(store.scratch_tokens.items.items[i]); + try store.extra_data.append(store.gpa, store.scratch_tokens.items.items[i]); i += 1; } return .{ .span = .{ .start = ed_start, .len = @as(u32, @intCast(end)) - start } }; @@ -2212,7 +2212,7 @@ pub fn exposedItemSpanFrom(store: *NodeStore, start: u32) std.mem.Allocator.Erro var i = @as(usize, @intCast(start)); const ed_start = @as(u32, @intCast(store.extra_data.items.len)); while (i < end) { - try store.extra_data.append(@intFromEnum(store.scratch_exposed_items.items.items[i])); + try store.extra_data.append(store.gpa, @intFromEnum(store.scratch_exposed_items.items.items[i])); i += 1; } return .{ .span = .{ .start = ed_start, .len = @as(u32, @intCast(end)) - start } }; @@ -2249,7 +2249,7 @@ pub fn whereClauseSpanFrom(store: *NodeStore, start: u32) std.mem.Allocator.Erro var i = @as(usize, @intCast(start)); const ed_start = @as(u32, @intCast(store.extra_data.items.len)); while (i < end) { - try store.extra_data.append(@intFromEnum(store.scratch_where_clauses.items.items[i])); + try store.extra_data.append(store.gpa, @intFromEnum(store.scratch_where_clauses.items.items[i])); i += 1; } return .{ .span = .{ .start = ed_start, .len = @as(u32, @intCast(end)) - start } }; diff --git a/src/parse/Parser.zig b/src/parse/Parser.zig index e165e099b6..38b83c685f 100644 --- a/src/parse/Parser.zig +++ b/src/parse/Parser.zig @@ -29,8 +29,8 @@ gpa: std.mem.Allocator, pos: TokenIdx, tok_buf: TokenizedBuffer, store: NodeStore, -scratch_nodes: std.ArrayListUnmanaged(Node.Idx), -diagnostics: std.ArrayListUnmanaged(AST.Diagnostic), +scratch_nodes: std.ArrayList(Node.Idx), +diagnostics: std.ArrayList(AST.Diagnostic), cached_malformed_node: ?Node.Idx, nesting_counter: u8, diff --git a/src/parse/mod.zig b/src/parse/mod.zig index bf2945064c..c78a9a4e17 100644 --- a/src/parse/mod.zig +++ b/src/parse/mod.zig @@ -52,7 +52,7 @@ fn runParse(env: *CommonEnv, gpa: std.mem.Allocator, parserCall: *const fn (*Par const idx = try parserCall(&parser); const tokenize_diagnostics_slice = try gpa.dupe(tokenize.Diagnostic, result.messages); - const tokenize_diagnostics = std.ArrayListUnmanaged(tokenize.Diagnostic).fromOwnedSlice(tokenize_diagnostics_slice); + const tokenize_diagnostics = std.ArrayList(tokenize.Diagnostic).fromOwnedSlice(tokenize_diagnostics_slice); return .{ .env = env, diff --git a/src/parse/test/ast_node_store_test.zig b/src/parse/test/ast_node_store_test.zig index a8e15cdb22..41d04bf349 100644 --- a/src/parse/test/ast_node_store_test.zig +++ b/src/parse/test/ast_node_store_test.zig @@ -54,10 +54,10 @@ test "NodeStore round trip - Headers" { var store = try NodeStore.initCapacity(gpa, NodeStore.AST_HEADER_NODE_COUNT); defer store.deinit(); - var headers = std.array_list.Managed(AST.Header).init(gpa); - defer headers.deinit(); + var headers = std.ArrayList(AST.Header).empty; + defer headers.deinit(gpa); - try headers.append(AST.Header{ + try headers.append(gpa, AST.Header{ .app = .{ .packages = rand_idx(AST.Collection.Idx), .platform_idx = rand_idx(AST.RecordField.Idx), @@ -66,14 +66,14 @@ test "NodeStore round trip - Headers" { }, }); - try headers.append(AST.Header{ + try headers.append(gpa, AST.Header{ .module = .{ .exposes = rand_idx(AST.Collection.Idx), .region = rand_region(), }, }); - try headers.append(AST.Header{ + try headers.append(gpa, AST.Header{ .package = .{ .exposes = rand_idx(AST.Collection.Idx), .packages = rand_idx(AST.Collection.Idx), @@ -81,7 +81,7 @@ test "NodeStore round trip - Headers" { }, }); - try headers.append(AST.Header{ + try headers.append(gpa, AST.Header{ .platform = .{ .exposes = rand_idx(AST.Collection.Idx), .name = rand_token_idx(), @@ -93,7 +93,7 @@ test "NodeStore round trip - Headers" { }, }); - try headers.append(AST.Header{ + try headers.append(gpa, AST.Header{ .hosted = .{ .exposes = rand_idx(AST.Collection.Idx), .region = rand_region(), @@ -126,48 +126,48 @@ test "NodeStore round trip - Statement" { var store = try NodeStore.initCapacity(gpa, NodeStore.AST_STATEMENT_NODE_COUNT); defer store.deinit(); - var statements = std.array_list.Managed(AST.Statement).init(gpa); - defer statements.deinit(); + var statements = std.ArrayList(AST.Statement).empty; + defer statements.deinit(gpa); - try statements.append(AST.Statement{ + try statements.append(gpa, AST.Statement{ .decl = .{ .body = rand_idx(AST.Expr.Idx), .pattern = rand_idx(AST.Pattern.Idx), .region = rand_region(), }, }); - try statements.append(AST.Statement{ + try statements.append(gpa, AST.Statement{ .@"var" = .{ .name = rand_token_idx(), .body = rand_idx(AST.Expr.Idx), .region = rand_region(), }, }); - try statements.append(AST.Statement{ + try statements.append(gpa, AST.Statement{ .expr = .{ .expr = rand_idx(AST.Expr.Idx), .region = rand_region(), }, }); - try statements.append(AST.Statement{ + try statements.append(gpa, AST.Statement{ .crash = .{ .expr = rand_idx(AST.Expr.Idx), .region = rand_region(), }, }); - try statements.append(AST.Statement{ + try statements.append(gpa, AST.Statement{ .dbg = .{ .expr = rand_idx(AST.Expr.Idx), .region = rand_region(), }, }); - try statements.append(AST.Statement{ + try statements.append(gpa, AST.Statement{ .expect = .{ .body = rand_idx(AST.Expr.Idx), .region = rand_region(), }, }); - try statements.append(AST.Statement{ + try statements.append(gpa, AST.Statement{ .@"for" = .{ .patt = rand_idx(AST.Pattern.Idx), .expr = rand_idx(AST.Expr.Idx), @@ -175,14 +175,14 @@ test "NodeStore round trip - Statement" { .region = rand_region(), }, }); - try statements.append(AST.Statement{ + try statements.append(gpa, AST.Statement{ .@"return" = .{ .expr = rand_idx(AST.Expr.Idx), .region = rand_region(), }, }); // Simple import with no tokens - try statements.append(AST.Statement{ + try statements.append(gpa, AST.Statement{ .import = .{ .alias_tok = null, .module_name_tok = rand_token_idx(), @@ -192,7 +192,7 @@ test "NodeStore round trip - Statement" { }, }); // Import with alias - try statements.append(AST.Statement{ + try statements.append(gpa, AST.Statement{ .import = .{ .alias_tok = rand_token_idx(), .module_name_tok = rand_token_idx(), @@ -202,7 +202,7 @@ test "NodeStore round trip - Statement" { }, }); // Import with qualifier but no alias - try statements.append(AST.Statement{ + try statements.append(gpa, AST.Statement{ .import = .{ .alias_tok = null, .module_name_tok = rand_token_idx(), @@ -212,7 +212,7 @@ test "NodeStore round trip - Statement" { }, }); // Import with both qualifier and alias - try statements.append(AST.Statement{ + try statements.append(gpa, AST.Statement{ .import = .{ .alias_tok = rand_token_idx(), .module_name_tok = rand_token_idx(), @@ -221,7 +221,7 @@ test "NodeStore round trip - Statement" { .exposes = AST.ExposedItem.Span{ .span = rand_span() }, }, }); - try statements.append(AST.Statement{ + try statements.append(gpa, AST.Statement{ .type_decl = .{ .anno = rand_idx(AST.TypeAnno.Idx), .header = rand_idx(AST.TypeHeader.Idx), @@ -231,7 +231,7 @@ test "NodeStore round trip - Statement" { .associated = null, }, }); - try statements.append(AST.Statement{ + try statements.append(gpa, AST.Statement{ .type_anno = .{ .name = rand_token_idx(), .anno = rand_idx(AST.TypeAnno.Idx), @@ -268,16 +268,16 @@ test "NodeStore round trip - Pattern" { var expected_test_count: usize = NodeStore.AST_PATTERN_NODE_COUNT; - var patterns = std.array_list.Managed(AST.Pattern).init(gpa); - defer patterns.deinit(); + var patterns = std.ArrayList(AST.Pattern).empty; + defer patterns.deinit(gpa); - try patterns.append(AST.Pattern{ + try patterns.append(gpa, AST.Pattern{ .ident = .{ .ident_tok = rand_token_idx(), .region = rand_region(), }, }); - try patterns.append(AST.Pattern{ + try patterns.append(gpa, AST.Pattern{ .tag = .{ .args = AST.Pattern.Span{ .span = rand_span() }, .qualifiers = AST.Token.Span{ .span = rand_span() }, @@ -285,67 +285,67 @@ test "NodeStore round trip - Pattern" { .tag_tok = rand_token_idx(), }, }); - try patterns.append(AST.Pattern{ + try patterns.append(gpa, AST.Pattern{ .int = .{ .number_tok = rand_token_idx(), .region = rand_region(), }, }); - try patterns.append(AST.Pattern{ + try patterns.append(gpa, AST.Pattern{ .frac = .{ .number_tok = rand_token_idx(), .region = rand_region(), }, }); - try patterns.append(AST.Pattern{ + try patterns.append(gpa, AST.Pattern{ .string = .{ .expr = rand_idx(AST.Expr.Idx), .region = rand_region(), .string_tok = rand_token_idx(), }, }); - try patterns.append(AST.Pattern{ + try patterns.append(gpa, AST.Pattern{ .single_quote = .{ .region = rand_region(), .token = rand_token_idx(), }, }); - try patterns.append(AST.Pattern{ + try patterns.append(gpa, AST.Pattern{ .record = .{ .fields = AST.PatternRecordField.Span{ .span = rand_span() }, .region = rand_region(), }, }); - try patterns.append(AST.Pattern{ + try patterns.append(gpa, AST.Pattern{ .list = .{ .patterns = AST.Pattern.Span{ .span = rand_span() }, .region = rand_region(), }, }); - try patterns.append(AST.Pattern{ + try patterns.append(gpa, AST.Pattern{ .list_rest = .{ .name = rand_token_idx(), .region = rand_region(), }, }); - try patterns.append(AST.Pattern{ + try patterns.append(gpa, AST.Pattern{ .tuple = .{ .patterns = AST.Pattern.Span{ .span = rand_span() }, .region = rand_region(), }, }); - try patterns.append(AST.Pattern{ + try patterns.append(gpa, AST.Pattern{ .underscore = .{ .region = rand_region(), }, }); - try patterns.append(AST.Pattern{ + try patterns.append(gpa, AST.Pattern{ .alternatives = .{ .patterns = AST.Pattern.Span{ .span = rand_span() }, .region = rand_region(), }, }); - try patterns.append(AST.Pattern{ + try patterns.append(gpa, AST.Pattern{ .as = .{ .name = rand_token_idx(), .region = rand_region(), .pattern = rand_idx(AST.Pattern.Idx) }, }); @@ -378,53 +378,53 @@ test "NodeStore round trip - TypeAnno" { var expected_test_count: usize = NodeStore.AST_TYPE_ANNO_NODE_COUNT; - var ty_annos = std.array_list.Managed(AST.TypeAnno).init(gpa); - defer ty_annos.deinit(); + var ty_annos = std.ArrayList(AST.TypeAnno).empty; + defer ty_annos.deinit(gpa); - try ty_annos.append(AST.TypeAnno{ + try ty_annos.append(gpa, AST.TypeAnno{ .apply = .{ .args = AST.TypeAnno.Span{ .span = rand_span() }, .region = rand_region(), }, }); - try ty_annos.append(AST.TypeAnno{ + try ty_annos.append(gpa, AST.TypeAnno{ .ty_var = .{ .region = rand_region(), .tok = rand_token_idx(), }, }); - try ty_annos.append(AST.TypeAnno{ + try ty_annos.append(gpa, AST.TypeAnno{ .underscore = .{ .region = rand_region(), }, }); - try ty_annos.append(AST.TypeAnno{ + try ty_annos.append(gpa, AST.TypeAnno{ .ty = .{ .qualifiers = AST.Token.Span{ .span = rand_span() }, .region = rand_region(), .token = rand_token_idx(), }, }); - try ty_annos.append(AST.TypeAnno{ + try ty_annos.append(gpa, AST.TypeAnno{ .tag_union = .{ .open_anno = rand_idx(AST.TypeAnno.Idx), .tags = AST.TypeAnno.Span{ .span = rand_span() }, .region = rand_region(), }, }); - try ty_annos.append(AST.TypeAnno{ + try ty_annos.append(gpa, AST.TypeAnno{ .tuple = .{ .annos = AST.TypeAnno.Span{ .span = rand_span() }, .region = rand_region(), }, }); - try ty_annos.append(AST.TypeAnno{ + try ty_annos.append(gpa, AST.TypeAnno{ .record = .{ .fields = AST.AnnoRecordField.Span{ .span = rand_span() }, .region = rand_region(), }, }); - try ty_annos.append(AST.TypeAnno{ + try ty_annos.append(gpa, AST.TypeAnno{ .@"fn" = .{ .args = AST.TypeAnno.Span{ .span = rand_span() }, .ret = rand_idx(AST.TypeAnno.Idx), @@ -432,7 +432,7 @@ test "NodeStore round trip - TypeAnno" { .region = rand_region(), }, }); - try ty_annos.append(AST.TypeAnno{ + try ty_annos.append(gpa, AST.TypeAnno{ .parens = .{ .anno = rand_idx(AST.TypeAnno.Idx), .region = rand_region(), @@ -468,74 +468,74 @@ test "NodeStore round trip - Expr" { var expected_test_count: usize = NodeStore.AST_EXPR_NODE_COUNT; - var expressions = std.array_list.Managed(AST.Expr).init(gpa); - defer expressions.deinit(); + var expressions = std.ArrayList(AST.Expr).empty; + defer expressions.deinit(gpa); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .int = .{ .region = rand_region(), .token = rand_token_idx(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .frac = .{ .region = rand_region(), .token = rand_token_idx(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .single_quote = .{ .region = rand_region(), .token = rand_token_idx(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .string_part = .{ .region = rand_region(), .token = rand_token_idx(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .string = .{ .parts = AST.Expr.Span{ .span = rand_span() }, .region = rand_region(), .token = rand_token_idx(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .list = .{ .items = AST.Expr.Span{ .span = rand_span() }, .region = rand_region(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .tuple = .{ .items = AST.Expr.Span{ .span = rand_span() }, .region = rand_region(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .record = .{ .ext = rand_idx(AST.Expr.Idx), .fields = AST.RecordField.Span{ .span = rand_span() }, .region = rand_region(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .tag = .{ .qualifiers = AST.Token.Span{ .span = rand_span() }, .region = rand_region(), .token = rand_token_idx(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .lambda = .{ .args = AST.Pattern.Span{ .span = rand_span() }, .region = rand_region(), .body = rand_idx(AST.Expr.Idx), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .apply = .{ .@"fn" = rand_idx(AST.Expr.Idx), .args = AST.Expr.Span{ .span = rand_span() }, @@ -543,7 +543,7 @@ test "NodeStore round trip - Expr" { }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .field_access = .{ .left = rand_idx(AST.Expr.Idx), .right = rand_idx(AST.Expr.Idx), @@ -551,7 +551,7 @@ test "NodeStore round trip - Expr" { .region = rand_region(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .local_dispatch = .{ .left = rand_idx(AST.Expr.Idx), .right = rand_idx(AST.Expr.Idx), @@ -559,7 +559,7 @@ test "NodeStore round trip - Expr" { .region = rand_region(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .bin_op = .{ .left = rand_idx(AST.Expr.Idx), .right = rand_idx(AST.Expr.Idx), @@ -567,21 +567,21 @@ test "NodeStore round trip - Expr" { .region = rand_region(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .suffix_single_question = .{ .expr = rand_idx(AST.Expr.Idx), .operator = rand_token_idx(), .region = rand_region(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .unary_op = .{ .expr = rand_idx(AST.Expr.Idx), .operator = rand_token_idx(), .region = rand_region(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .if_then_else = .{ .@"else" = rand_idx(AST.Expr.Idx), .condition = rand_idx(AST.Expr.Idx), @@ -589,37 +589,37 @@ test "NodeStore round trip - Expr" { .region = rand_region(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .match = .{ .branches = AST.MatchBranch.Span{ .span = rand_span() }, .expr = rand_idx(AST.Expr.Idx), .region = rand_region(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .ident = .{ .qualifiers = AST.Token.Span{ .span = rand_span() }, .region = rand_region(), .token = rand_token_idx(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .dbg = .{ .expr = rand_idx(AST.Expr.Idx), .region = rand_region(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .record_builder = .{ .fields = rand_idx(AST.RecordField.Idx), .mapper = rand_idx(AST.Expr.Idx), .region = rand_region(), }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .ellipsis = .{ .region = rand_region() }, }); - try expressions.append(AST.Expr{ + try expressions.append(gpa, AST.Expr{ .block = .{ .region = rand_region(), .statements = AST.Statement.Span{ .span = rand_span() }, diff --git a/src/repl/eval.zig b/src/repl/eval.zig index cec493cadd..60b0714404 100644 --- a/src/repl/eval.zig +++ b/src/repl/eval.zig @@ -27,12 +27,13 @@ const LoadedModule = struct { gpa: std.mem.Allocator, fn deinit(self: *LoadedModule) void { - // IMPORTANT: When a module is deserialized from a buffer, all its internal structures - // (common, types, external_decls, imports, store) contain pointers INTO the buffer, - // not separately allocated memory. Therefore we should NOT call deinit() on any of them. - // The only memory we need to free is: - // 1. The buffer itself (which contains all the deserialized data) - // 2. The env struct itself (which was allocated with create()) + // IMPORTANT: When a module is deserialized from a buffer, most of its internal structures + // (common, types, external_decls, store) contain pointers INTO the buffer, + // not separately allocated memory. However, the imports.map is allocated separately + // during deserialization and must be freed. + + // Free the imports map (allocated in CIR.Import.Store.Serialized.deserialize) + self.env.imports.map.deinit(self.gpa); // Free the buffer (all data structures point into this buffer) self.gpa.free(self.buffer); @@ -216,9 +217,9 @@ pub const Repl = struct { defer tree.deinit(); try module_env.pushToSExprTree(expr_idx, &tree); - var can_buffer = std.array_list.Managed(u8).init(self.allocator); - defer can_buffer.deinit(); - try tree.toStringPretty(can_buffer.writer().any(), .include_linecol); + var can_buffer = std.ArrayList(u8).empty; + defer can_buffer.deinit(self.allocator); + try tree.toStringPretty(can_buffer.writer(self.allocator).any(), .include_linecol); const can_html = try self.allocator.dupe(u8, can_buffer.items); try self.debug_can_html.append(can_html); @@ -230,9 +231,9 @@ pub const Repl = struct { defer tree.deinit(); try module_env.pushTypesToSExprTree(expr_idx, &tree); - var types_buffer = std.array_list.Managed(u8).init(self.allocator); - defer types_buffer.deinit(); - try tree.toStringPretty(types_buffer.writer().any(), .include_linecol); + var types_buffer = std.ArrayList(u8).empty; + defer types_buffer.deinit(self.allocator); + try tree.toStringPretty(types_buffer.writer(self.allocator).any(), .include_linecol); const types_html = try self.allocator.dupe(u8, types_buffer.items); try self.debug_types_html.append(types_html); @@ -429,29 +430,29 @@ pub const Repl = struct { return try self.allocator.dupe(u8, current_expr); } - var buffer = std.array_list.Managed(u8).init(self.allocator); - defer buffer.deinit(); + var buffer = std.ArrayList(u8).empty; + errdefer buffer.deinit(self.allocator); // Start block - try buffer.appendSlice("{\n"); + try buffer.appendSlice(self.allocator, "{\n"); // Add all definitions in order var iterator = self.definitions.iterator(); while (iterator.next()) |kv| { - try buffer.appendSlice(" "); - try buffer.appendSlice(kv.value_ptr.*); - try buffer.append('\n'); + try buffer.appendSlice(self.allocator, " "); + try buffer.appendSlice(self.allocator, kv.value_ptr.*); + try buffer.append(self.allocator, '\n'); } // Add current expression - try buffer.appendSlice(" "); - try buffer.appendSlice(current_expr); - try buffer.append('\n'); + try buffer.appendSlice(self.allocator, " "); + try buffer.appendSlice(self.allocator, current_expr); + try buffer.append(self.allocator, '\n'); // End block - try buffer.append('}'); + try buffer.append(self.allocator, '}'); - return try buffer.toOwnedSlice(); + return try buffer.toOwnedSlice(self.allocator); } /// Evaluate source code diff --git a/src/reporting/document.zig b/src/reporting/document.zig index 141dcba2cc..ddfa39d3c6 100644 --- a/src/reporting/document.zig +++ b/src/reporting/document.zig @@ -698,13 +698,13 @@ test "Document string memory safety" { defer document.deinit(); // Create temporary strings that would be freed in real usage - var temp_text = std.array_list.Managed(u8).init(gpa); - defer temp_text.deinit(); - try temp_text.appendSlice("This is test text"); + var temp_text = std.ArrayList(u8).empty; + defer temp_text.deinit(gpa); + try temp_text.appendSlice(gpa, "This is test text"); - var temp_annotated = std.array_list.Managed(u8).init(gpa); - defer temp_annotated.deinit(); - try temp_annotated.appendSlice("This is annotated"); + var temp_annotated = std.ArrayList(u8).empty; + defer temp_annotated.deinit(gpa); + try temp_annotated.appendSlice(gpa, "This is annotated"); // Add text and annotated content (should be copied) try document.addText(temp_text.items); diff --git a/src/reporting/test.zig b/src/reporting/test.zig index f00a7b60cd..f9a3d6c052 100644 --- a/src/reporting/test.zig +++ b/src/reporting/test.zig @@ -19,8 +19,8 @@ const ColorPalette = @import("style.zig").ColorPalette; test "SYNTAX_PROBLEM report along with all four render types" { const gpa = testing.allocator; - var buffer = std.array_list.Managed(u8).init(gpa); - defer buffer.deinit(); + var buffer = std.ArrayList(u8).empty; + defer buffer.deinit(gpa); // Create a Report var r = Report.init(gpa, "SYNTAX PROBLEM", .runtime_error); diff --git a/src/snapshot_tool/main.zig b/src/snapshot_tool/main.zig index 6f0fe9f67c..ce7ff7ea14 100644 --- a/src/snapshot_tool/main.zig +++ b/src/snapshot_tool/main.zig @@ -572,7 +572,7 @@ fn renderReportsToExpectedContent(allocator: std.mem.Allocator, reports: *const } // Render all reports to markdown and then parse the problems - var problems_buffer_unmanaged = std.ArrayListUnmanaged(u8).empty; + var problems_buffer_unmanaged = std.ArrayList(u8).empty; var problems_writer_allocating: std.Io.Writer.Allocating = .fromArrayList(allocator, &problems_buffer_unmanaged); defer problems_buffer_unmanaged.deinit(allocator); @@ -1478,11 +1478,11 @@ fn processSnapshotContent( } // Buffer all output in memory before writing files - var md_buffer_unmanaged = std.ArrayListUnmanaged(u8).empty; + var md_buffer_unmanaged = std.ArrayList(u8).empty; var md_writer_allocating: std.Io.Writer.Allocating = .fromArrayList(allocator, &md_buffer_unmanaged); defer md_buffer_unmanaged.deinit(allocator); - var html_buffer_unmanaged: ?std.ArrayListUnmanaged(u8) = if (config.generate_html) std.ArrayListUnmanaged(u8).empty else null; + var html_buffer_unmanaged: ?std.ArrayList(u8) = if (config.generate_html) std.ArrayList(u8).empty else null; var html_writer_allocating: ?std.Io.Writer.Allocating = if (config.generate_html) .fromArrayList(allocator, &html_buffer_unmanaged.?) else null; defer { if (html_buffer_unmanaged) |*buf| buf.deinit(allocator); @@ -2490,7 +2490,7 @@ fn generateTypesSection(output: *DualOutput, can_ir: *ModuleEnv, maybe_expr_idx: /// Generate TYPES section displaying types store for both markdown and HTML /// This is used for debugging. fn generateTypesStoreSection(gpa: std.mem.Allocator, output: *DualOutput, can_ir: *ModuleEnv) !void { - var solved_unmanaged = std.ArrayListUnmanaged(u8).empty; + var solved_unmanaged = std.ArrayList(u8).empty; var solved_writer: std.Io.Writer.Allocating = .fromArrayList(output.gpa, &solved_unmanaged); defer solved_unmanaged.deinit(output.gpa); @@ -2607,7 +2607,7 @@ fn generateHtmlClosing(output: *DualOutput) !void { } /// Write HTML buffer to file -fn writeHtmlFile(gpa: Allocator, snapshot_path: []const u8, html_buffer: *std.ArrayListUnmanaged(u8)) !void { +fn writeHtmlFile(gpa: Allocator, snapshot_path: []const u8, html_buffer: *std.ArrayList(u8)) !void { // Convert .md path to .html path const html_path = blk: { if (std.mem.endsWith(u8, snapshot_path, ".md")) { @@ -2805,11 +2805,11 @@ fn processReplSnapshot(allocator: Allocator, content: Content, output_path: []co log("Processing REPL snapshot: {s}", .{output_path}); // Buffer all output in memory before writing files - var md_buffer_unmanaged = std.ArrayListUnmanaged(u8).empty; + var md_buffer_unmanaged = std.ArrayList(u8).empty; var md_writer_allocating: std.Io.Writer.Allocating = .fromArrayList(allocator, &md_buffer_unmanaged); defer md_buffer_unmanaged.deinit(allocator); - var html_buffer_unmanaged: ?std.ArrayListUnmanaged(u8) = if (config.generate_html) std.ArrayListUnmanaged(u8).empty else null; + var html_buffer_unmanaged: ?std.ArrayList(u8) = if (config.generate_html) std.ArrayList(u8).empty else null; var html_writer_allocating: ?std.Io.Writer.Allocating = if (config.generate_html) .fromArrayList(allocator, &html_buffer_unmanaged.?) else null; defer { if (html_buffer_unmanaged) |*buf| buf.deinit(allocator); diff --git a/src/types/instantiate.zig b/src/types/instantiate.zig index b4dfaa2e2a..8df2b13fbb 100644 --- a/src/types/instantiate.zig +++ b/src/types/instantiate.zig @@ -194,13 +194,13 @@ pub const Instantiator = struct { } fn instantiateAlias(self: *Self, alias: Alias) std.mem.Allocator.Error!Content { - var fresh_vars = std.array_list.Managed(Var).init(self.store.gpa); - defer fresh_vars.deinit(); + var fresh_vars = std.ArrayList(Var).empty; + defer fresh_vars.deinit(self.store.gpa); var iter = self.store.iterAliasArgs(alias); while (iter.next()) |arg_var| { const fresh_elem = try self.instantiateVar(arg_var); - try fresh_vars.append(fresh_elem); + try fresh_vars.append(self.store.gpa, fresh_elem); } const backing_var = self.store.getAliasBackingVar(alias); @@ -233,13 +233,13 @@ pub const Instantiator = struct { const backing_var = self.store.getNominalBackingVar(nominal); const fresh_backing_var = try self.instantiateVar(backing_var); - var fresh_vars = std.array_list.Managed(Var).init(self.store.gpa); - defer fresh_vars.deinit(); + var fresh_vars = std.ArrayList(Var).empty; + defer fresh_vars.deinit(self.store.gpa); var iter = self.store.iterNominalArgs(nominal); while (iter.next()) |arg_var| { const fresh_elem = try self.instantiateVar(arg_var); - try fresh_vars.append(fresh_elem); + try fresh_vars.append(self.store.gpa, fresh_elem); } return (try self.store.mkNominal(nominal.ident, fresh_backing_var, fresh_vars.items, nominal.origin_module)).structure.nominal_type; @@ -247,12 +247,12 @@ pub const Instantiator = struct { fn instantiateTuple(self: *Self, tuple: Tuple) std.mem.Allocator.Error!Tuple { const elems_slice = self.store.sliceVars(tuple.elems); - var fresh_elems = std.array_list.Managed(Var).init(self.store.gpa); - defer fresh_elems.deinit(); + var fresh_elems = std.ArrayList(Var).empty; + defer fresh_elems.deinit(self.store.gpa); for (elems_slice) |elem_var| { const fresh_elem = try self.instantiateVar(elem_var); - try fresh_elems.append(fresh_elem); + try fresh_elems.append(self.store.gpa, fresh_elem); } const fresh_elems_range = try self.store.appendVars(fresh_elems.items); @@ -276,12 +276,12 @@ pub const Instantiator = struct { fn instantiateFunc(self: *Self, func: Func) std.mem.Allocator.Error!Func { const args_slice = self.store.sliceVars(func.args); - var fresh_args = std.array_list.Managed(Var).init(self.store.gpa); - defer fresh_args.deinit(); + var fresh_args = std.ArrayList(Var).empty; + defer fresh_args.deinit(self.store.gpa); for (args_slice) |arg_var| { const fresh_arg = try self.instantiateVar(arg_var); - try fresh_args.append(fresh_arg); + try fresh_args.append(self.store.gpa, fresh_arg); } const fresh_ret = try self.instantiateVar(func.ret); @@ -296,12 +296,12 @@ pub const Instantiator = struct { fn instantiateRecordFields(self: *Self, fields: RecordField.SafeMultiList.Range) std.mem.Allocator.Error!RecordField.SafeMultiList.Range { const fields_slice = self.store.getRecordFieldsSlice(fields); - var fresh_fields = std.array_list.Managed(RecordField).init(self.store.gpa); - defer fresh_fields.deinit(); + var fresh_fields = std.ArrayList(RecordField).empty; + defer fresh_fields.deinit(self.store.gpa); for (fields_slice.items(.name), fields_slice.items(.var_)) |name, type_var| { const fresh_type = try self.instantiateVar(type_var); - _ = try fresh_fields.append(RecordField{ + _ = try fresh_fields.append(self.store.gpa, RecordField{ .name = name, .var_ = fresh_type, }); @@ -313,12 +313,12 @@ pub const Instantiator = struct { fn instantiateRecord(self: *Self, record: Record) std.mem.Allocator.Error!Record { const fields_slice = self.store.getRecordFieldsSlice(record.fields); - var fresh_fields = std.array_list.Managed(RecordField).init(self.store.gpa); - defer fresh_fields.deinit(); + var fresh_fields = std.ArrayList(RecordField).empty; + defer fresh_fields.deinit(self.store.gpa); for (fields_slice.items(.name), fields_slice.items(.var_)) |name, type_var| { const fresh_type = try self.instantiateVar(type_var); - _ = try fresh_fields.append(RecordField{ + _ = try fresh_fields.append(self.store.gpa, RecordField{ .name = name, .var_ = fresh_type, }); @@ -334,22 +334,22 @@ pub const Instantiator = struct { fn instantiateTagUnion(self: *Self, tag_union: TagUnion) std.mem.Allocator.Error!TagUnion { const tags_slice = self.store.getTagsSlice(tag_union.tags); - var fresh_tags = std.array_list.Managed(Tag).init(self.store.gpa); - defer fresh_tags.deinit(); + var fresh_tags = std.ArrayList(Tag).empty; + defer fresh_tags.deinit(self.store.gpa); for (tags_slice.items(.name), tags_slice.items(.args)) |tag_name, tag_args| { - var fresh_args = std.array_list.Managed(Var).init(self.store.gpa); - defer fresh_args.deinit(); + var fresh_args = std.ArrayList(Var).empty; + defer fresh_args.deinit(self.store.gpa); const args_slice = self.store.sliceVars(tag_args); for (args_slice) |arg_var| { const fresh_arg = try self.instantiateVar(arg_var); - try fresh_args.append(fresh_arg); + try fresh_args.append(self.store.gpa, fresh_arg); } const fresh_args_range = try self.store.appendVars(fresh_args.items); - _ = try fresh_tags.append(Tag{ + _ = try fresh_tags.append(self.store.gpa, Tag{ .name = tag_name, .args = fresh_args_range, }); @@ -371,12 +371,12 @@ pub const Instantiator = struct { if (constraints_len == 0) { return StaticDispatchConstraint.SafeList.Range.empty(); } else { - var fresh_constraints = try std.array_list.Managed(StaticDispatchConstraint).initCapacity(self.store.gpa, constraints.len()); - defer fresh_constraints.deinit(); + var fresh_constraints = try std.ArrayList(StaticDispatchConstraint).initCapacity(self.store.gpa, constraints.len()); + defer fresh_constraints.deinit(self.store.gpa); for (self.store.sliceStaticDispatchConstraints(constraints)) |constraint| { const fresh_constraint = try self.instantiateStaticDispatchConstraint(constraint); - try fresh_constraints.append(fresh_constraint); + try fresh_constraints.append(self.store.gpa, fresh_constraint); } const fresh_constraints_range = try self.store.appendStaticDispatchConstraints(fresh_constraints.items); diff --git a/src/watch/watch.zig b/src/watch/watch.zig index 308b36263f..ce3a1f4a1b 100644 --- a/src/watch/watch.zig +++ b/src/watch/watch.zig @@ -1368,18 +1368,17 @@ test "thread safety" { const global = struct { var event_count: std.atomic.Value(u32) = std.atomic.Value(u32).init(0); var mutex: std.Thread.Mutex = .{}; - var events: std.array_list.Managed([]const u8) = undefined; + var events: std.ArrayList([]const u8) = .empty; }; - global.events = std.array_list.Managed([]const u8).init(allocator); - defer global.events.deinit(); + defer global.events.deinit(allocator); const callback = struct { fn cb(event: WatchEvent) void { _ = global.event_count.fetchAdd(1, .seq_cst); global.mutex.lock(); defer global.mutex.unlock(); - global.events.append(allocator.dupe(u8, event.path) catch return) catch return; + global.events.append(allocator, allocator.dupe(u8, event.path) catch return) catch return; } }.cb; @@ -1541,14 +1540,14 @@ test "windows long path handling" { } // Create the nested directories - var current_path = std.array_list.Managed(u8).init(allocator); - defer current_path.deinit(); + var current_path = std.ArrayList(u8).empty; + defer current_path.deinit(allocator); for (path_components.items) |component| { if (current_path.items.len > 0) { - try current_path.append(std.fs.path.sep); + try current_path.append(allocator, std.fs.path.sep); } - try current_path.appendSlice(component); + try current_path.appendSlice(allocator, component); try temp_dir.dir.makePath(current_path.items); } diff --git a/test/compile/has_parse_error.roc b/test/compile/has_parse_error.roc new file mode 100644 index 0000000000..27bf86d4bf --- /dev/null +++ b/test/compile/has_parse_error.roc @@ -0,0 +1,7 @@ +app [main] {} + +# This file intentionally has a parse error for testing stderr reporting +main = + # Missing closing quote to trigger tokenization error + x = "unclosed string + x diff --git a/test/playground-integration/main.zig b/test/playground-integration/main.zig index 10dcda3d24..d645864392 100644 --- a/test/playground-integration/main.zig +++ b/test/playground-integration/main.zig @@ -841,15 +841,15 @@ fn runTests(arena: std.mem.Allocator, gpa: std.mem.Allocator, test_cases: []cons .skipped = 0, }; - var failures = std.array_list.Managed(TestFailure).init(arena); - defer failures.deinit(); + var failures = std.ArrayList(TestFailure).empty; + defer failures.deinit(arena); for (test_cases) |case| { logDebug("\n[INFO] Setting up WASM interface for test case: {s}...\n", .{case.name}); var wasm_interface = setupWasm(gpa, arena, wasm_path) catch |err| { logDebug("[ERROR] Failed to setup WASM for test case '{s}': {}\n", .{ case.name, err }); stats.failed += 1; - try failures.append(.{ + try failures.append(arena, .{ .case_name = case.name, .step_index = 0, .message = "WASM setup failed", @@ -865,7 +865,7 @@ fn runTests(arena: std.mem.Allocator, gpa: std.mem.Allocator, test_cases: []cons .failed => { stats.failed += 1; const failure_msg = case_execution_result.failure_message orelse "Test failed"; - try failures.append(.{ + try failures.append(arena, .{ .case_name = case.name, .step_index = 0, // Could be enhanced to track specific step .message = failure_msg, @@ -964,8 +964,8 @@ pub fn main() !void { const playground_wasm_path = wasm_path orelse "zig-out/bin/playground.wasm"; // Setup our test cases - var test_cases = std.array_list.Managed(TestCase).init(allocator); - defer test_cases.deinit(); // This will free the TestCase structs and their `steps` slices. + var test_cases = std.ArrayList(TestCase).empty; + defer test_cases.deinit(allocator); // This will free the TestCase structs and their `steps` slices. // Functional Test var happy_path_steps = try allocator.alloc(MessageStep, 8); @@ -1009,21 +1009,21 @@ pub fn main() !void { .expected_status = "SUCCESS", .expected_hover_info_contains = "Str", }; - try test_cases.append(.{ + try test_cases.append(allocator, .{ .name = "Happy Path - Simple Roc Program", .steps = happy_path_steps, }); // Error Handling Test const syntax_error_code_val = try TestData.syntaxErrorRocCode(allocator); - try test_cases.append(try createSimpleTest(allocator, "Syntax Error - Mismatched Braces", syntax_error_code_val, .{ .min_errors = 1, .error_messages = &.{"LIST NOT CLOSED"} }, true)); + try test_cases.append(allocator, try createSimpleTest(allocator, "Syntax Error - Mismatched Braces", syntax_error_code_val, .{ .min_errors = 1, .error_messages = &.{"LIST NOT CLOSED"} }, true)); const type_error_code_val = try TestData.typeErrorRocCode(allocator); - try test_cases.append(try createSimpleTest(allocator, "Type Error - Adding String and Number", type_error_code_val, .{ .min_errors = 1, .error_messages = &.{"TYPE MISMATCH"} }, true)); + try test_cases.append(allocator, try createSimpleTest(allocator, "Type Error - Adding String and Number", type_error_code_val, .{ .min_errors = 1, .error_messages = &.{"TYPE MISMATCH"} }, true)); // Empty Source Test const empty_source_code = try allocator.dupe(u8, ""); - try test_cases.append(try createSimpleTest(allocator, "Empty Source Code", empty_source_code, null, false)); // Disable diagnostic expectations + try test_cases.append(allocator, try createSimpleTest(allocator, "Empty Source Code", empty_source_code, null, false)); // Disable diagnostic expectations // Code Formatting Test var formatted_test_steps = try allocator.alloc(MessageStep, 3); @@ -1040,7 +1040,7 @@ pub fn main() !void { .expected_status = "SUCCESS", .expected_data_contains = "foo", }; - try test_cases.append(.{ + try test_cases.append(allocator, .{ .name = "QUERY_FORMATTED - Code Formatting", .steps = formatted_test_steps, }); @@ -1053,7 +1053,7 @@ pub fn main() !void { .expected_status = "INVALID_MESSAGE", .expected_message_contains = "Unknown message type", }; - try test_cases.append(.{ + try test_cases.append(allocator, .{ .name = "Invalid Message Type", .steps = invalid_msg_type_steps, }); @@ -1077,7 +1077,7 @@ pub fn main() !void { .owned_source = happy_code_after_reset, }; reset_test_steps[4] = .{ .message = .{ .type = "QUERY_TYPES" }, .expected_status = "SUCCESS", .expected_data_contains = "inferred-types" }; - try test_cases.append(.{ + try test_cases.append(allocator, .{ .name = "RESET Message Functionality", .steps = reset_test_steps, }); @@ -1099,7 +1099,7 @@ pub fn main() !void { .expected_diagnostics = .{ .min_errors = 1, .error_messages = &.{"LIST NOT CLOSED"} }, .owned_source = code_for_mem_test_2, }; - try test_cases.append(.{ + try test_cases.append(allocator, .{ .name = "Memory Corruption on Reset - Load, Reset, Load", .steps = memory_corruption_steps, }); @@ -1127,7 +1127,7 @@ pub fn main() !void { .expected_status = "SUCCESS", .expected_hover_info_contains = "Num(Int(Signed32))", }; - try test_cases.append(.{ + try test_cases.append(allocator, .{ .name = "GET_HOVER_INFO - Specific Type Query", .steps = get_hover_info_steps, }); @@ -1142,7 +1142,7 @@ pub fn main() !void { repl_lifecycle_steps[3] = .{ .message = .{ .type = "CLEAR_REPL" }, .expected_status = "SUCCESS", .expected_message_contains = "REPL cleared" }; repl_lifecycle_steps[4] = .{ .message = .{ .type = "RESET" }, .expected_status = "SUCCESS" }; - try test_cases.append(.{ + try test_cases.append(allocator, .{ .name = "REPL Lifecycle - Init, Step, Clear, Reset", .steps = repl_lifecycle_steps, }); @@ -1156,7 +1156,7 @@ pub fn main() !void { repl_core_steps[4] = .{ .message = .{ .type = "REPL_STEP", .input = "y" }, .expected_status = "SUCCESS", .expected_result_output_contains = "15" }; repl_core_steps[5] = .{ .message = .{ .type = "RESET" }, .expected_status = "SUCCESS" }; - try test_cases.append(.{ + try test_cases.append(allocator, .{ .name = "REPL Core - Definitions and Expressions", .steps = repl_core_steps, }); @@ -1176,7 +1176,7 @@ pub fn main() !void { }; repl_redefinition_steps[7] = .{ .message = .{ .type = "RESET" }, .expected_status = "SUCCESS" }; - try test_cases.append(.{ + try test_cases.append(allocator, .{ .name = "REPL Variable Redefinition - Dependency Updates", .steps = repl_redefinition_steps, }); @@ -1200,7 +1200,7 @@ pub fn main() !void { }; repl_error_steps[5] = .{ .message = .{ .type = "RESET" }, .expected_status = "SUCCESS" }; - try test_cases.append(.{ + try test_cases.append(allocator, .{ .name = "REPL Error Handling - Invalid Syntax Recovery", .steps = repl_error_steps, }); @@ -1217,7 +1217,7 @@ pub fn main() !void { .expected_data_contains = "can-ir", }; - try test_cases.append(.{ + try test_cases.append(allocator, .{ .name = "REPL Compiler Integration - Query After Evaluation", .steps = repl_compiler_steps, }); @@ -1238,7 +1238,7 @@ pub fn main() !void { }; repl_isolation_steps[5] = .{ .message = .{ .type = "QUERY_TYPES" }, .expected_status = "SUCCESS" }; - try test_cases.append(.{ + try test_cases.append(allocator, .{ .name = "REPL State Isolation - Mode Switching", .steps = repl_isolation_steps, }); diff --git a/test/snapshots/bound_type_var_no_annotation.md b/test/snapshots/bound_type_var_no_annotation.md index 0fb0db6e72..fb4fa803a6 100644 --- a/test/snapshots/bound_type_var_no_annotation.md +++ b/test/snapshots/bound_type_var_no_annotation.md @@ -217,9 +217,9 @@ main! = |_| { (p-assign (ident "main!")) (e-closure (captures - (capture (ident "addOne")) + (capture (ident "identity")) (capture (ident "combine")) - (capture (ident "identity"))) + (capture (ident "addOne"))) (e-lambda (args (p-underscore)) diff --git a/test/snapshots/can_import_exposing_types.md b/test/snapshots/can_import_exposing_types.md index 9a8e8634ce..4082de4950 100644 --- a/test/snapshots/can_import_exposing_types.md +++ b/test/snapshots/can_import_exposing_types.md @@ -880,8 +880,8 @@ combineResults = |jsonResult, httpStatus| (p-assign (ident "combineResults")) (e-closure (captures - (capture (ident "error")) - (capture (ident "value"))) + (capture (ident "value")) + (capture (ident "error"))) (e-lambda (args (p-assign (ident "jsonResult")) diff --git a/test/snapshots/can_import_type_annotations.md b/test/snapshots/can_import_type_annotations.md index 48acae5ea3..60ea95c215 100644 --- a/test/snapshots/can_import_type_annotations.md +++ b/test/snapshots/can_import_type_annotations.md @@ -559,10 +559,10 @@ combineResults = |result1, result2| (p-assign (ident "combineResults")) (e-closure (captures + (capture (ident "value1")) (capture (ident "value2")) (capture (ident "err")) - (capture (ident "err")) - (capture (ident "value1"))) + (capture (ident "err"))) (e-lambda (args (p-assign (ident "result1")) diff --git a/test/snapshots/expr/ann_effectful_fn.md b/test/snapshots/expr/ann_effectful_fn.md index d296b94e02..812028197f 100644 --- a/test/snapshots/expr/ann_effectful_fn.md +++ b/test/snapshots/expr/ann_effectful_fn.md @@ -13,9 +13,31 @@ type=expr } ~~~ # EXPECTED -NIL +UNUSED VALUE - ann_effectful_fn.md:2:35:2:39 +UNUSED VALUE - ann_effectful_fn.md:2:40:2:53 # PROBLEMS -NIL +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**ann_effectful_fn.md:2:35:2:39:** +```roc + launchTheNukes : {} => Result Bool LaunchNukeErr +``` + ^^^^ + +It has the type: + _[Bool]_others_ + +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**ann_effectful_fn.md:2:40:2:53:** +```roc + launchTheNukes : {} => Result Bool LaunchNukeErr +``` + ^^^^^^^^^^^^^ + +It has the type: + _[LaunchNukeErr]_others_ + # TOKENS ~~~zig OpenCurly, diff --git a/test/snapshots/formatting/multiline/everything.md b/test/snapshots/formatting/multiline/everything.md index a849c396f6..61ee03c59c 100644 --- a/test/snapshots/formatting/multiline/everything.md +++ b/test/snapshots/formatting/multiline/everything.md @@ -683,10 +683,10 @@ h = |x, y| { (p-assign (ident "h")) (e-closure (captures - (capture (ident "a")) (capture (ident "h")) (capture (ident "a")) (capture (ident "a")) + (capture (ident "a")) (capture (ident "a"))) (e-lambda (args diff --git a/test/snapshots/formatting/multiline_without_comma/everything.md b/test/snapshots/formatting/multiline_without_comma/everything.md index 259b43e957..9e2788aa31 100644 --- a/test/snapshots/formatting/multiline_without_comma/everything.md +++ b/test/snapshots/formatting/multiline_without_comma/everything.md @@ -1763,6 +1763,7 @@ h = |x, y| { (p-assign (ident "h")) (e-closure (captures + (capture (ident "h")) (capture (ident "a")) (capture (ident "a")) (capture (ident "h")) diff --git a/test/snapshots/formatting/singleline/everything.md b/test/snapshots/formatting/singleline/everything.md index 985a8990a3..c82fba13a4 100644 --- a/test/snapshots/formatting/singleline/everything.md +++ b/test/snapshots/formatting/singleline/everything.md @@ -371,10 +371,10 @@ NO CHANGE (p-assign (ident "h")) (e-closure (captures - (capture (ident "a")) (capture (ident "h")) (capture (ident "a")) (capture (ident "a")) + (capture (ident "a")) (capture (ident "a"))) (e-lambda (args diff --git a/test/snapshots/formatting/singleline_with_comma/everything.md b/test/snapshots/formatting/singleline_with_comma/everything.md index 2d1601fd85..5e8749eed4 100644 --- a/test/snapshots/formatting/singleline_with_comma/everything.md +++ b/test/snapshots/formatting/singleline_with_comma/everything.md @@ -484,10 +484,10 @@ h = | (p-assign (ident "h")) (e-closure (captures - (capture (ident "a")) (capture (ident "h")) (capture (ident "a")) (capture (ident "a")) + (capture (ident "a")) (capture (ident "a"))) (e-lambda (args diff --git a/test/snapshots/fuzz_crash/fuzz_crash_019.md b/test/snapshots/fuzz_crash/fuzz_crash_019.md index eecbe9b47c..967df12709 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_019.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_019.md @@ -163,7 +163,9 @@ UNDEFINED VARIABLE - fuzz_crash_019.md:80:3:80:6 CRASH EXPECTS STRING - fuzz_crash_019.md:86:3:86:11 UNDEFINED VARIABLE - fuzz_crash_019.md:87:11:87:12 UNDEFINED VARIABLE - fuzz_crash_019.md:89:3:89:6 -NOT IMPLEMENTED - :0:0:0:0 +UNDEFINED VARIABLE - fuzz_crash_019.md:92:11:92:15 +UNDEFINED VARIABLE - fuzz_crash_019.md:93:2:93:7 +UNDEFINED VARIABLE - fuzz_crash_019.md:94:3:94:6 UNDEFINED VARIABLE - fuzz_crash_019.md:96:34:96:37 UNDEFINED VARIABLE - fuzz_crash_019.md:96:47:96:52 UNDEFINED VARIABLE - fuzz_crash_019.md:96:54:96:57 @@ -187,8 +189,15 @@ UNDEFINED VARIABLE - fuzz_crash_019.md:120:1:120:2 UNDEFINED VARIABLE - fuzz_crash_019.md:120:6:120:9 EXPOSED BUT NOT DEFINED - fuzz_crash_019.md:2:6:2:11 TOO FEW ARGS - fuzz_crash_019.md:17:3:18:4 +UNUSED VALUE - fuzz_crash_019.md:39:2:39:3 INCOMPATIBLE MATCH PATTERNS - fuzz_crash_019.md:52:2:52:2 +UNUSED VALUE - fuzz_crash_019.md:1:1:1:1 TYPE MISMATCH - fuzz_crash_019.md:84:2:86:3 +UNUSED VALUE - fuzz_crash_019.md:84:2:86:3 +UNUSED VALUE - fuzz_crash_019.md:86:11:86:17 +UNUSED VALUE - fuzz_crash_019.md:98:4:104:3 +UNUSED VALUE - fuzz_crash_019.md:105:2:105:54 +UNUSED VALUE - fuzz_crash_019.md:105:55:105:85 # PROBLEMS **PARSE ERROR** A parsing error occurred: `match_branch_missing_arrow` @@ -586,10 +595,38 @@ Is there an `import` or `exposing` missing up-top? ^^^ -**NOT IMPLEMENTED** -This feature is not yet implemented: statement type in block +**UNDEFINED VARIABLE** +Nothing is named `list` in this scope. +Is there an `import` or `exposing` missing up-top? + +**fuzz_crash_019.md:92:11:92:15:** +```roc + for n in list { +``` + ^^^^ + + +**UNDEFINED VARIABLE** +Nothing is named `line!` in this scope. +Is there an `import` or `exposing` missing up-top? + +**fuzz_crash_019.md:93:2:93:7:** +```roc + line!("Ag ${n} to ${er}") +``` + ^^^^^ + + +**UNDEFINED VARIABLE** +Nothing is named `ber` in this scope. +Is there an `import` or `exposing` missing up-top? + +**fuzz_crash_019.md:94:3:94:6:** +```roc + ber + n +``` + ^^^ -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! **UNDEFINED VARIABLE** Nothing is named `tag` in this scope. @@ -846,6 +883,17 @@ The type _List_ expects argument, but got instead. +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_019.md:39:2:39:3:** +```roc + 1 +``` + ^ + +It has the type: + _Num(_size)_ + **INCOMPATIBLE MATCH PATTERNS** The pattern in the fourth branch of this `match` differs from previous ones: **fuzz_crash_019.md:52:2:** @@ -881,6 +929,17 @@ All patterns in an `match` must have compatible types. +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_019.md:1:1:1:1:** +```roc +# Thnt! +``` +^ + +It has the type: + __f_ + **TYPE MISMATCH** This expression is used in an unexpected way: **fuzz_crash_019.md:84:2:86:3:** @@ -896,6 +955,67 @@ It has the type: But I expected it to be: _[Blue]_others, [Tb]_others2 -> Error_ +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_019.md:84:2:86:3:** +```roc + me( + ..., # r + )crash ke"Unr!" #) +``` + +It has the type: + __f_ + +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_019.md:86:11:86:17:** +```roc + )crash ke"Unr!" #) +``` + ^^^^^^ + +It has the type: + _Str_ + +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_019.md:98:4:104:3:** +```roc + m ( + 123, + "World",ag1, + O, # nt + (ne, tuple), + [1, 2, 3], + ) +``` + +It has the type: + _(Num(_size), Str, Error, [O]_others, (Error, Error), List(Num(_size2)))_ + +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_019.md:105:2:105:54:** +```roc + b?? 12 > 5 or 13 + 2 < 5 and 10 - 1 >= 16 or 12 <= 3 e_fn(arg1)?.od()?.ned()?.recd? +``` + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It has the type: + _Bool_ + +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_019.md:105:55:105:85:** +```roc + b?? 12 > 5 or 13 + 2 < 5 and 10 - 1 >= 16 or 12 <= 3 e_fn(arg1)?.od()?.ned()?.recd? +``` + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It has the type: + __f_ + # TOKENS ~~~zig KwApp,OpenSquare,LowerIdent,CloseSquare,OpenCurly,LowerIdent,OpColon,KwPlatform,StringStart,StringPart,StringEnd,CloseCurly, @@ -1686,7 +1806,25 @@ expect { (p-assign (ident "er")))) (e-num (value "456")) (e-num (value "9"))))) - (s-runtime-error (tag "not_implemented")) + (s-for + (p-assign (ident "n")) + (e-runtime-error (tag "ident_not_in_scope")) + (e-block + (s-expr + (e-call + (e-runtime-error (tag "ident_not_in_scope")) + (e-string + (e-literal (string "Ag ")) + (e-lookup-local + (p-assign (ident "n"))) + (e-literal (string " to ")) + (e-lookup-local + (p-assign (ident "er"))) + (e-literal (string ""))))) + (e-binop (op "add") + (e-runtime-error (tag "ident_not_in_scope")) + (e-lookup-local + (p-assign (ident "n")))))) (s-let (p-assign (ident "rd")) (e-record diff --git a/test/snapshots/fuzz_crash/fuzz_crash_020.md b/test/snapshots/fuzz_crash/fuzz_crash_020.md index 5e9ebd4d4e..f3f20a1ee7 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_020.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_020.md @@ -164,7 +164,9 @@ UNDEFINED VARIABLE - fuzz_crash_020.md:80:3:80:6 CRASH EXPECTS STRING - fuzz_crash_020.md:86:3:86:11 UNDEFINED VARIABLE - fuzz_crash_020.md:87:11:87:12 UNDEFINED VARIABLE - fuzz_crash_020.md:89:3:89:6 -NOT IMPLEMENTED - :0:0:0:0 +UNDEFINED VARIABLE - fuzz_crash_020.md:92:11:92:15 +UNDEFINED VARIABLE - fuzz_crash_020.md:93:2:93:7 +UNDEFINED VARIABLE - fuzz_crash_020.md:94:3:94:6 UNDEFINED VARIABLE - fuzz_crash_020.md:96:34:96:37 UNDEFINED VARIABLE - fuzz_crash_020.md:96:47:96:52 UNDEFINED VARIABLE - fuzz_crash_020.md:96:54:96:57 @@ -188,7 +190,13 @@ UNDEFINED VARIABLE - fuzz_crash_020.md:120:1:120:2 UNDEFINED VARIABLE - fuzz_crash_020.md:120:6:120:9 EXPOSED BUT NOT DEFINED - fuzz_crash_020.md:2:6:2:11 TOO FEW ARGS - fuzz_crash_020.md:17:3:18:4 +UNUSED VALUE - fuzz_crash_020.md:39:2:39:3 INCOMPATIBLE MATCH PATTERNS - fuzz_crash_020.md:52:2:52:2 +UNUSED VALUE - fuzz_crash_020.md:1:1:1:1 +UNUSED VALUE - fuzz_crash_020.md:86:11:86:17 +UNUSED VALUE - fuzz_crash_020.md:98:4:104:3 +UNUSED VALUE - fuzz_crash_020.md:105:2:105:54 +UNUSED VALUE - fuzz_crash_020.md:105:55:105:85 # PROBLEMS **PARSE ERROR** A parsing error occurred: `match_branch_missing_arrow` @@ -597,10 +605,38 @@ Is there an `import` or `exposing` missing up-top? ^^^ -**NOT IMPLEMENTED** -This feature is not yet implemented: statement type in block +**UNDEFINED VARIABLE** +Nothing is named `list` in this scope. +Is there an `import` or `exposing` missing up-top? + +**fuzz_crash_020.md:92:11:92:15:** +```roc + for n in list { +``` + ^^^^ + + +**UNDEFINED VARIABLE** +Nothing is named `line!` in this scope. +Is there an `import` or `exposing` missing up-top? + +**fuzz_crash_020.md:93:2:93:7:** +```roc + line!("Ag ${n} to ${er}") +``` + ^^^^^ + + +**UNDEFINED VARIABLE** +Nothing is named `ber` in this scope. +Is there an `import` or `exposing` missing up-top? + +**fuzz_crash_020.md:94:3:94:6:** +```roc + ber + n +``` + ^^^ -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! **UNDEFINED VARIABLE** Nothing is named `tag` in this scope. @@ -857,6 +893,17 @@ The type _List_ expects argument, but got instead. +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_020.md:39:2:39:3:** +```roc + 1 +``` + ^ + +It has the type: + _Num(_size)_ + **INCOMPATIBLE MATCH PATTERNS** The pattern in the fourth branch of this `match` differs from previous ones: **fuzz_crash_020.md:52:2:** @@ -892,6 +939,66 @@ All patterns in an `match` must have compatible types. +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_020.md:1:1:1:1:** +```roc +# Thnt! +``` +^ + +It has the type: + __f_ + +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_020.md:86:11:86:17:** +```roc + )crash ke"Unr!" #) +``` + ^^^^^^ + +It has the type: + _Str_ + +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_020.md:98:4:104:3:** +```roc + m ( + 123, + "World",ag1, + O, # nt + (ne, tuple), + [1, 2, 3], + ) +``` + +It has the type: + _(Num(_size), Str, Error, [O]_others, (Error, Error), List(Num(_size2)))_ + +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_020.md:105:2:105:54:** +```roc + b?? 12 > 5 or 13 + 2 < 5 and 10 - 1 >= 16 or 12 <= 3 e_fn(arg1)?.od()?.ned()?.recd? +``` + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It has the type: + _Bool_ + +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_020.md:105:55:105:85:** +```roc + b?? 12 > 5 or 13 + 2 < 5 and 10 - 1 >= 16 or 12 <= 3 e_fn(arg1)?.od()?.ned()?.recd? +``` + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It has the type: + __f_ + # TOKENS ~~~zig KwApp,OpenSquare,LowerIdent,CloseSquare,OpenCurly,LowerIdent,OpColon,KwPlatform,StringStart,StringPart,StringEnd,CloseCurly, @@ -1678,7 +1785,25 @@ expect { (p-assign (ident "er")))) (e-num (value "456")) (e-num (value "9"))))) - (s-runtime-error (tag "not_implemented")) + (s-for + (p-assign (ident "n")) + (e-runtime-error (tag "ident_not_in_scope")) + (e-block + (s-expr + (e-call + (e-runtime-error (tag "ident_not_in_scope")) + (e-string + (e-literal (string "Ag ")) + (e-lookup-local + (p-assign (ident "n"))) + (e-literal (string " to ")) + (e-lookup-local + (p-assign (ident "er"))) + (e-literal (string ""))))) + (e-binop (op "add") + (e-runtime-error (tag "ident_not_in_scope")) + (e-lookup-local + (p-assign (ident "n")))))) (s-let (p-assign (ident "rd")) (e-record diff --git a/test/snapshots/fuzz_crash/fuzz_crash_023.md b/test/snapshots/fuzz_crash/fuzz_crash_023.md index 0c4ebb8db2..1736e703be 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_023.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_023.md @@ -253,7 +253,7 @@ UNDEFINED VARIABLE - fuzz_crash_023.md:141:2:141:6 UNDECLARED TYPE - fuzz_crash_023.md:143:14:143:20 UNDEFINED VARIABLE - fuzz_crash_023.md:147:9:147:13 UNDEFINED VARIABLE - fuzz_crash_023.md:158:2:158:11 -NOT IMPLEMENTED - :0:0:0:0 +UNDEFINED VARIABLE - fuzz_crash_023.md:175:3:175:15 UNRECOGNIZED SYNTAX - fuzz_crash_023.md:178:38:178:40 UNRECOGNIZED SYNTAX - fuzz_crash_023.md:178:40:178:41 UNRECOGNIZED SYNTAX - fuzz_crash_023.md:178:45:178:46 @@ -268,7 +268,6 @@ UNDEFINED VARIABLE - fuzz_crash_023.md:191:2:191:14 UNDEFINED VARIABLE - fuzz_crash_023.md:193:4:193:13 UNUSED VARIABLE - fuzz_crash_023.md:164:2:164:18 UNUSED VARIABLE - fuzz_crash_023.md:165:2:165:14 -UNUSED VARIABLE - fuzz_crash_023.md:166:2:166:6 UNUSED VARIABLE - fuzz_crash_023.md:178:2:178:8 UNUSED VARIABLE - fuzz_crash_023.md:180:2:180:17 UNUSED VARIABLE - fuzz_crash_023.md:188:2:188:15 @@ -276,7 +275,10 @@ UNUSED VARIABLE - fuzz_crash_023.md:189:2:189:23 UNDECLARED TYPE - fuzz_crash_023.md:201:9:201:14 INVALID IF CONDITION - fuzz_crash_023.md:70:5:70:5 INCOMPATIBLE MATCH PATTERNS - fuzz_crash_023.md:84:2:84:2 +UNUSED VALUE - fuzz_crash_023.md:1:1:1:1 TYPE MISMATCH - fuzz_crash_023.md:155:2:157:3 +UNUSED VALUE - fuzz_crash_023.md:155:2:157:3 +UNUSED VALUE - fuzz_crash_023.md:178:42:178:45 # PROBLEMS **PARSE ERROR** A parsing error occurred: `expected_expr_record_field_name` @@ -679,10 +681,16 @@ Is there an `import` or `exposing` missing up-top? ^^^^^^^^^ -**NOT IMPLEMENTED** -This feature is not yet implemented: statement type in block +**UNDEFINED VARIABLE** +Nothing is named `line!` in this scope. +Is there an `import` or `exposing` missing up-top? + +**fuzz_crash_023.md:175:3:175:15:** +```roc + Stdout.line!("Adding ${n} to ${number}") +``` + ^^^^^^^^^^^^ -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! **UNRECOGNIZED SYNTAX** I don't recognize this syntax. @@ -827,18 +835,6 @@ The unused variable is declared here: ^^^^^^^^^^^^ -**UNUSED VARIABLE** -Variable `list` is not used anywhere in your code. - -If you don't need this variable, prefix it with an underscore like `_list` to suppress this warning. -The unused variable is declared here: -**fuzz_crash_023.md:166:2:166:6:** -```roc - list = [ -``` - ^^^^ - - **UNUSED VARIABLE** Variable `record` is not used anywhere in your code. @@ -983,6 +979,17 @@ All patterns in an `match` must have compatible types. +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_023.md:1:1:1:1:** +```roc +# This is a module comment! +``` +^ + +It has the type: + __d_ + **TYPE MISMATCH** This expression is used in an unexpected way: **fuzz_crash_023.md:155:2:157:3:** @@ -998,6 +1005,29 @@ It has the type: But I expected it to be: _[Red][Blue, Green]_others, _arg -> Error_ +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_023.md:155:2:157:3:** +```roc + match_time( + ..., # Single args with comment + ) +``` + +It has the type: + __d_ + +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_023.md:178:42:178:45:** +```roc + record = { foo: 123, bar: "Hello", ;az: tag, qux: Ok(world), punned } +``` + ^^^ + +It has the type: + _[Blue]_others_ + # TOKENS ~~~zig KwApp,OpenSquare,LowerIdent,CloseSquare,OpenCurly,LowerIdent,OpColon,KwPlatform,StringStart,StringPart,StringEnd,CloseCurly, @@ -1973,8 +2003,8 @@ expect { (e-closure (captures (capture (ident "x")) - (capture (ident "dude")) - (capture (ident "x"))) + (capture (ident "x")) + (capture (ident "dude"))) (e-lambda (args (p-assign (ident "a")) @@ -2247,7 +2277,30 @@ expect { (p-assign (ident "number"))))) (e-num (value "456")) (e-num (value "789"))))) - (s-runtime-error (tag "not_implemented")) + (s-for + (p-assign (ident "n")) + (e-lookup-local + (p-assign (ident "list"))) + (e-block + (s-expr + (e-call + (e-runtime-error (tag "ident_not_in_scope")) + (e-string + (e-literal (string "Adding ")) + (e-lookup-local + (p-assign (ident "n"))) + (e-literal (string " to ")) + (e-lookup-local + (p-assign (ident "number"))) + (e-literal (string ""))))) + (s-reassign + (p-assign (ident "number")) + (e-binop (op "add") + (e-lookup-local + (p-assign (ident "number"))) + (e-lookup-local + (p-assign (ident "n"))))) + (e-empty_record))) (s-let (p-assign (ident "record")) (e-runtime-error (tag "expr_not_canonicalized"))) diff --git a/test/snapshots/fuzz_crash/fuzz_crash_027.md b/test/snapshots/fuzz_crash/fuzz_crash_027.md index db86ba1a2a..5ba934c3ca 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_027.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_027.md @@ -208,7 +208,7 @@ UNDEFINED VARIABLE - fuzz_crash_027.md:97:2:97:6 UNDECLARED TYPE - fuzz_crash_027.md:99:14:99:20 UNDEFINED VARIABLE - fuzz_crash_027.md:103:9:103:13 UNDEFINED VARIABLE - fuzz_crash_027.md:114:2:114:11 -NOT IMPLEMENTED - :0:0:0:0 +UNDEFINED VARIABLE - fuzz_crash_027.md:128:2:128:7 UNDEFINED VARIABLE - fuzz_crash_027.md:131:63:131:69 UNDEFINED VARIABLE - fuzz_crash_027.md:132:42:132:48 UNDEFINED VARIABLE - fuzz_crash_027.md:136:3:136:7 @@ -218,7 +218,6 @@ NOT IMPLEMENTED - :0:0:0:0 UNDEFINED VARIABLE - fuzz_crash_027.md:145:4:145:13 UNUSED VARIABLE - fuzz_crash_027.md:119:2:119:10 UNUSED VARIABLE - fuzz_crash_027.md:120:2:120:6 -UNUSED VARIABLE - fuzz_crash_027.md:121:2:121:6 UNUSED VARIABLE - fuzz_crash_027.md:131:2:131:8 UNUSED VARIABLE - fuzz_crash_027.md:133:2:133:9 UNUSED VARIABLE - fuzz_crash_027.md:141:2:141:7 @@ -227,7 +226,9 @@ UNDECLARED TYPE - fuzz_crash_027.md:153:9:153:14 TOO FEW ARGS - fuzz_crash_027.md:21:3:22:4 INVALID IF CONDITION - fuzz_crash_027.md:50:5:50:5 INCOMPATIBLE MATCH PATTERNS - fuzz_crash_027.md:64:2:64:2 +UNUSED VALUE - fuzz_crash_027.md:1:1:1:1 TYPE MISMATCH - fuzz_crash_027.md:111:2:113:3 +UNUSED VALUE - fuzz_crash_027.md:111:2:113:3 TYPE MISMATCH - fuzz_crash_027.md:143:2:147:3 # PROBLEMS **LEADING ZERO** @@ -674,10 +675,16 @@ Is there an `import` or `exposing` missing up-top? ^^^^^^^^^ -**NOT IMPLEMENTED** -This feature is not yet implemented: statement type in block +**UNDEFINED VARIABLE** +Nothing is named `line!` in this scope. +Is there an `import` or `exposing` missing up-top? + +**fuzz_crash_027.md:128:2:128:7:** +```roc + line!("Adding ${n} to ${number}") +``` + ^^^^^ -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! **UNDEFINED VARIABLE** Nothing is named `punned` in this scope. @@ -774,18 +781,6 @@ The unused variable is declared here: ^^^^ -**UNUSED VARIABLE** -Variable `list` is not used anywhere in your code. - -If you don't need this variable, prefix it with an underscore like `_list` to suppress this warning. -The unused variable is declared here: -**fuzz_crash_027.md:121:2:121:6:** -```roc - list = [ -``` - ^^^^ - - **UNUSED VARIABLE** Variable `record` is not used anywhere in your code. @@ -916,6 +911,17 @@ All patterns in an `match` must have compatible types. +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_027.md:1:1:1:1:** +```roc +# Thnt! +``` +^ + +It has the type: + __d_ + **TYPE MISMATCH** This expression is used in an unexpected way: **fuzz_crash_027.md:111:2:113:3:** @@ -931,6 +937,18 @@ It has the type: But I expected it to be: _[Red, Blue]_others, _arg -> Error_ +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**fuzz_crash_027.md:111:2:113:3:** +```roc + match_time( + ..., # + ) +``` + +It has the type: + __d_ + **TYPE MISMATCH** This expression is used in an unexpected way: **fuzz_crash_027.md:143:2:147:3:** @@ -1973,7 +1991,30 @@ expect { (e-list (elems (e-num (value "456"))))) - (s-runtime-error (tag "not_implemented")) + (s-for + (p-assign (ident "n")) + (e-lookup-local + (p-assign (ident "list"))) + (e-block + (s-expr + (e-call + (e-runtime-error (tag "ident_not_in_scope")) + (e-string + (e-literal (string "Adding ")) + (e-lookup-local + (p-assign (ident "n"))) + (e-literal (string " to ")) + (e-lookup-local + (p-assign (ident "number"))) + (e-literal (string ""))))) + (s-reassign + (p-assign (ident "number")) + (e-binop (op "add") + (e-lookup-local + (p-assign (ident "number"))) + (e-lookup-local + (p-assign (ident "n"))))) + (e-empty_record))) (s-let (p-assign (ident "record")) (e-record diff --git a/test/snapshots/fuzz_crash/fuzz_crash_028.md b/test/snapshots/fuzz_crash/fuzz_crash_028.md index 443ccc0c62..919c4669e3 100644 Binary files a/test/snapshots/fuzz_crash/fuzz_crash_028.md and b/test/snapshots/fuzz_crash/fuzz_crash_028.md differ diff --git a/test/snapshots/fuzz_crash/fuzz_crash_032.md b/test/snapshots/fuzz_crash/fuzz_crash_032.md index 6e925909f4..bdd4b78021 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_032.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_032.md @@ -26,7 +26,6 @@ UNEXPECTED TOKEN IN PATTERN - fuzz_crash_032.md:7:21:7:22 PARSE ERROR - fuzz_crash_032.md:7:22:7:22 UNDECLARED TYPE VARIABLE - fuzz_crash_032.md:1:14:1:17 UNDECLARED TYPE - fuzz_crash_032.md:1:21:1:24 -NOT IMPLEMENTED - :0:0:0:0 UNDECLARED TYPE - fuzz_crash_032.md:4:25:4:30 EXPECTED NOMINAL TYPE - fuzz_crash_032.md:6:26:6:37 INVALID PATTERN - :0:0:0:0 @@ -158,11 +157,6 @@ LocalStatus :lue => Loc= [Pending, Complete] ^^^ -**NOT IMPLEMENTED** -This feature is not yet implemented: statement type in block - -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! - **UNDECLARED TYPE** The type _Color_ is not declared in this scope. @@ -296,7 +290,6 @@ olor = |color| { (args (p-assign (ident "color"))) (e-block - (s-runtime-error (tag "not_implemented")) (s-expr (e-runtime-error (tag "undeclared_type"))) (e-match diff --git a/test/snapshots/fuzz_crash/fuzz_crash_049.md b/test/snapshots/fuzz_crash/fuzz_crash_049.md index 0b302683dd..0a206628ba 100644 Binary files a/test/snapshots/fuzz_crash/fuzz_crash_049.md and b/test/snapshots/fuzz_crash/fuzz_crash_049.md differ diff --git a/test/snapshots/lambda_capture/lambda_capture_advanced.md b/test/snapshots/lambda_capture/lambda_capture_advanced.md index 4d16851b5a..7d2c15d586 100644 --- a/test/snapshots/lambda_capture/lambda_capture_advanced.md +++ b/test/snapshots/lambda_capture/lambda_capture_advanced.md @@ -56,9 +56,9 @@ NO CHANGE (p-assign (ident "c"))) (e-closure (captures - (capture (ident "c")) + (capture (ident "a")) (capture (ident "b")) - (capture (ident "a"))) + (capture (ident "c"))) (e-lambda (args (p-assign (ident "x"))) diff --git a/test/snapshots/lambda_capture/lambda_capture_deep_nesting.md b/test/snapshots/lambda_capture/lambda_capture_deep_nesting.md index c953210db1..11fc5516e3 100644 --- a/test/snapshots/lambda_capture/lambda_capture_deep_nesting.md +++ b/test/snapshots/lambda_capture/lambda_capture_deep_nesting.md @@ -76,25 +76,25 @@ NO CHANGE (p-assign (ident "b"))) (e-closure (captures - (capture (ident "b")) - (capture (ident "a"))) + (capture (ident "a")) + (capture (ident "b"))) (e-lambda (args (p-assign (ident "c"))) (e-closure (captures - (capture (ident "c")) + (capture (ident "a")) (capture (ident "b")) - (capture (ident "a"))) + (capture (ident "c"))) (e-lambda (args (p-assign (ident "d"))) (e-closure (captures - (capture (ident "c")) + (capture (ident "a")) (capture (ident "b")) - (capture (ident "d")) - (capture (ident "a"))) + (capture (ident "c")) + (capture (ident "d"))) (e-lambda (args (p-assign (ident "e"))) diff --git a/test/snapshots/lambda_parameter_unused.md b/test/snapshots/lambda_parameter_unused.md index 5f2766b992..71bede0bf2 100644 --- a/test/snapshots/lambda_parameter_unused.md +++ b/test/snapshots/lambda_parameter_unused.md @@ -254,10 +254,10 @@ main! = |_| { (p-assign (ident "main!")) (e-closure (captures - (capture (ident "multiply")) (capture (ident "add")) - (capture (ident "double")) - (capture (ident "process"))) + (capture (ident "multiply")) + (capture (ident "process")) + (capture (ident "double"))) (e-lambda (args (p-underscore)) diff --git a/test/snapshots/let_polymorphism_records.md b/test/snapshots/let_polymorphism_records.md index e240d7a8b3..95b59733ec 100644 --- a/test/snapshots/let_polymorphism_records.md +++ b/test/snapshots/let_polymorphism_records.md @@ -46,6 +46,7 @@ main = |_| { UNEXPECTED TOKEN IN EXPRESSION - let_polymorphism_records.md:19:50:19:51 UNRECOGNIZED SYNTAX - let_polymorphism_records.md:19:50:19:51 UNUSED VARIABLE - let_polymorphism_records.md:19:27:19:36 +UNUSED VALUE - let_polymorphism_records.md:19:40:19:49 # PROBLEMS **UNEXPECTED TOKEN IN EXPRESSION** The token **&** is not expected in an expression. @@ -81,6 +82,17 @@ update_data = |container, new_value| { container & data: new_value } ^^^^^^^^^ +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**let_polymorphism_records.md:19:40:19:49:** +```roc +update_data = |container, new_value| { container & data: new_value } +``` + ^^^^^^^^^ + +It has the type: + __a_ + # TOKENS ~~~zig KwApp,OpenSquare,LowerIdent,CloseSquare,OpenCurly,LowerIdent,OpColon,KwPlatform,StringStart,StringPart,StringEnd,CloseCurly, diff --git a/test/snapshots/nominal/nominal_mixed_scope.md b/test/snapshots/nominal/nominal_mixed_scope.md index e45cae120c..1e99f0a3b7 100644 --- a/test/snapshots/nominal/nominal_mixed_scope.md +++ b/test/snapshots/nominal/nominal_mixed_scope.md @@ -22,7 +22,6 @@ processColor = |color| { ~~~ # EXPECTED IMPORT MUST BE TOP LEVEL - nominal_mixed_scope.md:7:5:7:11 -NOT IMPLEMENTED - :0:0:0:0 UNDECLARED TYPE - nominal_mixed_scope.md:7:12:7:17 UNDECLARED TYPE - nominal_mixed_scope.md:10:9:10:12 UNDECLARED TYPE - nominal_mixed_scope.md:11:9:11:12 @@ -39,11 +38,6 @@ Move this import to the top of the file, after the module header but before any ^^^^^^ -**NOT IMPLEMENTED** -This feature is not yet implemented: statement type in block - -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! - **UNDECLARED TYPE** The type _Color_ is not declared in this scope. @@ -166,7 +160,6 @@ processColor = |color| { (args (p-assign (ident "color"))) (e-block - (s-runtime-error (tag "not_implemented")) (s-expr (e-runtime-error (tag "undeclared_type"))) (e-match diff --git a/test/snapshots/plume_package/Color.md b/test/snapshots/plume_package/Color.md index 0d91c5435d..df4078c2ac 100644 --- a/test/snapshots/plume_package/Color.md +++ b/test/snapshots/plume_package/Color.md @@ -839,12 +839,12 @@ is_named_color = |str| { (p-assign (ident "hex")) (e-closure (captures - (capture (ident "b")) - (capture (ident "f")) - (capture (ident "d")) (capture (ident "a")) + (capture (ident "b")) (capture (ident "c")) + (capture (ident "d")) (capture (ident "e")) + (capture (ident "f")) (capture (ident "is_valid"))) (e-lambda (args @@ -998,14 +998,14 @@ is_named_color = |str| { (captures (capture (ident "to_str")) (capture (ident "r")) - (capture (ident "inner")) - (capture (ident "g")) (capture (ident "g")) (capture (ident "b")) (capture (ident "r")) - (capture (ident "inner")) + (capture (ident "g")) + (capture (ident "b")) (capture (ident "a")) - (capture (ident "b"))) + (capture (ident "inner")) + (capture (ident "inner"))) (e-lambda (args (p-assign (ident "color"))) diff --git a/test/snapshots/records/record_different_fields_error.md b/test/snapshots/records/record_different_fields_error.md index ca9d2297d7..9026d5e99d 100644 --- a/test/snapshots/records/record_different_fields_error.md +++ b/test/snapshots/records/record_different_fields_error.md @@ -59,6 +59,10 @@ UNDEFINED VARIABLE - record_different_fields_error.md:7:5:7:10 UNRECOGNIZED SYNTAX - record_different_fields_error.md:7:10:7:17 UNRECOGNIZED SYNTAX - record_different_fields_error.md:7:17:7:18 UNRECOGNIZED SYNTAX - record_different_fields_error.md:7:30:7:31 +UNUSED VALUE - record_different_fields_error.md:4:5:4:15 +UNUSED VALUE - record_different_fields_error.md:4:17:4:25 +UNUSED VALUE - record_different_fields_error.md:5:17:5:24 +UNUSED VALUE - record_different_fields_error.md:7:19:7:30 # PROBLEMS **UNEXPECTED TOKEN IN TYPE ANNOTATION** The token **"** is not expected in a type annotation. @@ -541,6 +545,50 @@ I don't recognize this syntax. This might be a syntax error, an unsupported language feature, or a typo. +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**record_different_fields_error.md:4:5:4:15:** +```roc + PascalCase: "pascal", +``` + ^^^^^^^^^^ + +It has the type: + _[PascalCase]_others_ + +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**record_different_fields_error.md:4:17:4:25:** +```roc + PascalCase: "pascal", +``` + ^^^^^^^^ + +It has the type: + _Str_ + +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**record_different_fields_error.md:5:17:5:24:** +```roc + kebab-case: "kebab", +``` + ^^^^^^^ + +It has the type: + _Str_ + +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**record_different_fields_error.md:7:19:7:30:** +```roc + field@symbol: "at symbol", +``` + ^^^^^^^^^^^ + +It has the type: + _Str_ + # TOKENS ~~~zig OpenCurly, diff --git a/test/snapshots/records/record_different_fields_reserved_error.md b/test/snapshots/records/record_different_fields_reserved_error.md index 5158d7462d..6af86dbaae 100644 --- a/test/snapshots/records/record_different_fields_reserved_error.md +++ b/test/snapshots/records/record_different_fields_reserved_error.md @@ -39,7 +39,6 @@ UNRECOGNIZED SYNTAX - record_different_fields_reserved_error.md:3:25:3:26 UNRECOGNIZED SYNTAX - record_different_fields_reserved_error.md:3:26:3:27 UNRECOGNIZED SYNTAX - record_different_fields_reserved_error.md:4:11:4:12 UNRECOGNIZED SYNTAX - record_different_fields_reserved_error.md:4:29:4:30 -NOT IMPLEMENTED - :0:0:0:0 UNRECOGNIZED SYNTAX - record_different_fields_reserved_error.md:5:11:5:12 UNRECOGNIZED SYNTAX - record_different_fields_reserved_error.md:5:26:5:27 UNRECOGNIZED SYNTAX - record_different_fields_reserved_error.md:6:5:6:8 @@ -50,6 +49,8 @@ UNRECOGNIZED SYNTAX - record_different_fields_reserved_error.md:7:5:7:7 UNRECOGNIZED SYNTAX - record_different_fields_reserved_error.md:7:7:7:8 DOES NOT EXIST - record_different_fields_reserved_error.md:7:9:7:19 UNRECOGNIZED SYNTAX - record_different_fields_reserved_error.md:7:19:7:20 +UNUSED VALUE - record_different_fields_reserved_error.md:4:13:4:29 +UNUSED VALUE - record_different_fields_reserved_error.md:5:13:5:26 # PROBLEMS **UNEXPECTED TOKEN IN EXPRESSION** The token **:** is not expected in an expression. @@ -315,11 +316,6 @@ I don't recognize this syntax. This might be a syntax error, an unsupported language feature, or a typo. -**NOT IMPLEMENTED** -This feature is not yet implemented: statement type in block - -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! - **UNRECOGNIZED SYNTAX** I don't recognize this syntax. @@ -428,6 +424,28 @@ I don't recognize this syntax. This might be a syntax error, an unsupported language feature, or a typo. +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**record_different_fields_reserved_error.md:4:13:4:29:** +```roc + expect: "test assertion", +``` + ^^^^^^^^^^^^^^^^ + +It has the type: + _Str_ + +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**record_different_fields_reserved_error.md:5:13:5:26:** +```roc + import: "module load", +``` + ^^^^^^^^^^^^^ + +It has the type: + _Str_ + # TOKENS ~~~zig OpenCurly, @@ -506,7 +524,6 @@ EndOfFile, (e-literal (string "test assertion")))) (s-expr (e-runtime-error (tag "expr_not_canonicalized"))) - (s-runtime-error (tag "not_implemented")) (s-expr (e-runtime-error (tag "expr_not_canonicalized"))) (s-expr diff --git a/test/snapshots/statement/dbg_stmt_block_example.md b/test/snapshots/statement/dbg_stmt_block_example.md index 682f4825bd..2b9b004329 100644 --- a/test/snapshots/statement/dbg_stmt_block_example.md +++ b/test/snapshots/statement/dbg_stmt_block_example.md @@ -79,7 +79,7 @@ foo = |num| { ~~~clojure (inferred-types (defs - (patt (type "a -> a"))) + (patt (type "a -> a where [a.to_str : a -> ba.to_str : a -> b]"))) (expressions - (expr (type "a -> a")))) + (expr (type "a -> a where [a.to_str : a -> ba.to_str : a -> b]")))) ~~~ diff --git a/test/snapshots/statement/for_stmt.md b/test/snapshots/statement/for_stmt.md new file mode 100644 index 0000000000..f01370797e --- /dev/null +++ b/test/snapshots/statement/for_stmt.md @@ -0,0 +1,109 @@ +# META +~~~ini +description=For expression stmt +type=snippet +~~~ +# SOURCE +~~~roc +foo : U64 +foo = { + var result = 0 + for x in [1, 2, 3] { + result = result + x + } + result +} +~~~ +# EXPECTED +NIL +# PROBLEMS +NIL +# TOKENS +~~~zig +LowerIdent,OpColon,UpperIdent, +LowerIdent,OpAssign,OpenCurly, +KwVar,LowerIdent,OpAssign,Int, +KwFor,LowerIdent,KwIn,OpenSquare,Int,Comma,Int,Comma,Int,CloseSquare,OpenCurly, +LowerIdent,OpAssign,LowerIdent,OpPlus,LowerIdent, +CloseCurly, +LowerIdent, +CloseCurly, +EndOfFile, +~~~ +# PARSE +~~~clojure +(file + (type-module) + (statements + (s-type-anno (name "foo") + (ty (name "U64"))) + (s-decl + (p-ident (raw "foo")) + (e-block + (statements + (s-var (name "result") + (e-int (raw "0"))) + (s-for + (p-ident (raw "x")) + (e-list + (e-int (raw "1")) + (e-int (raw "2")) + (e-int (raw "3"))) + (e-block + (statements + (s-decl + (p-ident (raw "result")) + (e-binop (op "+") + (e-ident (raw "result")) + (e-ident (raw "x"))))))) + (e-ident (raw "result"))))))) +~~~ +# FORMATTED +~~~roc +foo : U64 +foo = { + var result = 0 + for x in [1, 2, 3] { + result = result + x + } + result +} +~~~ +# CANONICALIZE +~~~clojure +(can-ir + (d-let + (p-assign (ident "foo")) + (e-block + (s-var + (p-assign (ident "result")) + (e-num (value "0"))) + (s-for + (p-assign (ident "x")) + (e-list + (elems + (e-num (value "1")) + (e-num (value "2")) + (e-num (value "3")))) + (e-block + (s-reassign + (p-assign (ident "result")) + (e-binop (op "add") + (e-lookup-local + (p-assign (ident "result"))) + (e-lookup-local + (p-assign (ident "x"))))) + (e-empty_record))) + (e-lookup-local + (p-assign (ident "result")))) + (annotation + (ty-lookup (name "U64") (builtin))))) +~~~ +# TYPES +~~~clojure +(inferred-types + (defs + (patt (type "Num(Int(Unsigned64))"))) + (expressions + (expr (type "Num(Int(Unsigned64))")))) +~~~ diff --git a/test/snapshots/syntax_grab_bag.md b/test/snapshots/syntax_grab_bag.md index 63bf5d2ad0..83868a671a 100644 --- a/test/snapshots/syntax_grab_bag.md +++ b/test/snapshots/syntax_grab_bag.md @@ -248,7 +248,7 @@ UNDEFINED VARIABLE - syntax_grab_bag.md:141:2:141:6 UNDECLARED TYPE - syntax_grab_bag.md:143:14:143:20 UNDEFINED VARIABLE - syntax_grab_bag.md:147:9:147:13 UNDEFINED VARIABLE - syntax_grab_bag.md:158:2:158:11 -NOT IMPLEMENTED - :0:0:0:0 +UNDEFINED VARIABLE - syntax_grab_bag.md:175:3:175:15 UNDEFINED VARIABLE - syntax_grab_bag.md:178:63:178:69 UNDEFINED VARIABLE - syntax_grab_bag.md:179:42:179:48 UNDEFINED VARIABLE - syntax_grab_bag.md:183:3:183:7 @@ -260,7 +260,6 @@ UNDEFINED VARIABLE - syntax_grab_bag.md:191:2:191:14 UNDEFINED VARIABLE - syntax_grab_bag.md:193:4:193:13 UNUSED VARIABLE - syntax_grab_bag.md:164:2:164:18 UNUSED VARIABLE - syntax_grab_bag.md:165:2:165:14 -UNUSED VARIABLE - syntax_grab_bag.md:166:2:166:6 UNUSED VARIABLE - syntax_grab_bag.md:178:2:178:8 UNUSED VARIABLE - syntax_grab_bag.md:180:2:180:17 UNUSED VARIABLE - syntax_grab_bag.md:188:2:188:15 @@ -268,7 +267,9 @@ UNUSED VARIABLE - syntax_grab_bag.md:189:2:189:23 UNDECLARED TYPE - syntax_grab_bag.md:201:9:201:14 INVALID IF CONDITION - syntax_grab_bag.md:70:5:70:5 INCOMPATIBLE MATCH PATTERNS - syntax_grab_bag.md:84:2:84:2 +UNUSED VALUE - syntax_grab_bag.md:1:1:1:1 TYPE MISMATCH - syntax_grab_bag.md:155:2:157:3 +UNUSED VALUE - syntax_grab_bag.md:155:2:157:3 # PROBLEMS **UNDECLARED TYPE** The type _Bar_ is not declared in this scope. @@ -616,10 +617,16 @@ Is there an `import` or `exposing` missing up-top? ^^^^^^^^^ -**NOT IMPLEMENTED** -This feature is not yet implemented: statement type in block +**UNDEFINED VARIABLE** +Nothing is named `line!` in this scope. +Is there an `import` or `exposing` missing up-top? + +**syntax_grab_bag.md:175:3:175:15:** +```roc + Stdout.line!("Adding ${n} to ${number}") +``` + ^^^^^^^^^^^^ -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! **UNDEFINED VARIABLE** Nothing is named `punned` in this scope. @@ -732,18 +739,6 @@ The unused variable is declared here: ^^^^^^^^^^^^ -**UNUSED VARIABLE** -Variable `list` is not used anywhere in your code. - -If you don't need this variable, prefix it with an underscore like `_list` to suppress this warning. -The unused variable is declared here: -**syntax_grab_bag.md:166:2:166:6:** -```roc - list = [ -``` - ^^^^ - - **UNUSED VARIABLE** Variable `record` is not used anywhere in your code. @@ -888,6 +883,17 @@ All patterns in an `match` must have compatible types. +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**syntax_grab_bag.md:1:1:1:1:** +```roc +# This is a module comment! +``` +^ + +It has the type: + __d_ + **TYPE MISMATCH** This expression is used in an unexpected way: **syntax_grab_bag.md:155:2:157:3:** @@ -903,6 +909,18 @@ It has the type: But I expected it to be: _[Red][Blue, Green]_others, _arg -> Error_ +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**syntax_grab_bag.md:155:2:157:3:** +```roc + match_time( + ..., # Single args with comment + ) +``` + +It has the type: + __d_ + # TOKENS ~~~zig KwApp,OpenSquare,LowerIdent,CloseSquare,OpenCurly,LowerIdent,OpColon,KwPlatform,StringStart,StringPart,StringEnd,CloseCurly, @@ -1883,8 +1901,8 @@ expect { (e-closure (captures (capture (ident "x")) - (capture (ident "dude")) - (capture (ident "x"))) + (capture (ident "x")) + (capture (ident "dude"))) (e-lambda (args (p-assign (ident "a")) @@ -2157,7 +2175,30 @@ expect { (p-assign (ident "number"))))) (e-num (value "456")) (e-num (value "789"))))) - (s-runtime-error (tag "not_implemented")) + (s-for + (p-assign (ident "n")) + (e-lookup-local + (p-assign (ident "list"))) + (e-block + (s-expr + (e-call + (e-runtime-error (tag "ident_not_in_scope")) + (e-string + (e-literal (string "Adding ")) + (e-lookup-local + (p-assign (ident "n"))) + (e-literal (string " to ")) + (e-lookup-local + (p-assign (ident "number"))) + (e-literal (string ""))))) + (s-reassign + (p-assign (ident "number")) + (e-binop (op "add") + (e-lookup-local + (p-assign (ident "number"))) + (e-lookup-local + (p-assign (ident "n"))))) + (e-empty_record))) (s-let (p-assign (ident "record")) (e-record diff --git a/test/snapshots/type_annotation_basic.md b/test/snapshots/type_annotation_basic.md index ae70aa7298..64e215498d 100644 --- a/test/snapshots/type_annotation_basic.md +++ b/test/snapshots/type_annotation_basic.md @@ -230,9 +230,9 @@ main! = |_| { (p-assign (ident "main!")) (e-closure (captures - (capture (ident "addOne")) (capture (ident "identity")) - (capture (ident "combine"))) + (capture (ident "combine")) + (capture (ident "addOne"))) (e-lambda (args (p-underscore)) diff --git a/test/snapshots/type_var_collision_simple.md b/test/snapshots/type_var_collision_simple.md index 8cf90e1aec..61589f4d3e 100644 --- a/test/snapshots/type_var_collision_simple.md +++ b/test/snapshots/type_var_collision_simple.md @@ -207,9 +207,9 @@ main! = |_| { (capture (ident "identity")) (capture (ident "identity2")) (capture (ident "pair")) + (capture (ident "a")) (capture (ident "b")) - (capture (ident "c")) - (capture (ident "a"))) + (capture (ident "c"))) (e-lambda (args (p-underscore)) diff --git a/test/snapshots/type_var_name_avoids_collision.md b/test/snapshots/type_var_name_avoids_collision.md index f83e06eb56..80607232d4 100644 --- a/test/snapshots/type_var_name_avoids_collision.md +++ b/test/snapshots/type_var_name_avoids_collision.md @@ -529,13 +529,13 @@ main! = |_| { (p-assign (ident "main!")) (e-closure (captures + (capture (ident "identity")) + (capture (ident "anotherIdentity")) + (capture (ident "combine")) + (capture (ident "yetAnotherIdentity")) (capture (ident "finalIdentity")) (capture (ident "a")) - (capture (ident "anotherIdentity")) - (capture (ident "f")) - (capture (ident "identity")) - (capture (ident "combine")) - (capture (ident "yetAnotherIdentity"))) + (capture (ident "f"))) (e-lambda (args (p-underscore)) diff --git a/test/snapshots/unused_vars_simple.md b/test/snapshots/unused_vars_simple.md index 41b873c187..01a784c2bf 100644 --- a/test/snapshots/unused_vars_simple.md +++ b/test/snapshots/unused_vars_simple.md @@ -206,9 +206,9 @@ main! = |_| { (p-assign (ident "main!")) (e-closure (captures + (capture (ident "unused_regular")) (capture (ident "used_underscore")) (capture (ident "unused_underscore")) - (capture (ident "unused_regular")) (capture (ident "used_regular"))) (e-lambda (args