v
v copied to clipboard
cgen: option values with or-blocks seem to be broken!
Describe the bug
Optional type (e.g., ?string) with an or-block should evaluate to the underlying type (e.g., string).
It seems sometime recently the " or {other_value} " bit stoped working altogether and sometimes causes a C compiler error.
Expected Behavior
Option values with an or-block should work as expected.
Current Behavior
Currently, can:
- resolve to nothing (i.e., the "or {other_value}" is simply ignored), or
- generate a C errors where the types are too dissimilar.
Reproduction Steps
struct Foo {
mut:
x string
y ?string
}
fn main() {
a := ?string(none)
mut foo := Foo{}
foo.x = a or {"test"} // WRONG: sets foo.x to empty string when a==none
foo.y = a or {"test"} // C ERROR (see below)
}
Generated C code (comments by me):
VV_LOCAL_SYMBOL void main__main(void) {
_option_string a = (_option_string){ .state=2, .err=_const_none__, .data={EMPTY_STRUCT_INITIALIZATION} };
_option_string _t1 = (_option_string){ .state=2, .err=_const_none__, .data={EMPTY_STRUCT_INITIALIZATION} };
main__Foo foo = ((main__Foo){.x = (string){.str=(byteptr)"", .is_lit=1},.y = _t1,});
foo.x = /*opt*/(*(string*)a.data); // WHERE HAS 'or {"test"}' GONE????
_option_string _t2;
_option_ok(&(string[]) { a }, (_option*)(&_t2), sizeof(string)); // C ERROR (see below)
foo.y = _t2;
}
The C error is as follows:
error: initializing 'u8 *' (aka 'unsigned char *') with an expression of incompatible type '_option_string' (aka 'struct _option_string')
_option_ok(&(string[]) { a }, (_option*)(&_t2), sizeof(string));
^
1 warning and 1 error generated.
Possible Solution
No response
Additional Information/Context
No response
V version
V 0.3.3 2597efa
Environment details (OS name and version, etc.)
MacOs
Seems the code to handle the or-blocks broke in https://github.com/vlang/v/commit/6944d542577d0cd6b4f95abf5abd6da49a9473d5.
Before this commit:
if (a.state != 0) {
IError err = a.err;
*(string*) a.data = _SLIT("test");
}
foo.x = /*opt*/(*(string*)a.data);
;
if (a.state != 0) {
IError err = a.err;
*(string*) a.data = _SLIT("test");
}
_option_string _t2;
_option_ok(&(string[]) { a }, (_option*)(&_t2), sizeof(string));
foo.y = _t2;
And after:
foo.x = /*opt*/(*(string*)a.data);
_option_string _t2;
_option_ok(&(string[]) { a }, (_option*)(&_t2), sizeof(string));
foo.y = _t2;
@yuyi98 🙂