aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-11-22 19:00:30 -0500
committerGitHub <noreply@github.com>2021-11-22 19:00:30 -0500
commit11330cbcc55f7d7dbd2de2f5acd7b097cd19788c (patch)
tree68f25f32b59d803986f67f80e660fb8b76fc3025 /src
parent691090f3429b8625252dd5cfec101f2a9e171463 (diff)
parent2b589d71fbcacb2e8bc8746dd4b675e57b3a53df (diff)
downloadzig-11330cbcc55f7d7dbd2de2f5acd7b097cd19788c.tar.gz
zig-11330cbcc55f7d7dbd2de2f5acd7b097cd19788c.zip
Merge pull request #10201 from Snektron/stage2-more-coercion
stage2: more in-memory coercion
Diffstat (limited to 'src')
-rw-r--r--src/Sema.zig145
1 files changed, 97 insertions, 48 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index a82bc75319..b873af4c7e 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -12364,31 +12364,6 @@ fn coerce(
// T to E!T or E to E!T
return sema.wrapErrorUnion(block, dest_ty, inst, inst_src);
},
- .ErrorSet => switch (inst_ty.zigTypeTag()) {
- .ErrorSet => {
- // Coercion to `anyerror`. Note that this check can return false positives
- // in case the error sets did not get resolved.
- if (dest_ty.isAnyError()) {
- return sema.coerceCompatibleErrorSets(block, inst, inst_src);
- }
- // If both are inferred error sets of functions, and
- // the dest includes the source function, the coercion is OK.
- // This check is important because it works without forcing a full resolution
- // of inferred error sets.
- if (inst_ty.castTag(.error_set_inferred)) |src_payload| {
- if (dest_ty.castTag(.error_set_inferred)) |dst_payload| {
- const src_func = src_payload.data.func;
- const dst_func = dst_payload.data.func;
-
- if (src_func == dst_func or dst_payload.data.functions.contains(src_func)) {
- return sema.coerceCompatibleErrorSets(block, inst, inst_src);
- }
- }
- }
- // TODO full error set resolution and compare sets by names.
- },
- else => {},
- },
.Union => switch (inst_ty.zigTypeTag()) {
.Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src),
else => {},
@@ -12441,16 +12416,110 @@ fn coerceInMemoryAllowed(dest_ty: Type, src_ty: Type, dest_is_mut: bool, target:
return coerceInMemoryAllowedPtrs(dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target);
}
+ // Functions
+ if (dest_ty.zigTypeTag() == .Fn and src_ty.zigTypeTag() == .Fn) {
+ return coerceInMemoryAllowedFns(dest_ty, src_ty, target);
+ }
+
+ // Error Unions
+ if (dest_ty.zigTypeTag() == .ErrorUnion and src_ty.zigTypeTag() == .ErrorUnion) {
+ const child = coerceInMemoryAllowed(dest_ty.errorUnionPayload(), src_ty.errorUnionPayload(), dest_is_mut, target);
+ if (child == .no_match) {
+ return child;
+ }
+ return coerceInMemoryAllowed(dest_ty.errorUnionSet(), src_ty.errorUnionSet(), dest_is_mut, target);
+ }
+
+ // Error Sets
+ if (dest_ty.zigTypeTag() == .ErrorSet and src_ty.zigTypeTag() == .ErrorSet) {
+ return coerceInMemoryAllowedErrorSets(dest_ty, src_ty);
+ }
+
// TODO: arrays
// TODO: non-pointer-like optionals
- // TODO: error unions
- // TODO: error sets
- // TODO: functions
// TODO: vectors
return .no_match;
}
+fn coerceInMemoryAllowedErrorSets(
+ dest_ty: Type,
+ src_ty: Type,
+) InMemoryCoercionResult {
+ // Coercion to `anyerror`. Note that this check can return false positives
+ // in case the error sets did not get resolved.
+ if (dest_ty.isAnyError()) {
+ return .ok;
+ }
+ // If both are inferred error sets of functions, and
+ // the dest includes the source function, the coercion is OK.
+ // This check is important because it works without forcing a full resolution
+ // of inferred error sets.
+ if (src_ty.castTag(.error_set_inferred)) |src_payload| {
+ if (dest_ty.castTag(.error_set_inferred)) |dst_payload| {
+ const src_func = src_payload.data.func;
+ const dst_func = dst_payload.data.func;
+
+ if (src_func == dst_func or dst_payload.data.functions.contains(src_func)) {
+ return .ok;
+ }
+ }
+ }
+
+ // TODO full error set resolution and compare sets by names.
+ return .no_match;
+}
+
+fn coerceInMemoryAllowedFns(
+ dest_ty: Type,
+ src_ty: Type,
+ target: std.Target,
+) InMemoryCoercionResult {
+ const dest_info = dest_ty.fnInfo();
+ const src_info = src_ty.fnInfo();
+
+ if (dest_info.is_var_args != src_info.is_var_args) {
+ return .no_match;
+ }
+
+ if (dest_info.is_generic != src_info.is_generic) {
+ return .no_match;
+ }
+
+ if (!src_info.return_type.isNoReturn()) {
+ const rt = coerceInMemoryAllowed(dest_info.return_type, src_info.return_type, false, target);
+ if (rt == .no_match) {
+ return rt;
+ }
+ }
+
+ if (dest_info.param_types.len != src_info.param_types.len) {
+ return .no_match;
+ }
+
+ for (dest_info.param_types) |dest_param_ty, i| {
+ const src_param_ty = src_info.param_types[i];
+
+ if (dest_info.comptime_params[i] != src_info.comptime_params[i]) {
+ return .no_match;
+ }
+
+ // TODO: nolias
+
+ // Note: Cast direction is reversed here.
+ const param = coerceInMemoryAllowed(src_param_ty, dest_param_ty, false, target);
+ if (param == .no_match) {
+ return param;
+ }
+ }
+
+ if (dest_info.cc != src_info.cc) {
+ return .no_match;
+ }
+
+ return .ok;
+}
+
fn coerceInMemoryAllowedPtrs(
dest_ty: Type,
src_ty: Type,
@@ -13198,26 +13267,6 @@ fn coerceVectorInMemory(
return block.addBitCast(dest_ty, inst);
}
-fn coerceCompatibleErrorSets(
- sema: *Sema,
- block: *Block,
- err_set: Air.Inst.Ref,
- err_set_src: LazySrcLoc,
-) !Air.Inst.Ref {
- if (try sema.resolveDefinedValue(block, err_set_src, err_set)) |err_set_val| {
- // Same representation works.
- return sema.addConstant(Type.anyerror, err_set_val);
- }
- try sema.requireRuntimeBlock(block, err_set_src);
- return block.addInst(.{
- .tag = .bitcast,
- .data = .{ .ty_op = .{
- .ty = Air.Inst.Ref.anyerror_type,
- .operand = err_set,
- } },
- });
-}
-
fn analyzeDeclVal(
sema: *Sema,
block: *Block,