Skip to content

@couldCoerce - check if a type will coerce to another #3641

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

Closed
travisstaloch opened this issue Nov 10, 2019 · 2 comments
Closed

@couldCoerce - check if a type will coerce to another #3641

travisstaloch opened this issue Nov 10, 2019 · 2 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@travisstaloch
Copy link
Contributor

travisstaloch commented Nov 10, 2019

Sometimes its safe to assign a variable to a similar type when the types don't exactly match. Such is the case with []const u8 and [3]u8. Checking if the types match fails, but it IS safe to assign a []const u8 variable to a value of type [3]u8. I would like to be able to test if [3]u8 can be coerced into a []const u8.

I ran into this issue trying to instantiate a tagged union from a runtime known tag, I check the union field type against val: var on line 82 of the linked gist. It would have been safe to assign the value, but because the types don't match control flow proceeds into the 'else unreachable' branch.

A @couldCoerce method would eliminate the need for possibly complex type comparisons necessary to determine wether it is safe to perform this assignment.

//            if (unionField.field_type == @typeOf(val)) {
            if (@couldCoerce(unionField.field_type, @typeOf(val))) {
                return @unionInit(Tagged, unionField.name, val);
...

Here is a condensed version of the gist:

const std = @import("std");

const Tag = {A, B,  C };
const Tagged = union(Tag) {
    A: bool,
    B: i32,
    C: []const u8,
};

pub fn main() anyerror!void {
    var tagged = Tagged{ .A = true };
    var tag = @as(Tag, tagged);
    tag = .C;

    tagged = try initTagged3(tag, "foo");
}

fn initTagged3(tag: Tag, val: var) !Tagged {
    const uT = @typeInfo(Tagged).Union;
    inline for (uT.fields) |unionField| {
        if (@intToEnum(Tag, unionField.enum_field.?.value) == tag) {
            if (unionField.field_type == @typeOf(val)) {
            // **********************************
            // Proposed change
            // if (@couldCoerce(unionField.field_type, @typeOf(val))) {
            // **********************************
                return @unionInit(Tagged, unionField.name, val);
            } else {
                unreachable;
            }
        }
    }
    return error.Invalid;
}
@daurnimator daurnimator added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Nov 10, 2019
@andrewrk andrewrk added this to the 0.7.0 milestone Nov 14, 2019
@andrewrk andrewrk modified the milestones: 0.7.0, 0.8.0 Oct 27, 2020
@andrewrk andrewrk modified the milestones: 0.8.0, 0.9.0 May 19, 2021
@andrewrk andrewrk modified the milestones: 0.9.0, 0.10.0 Nov 23, 2021
@billzez
Copy link
Contributor

billzez commented Jan 13, 2023

I would also find this useful. Can this be reopened?

@maxzhao
Copy link
Contributor

maxzhao commented Jan 13, 2023

please reopen, it's very useful for some case

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