From fff8eff2bd0cc36b192d0ab43b522161227c3c2d Mon Sep 17 00:00:00 2001
From: Loris Cro
Date: Thu, 13 Feb 2025 20:05:00 +0100
Subject: [PATCH 01/12] initial implementation of `@deprecated`
---
lib/std/zig/AstGen.zig | 13 +++++++++++++
lib/std/zig/AstRlAnnotate.zig | 7 +++++--
lib/std/zig/BuiltinFn.zig | 9 +++++++++
lib/std/zig/Zir.zig | 4 ++++
src/Compilation.zig | 1 +
src/Package/Module.zig | 11 +++++++++++
src/Sema.zig | 10 ++++++++++
src/main.zig | 6 ++++++
src/print_zir.zig | 1 +
9 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig
index 5dc41cc9d2..56254411ce 100644
--- a/lib/std/zig/AstGen.zig
+++ b/lib/std/zig/AstGen.zig
@@ -9695,6 +9695,19 @@ fn builtinCall(
.volatile_cast,
=> return ptrCast(gz, scope, ri, node),
+ .deprecated => {
+ _ = try gz.addExtendedNodeSmall(.deprecated, node, 0);
+ switch (params.len) {
+ 0 => return .void_value,
+ 1 => return expr(gz, scope, ri, params[0]),
+ else => return astgen.failNode(
+ node,
+ "expected 0 or 1 argument, found {}",
+ .{params.len},
+ ),
+ }
+ },
+
// zig fmt: off
.has_decl => return hasDeclOrField(gz, scope, ri, node, params[0], params[1], .has_decl),
.has_field => return hasDeclOrField(gz, scope, ri, node, params[0], params[1], .has_field),
diff --git a/lib/std/zig/AstRlAnnotate.zig b/lib/std/zig/AstRlAnnotate.zig
index ccc23b18aa..f58ba213cd 100644
--- a/lib/std/zig/AstRlAnnotate.zig
+++ b/lib/std/zig/AstRlAnnotate.zig
@@ -817,8 +817,6 @@ fn blockExpr(astrl: *AstRlAnnotate, parent_block: ?*Block, ri: ResultInfo, node:
}
fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.Node.Index, args: []const Ast.Node.Index) !bool {
- _ = ri; // Currently, no builtin consumes its result location.
-
const tree = astrl.tree;
const main_tokens = tree.nodes.items(.main_token);
const builtin_token = main_tokens[node];
@@ -828,6 +826,11 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
if (expected != args.len) return false;
}
switch (info.tag) {
+ .deprecated => if (args.len >= 1) {
+ return astrl.expr(args[0], block, ri);
+ } else {
+ return false;
+ },
.import => return false,
.branch_hint => {
_ = try astrl.expr(args[0], block, ResultInfo.type_only);
diff --git a/lib/std/zig/BuiltinFn.zig b/lib/std/zig/BuiltinFn.zig
index 1bf31cd165..c0e0b522a3 100644
--- a/lib/std/zig/BuiltinFn.zig
+++ b/lib/std/zig/BuiltinFn.zig
@@ -121,6 +121,7 @@ pub const Tag = enum {
work_item_id,
work_group_size,
work_group_id,
+ deprecated,
};
pub const EvalToError = enum {
@@ -1016,6 +1017,14 @@ pub const list = list: {
.illegal_outside_function = true,
},
},
+ .{
+ "@deprecated",
+ .{
+ .tag = .deprecated,
+ .param_count = null,
+ .eval_to_error = .maybe,
+ },
+ },
});
};
diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig
index 5d013635cb..ea69bc2da0 100644
--- a/lib/std/zig/Zir.zig
+++ b/lib/std/zig/Zir.zig
@@ -2112,6 +2112,9 @@ pub const Inst = struct {
/// any code may have gone here, avoiding false-positive "unreachable code" errors.
astgen_error,
+ /// `operand` is `src_node: i32`.
+ deprecated,
+
pub const InstData = struct {
opcode: Extended,
small: u16,
@@ -4310,6 +4313,7 @@ fn findTrackableInner(
.value_placeholder => unreachable,
// Once again, we start with the boring tags.
+ .deprecated,
.this,
.ret_addr,
.builtin_src,
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 969a399640..7331bf2097 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -869,6 +869,7 @@ pub const cache_helpers = struct {
hh.add(mod.sanitize_c);
hh.add(mod.sanitize_thread);
hh.add(mod.fuzz);
+ hh.add(mod.allow_deprecated);
hh.add(mod.unwind_tables);
hh.add(mod.structured_cfg);
hh.add(mod.no_builtin);
diff --git a/src/Package/Module.zig b/src/Package/Module.zig
index 0dec7bde76..6bd33dffa1 100644
--- a/src/Package/Module.zig
+++ b/src/Package/Module.zig
@@ -27,6 +27,7 @@ red_zone: bool,
sanitize_c: bool,
sanitize_thread: bool,
fuzz: bool,
+allow_deprecated: bool,
unwind_tables: std.builtin.UnwindTables,
cc_argv: []const []const u8,
/// (SPIR-V) whether to generate a structured control flow graph or not
@@ -95,6 +96,7 @@ pub const CreateOptions = struct {
sanitize_c: ?bool = null,
sanitize_thread: ?bool = null,
fuzz: ?bool = null,
+ allow_deprecated: ?bool = null,
structured_cfg: ?bool = null,
no_builtin: ?bool = null,
};
@@ -234,6 +236,12 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
break :b false;
};
+ const allow_deprecated = b: {
+ if (options.inherited.allow_deprecated) |x| break :b x;
+ if (options.parent) |p| break :b p.allow_deprecated;
+ break :b false;
+ };
+
const code_model = b: {
if (options.inherited.code_model) |x| break :b x;
if (options.parent) |p| break :b p.code_model;
@@ -380,6 +388,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
.sanitize_c = sanitize_c,
.sanitize_thread = sanitize_thread,
.fuzz = fuzz,
+ .allow_deprecated = allow_deprecated,
.unwind_tables = unwind_tables,
.cc_argv = options.cc_argv,
.structured_cfg = structured_cfg,
@@ -474,6 +483,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
.sanitize_c = sanitize_c,
.sanitize_thread = sanitize_thread,
.fuzz = fuzz,
+ .allow_deprecated = allow_deprecated,
.unwind_tables = unwind_tables,
.cc_argv = &.{},
.structured_cfg = structured_cfg,
@@ -532,6 +542,7 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*P
.sanitize_c = undefined,
.sanitize_thread = undefined,
.fuzz = undefined,
+ .allow_deprecated = undefined,
.unwind_tables = undefined,
.cc_argv = undefined,
.structured_cfg = undefined,
diff --git a/src/Sema.zig b/src/Sema.zig
index 9e729a17ea..e68177433d 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -1091,6 +1091,7 @@ fn analyzeBodyInner(
const map = &sema.inst_map;
const tags = sema.code.instructions.items(.tag);
const datas = sema.code.instructions.items(.data);
+ const mod = block.ownerModule();
var crash_info = crash_report.prepAnalyzeBody(sema, block, body);
crash_info.push();
@@ -1341,6 +1342,15 @@ fn analyzeBodyInner(
.extended => ext: {
const extended = datas[@intFromEnum(inst)].extended;
break :ext switch (extended.opcode) {
+ .deprecated => {
+ if (!mod.allow_deprecated) {
+ const src_node: i32 = @bitCast(extended.operand);
+ const src = block.nodeOffset(src_node);
+ return sema.fail(block, src, "found deprecated code", .{});
+ }
+
+ break :ext .void_value;
+ },
// zig fmt: off
.struct_decl => try sema.zirStructDecl( block, extended, inst),
.enum_decl => try sema.zirEnumDecl( block, extended, inst),
diff --git a/src/main.zig b/src/main.zig
index 5e66244484..ed862b03a0 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -520,6 +520,8 @@ const usage_build_generic =
\\ -fno-sanitize-thread Disable Thread Sanitizer
\\ -ffuzz Enable fuzz testing instrumentation
\\ -fno-fuzz Disable fuzz testing instrumentation
+ \\ -fallow-deprecated Allow usage of deprecated code
+ \\ -fno-allow-deprecated Disallow usage of deprecated code
\\ -funwind-tables Always produce unwind table entries for all functions
\\ -fasync-unwind-tables Always produce asynchronous unwind table entries for all functions
\\ -fno-unwind-tables Never produce unwind table entries
@@ -1454,6 +1456,10 @@ fn buildOutputType(
mod_opts.fuzz = true;
} else if (mem.eql(u8, arg, "-fno-fuzz")) {
mod_opts.fuzz = false;
+ } else if (mem.eql(u8, arg, "-fallow-deprecated")) {
+ mod_opts.allow_deprecated = true;
+ } else if (mem.eql(u8, arg, "-fno-allow-deprecated")) {
+ mod_opts.allow_deprecated = false;
} else if (mem.eql(u8, arg, "-fllvm")) {
create_module.opts.use_llvm = true;
} else if (mem.eql(u8, arg, "-fno-llvm")) {
diff --git a/src/print_zir.zig b/src/print_zir.zig
index 46f399dda9..ab3fa1aadc 100644
--- a/src/print_zir.zig
+++ b/src/print_zir.zig
@@ -535,6 +535,7 @@ const Writer = struct {
.c_va_start,
.in_comptime,
.value_placeholder,
+ .deprecated,
=> try self.writeExtNode(stream, extended),
.builtin_src => {
From ba7cd8121d5a52beb1e9844a784ec7a439ee6cfd Mon Sep 17 00:00:00 2001
From: Loris Cro
Date: Thu, 13 Feb 2025 20:58:11 +0100
Subject: [PATCH 02/12] `@deprecated`: add build system support
---
lib/compiler/build_runner.zig | 6 ++++++
lib/std/Build.zig | 5 +++++
lib/std/Build/Module.zig | 6 ++++++
3 files changed, 17 insertions(+)
diff --git a/lib/compiler/build_runner.zig b/lib/compiler/build_runner.zig
index a434ceed24..114a9e3acf 100644
--- a/lib/compiler/build_runner.zig
+++ b/lib/compiler/build_runner.zig
@@ -260,6 +260,10 @@ pub fn main() !void {
graph.incremental = true;
} else if (mem.eql(u8, arg, "-fno-incremental")) {
graph.incremental = false;
+ } else if (mem.eql(u8, arg, "-fallow-deprecated")) {
+ graph.allow_deprecated = true;
+ } else if (mem.eql(u8, arg, "-fno-allow-deprecated")) {
+ graph.allow_deprecated = false;
} else if (mem.eql(u8, arg, "-fwine")) {
builder.enable_wine = true;
} else if (mem.eql(u8, arg, "-fno-wine")) {
@@ -1283,6 +1287,8 @@ fn usage(b: *std.Build, out_stream: anytype) !void {
\\ new Omit cached steps
\\ failures (Default) Only print failed steps
\\ none Do not print the build summary
+ \\ -fallow-deprecated Allow usage of deprecated code for the entire build graph
+ \\ -fno-allow-deprecated Disallow usage of deprecated code for the entire build graph
\\ -j Limit concurrent jobs (default is to use all CPU cores)
\\ --maxrss Limit memory usage (default is to use available memory)
\\ --skip-oom-steps Instead of failing, skip steps that would exceed --maxrss
diff --git a/lib/std/Build.zig b/lib/std/Build.zig
index 4afdcd2bff..0ba5c43a46 100644
--- a/lib/std/Build.zig
+++ b/lib/std/Build.zig
@@ -94,6 +94,9 @@ available_deps: AvailableDeps,
release_mode: ReleaseMode,
+// True only for the top-level builder.
+is_root: bool = false,
+
pub const ReleaseMode = enum {
off,
any,
@@ -118,6 +121,7 @@ pub const Graph = struct {
/// Information about the native target. Computed before build() is invoked.
host: ResolvedTarget,
incremental: ?bool = null,
+ allow_deprecated: ?bool = null,
random_seed: u32 = 0,
dependency_cache: InitializedDepMap = .empty,
allow_so_scripts: ?bool = null,
@@ -304,6 +308,7 @@ pub fn create(
.pkg_hash = "",
.available_deps = available_deps,
.release_mode = .off,
+ .is_root = true,
};
try b.top_level_steps.put(arena, b.install_tls.step.name, &b.install_tls);
try b.top_level_steps.put(arena, b.uninstall_tls.step.name, &b.uninstall_tls);
diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig
index f299946731..d93fe84416 100644
--- a/lib/std/Build/Module.zig
+++ b/lib/std/Build/Module.zig
@@ -25,6 +25,7 @@ stack_check: ?bool,
sanitize_c: ?bool,
sanitize_thread: ?bool,
fuzz: ?bool,
+allow_deprecated: ?bool,
code_model: std.builtin.CodeModel,
valgrind: ?bool,
pic: ?bool,
@@ -284,6 +285,7 @@ pub fn init(
.owner = owner,
.root_source_file = if (options.root_source_file) |lp| lp.dupe(owner) else null,
.import_table = .{},
+ .allow_deprecated = owner.graph.allow_deprecated orelse !owner.is_root,
.resolved_target = options.target,
.optimize = options.optimize,
.link_libc = options.link_libc,
@@ -557,6 +559,10 @@ pub fn appendZigProcessFlags(
try addFlag(zig_args, m.pic, "-fPIC", "-fno-PIC");
try addFlag(zig_args, m.red_zone, "-mred-zone", "-mno-red-zone");
+ if (m.root_source_file != null) {
+ try addFlag(zig_args, m.allow_deprecated, "-fallow-deprecated", "-fno-allow-deprecated");
+ }
+
if (m.dwarf_format) |dwarf_format| {
try zig_args.append(switch (dwarf_format) {
.@"32" => "-gdwarf32",
From 06a66745a0b5c666608482645bc61523618dab85 Mon Sep 17 00:00:00 2001
From: Loris Cro
Date: Sat, 15 Feb 2025 18:04:29 +0100
Subject: [PATCH 03/12] `@deprecated`: add langref entry
---
doc/langref.html.in | 37 +++++++++++++++++++++++++
doc/langref/test_deprecated_builtin.zig | 22 +++++++++++++++
2 files changed, 59 insertions(+)
create mode 100644 doc/langref/test_deprecated_builtin.zig
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 96034d9173..cf9aa4fb93 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -4740,6 +4740,43 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
{#see_also|@cVaArg|@cVaCopy|@cVaEnd#}
{#header_close#}
+
+ {#header_open|@deprecated#}
+ {#syntax#}@deprecated(value: anytype) @TypeOf(value){#endsyntax#}
+ {#syntax#}@deprecated() void{#endsyntax#}
+
+ Used to mark a given code path as deprecated. It evaluates to the same value
+ passed in as argument, or the {#syntax#}void{#endsyntax#} value when given none.
+
+
+ As an example, in Zig 0.14.0 {#syntax#}std.time.sleep{#endsyntax#} was
+ deprecated and the sleep function was moved to {#syntax#}std.Thread.sleep{#endsyntax#}.
+ This is how this deprecation could have been expressed:
+
+ {#syntax_block|zig|lib/std/time.zig#}
+pub const sleep = @deprecated(std.Thread.sleep); // moved
+ {#end_syntax_block#}
+
+
+ By default it is a compile error to depend on deprecated code in
+ a module defined by the root package, while it is not in modules defined
+ by dependencies. This behavior can be overridden for the entire dependency
+ tree by passing {#syntax#}-fallow-deprecated{#endsyntax#} or
+ {#syntax#}-fno-allow-deprecated{#endsyntax#} to {#syntax#}zig build{#endsyntax#}.
+
+
+ Usage of this builtin is meant to help direct consumers discover (and remove)
+ their dependance on deprecated code during the grace period before a deprecated
+ functionality is turned into a {#syntax#}@compileError{#endsyntax#} or
+ removed entirely.
+
+
+
+ {#syntax#}@deprecated{#endsyntax#} can also be used without argument:
+ {#code|test_deprecated_builtin.zig#}
+
+
+ {#header_close#}
{#header_open|@divExact#}
{#syntax#}@divExact(numerator: T, denominator: T) T{#endsyntax#}
diff --git a/doc/langref/test_deprecated_builtin.zig b/doc/langref/test_deprecated_builtin.zig
new file mode 100644
index 0000000000..46a0890090
--- /dev/null
+++ b/doc/langref/test_deprecated_builtin.zig
@@ -0,0 +1,22 @@
+test "deprecated code path" {
+ compute(.greedy, false, 42);
+}
+
+const Strategy = enum { greedy, expensive, fast };
+fn compute(comptime strat: Strategy, comptime foo: bool, bar: usize) void {
+ switch (strat) {
+ .greedy => {
+ // This combination turned out to be ineffective.
+ if (!foo) @deprecated(); // use fast strategy when foo is false
+ runGreedy(foo, bar);
+ },
+ .expensive => runExpensive(foo, bar),
+ .fast => runFast(foo, bar),
+ }
+}
+
+extern fn runGreedy(foo: bool, bar: usize) void;
+extern fn runExpensive(foo: bool, bar: usize) void;
+extern fn runFast(foo: bool, bar: usize) void;
+
+// test_error=deprecated
From c75fdd96d2cb9bd211ff20c7e9ee2ef119cc189f Mon Sep 17 00:00:00 2001
From: Loris Cro
Date: Sat, 15 Feb 2025 20:03:04 +0100
Subject: [PATCH 04/12] `@deprecated`: add tests
---
src/Sema.zig | 18 ++++----
test/compile_errors.zig | 14 ++++++
test/tests.zig | 94 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 117 insertions(+), 9 deletions(-)
diff --git a/src/Sema.zig b/src/Sema.zig
index e68177433d..c53369bffc 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -1342,15 +1342,6 @@ fn analyzeBodyInner(
.extended => ext: {
const extended = datas[@intFromEnum(inst)].extended;
break :ext switch (extended.opcode) {
- .deprecated => {
- if (!mod.allow_deprecated) {
- const src_node: i32 = @bitCast(extended.operand);
- const src = block.nodeOffset(src_node);
- return sema.fail(block, src, "found deprecated code", .{});
- }
-
- break :ext .void_value;
- },
// zig fmt: off
.struct_decl => try sema.zirStructDecl( block, extended, inst),
.enum_decl => try sema.zirEnumDecl( block, extended, inst),
@@ -1414,6 +1405,15 @@ fn analyzeBodyInner(
i += 1;
continue;
},
+ .deprecated => {
+ if (!mod.allow_deprecated) {
+ const src_node: i32 = @bitCast(extended.operand);
+ const src = block.nodeOffset(src_node);
+ return sema.fail(block, src, "found deprecated code", .{});
+ }
+
+ break :ext .void_value;
+ },
.disable_instrumentation => {
try sema.zirDisableInstrumentation();
i += 1;
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 109347cde8..03e9324b02 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -250,4 +250,18 @@ pub fn addCases(ctx: *Cases, b: *std.Build) !void {
":1:5: error: expected expression, found 'invalid token'",
});
}
+
+ {
+ const case = ctx.obj("usage of deprecated code", b.graph.host);
+
+ case.addError(
+ \\const bad = @deprecated(42);
+ \\
+ \\pub export fn foo() usize {
+ \\ return bad;
+ \\}
+ , &[_][]const u8{
+ ":1:13: error: found deprecated code",
+ });
+ }
}
diff --git a/test/tests.zig b/test/tests.zig
index 7ef5a33a03..45cba01c7f 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -1176,6 +1176,100 @@ pub fn addCliTests(b: *std.Build) *Step {
step.dependOn(&cleanup.step);
}
+ {
+ // Test `zig build -fallow-deprecated`.
+
+ const deprecated_check: std.Build.Step.Run.StdIo.Check = .{
+ .expect_stderr_match = "found deprecated code",
+ };
+
+ const tmp_path = b.makeTempPath();
+
+ // create custom main.zig file containing a deprecated decl
+ {
+ const new_main_src =
+ \\const bad = @deprecated(42);
+ \\
+ \\pub fn main() u8 {
+ \\ return bad;
+ \\}
+ \\
+ \\test {
+ \\ if (bad != 42) return error.Bad;
+ \\}
+ ;
+
+ var src_dir = std.fs.cwd().makeOpenPath(b.pathJoin(&.{ tmp_path, "src" }), .{}) catch unreachable;
+ defer src_dir.close();
+
+ var main = src_dir.createFile("main.zig", .{}) catch unreachable;
+ defer main.close();
+
+ main.writeAll(new_main_src) catch unreachable;
+ }
+
+ const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init" });
+ init_exe.setCwd(.{ .cwd_relative = tmp_path });
+ init_exe.setName("zig init");
+ init_exe.expectStdOutEqual("");
+ init_exe.expectStdErrEqual("info: created build.zig\n" ++
+ "info: created build.zig.zon\n" ++
+ "info: preserving already existing file: src" ++ s ++ "main.zig\n" ++
+ "info: created src" ++ s ++ "root.zig\n");
+
+ const run_test_bad = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "test", "--color", "off" });
+ run_test_bad.setCwd(.{ .cwd_relative = tmp_path });
+ run_test_bad.setName("zig build test");
+ run_test_bad.expectExitCode(1);
+ run_test_bad.expectStdOutEqual("");
+ run_test_bad.addCheck(deprecated_check);
+ run_test_bad.step.dependOn(&init_exe.step);
+
+ const run_test = b.addSystemCommand(&.{
+ b.graph.zig_exe,
+ "build",
+ "test",
+ "--color",
+ "off",
+ "-fallow-deprecated",
+ });
+ run_test.setCwd(.{ .cwd_relative = tmp_path });
+ run_test.setName("zig build test");
+ run_test.expectExitCode(0);
+ run_test.expectStdOutEqual("");
+ run_test.expectStdErrEqual("");
+ run_test.step.dependOn(&init_exe.step);
+
+ const run_build_bad = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "--color", "off" });
+ run_build_bad.setCwd(.{ .cwd_relative = tmp_path });
+ run_build_bad.setName("zig build test");
+ run_build_bad.expectExitCode(1);
+ run_build_bad.expectStdOutEqual("");
+ run_build_bad.addCheck(deprecated_check);
+ run_build_bad.step.dependOn(&init_exe.step);
+
+ const run_build = b.addSystemCommand(&.{
+ b.graph.zig_exe,
+ "build",
+ "--color",
+ "off",
+ "-fallow-deprecated",
+ });
+ run_build.setCwd(.{ .cwd_relative = tmp_path });
+ run_build.setName("zig build test");
+ run_build.expectExitCode(0);
+ run_build.expectStdOutEqual("");
+ run_build.expectStdErrEqual("");
+ run_build.step.dependOn(&init_exe.step);
+
+ const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path });
+ cleanup.step.dependOn(&run_test.step);
+ cleanup.step.dependOn(&run_test_bad.step);
+ cleanup.step.dependOn(&run_build.step);
+ cleanup.step.dependOn(&run_build_bad.step);
+
+ step.dependOn(&cleanup.step);
+ }
// Test Godbolt API
if (builtin.os.tag == .linux and builtin.cpu.arch == .x86_64) {
const tmp_path = b.makeTempPath();
From 466fa311b18e7178921f6e37d6b0244b3c707b5d Mon Sep 17 00:00:00 2001
From: Loris Cro
Date: Mon, 17 Feb 2025 17:37:10 +0100
Subject: [PATCH 05/12] `@deprecated`: optimize sema implementation
mlugg suggested a better way of implementing analysis of an istruction
that cannot be referenced by other instructions.
---
src/Sema.zig | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/Sema.zig b/src/Sema.zig
index c53369bffc..9e4c4d6bd2 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -1412,7 +1412,8 @@ fn analyzeBodyInner(
return sema.fail(block, src, "found deprecated code", .{});
}
- break :ext .void_value;
+ i += 1;
+ continue;
},
.disable_instrumentation => {
try sema.zirDisableInstrumentation();
From e3da2852f421ec2e7d568373b3f29030818e1d77 Mon Sep 17 00:00:00 2001
From: Loris Cro
Date: Sun, 23 Feb 2025 17:57:28 +0100
Subject: [PATCH 06/12] `@deprecated`: add suggested changes to langref entry
---
doc/langref.html.in | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index cf9aa4fb93..058a137e74 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -4746,19 +4746,18 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
{#syntax#}@deprecated() void{#endsyntax#}
Used to mark a given code path as deprecated. It evaluates to the same value
- passed in as argument, or the {#syntax#}void{#endsyntax#} value when given none.
+ passed in as argument, or the void value when given none.
- As an example, in Zig 0.14.0 {#syntax#}std.time.sleep{#endsyntax#} was
- deprecated and the sleep function was moved to {#syntax#}std.Thread.sleep{#endsyntax#}.
- This is how this deprecation could have been expressed:
-
- {#syntax_block|zig|lib/std/time.zig#}
-pub const sleep = @deprecated(std.Thread.sleep); // moved
- {#end_syntax_block#}
+ As an example, a library that wishes to move or rename a declaration, while
+ deprecating usage of the old name can use {#syntax#}@deprecated{#endsyntax#} like so:
+ {#syntax_block|zig|root.zig#}
+pub const fooToBar = @deprecated(bar.fromFoo); // moved
+ {#end_syntax_block#}
+
- By default it is a compile error to depend on deprecated code in
+ By default it is a compile error to reference deprecated code in
a module defined by the root package, while it is not in modules defined
by dependencies. This behavior can be overridden for the entire dependency
tree by passing {#syntax#}-fallow-deprecated{#endsyntax#} or
@@ -4772,9 +4771,9 @@ pub const sleep = @deprecated(std.Thread.sleep); // moved
- {#syntax#}@deprecated{#endsyntax#} can also be used without argument:
- {#code|test_deprecated_builtin.zig#}
+ Using {#syntax#}@deprecated{#endsyntax#} without an argument can be useful inside of blocks:
+ {#code|test_deprecated_builtin.zig#}
{#header_close#}
From 25790e95f1e8563f439bb13c460fdd4a46e68c43 Mon Sep 17 00:00:00 2001
From: Loris Cro
Date: Sun, 23 Feb 2025 18:15:27 +0100
Subject: [PATCH 07/12] `@deprecated`: remove per-module flag in Build
This implementation looks at the builder of each
module in the build graph instead of storing a
boolean for each module.
---
lib/std/Build.zig | 2 +-
lib/std/Build/Module.zig | 5 ++---
lib/std/zig/Zir.zig | 2 +-
test/cases/compile_errors/deprecated.zig | 9 +++++++++
test/compile_errors.zig | 14 --------------
test/tests.zig | 6 +++---
6 files changed, 16 insertions(+), 22 deletions(-)
create mode 100644 test/cases/compile_errors/deprecated.zig
diff --git a/lib/std/Build.zig b/lib/std/Build.zig
index 0ba5c43a46..1add40d5df 100644
--- a/lib/std/Build.zig
+++ b/lib/std/Build.zig
@@ -94,7 +94,7 @@ available_deps: AvailableDeps,
release_mode: ReleaseMode,
-// True only for the top-level builder.
+/// `true` only for the root `Build`; `false` for any `Build` belonging to a dependency.
is_root: bool = false,
pub const ReleaseMode = enum {
diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig
index d93fe84416..8a8b9573e4 100644
--- a/lib/std/Build/Module.zig
+++ b/lib/std/Build/Module.zig
@@ -25,7 +25,6 @@ stack_check: ?bool,
sanitize_c: ?bool,
sanitize_thread: ?bool,
fuzz: ?bool,
-allow_deprecated: ?bool,
code_model: std.builtin.CodeModel,
valgrind: ?bool,
pic: ?bool,
@@ -285,7 +284,6 @@ pub fn init(
.owner = owner,
.root_source_file = if (options.root_source_file) |lp| lp.dupe(owner) else null,
.import_table = .{},
- .allow_deprecated = owner.graph.allow_deprecated orelse !owner.is_root,
.resolved_target = options.target,
.optimize = options.optimize,
.link_libc = options.link_libc,
@@ -560,7 +558,8 @@ pub fn appendZigProcessFlags(
try addFlag(zig_args, m.red_zone, "-mred-zone", "-mno-red-zone");
if (m.root_source_file != null) {
- try addFlag(zig_args, m.allow_deprecated, "-fallow-deprecated", "-fno-allow-deprecated");
+ const allow_deprecated = m.owner.graph.allow_deprecated orelse !m.owner.is_root;
+ try addFlag(zig_args, allow_deprecated, "-fallow-deprecated", "-fno-allow-deprecated");
}
if (m.dwarf_format) |dwarf_format| {
diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig
index ea69bc2da0..2939f5be65 100644
--- a/lib/std/zig/Zir.zig
+++ b/lib/std/zig/Zir.zig
@@ -4313,7 +4313,6 @@ fn findTrackableInner(
.value_placeholder => unreachable,
// Once again, we start with the boring tags.
- .deprecated,
.this,
.ret_addr,
.builtin_src,
@@ -4367,6 +4366,7 @@ fn findTrackableInner(
.tuple_decl,
.dbg_empty_stmt,
.astgen_error,
+ .deprecated,
=> return,
// `@TypeOf` has a body.
diff --git a/test/cases/compile_errors/deprecated.zig b/test/cases/compile_errors/deprecated.zig
new file mode 100644
index 0000000000..fdfabc1a5b
--- /dev/null
+++ b/test/cases/compile_errors/deprecated.zig
@@ -0,0 +1,9 @@
+const bad = @deprecated(42);
+
+pub export fn foo() usize {
+ return bad;
+}
+
+// error
+//
+// :1:13: error: found deprecated code
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 03e9324b02..109347cde8 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -250,18 +250,4 @@ pub fn addCases(ctx: *Cases, b: *std.Build) !void {
":1:5: error: expected expression, found 'invalid token'",
});
}
-
- {
- const case = ctx.obj("usage of deprecated code", b.graph.host);
-
- case.addError(
- \\const bad = @deprecated(42);
- \\
- \\pub export fn foo() usize {
- \\ return bad;
- \\}
- , &[_][]const u8{
- ":1:13: error: found deprecated code",
- });
- }
}
diff --git a/test/tests.zig b/test/tests.zig
index 45cba01c7f..1bf6741206 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -1199,13 +1199,13 @@ pub fn addCliTests(b: *std.Build) *Step {
\\}
;
- var src_dir = std.fs.cwd().makeOpenPath(b.pathJoin(&.{ tmp_path, "src" }), .{}) catch unreachable;
+ var src_dir = std.fs.cwd().makeOpenPath(b.pathJoin(&.{ tmp_path, "src" }), .{}) catch @panic("unable to create tmp path");
defer src_dir.close();
- var main = src_dir.createFile("main.zig", .{}) catch unreachable;
+ var main = src_dir.createFile("main.zig", .{}) catch @panic("unable to create main.zig");
defer main.close();
- main.writeAll(new_main_src) catch unreachable;
+ main.writeAll(new_main_src) catch @panic("unable to write to main.zig");
}
const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init" });
From 7c2649f89dc76afca46c3aa5c675719b647cdd10 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 25 Feb 2025 22:42:04 -0800
Subject: [PATCH 08/12] langref: fix whitespace
---
doc/langref.html.in | 58 ++++++++++++++++++++++-----------------------
test/tests.zig | 2 +-
2 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 058a137e74..b54ba4b152 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -2288,7 +2288,7 @@ or
{#code|test_aligned_struct_fields.zig#}
- Equating packed structs results in a comparison of the backing integer,
+ Equating packed structs results in a comparison of the backing integer,
and only works for the `==` and `!=` operators.
{#code|test_packed_struct_equality.zig#}
@@ -4086,7 +4086,7 @@ fn performFn(start_value: i32) i32 {
special-case syntax.
- Here is an example of a generic {#syntax#}List{#endsyntax#} data structure.
+ Here is an example of a generic {#syntax#}List{#endsyntax#} data structure.
{#code|generic_data_structure.zig#}
@@ -4291,10 +4291,10 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void {
{#syntax#}@addrSpaceCast(ptr: anytype) anytype{#endsyntax#}
Converts a pointer from one address space to another. The new address space is inferred
- based on the result type. Depending on the current target and address spaces, this cast
- may be a no-op, a complex operation, or illegal. If the cast is legal, then the resulting
- pointer points to the same memory location as the pointer operand. It is always valid to
- cast a pointer between the same address spaces.
+ based on the result type. Depending on the current target and address spaces, this cast
+ may be a no-op, a complex operation, or illegal. If the cast is legal, then the resulting
+ pointer points to the same memory location as the pointer operand. It is always valid to
+ cast a pointer between the same address spaces.
{#header_close#}
{#header_open|@addWithOverflow#}
@@ -4307,7 +4307,7 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void {
{#syntax#}@alignCast(ptr: anytype) anytype{#endsyntax#}
{#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}?*T{#endsyntax#}, or {#syntax#}[]T{#endsyntax#}.
- Changes the alignment of a pointer. The alignment to use is inferred based on the result type.
+ Changes the alignment of a pointer. The alignment to use is inferred based on the result type.
A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added
to the generated code to make sure the pointer is aligned as promised.
@@ -4384,7 +4384,7 @@ comptime {
{#syntax#}@bitCast(value: anytype) anytype{#endsyntax#}
Converts a value of one type to another type. The return type is the
- inferred result type.
+ inferred result type.
Asserts that {#syntax#}@sizeOf(@TypeOf(value)) == @sizeOf(DestType){#endsyntax#}.
@@ -4740,41 +4740,41 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
{#see_also|@cVaArg|@cVaCopy|@cVaEnd#}
{#header_close#}
-
+
{#header_open|@deprecated#}
{#syntax#}@deprecated(value: anytype) @TypeOf(value){#endsyntax#}
{#syntax#}@deprecated() void{#endsyntax#}
- Used to mark a given code path as deprecated. It evaluates to the same value
- passed in as argument, or the void value when given none.
+ Used to mark a given code path as deprecated. It evaluates to the same value
+ passed in as argument, or the void value when given none.
As an example, a library that wishes to move or rename a declaration, while
- deprecating usage of the old name can use {#syntax#}@deprecated{#endsyntax#} like so:
-
+ deprecating usage of the old name can use {#syntax#}@deprecated{#endsyntax#} like so:
+
{#syntax_block|zig|root.zig#}
pub const fooToBar = @deprecated(bar.fromFoo); // moved
{#end_syntax_block#}
By default it is a compile error to reference deprecated code in
- a module defined by the root package, while it is not in modules defined
- by dependencies. This behavior can be overridden for the entire dependency
- tree by passing {#syntax#}-fallow-deprecated{#endsyntax#} or
- {#syntax#}-fno-allow-deprecated{#endsyntax#} to {#syntax#}zig build{#endsyntax#}.
+ a module defined by the root package, while it is not in modules defined
+ by dependencies. This behavior can be overridden for the entire dependency
+ tree by passing {#syntax#}-fallow-deprecated{#endsyntax#} or
+ {#syntax#}-fno-allow-deprecated{#endsyntax#} to {#syntax#}zig build{#endsyntax#}.
- Usage of this builtin is meant to help direct consumers discover (and remove)
- their dependance on deprecated code during the grace period before a deprecated
- functionality is turned into a {#syntax#}@compileError{#endsyntax#} or
- removed entirely.
+ Usage of this builtin is meant to help direct consumers discover (and remove)
+ their dependance on deprecated code during the grace period before a deprecated
+ functionality is turned into a {#syntax#}@compileError{#endsyntax#} or
+ removed entirely.
-
+
Using {#syntax#}@deprecated{#endsyntax#} without an argument can be useful inside of blocks:
-
+
{#code|test_deprecated_builtin.zig#}
-
+
{#header_close#}
{#header_open|@divExact#}
@@ -4891,8 +4891,8 @@ pub const fooToBar = @deprecated(bar.fromFoo); // moved
{#syntax#}@errorCast(value: anytype) anytype{#endsyntax#}
Converts an error set or error union value from one error set to another error set. The return type is the
- inferred result type. Attempting to convert an error which is not in the destination error
- set results in safety-checked {#link|Illegal Behavior#}.
+ inferred result type. Attempting to convert an error which is not in the destination error
+ set results in safety-checked {#link|Illegal Behavior#}.
{#header_close#}
@@ -4971,7 +4971,7 @@ pub const fooToBar = @deprecated(bar.fromFoo); // moved
{#syntax#}@floatFromInt(int: anytype) anytype{#endsyntax#}
Converts an integer to the closest floating point representation. The return type is the inferred result type.
- To convert the other way, use {#link|@intFromFloat#}. This operation is legal
+ To convert the other way, use {#link|@intFromFloat#}. This operation is legal
for all values of all integer types.
{#header_close#}
@@ -5063,7 +5063,7 @@ pub const fooToBar = @deprecated(bar.fromFoo); // moved
{#syntax#}@intCast(int: anytype) anytype{#endsyntax#}
Converts an integer to another integer while keeping the same numerical value.
- The return type is the inferred result type.
+ The return type is the inferred result type.
Attempting to convert a number which is out of range of the destination type results in
safety-checked {#link|Illegal Behavior#}.
@@ -5316,7 +5316,7 @@ pub const fooToBar = @deprecated(bar.fromFoo); // moved
{#syntax#}@ptrFromInt(address: usize) anytype{#endsyntax#}
Converts an integer to a {#link|pointer|Pointers#}. The return type is the inferred result type.
- To convert the other way, use {#link|@intFromPtr#}. Casting an address of 0 to a destination type
+ To convert the other way, use {#link|@intFromPtr#}. Casting an address of 0 to a destination type
which in not {#link|optional|Optional Pointers#} and does not have the {#syntax#}allowzero{#endsyntax#} attribute will result in a
{#link|Pointer Cast Invalid Null#} panic when runtime safety checks are enabled.
diff --git a/test/tests.zig b/test/tests.zig
index 1bf6741206..e8bbca2963 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -1195,7 +1195,7 @@ pub fn addCliTests(b: *std.Build) *Step {
\\}
\\
\\test {
- \\ if (bad != 42) return error.Bad;
+ \\ if (bad != 42) return error.Bad;
\\}
;
From 4ddb13468b372b2f722703b5e6d60997776c251a Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 25 Feb 2025 23:02:24 -0800
Subject: [PATCH 09/12] langref: update deprecated section
---
doc/langref.html.in | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index b54ba4b152..1aff0f2c6d 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -4745,36 +4745,36 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
{#syntax#}@deprecated(value: anytype) @TypeOf(value){#endsyntax#}
{#syntax#}@deprecated() void{#endsyntax#}
- Used to mark a given code path as deprecated. It evaluates to the same value
- passed in as argument, or the void value when given none.
+ Marks a given code path as scheduled for removal. Evaluates to the same
+ value passed in as argument, or the {#syntax#}void{#endsyntax#} value
+ when given none.
- As an example, a library that wishes to move or rename a declaration, while
- deprecating usage of the old name can use {#syntax#}@deprecated{#endsyntax#} like so:
+ When a public declaration has been moved to a new location, the old
+ location can be marked {#syntax#}@deprecated{#endsyntax#}:
{#syntax_block|zig|root.zig#}
pub const fooToBar = @deprecated(bar.fromFoo); // moved
{#end_syntax_block#}
-
- By default it is a compile error to reference deprecated code in
- a module defined by the root package, while it is not in modules defined
- by dependencies. This behavior can be overridden for the entire dependency
- tree by passing {#syntax#}-fallow-deprecated{#endsyntax#} or
- {#syntax#}-fno-allow-deprecated{#endsyntax#} to {#syntax#}zig build{#endsyntax#}.
+ By default deprecated code paths are disallowed in a module defined by
+ the root package but allowed in modules defined by the rest of the
+ dependency tree. This behavior can be overridden by passing
+ -fallow-deprecated or -fno-allow-deprecated to
+ zig build.
- Usage of this builtin is meant to help direct consumers discover (and remove)
- their dependance on deprecated code during the grace period before a deprecated
- functionality is turned into a {#syntax#}@compileError{#endsyntax#} or
- removed entirely.
+ The purpose of {#syntax#}@deprecated{#endsyntax#} is to provide at least
+ one version (a "grace period") of a package that supports both old and new APIs
+ simultaneously, while providing tooling for programmers to discover what needs
+ to be upgraded to migrate to the new API. Such a grace period has the key property
+ that it allows a project's dependency tree to be upgraded one package at a time.
-
- Using {#syntax#}@deprecated{#endsyntax#} without an argument can be useful inside of blocks:
+ Using {#syntax#}@deprecated{#endsyntax#} without an argument can be
+ useful inside of conditionally compiled blocks:
{#code|test_deprecated_builtin.zig#}
-
{#header_close#}
{#header_open|@divExact#}
From c5aa680c88f7c03718460ff38e7cb1f7c5482cf2 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 25 Feb 2025 23:50:56 -0800
Subject: [PATCH 10/12] don't inherit allowed deprecation from parent modules
Inheriting allow-deprecation from parent modules doesn't make too much
sense, so instead make them default to disallow unless otherwise
specified. This allows build system to avoid redundant
`-fno-allow-deprecated` args.
This makes the generated CLIs smaller, and makes zig1.wasm update not
needed.
Also represented `is_root` differently (moved to field of graph).
---
lib/compiler/build_runner.zig | 2 ++
lib/std/Build.zig | 7 ++-----
lib/std/Build/Module.zig | 7 +++----
src/Package/Module.zig | 1 -
4 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/lib/compiler/build_runner.zig b/lib/compiler/build_runner.zig
index 114a9e3acf..f159863ab6 100644
--- a/lib/compiler/build_runner.zig
+++ b/lib/compiler/build_runner.zig
@@ -80,6 +80,7 @@ pub fn main() !void {
.query = .{},
.result = try std.zig.system.resolveTargetQuery(.{}),
},
+ .root_builder = undefined, // populated below
};
graph.cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });
@@ -94,6 +95,7 @@ pub fn main() !void {
local_cache_directory,
dependencies.root_deps,
);
+ graph.root_builder = builder;
var targets = ArrayList([]const u8).init(arena);
var debug_log_scopes = ArrayList([]const u8).init(arena);
diff --git a/lib/std/Build.zig b/lib/std/Build.zig
index 1add40d5df..4f3364bb19 100644
--- a/lib/std/Build.zig
+++ b/lib/std/Build.zig
@@ -94,9 +94,6 @@ available_deps: AvailableDeps,
release_mode: ReleaseMode,
-/// `true` only for the root `Build`; `false` for any `Build` belonging to a dependency.
-is_root: bool = false,
-
pub const ReleaseMode = enum {
off,
any,
@@ -121,10 +118,11 @@ pub const Graph = struct {
/// Information about the native target. Computed before build() is invoked.
host: ResolvedTarget,
incremental: ?bool = null,
- allow_deprecated: ?bool = null,
random_seed: u32 = 0,
dependency_cache: InitializedDepMap = .empty,
allow_so_scripts: ?bool = null,
+ allow_deprecated: ?bool = null,
+ root_builder: *std.Build,
};
const AvailableDeps = []const struct { []const u8, []const u8 };
@@ -308,7 +306,6 @@ pub fn create(
.pkg_hash = "",
.available_deps = available_deps,
.release_mode = .off,
- .is_root = true,
};
try b.top_level_steps.put(arena, b.install_tls.step.name, &b.install_tls);
try b.top_level_steps.put(arena, b.uninstall_tls.step.name, &b.uninstall_tls);
diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig
index 8a8b9573e4..40b9a5e619 100644
--- a/lib/std/Build/Module.zig
+++ b/lib/std/Build/Module.zig
@@ -557,10 +557,9 @@ pub fn appendZigProcessFlags(
try addFlag(zig_args, m.pic, "-fPIC", "-fno-PIC");
try addFlag(zig_args, m.red_zone, "-mred-zone", "-mno-red-zone");
- if (m.root_source_file != null) {
- const allow_deprecated = m.owner.graph.allow_deprecated orelse !m.owner.is_root;
- try addFlag(zig_args, allow_deprecated, "-fallow-deprecated", "-fno-allow-deprecated");
- }
+ // -fno-allow-deprecated is the CLI default, and not inherited, so only pass the flag if true.
+ const allow_deprecated = m.owner.graph.allow_deprecated orelse (m.owner.graph.root_builder != m.owner);
+ if (allow_deprecated == true) try zig_args.append("-fallow-deprecated");
if (m.dwarf_format) |dwarf_format| {
try zig_args.append(switch (dwarf_format) {
diff --git a/src/Package/Module.zig b/src/Package/Module.zig
index 6bd33dffa1..c5aa21a105 100644
--- a/src/Package/Module.zig
+++ b/src/Package/Module.zig
@@ -238,7 +238,6 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
const allow_deprecated = b: {
if (options.inherited.allow_deprecated) |x| break :b x;
- if (options.parent) |p| break :b p.allow_deprecated;
break :b false;
};
From f74a856d84af4c43057febc0a871caa0e69bbfc8 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 25 Feb 2025 23:59:48 -0800
Subject: [PATCH 11/12] reword deprecated error slightly
"found" -> "reached" to match "reached unreachable code"
---
src/Sema.zig | 2 +-
test/cases/compile_errors/deprecated.zig | 2 +-
test/tests.zig | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/Sema.zig b/src/Sema.zig
index 9e4c4d6bd2..2d5407532a 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -1409,7 +1409,7 @@ fn analyzeBodyInner(
if (!mod.allow_deprecated) {
const src_node: i32 = @bitCast(extended.operand);
const src = block.nodeOffset(src_node);
- return sema.fail(block, src, "found deprecated code", .{});
+ return sema.fail(block, src, "reached deprecated code", .{});
}
i += 1;
diff --git a/test/cases/compile_errors/deprecated.zig b/test/cases/compile_errors/deprecated.zig
index fdfabc1a5b..98921a0742 100644
--- a/test/cases/compile_errors/deprecated.zig
+++ b/test/cases/compile_errors/deprecated.zig
@@ -6,4 +6,4 @@ pub export fn foo() usize {
// error
//
-// :1:13: error: found deprecated code
+// :1:13: error: reached deprecated code
diff --git a/test/tests.zig b/test/tests.zig
index e8bbca2963..694b0002f4 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -1180,7 +1180,7 @@ pub fn addCliTests(b: *std.Build) *Step {
// Test `zig build -fallow-deprecated`.
const deprecated_check: std.Build.Step.Run.StdIo.Check = .{
- .expect_stderr_match = "found deprecated code",
+ .expect_stderr_match = "reached deprecated code",
};
const tmp_path = b.makeTempPath();
From 43a949ee95ce72003bb2d2ee22e1f4b5aea96739 Mon Sep 17 00:00:00 2001
From: Loris Cro
Date: Wed, 26 Feb 2025 11:33:54 +0100
Subject: [PATCH 12/12] fix regressed build system unit test
---
lib/std/Build/Step/Options.zig | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lib/std/Build/Step/Options.zig b/lib/std/Build/Step/Options.zig
index dd09c0b5c0..fda358ee37 100644
--- a/lib/std/Build/Step/Options.zig
+++ b/lib/std/Build/Step/Options.zig
@@ -514,6 +514,7 @@ test Options {
.result = try std.zig.system.resolveTargetQuery(.{}),
},
.zig_lib_directory = std.Build.Cache.Directory.cwd(),
+ .root_builder = undefined,
};
var builder = try std.Build.create(
@@ -523,6 +524,8 @@ test Options {
&.{},
);
+ graph.root_builder = builder;
+
const options = builder.addOptions();
const KeywordEnum = enum {