Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add @Here() builtin for in-situ reference of known destination Type #20236

Closed
expikr opened this issue Jun 8, 2024 · 10 comments
Closed

add @Here() builtin for in-situ reference of known destination Type #20236

expikr opened this issue Jun 8, 2024 · 10 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@expikr
Copy link
Contributor

expikr commented Jun 8, 2024

This provides an alternative for usecase 1A and 2A in the accepted proposal #9938 to reduce its scope (and complexity debt) down to just the addition of a streamlined union-literal syntax without changing the current rules for explicit location inference of enum literals or imposing the namespace restriction described in @mlugg's acceptance notice.

From what I could see, the crux of the proposal was a need to access the destination namespace at callsite, in order to DRY destination types that are already explicitly known anyways.

The streamlining of union-literals in the original proposal seems to be adjacent to the motivation of callsite-type access, they are only syntactically related by the fact that Zig uses the same symbol for namespaced declarations and field access, but conceptually they are really two separate proposals.

By making the inferred namespace-access functionality into a builtin instead of a change to the syntax, not only is the functionality achieved with significantly less syntactic complexity, it also decouples the two disparate motivations of the original proposal into separate changes that can be evaluated on their individual merit.

Usecase demonstration

1A

const DeloreanOptions = packed struct {
    enable_flux_capacitor: bool,
    target_speed_mph: u7,
    enable_remote_control: bool = false,

    pub const time_travel: DeloreanOptions = .{
        .enable_flux_capacitor = true,
        .target_speed_mph = 88,
    };

    pub const highway: DeloreanOptions = .{
        .enable_flux_capacitor = false,
        .target_speed_mph = 60,
    };
};

pub fn startDelorean(options: DeloreanOptions) void { ... }

test {
    // invoke declarations in the namespace of the known result type
    startDelorean(@Here().time_travel);

    // The originally proposed late-binding proposal was omitted from the accepted version
    //// const highway_literal = .highway;
    //// startDelorean(highway_literal);

    // explicit instantiation of the location type works as expected
    startDelorean(.{
        .enable_flux_capacitor = true,
        .target_speed_mph = 88,
        .enable_remote_control = true,
    })
}

2A

var array_1: std.ArrayList(u32) = @Here().init(allocator); // forward declaration
var array_2 = @as(std.ArrayList(u32), @Here().init(allocator)); // inferred by @as

Using @Here() without an explicit result type will produce an error:

// error: @Here must have a known result type
var array_3 = @Here().init(allocator);
//            ^~~~~~~~~~~~~~~~~~~~~~~
// note: use @as to provide explicit result type


// error: @Here cannot infer from anytype
const ipi = math.complex.log(@Here().init(-1, 0));
//                           ^~~~~~~~~~~~~~~~~~~
// note: use @as to provide explicit result type
@Vexu Vexu added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Jun 8, 2024
@Vexu Vexu added this to the 0.14.0 milestone Jun 8, 2024
@nektro
Copy link
Contributor

nektro commented Jun 8, 2024

seems like a duplicate of #16313

@expikr
Copy link
Contributor Author

expikr commented Jun 8, 2024

Wholly orthogonal. That one is for body access, this one is for callsite access.

The builtin proposed there would be more comparable to a @There() builtin as opposed to @Here() proposed here.

I’d suggest reading the discussion in #9938 for context.

@expikr expikr changed the title add @Here() builtin to make result type available for reference add @Here() builtin to make destination Type available for reference Jun 8, 2024
@expikr expikr changed the title add @Here() builtin to make destination Type available for reference add @Here() builtin for in-situ reference of known destination Type Jun 8, 2024
@mlugg
Copy link
Member

mlugg commented Jun 8, 2024

Hm - the thing I don't like about this is that @Here() isn't using its own result type (it doesn't have one!). It's a builtin that doesn't mean anything in isolation - it only works in specific syntactic contexts (@Here().foo, @Here().bar()). That's a distinction which I think is better modelled by a genuine syntax feature rather than shoehorning it into a builtin. Also, this leaves enum literals in a slightly awkward state, with yet another way to do the same initialization:

const a = MyEnum.foo;
const b: MyEnum = .foo;
const c: MyEnum = @Here().foo;

I don't think that's a huge deal, but it's worth pointing out.

@expikr
Copy link
Contributor Author

expikr commented Jun 8, 2024

Note that there is precedence to similar indeterminate-type builtins with those which require @as, e.g. @intFromEnum et al, that cannot form a complete expression per se and instead must capture its destination context. Likewise this builtin captures its destination constraint and presents it for availability at invocation.

I’m also somewhat inclined to restrict the builtin to only access declarations and not union/enum members (cognitively it makes sense to have this “exception” being localized to a builtin as opposed to exceptions in the syntax rules itself), but I wouldn’t make it a strict requirement of this proposal.

@mlugg
Copy link
Member

mlugg commented Jun 8, 2024

Likewise this builtin captures its destination constraint and presents it for availability at invocation.

No, this builtin is different. Builtins like @enumFromInt utilize the result type they are provided; other than that, they work as atomic expressions. I can write @enumFromInt(...) in any expression which is forwarded a result type. In contrast, @Here() isn't interested in its own result type, because it doesn't receive one. If you consider a general field access foo.bar, knowing the type we expect from the field access tells us nothing about what type foo must be, so we can't propagate type information here; just the same, in @Here().bar, we can't propagate any type information to @Here(). Instead, the compiler will have to pick up on the syntax form @Here().foo, and treat it specially.

@expikr
Copy link
Contributor Author

expikr commented Jun 8, 2024

Hmm, I see what you mean. Would you say this is a similar problem to @splat having difficulty inferring result type in a chained arithmetic expression, as you described here?

#17274 (comment)

@kanashimia
Copy link

Wholly orthogonal. That one is for body access, this one is for callsite access.

Seems similar to what I proposed in the #16313 (comment)

Although you only get access to the current immediate type with @Here(), so it is much less useful.

@expikr
Copy link
Contributor Author

expikr commented Jun 9, 2024

It just occurred to me, how does @This() infer its result? It also seems to be a special case syntax form that doesn't quite fit under the regular framework.

@mlugg
Copy link
Member

mlugg commented Jun 9, 2024

@This() is completely orthogonal to the result location mechanism; it just has a separate well-defined behavior which is to return the innermost enclosing namespace type (aka, the type of the current namespace). That isn't relevant here, since the proposed @Here() explicitly is to do with result types, it just uses the result type of a different expression.

@mlugg
Copy link
Member

mlugg commented Sep 2, 2024

Rejected in favour of #9938.

@mlugg mlugg closed this as not planned Won't fix, can't repro, duplicate, stale Sep 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

5 participants