mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
This commit introduces the new `ref_coerced_ty` result type into AstGen.
This represents a expression which we want to treat as an lvalue, and
the pointer will be coerced to a given type.
This change gives known result types to many expressions, in particular
struct and array initializations. This allows certain casts to work
which previously required explicitly specifying types via `@as`. It also
eliminates our dependence on anonymous struct types for expressions of
the form `&.{ ... }` - this paves the way for #16865, and also results
in less Sema magic happening for such initializations, also leading to
potentially better runtime code.
As part of these changes, this commit also implements #17194 by
disallowing RLS on explicitly-typed struct and array initializations.
Apologies for linking these changes - it seemed rather pointless to try
and separate them, since they both make big changes to struct and array
initializations in AstGen. The rationale for this change can be found in
the proposal - in essence, performing RLS whilst maintaining the
semantics of the intermediary type is a very difficult problem to solve.
This allowed the problematic `coerce_result_ptr` ZIR instruction to be
completely eliminated, which in turn also simplified the logic for
inferred allocations in Sema - thanks to this, we almost break even on
line count!
In doing this, the ZIR instructions surrounding these initializations
have been restructured - some have been added and removed, and others
renamed for clarity (and their semantics changed slightly). In order to
optimize ZIR tag count, the `struct_init_anon_ref` and
`array_init_anon_ref` instructions have been removed in favour of using
`ref` on a standard anonymous value initialization, since these
instructions are now virtually never used.
Lastly, it's worth noting that this commit introduces a slightly strange
source of generic poison types: in the expression `@as(*anyopaque, &x)`,
the sub-expression `x` has a generic poison result type, despite no
generic code being involved. This turns out to be a logical choice,
because we don't know the result type for `x`, and the generic poison
type represents precisely this case, providing the semantics we need.
Resolves: #16512
Resolves: #17194
44 lines
1,012 B
Zig
44 lines
1,012 B
Zig
fn f(b: bool) void {
|
|
const x: i32 = if (b) h: {
|
|
break :h 1;
|
|
};
|
|
_ = x;
|
|
}
|
|
fn g(b: bool) void {
|
|
const y = if (b) h: {
|
|
break :h @as(i32, 1);
|
|
};
|
|
_ = y;
|
|
}
|
|
fn h() void {
|
|
// https://github.com/ziglang/zig/issues/12743
|
|
const T = struct { oh_no: *u32 };
|
|
var x: T = if (false) {};
|
|
_ = x;
|
|
}
|
|
fn k(b: bool) void {
|
|
// block_ptr case
|
|
const T = struct { oh_no: u32 };
|
|
var x = if (b) blk: {
|
|
break :blk if (false) T{ .oh_no = 2 };
|
|
} else T{ .oh_no = 1 };
|
|
_ = x;
|
|
}
|
|
export fn entry() void {
|
|
f(true);
|
|
g(true);
|
|
h();
|
|
k(true);
|
|
}
|
|
// error
|
|
// backend=stage2
|
|
// target=native
|
|
//
|
|
// :2:20: error: expected type 'i32', found 'void'
|
|
// :8:15: error: incompatible types: 'i32' and 'void'
|
|
// :8:25: note: type 'i32' here
|
|
// :16:16: error: expected type 'tmp.h.T', found 'void'
|
|
// :15:15: note: struct declared here
|
|
// :22:13: error: incompatible types: 'void' and 'tmp.k.T'
|
|
// :22:25: note: type 'void' here
|
|
// :24:13: note: type 'tmp.k.T' here
|