Type inference problem when overloading and using a bit_set that has default param

I’m not sure it if this is a problem with my approach, expected behavior, or bug. Could anyone clarify?

Goal:
A set of procedures that expect one type, or another type, or both, and have a bit_set with an optional default param. The bit_set is so I can just provide a compound literal for the bit_set without having to also provide a type or predefined variable. Also want the bit_set to be optional and not require an empty compound literal when I don’t want to use the bit_set (for usage/syntactic sugar reasons, save space, etc). If I try to overload the 3 possible procedures and give the bit_set a default, the compiler now expects a type when calling the procedure, which is not the same behavior with other types. From my perspective the types and/or overloaded procedures are not ambiguous, but maybe there’s something in the internals of Odin I’m not aware of.

Note: I did also try setting the default param to {.NONE}, which acts the same way. To make sure there was not an ambiguous collision with the bit_set being seen as an int, i backed it with u8. Also, I’m cloning /compiling Odin and OLS from nightly to have the latest.

My_Flags :: enum u8 {
	NONE,
	ONE,
	TWO,
}
My_Bit_SET :: distinct bit_set[My_Flags; u8]

my_proc_test1 :: proc {my_proc_1, my_proc_2, my_proc_3}

my_proc_1 :: proc(i: i32, mbs: My_Bit_SET = {}) {}
my_proc_2 :: proc(f: f32, mbs: My_Bit_SET = {}) {}
my_proc_3 :: proc(i: i32, f: f32, mbs: My_Bit_SET = {}) {}
my_proc_test1(1, {})		// does not work with default param
my_proc_test1(1, {.NONE})	// does not work with default param
my_proc_test1(1)			// works with default param

my_proc_test1(1.0, {})		// does not work with default param
my_proc_test1(1.0, {.NONE}) // does not work with default param
my_proc_test1(1.0)			// works with default param

my_proc_test1(1, 1.0, {})		// works with default param
my_proc_test1(1, 1.0, {.NONE})	// works with default param
my_proc_test1(1, 1.0)			// works with default param

I also did the following test, which works completely as expected:

my_proc_test2 :: proc {my_proc_4,my_proc_5,my_proc_6}
my_proc_4 :: proc(i: i32, u: u8 = 0) {}
my_proc_5 :: proc(f: f32, u: u8 = 0) {}
my_proc_6 :: proc(i: i32, f: f32, u: u8 = 0) {}
my_proc_test2(1, 0) //works
my_proc_test2(1 )   //works

my_proc_test2(1.0, 0) //works
my_proc_test2(1.0)    //works

my_proc_test2(1, 1.0, 0) //works
my_proc_test2(1, 1.0)    //works

Because {} is a valid scalar initialiser.

i: int = {}
fmt.println(i) // prints 0

The compiler cannot figure out if the compound literal is supposed to be a bitset or an f32. Either annotate the literal like My_Bit_Set{ .NONE }or call the proc with mbs = {.NONE}.

But yeah… The error message isn’t very helpful, and it might misses a check for empty compound literal, like in case of a simple assignment:

i: int = {1}
// Error: Illegal compound literal, int cannot be used as a compound literal with fields

Could you open an issue?

Thanks for the feedback.

Agreed the { } part was not good form. I included it to highlight that I tried every possibility.

Yes, I’ll open an issue. To make sure I’m correctly targeting the problem, I’ve reduced this to the part that matters. Below, .ONE and .TWO are clearly defined by My_Flags as u8, and should not be ambiguous to the compiler, correct?

My_Flags :: enum u8 {
	NONE,
	ONE,
	TWO,
}
My_Bit_SET :: distinct bit_set[My_Flags; u8]

my_proc_test :: proc {my_proc_1, my_proc_2, my_proc_3}

my_proc_1 :: proc(i: i32, mbs: My_Bit_SET = {.NONE}) {}
my_proc_2 :: proc(f: f32, mbs: My_Bit_SET = {.NONE}) {}
my_proc_3 :: proc(i: i32, f: f32, mbs: My_Bit_SET = {.NONE}) {}

// engine
main :: proc() {
	my_proc_test(1, {.ONE}) // does not work with default param
	my_proc_test(1)         //works with default param

	my_proc_test(1.0, {.TWO}) // does not work with default param
	my_proc_test(1.0)         //works with default param

	my_proc_test(1, 1.0, {.NONE}) //works with default param
	my_proc_test(1, 1.0)          //works with default param
}

This could be made to work with adding a type in front of .ONE or .TWO in the procedure call, but with Odin’s claim to type inference, its requirement is unexpected.