Hey, can I have a little walkthrough as to how the any construct works?

I appreciate that this is a fairly long code sample, but it's just a stretching of the legs of `any`. I was trying to use multiple examples to understand what the concept is but I am totally not seeing it at all. I can understand that I might be clobbering things by falling off the stack but I tried allocating in various ways and couldn't come up with a consistent rule set of what an any can hold so I would appreciate a little walkthrough here.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import "core:fmt.odin"
import "core:strings.odin"

Things :: struct
{
	string_literal, string_on_the_heap, number_literal, number_pointer, nil_value, true_value: any
}

make_things :: proc() -> Things
{
	four := new (int);
	four^ = 4;

	return Things
	{
		string_literal = "splat!",
		string_on_the_heap = strings.new_string("splat!"),
		number_literal = 4,
		number_pointer = four^,
		nil_value = nil,
		true_value = true
	};
}

make_map :: proc() -> map[string]any
{
	four := new (int);
	four^ = 4;

	result := map[string]any {};
	result["string literal"] = "splat!";
	result["string on the heap"] = strings.new_string("splat!");
	result["number literal"] = 4;
	result["number pointer"] = four^;
	result["nil"] = nil;
	result["true"] = true;
	return result;
}

make_any_1 :: proc() -> any { return 4; }
make_any_2 :: proc() -> any { return true; }
make_any_3 :: proc() -> any { return "splat!"; }

main :: proc()
{
	t := make_things();
	fmt.println("string literal =", t.string_literal.(string));
	fmt.println("string on the heap =", t.string_on_the_heap.(string));
	fmt.println("number literal =", t.number_literal.(int));
	fmt.println("number on the heap =", t.number_pointer.(int));
	fmt.println("nil value =", t.nil_value);
	fmt.println("true value =", t.true_value.(bool));
	// Output:
	//     string literal = splat!
	//     string on the heap =
	//     number literal = 0
	//     number on the heap = 4
	//     nil value = <nil>
	//     true value = false

	fmt.println();

	fmt.println(make_map());
	// Output:
	//     map[string literal=, string on the heap=, number literal=0, number pointer=4, nil=<nil>, true=false]

	fmt.println();

	fmt.println(make_any_1());           // 588412483136
	fmt.println(make_any_1().(int));     // 4
	fmt.println(make_any_2());           // false
	fmt.println(make_any_2().(bool));    // true
	fmt.println(make_any_3());           // <program crashes>
	fmt.println(make_any_3().(string));  // splat!
}
Oh, I just ran across issue #79 where you recommend using new_clone to keep the contents out of the stack. Which is very useful, however I am still confused as to why

(1) Why in the bottom paragraph it knew that make_any_1 returned an integer but couldn't tell which one unless I added the type check .(int)

(2) Why didn't strings.new_string() work inside make_map()?