v icon indicating copy to clipboard operation
v copied to clipboard

cgen: option values with or-blocks seem to be broken!

Open edam opened this issue 2 years ago • 2 comments

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

edam avatar Mar 07 '23 22:03 edam

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;

edam avatar Mar 07 '23 23:03 edam

@yuyi98 🙂

edam avatar Mar 07 '23 23:03 edam