Zig函数仅返回错误类型的语义疑问及catch相关编译问题
Zig错误类型返回值的行为疑问
不确定以下代码中的行为是Zig设计者的预期,还是存在编译错误:
const std = @import("std"); const expect = std.testing.expect; const expectError = std.testing.expectError; const MyErrors = error.MyError; fn returnError() @TypeOf(MyErrors){ return error.MyError; } fn returnErrorUnion() @TypeOf(MyErrors)!u64{ return error.MyError; } test "returnErrorCall" { try expect(returnError() catch 3 == 3); // Ok try expectError(error.MyError, returnError()); // Compile-time error } test "returnErrorUnionCall" { try expect(returnErrorUnion() catch 3 == 3); // Ok // Compile-time Error why? error.MyError != anyerror //try expectError(returnErrorUnion(), error.MyError); try expectError(error.MyError, returnErrorUnion());// Ok }
核心原因解析
returnError函数的返回类型:
@TypeOf(MyErrors)得到的是error{MyError}这个错误集类型,而非错误联合类型(ErrType!RetType)。returnError()直接返回的是一个错误值,不是包含错误或有效值的联合类型。returnError() catch 3能运行,是因为Zig允许对非错误联合类型使用catch:当表达式是错误值时,会进入catch分支返回备选值;如果是普通值则直接返回该值。expectError(error.MyError, returnError())编译报错,是因为expectError的第二个参数要求是错误联合类型的表达式(即可能产生错误或有效值的操作),而returnError()返回的是纯错误值,不符合参数类型要求。
returnErrorUnion函数的返回类型:
@TypeOf(MyErrors)!u64是标准的错误联合类型,包含error{MyError}错误集和u64有效值。- 注释掉的
try expectError(returnErrorUnion(), error.MyError)报错,纯粹是参数顺序错误:expectError的正确参数顺序是**(期望捕获的错误值, 可能出错的表达式)**,反过来会导致类型不匹配。 try expectError(error.MyError, returnErrorUnion())能正常运行,是因为参数顺序正确,且returnErrorUnion()是错误联合类型,符合expectError的参数要求。
- 注释掉的
对猜测的修正
returnError()返回的不是u16值,而是error{MyError}类型的错误实例。它和错误联合类型的核心区别是:错误联合是"错误或有效值"的二选一类型,而纯错误类型只是单一的错误值,不包含有效值分支,因此无法被try关键字处理(try仅用于解包错误联合)。
内容的提问来源于stack exchange,提问作者agatzan
相关产品推荐
相关产品推荐

