@@ -4503,14 +4503,14 @@ fn analyzeCall(
4503
4503
const arg_src = call_src; // TODO: better source location
4504
4504
if (i < fn_params_len) {
4505
4505
const param_ty = func_ty.fnParamType(i);
4506
- try sema.resolveTypeForCodegen (block, arg_src, param_ty);
4506
+ try sema.resolveTypeFully (block, arg_src, param_ty);
4507
4507
args[i] = try sema.coerce(block, param_ty, uncasted_arg, arg_src);
4508
4508
} else {
4509
4509
args[i] = uncasted_arg;
4510
4510
}
4511
4511
}
4512
4512
4513
- try sema.resolveTypeForCodegen (block, call_src, func_ty_info.return_type);
4513
+ try sema.resolveTypeFully (block, call_src, func_ty_info.return_type);
4514
4514
4515
4515
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len +
4516
4516
args.len);
@@ -4580,15 +4580,15 @@ fn finishGenericCall(
4580
4580
const param_ty = new_fn_ty.fnParamType(runtime_i);
4581
4581
const arg_src = call_src; // TODO: better source location
4582
4582
const uncasted_arg = uncasted_args[total_i];
4583
- try sema.resolveTypeForCodegen (block, arg_src, param_ty);
4583
+ try sema.resolveTypeFully (block, arg_src, param_ty);
4584
4584
const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);
4585
4585
runtime_args[runtime_i] = casted_arg;
4586
4586
runtime_i += 1;
4587
4587
}
4588
4588
total_i += 1;
4589
4589
}
4590
4590
4591
- try sema.resolveTypeForCodegen (block, call_src, new_fn_ty.fnReturnType());
4591
+ try sema.resolveTypeFully (block, call_src, new_fn_ty.fnReturnType());
4592
4592
}
4593
4593
try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +
4594
4594
runtime_args_len);
@@ -7318,8 +7318,8 @@ fn zirShr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
7318
7318
const lhs = sema.resolveInst(extra.lhs);
7319
7319
const rhs = sema.resolveInst(extra.rhs);
7320
7320
7321
- if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs )) |lhs_val | {
7322
- if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs )) |rhs_val | {
7321
+ if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs )) |rhs_val | {
7322
+ if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs )) |lhs_val | {
7323
7323
const lhs_ty = sema.typeOf(lhs);
7324
7324
if (lhs_val.isUndef() or rhs_val.isUndef()) {
7325
7325
return sema.addConstUndef(lhs_ty);
@@ -7331,6 +7331,12 @@ fn zirShr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
7331
7331
const val = try lhs_val.shr(rhs_val, sema.arena);
7332
7332
return sema.addConstant(lhs_ty, val);
7333
7333
}
7334
+ // Even if lhs is not comptime known, we can still deduce certain things based
7335
+ // on rhs.
7336
+ // If rhs is 0, return lhs without doing any calculations.
7337
+ else if (rhs_val.compareWithZero(.eq)) {
7338
+ return lhs;
7339
+ }
7334
7340
}
7335
7341
7336
7342
try sema.requireRuntimeBlock(block, src);
@@ -15222,7 +15228,7 @@ fn resolveStructLayout(
15222
15228
.field_types_wip, .layout_wip => {
15223
15229
return sema.fail(block, src, "struct {} depends on itself", .{ty});
15224
15230
},
15225
- .have_layout => return,
15231
+ .have_layout, .fully_resolved_wip, .fully_resolved => return,
15226
15232
}
15227
15233
struct_obj.status = .layout_wip;
15228
15234
for (struct_obj.fields.values()) |field| {
@@ -15244,7 +15250,7 @@ fn resolveUnionLayout(
15244
15250
.field_types_wip, .layout_wip => {
15245
15251
return sema.fail(block, src, "union {} depends on itself", .{ty});
15246
15252
},
15247
- .have_layout => return,
15253
+ .have_layout, .fully_resolved_wip, .fully_resolved => return,
15248
15254
}
15249
15255
union_obj.status = .layout_wip;
15250
15256
for (union_obj.fields.values()) |field| {
@@ -15253,7 +15259,7 @@ fn resolveUnionLayout(
15253
15259
union_obj.status = .have_layout;
15254
15260
}
15255
15261
15256
- fn resolveTypeForCodegen (
15262
+ fn resolveTypeFully (
15257
15263
sema: *Sema,
15258
15264
block: *Block,
15259
15265
src: LazySrcLoc,
@@ -15262,20 +15268,67 @@ fn resolveTypeForCodegen(
15262
15268
switch (ty.zigTypeTag()) {
15263
15269
.Pointer => {
15264
15270
const child_ty = try sema.resolveTypeFields(block, src, ty.childType());
15265
- return resolveTypeForCodegen (sema, block, src, child_ty);
15271
+ return resolveTypeFully (sema, block, src, child_ty);
15266
15272
},
15267
- .Struct => return resolveStructLayout (sema, block, src, ty),
15268
- .Union => return resolveUnionLayout (sema, block, src, ty),
15269
- .Array => return resolveTypeForCodegen (sema, block, src, ty.childType()),
15273
+ .Struct => return resolveStructFully (sema, block, src, ty),
15274
+ .Union => return resolveUnionFully (sema, block, src, ty),
15275
+ .Array => return resolveTypeFully (sema, block, src, ty.childType()),
15270
15276
.Optional => {
15271
15277
var buf: Type.Payload.ElemType = undefined;
15272
- return resolveTypeForCodegen (sema, block, src, ty.optionalChild(&buf));
15278
+ return resolveTypeFully (sema, block, src, ty.optionalChild(&buf));
15273
15279
},
15274
- .ErrorUnion => return resolveTypeForCodegen (sema, block, src, ty.errorUnionPayload()),
15280
+ .ErrorUnion => return resolveTypeFully (sema, block, src, ty.errorUnionPayload()),
15275
15281
else => {},
15276
15282
}
15277
15283
}
15278
15284
15285
+ fn resolveStructFully(
15286
+ sema: *Sema,
15287
+ block: *Block,
15288
+ src: LazySrcLoc,
15289
+ ty: Type,
15290
+ ) CompileError!void {
15291
+ try resolveStructLayout(sema, block, src, ty);
15292
+
15293
+ const resolved_ty = try sema.resolveTypeFields(block, src, ty);
15294
+ const struct_obj = resolved_ty.castTag(.@"struct").?.data;
15295
+ switch (struct_obj.status) {
15296
+ .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
15297
+ .fully_resolved_wip, .fully_resolved => return,
15298
+ }
15299
+
15300
+ // After we have resolve struct layout we have to go over the fields again to
15301
+ // make sure pointer fields get their child types resolved as well
15302
+ struct_obj.status = .fully_resolved_wip;
15303
+ for (struct_obj.fields.values()) |field| {
15304
+ try sema.resolveTypeFully(block, src, field.ty);
15305
+ }
15306
+ struct_obj.status = .fully_resolved;
15307
+ }
15308
+
15309
+ fn resolveUnionFully(
15310
+ sema: *Sema,
15311
+ block: *Block,
15312
+ src: LazySrcLoc,
15313
+ ty: Type,
15314
+ ) CompileError!void {
15315
+ try resolveUnionLayout(sema, block, src, ty);
15316
+
15317
+ const resolved_ty = try sema.resolveTypeFields(block, src, ty);
15318
+ const union_obj = resolved_ty.cast(Type.Payload.Union).?.data;
15319
+ switch (union_obj.status) {
15320
+ .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
15321
+ .fully_resolved_wip, .fully_resolved => return,
15322
+ }
15323
+
15324
+ // Same goes for unions (see comment about structs)
15325
+ union_obj.status = .fully_resolved_wip;
15326
+ for (union_obj.fields.values()) |field| {
15327
+ try sema.resolveTypeFully(block, src, field.ty);
15328
+ }
15329
+ union_obj.status = .fully_resolved;
15330
+ }
15331
+
15279
15332
fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!Type {
15280
15333
switch (ty.tag()) {
15281
15334
.@"struct" => {
@@ -15285,7 +15338,12 @@ fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Comp
15285
15338
.field_types_wip => {
15286
15339
return sema.fail(block, src, "struct {} depends on itself", .{ty});
15287
15340
},
15288
- .have_field_types, .have_layout, .layout_wip => return ty,
15341
+ .have_field_types,
15342
+ .have_layout,
15343
+ .layout_wip,
15344
+ .fully_resolved_wip,
15345
+ .fully_resolved,
15346
+ => return ty,
15289
15347
}
15290
15348
15291
15349
struct_obj.status = .field_types_wip;
@@ -15318,7 +15376,12 @@ fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Comp
15318
15376
.field_types_wip => {
15319
15377
return sema.fail(block, src, "union {} depends on itself", .{ty});
15320
15378
},
15321
- .have_field_types, .have_layout, .layout_wip => return ty,
15379
+ .have_field_types,
15380
+ .have_layout,
15381
+ .layout_wip,
15382
+ .fully_resolved_wip,
15383
+ .fully_resolved,
15384
+ => return ty,
15322
15385
}
15323
15386
15324
15387
union_obj.status = .field_types_wip;
0 commit comments