Skip to content

Expand RLS for ref result type #16512

@mlugg

Description

@mlugg

Motivation

Currently, using & uses the ref result location. This causes type information to be lost, which, as of #16163 landing, has meaningful effects on the language. First, consider this code snippet:

const S = struct { x: u32 };
const s: S = .{ .x = @intCast(val) };

This already works fine. The result type of S is forwarded to the struct init expression, which forwards field types onto each field init expression. Now, consider this (very similar) line:

const s: *const S = &.{ .x = @intCast(val) };

This currently fails to compile. The use of & means the struct init expression uses a ref result type, so has no type information to forward onto the field init expression. This means you either need to write &S{ ... }, or use @as to specify the field type.

Copy elision is also important here. Consider the following:

const T = struct { inner: struct { x: u32 } };
const t: *const T = &.{ .inner = .{ .x = 123 } };

Here, since there is not a known result type for the init expression, a copy of the inner struct cannot be avoided. The inner initialization is evaluated, then the result copied into the outer anon struct, which is then coerced to the correct type (potentially causing yet another copy).

Proposal

I'm going to explain this in terms of implementation details, because I think it's relatively easy to understand and is important to consider.

Introduce new result locations for typed refs. More specifically, expand AstGen.ResultInfo.Loc to add the following locations:

/// A pointer to the expression must be generated rather than the expression value itself.
/// The pointer child type (that is, the type of the expression) must be the provided type.
ref_ty: Zir.Inst.Ref,

When &a has a result location of .{ .ty = T }, a has a result location of .{ .ref_ty = S } where S is found through a new ptr_child ZIR instruction. This is made a little more complicated by slices, because if T is a []Foo, we cannot make S a concrete type, as it may be any [n]Foo. This can be solved by introducing an internal "unknown length array" type which ptr_child can return for slices. Care should be taken to avoid this fake type from leaking into other parts of the compiler.

Error Messages

Aside from helping with cast builtins and copy elision as already discussed, this proposal has an additional benefit of improving error messages. RLS can improve errors because field inits become individual pointer writes, so type errors are caught at the point of a field initialization rather than at the point of type coercion. #16508 details an error message which would be improved by this change.

Bonus Proposal: Removing Anonymous Struct Types

EDIT: moved to #16865

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedThis proposal is planned.proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions