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

"Maybe" assignment failing on struct initilization #3956

Open
xzores opened this issue Jul 21, 2024 · 6 comments
Open

"Maybe" assignment failing on struct initilization #3956

xzores opened this issue Jul 21, 2024 · 6 comments

Comments

@xzores
Copy link
Contributor

xzores commented Jul 21, 2024

Context

This was talked about at: https://discord.com/channels/568138951836172421/568871298428698645/1264674940611858482

Observe the following code:

state = {
        active_elements = make(map[Element]Element_container),
        gui_pipeline = render.pipeline_make(render.get_default_shader(), .blend, false, false),
        default_style = {
            default = default_appearance,
            hover = default_appearance,
            active = default_appearance,
        },
    }
    
    fmt.printf("default_style : %#v\n", state.default_style);
    assert(state.default_style.hover != nil); //This assertion fails.

The assertion failes.
Now observe the following code:

    state = {
        active_elements = make(map[Element]Element_container),
        gui_pipeline = render.pipeline_make(render.get_default_shader(), .blend, false, false),
        default_style = {
            default = default_appearance,
            hover = default_appearance,
            active = default_appearance,
        },
    }
    
    fmt.printf("default_style : %#v\n", state.default_style);
    state.default_style.hover = default_appearance; //This makes the bug go away.
    assert(state.default_style.hover != nil); //This assertion no longer fails.

The assertion no longer failes.

Odin version:
Odin: dev-2024-07-nightly:b4ca044
OS: Windows 11 Home Basic (version: 23H2), build 22631.3880
CPU: 13th Gen Intel(R) Core(TM) i9-13900HX
RAM: 32507 MiB
Backend: LLVM 17.0.1

Expected Behavior

I would expect that the first assertion did not fail.

Current Behavior

The first assertions fails.

Failure Information (for bugs)

I think this is a bug with "Maybe", it seems to not get assigned.

Steps to Reproduce

I have not been able to reproduce this is a simple setup. See "things tested" for more info.
To find a example which failes go to: https://github.com/xzores/furbs/tree/Bug_found
Download and Run the project, it should fail.

things tested

I have tested the following which DID work as expected:

        Temp :: struct {
	        a : int,
	        b : Maybe(int),
        }

	t : Temp = {
		a = 5,
		b = 5,
	}
	
	assert(t.b == 5, "b was not 5");

I have also tried:

Temp3 :: struct {
	e : int,
}

Temp2 :: struct {
	c : int,
	d : Maybe(Temp3),
}

Temp :: struct {
	a : int,
	b : Maybe(Temp2),
}

	t : Temp = {
		a = 5,
		b = Temp2{
			5,
			Temp3{
				5,
			},
		},
	}
	
assert(t.b != nil, "failed");
	
	if t2, ok := t.b.?; ok {
		assert(t.b != nil, "failed2");
		
		if t3, ok := t2.d.?; ok {
			assert(t3.e == 5, "failed3");
		}
	}

I have also tried:

Temp4 :: struct {
	e : int,
}

Temp3 :: union {
	Temp4,
}

Temp2 :: struct {
	c : int,
	d : Maybe(Temp3),
}

Temp :: struct {
	a : int,
	b : Maybe(Temp2),
}

	t : Temp = {
		a = 5,
		b = Temp2{
			5,
			Temp4{
				5,
			},
		},
	}
	
	assert(t.b != nil, "failed");
	
	if t2, ok := t.b.?; ok {
		assert(t.b != nil, "failed2");
		
		if t3, ok := t2.d.?; ok {
		
			assert(t3.(Temp4).e == 5, "failed3");
		}
	}
	

ALL OF THIS PASSED, so I have been unable to replicate the bug in a simpler setup.

@laytan
Copy link
Sponsor Collaborator

laytan commented Jul 21, 2024

Can you give us some code that triggers the assert in your linked repo, like a main proc that calls the procedure that asserts in it?

@xzores
Copy link
Contributor Author

xzores commented Jul 21, 2024

You will find it in regui/GUI.odin and then in the init function.

@laytan
Copy link
Sponsor Collaborator

laytan commented Jul 21, 2024

Yes but just putting a main proc that imports and calls that doesn't work and fails with errors about a missing package ex_defs

@laytan
Copy link
Sponsor Collaborator

laytan commented Jul 22, 2024

Ok got it down to this repro:

package bug

Bar :: union {
	int,
}

Foo :: union {
	Bar,
}

FooBar :: struct {
	foo: Foo,
}

main :: proc() {
	foo := FooBar {
		foo = 69, // Make this `Bar(69)` and it fixes it.
	}
	assert(foo.foo != nil)
}

It has to do with this hack:

// HACK TODO(bill): THIS IS A MASSIVE HACK!!!!

Adding a panic at types.cpp:3005 confirms the issue: GB_PANIC("type %s is not a variant of the union %s!\n", type_to_string(v), type_to_string(u));

This hack evidently does not work with nested unions.

I ran out of time to think of a fix (would probably be some kind of recursive/looping solution to account for multiple levels) so I am leaving this info here.

@xzores
Copy link
Contributor Author

xzores commented Jul 22, 2024

Hmm, I don't experience this, as you can see in my project it seems to work fine for the double union (the "default" struct member), but it does not work for the Maybe and then double union (The "hover" and "active" struct memebers.)

Here is the struct for clarification:

Style :: struct {
	default : Appearance,            //Works
	hover : Maybe(Appearance), //Does not work
	active : Maybe(Appearance), //Does not work
}

Appearance :: union {
	Colored_appearance,
	Patched_appearance,
	Textured_appearance,
}

@laytan
Copy link
Sponsor Collaborator

laytan commented Jul 22, 2024

Don't experience what? Remember a Maybe is just a union under the hood. And this also only happens with compound literals with inferred types. I am 99% sure this is your bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants