I’m not totally sure, but it looks like you are coercing the u8 into a slice type, since you are using double quotes which is the string literal syntax. So what I’m thinking is, is that calling var num: u8 = "" is not really an error. However when you go to reassign that variable back into an integer by calling num = 1, then really you are misusing the previous assignment. I would use = undefined when initializing an empty variable, if you want to save it for later.
So basically my opinion is that the first line of your code is not really a semantic error. Though I’m not really sure why you would want to do type coercion here. So you might argue that trying to do type coercion when initializing an empty variable should generate a warning.
I think it’s safe to say this is de-emphasizing the validation policy outside of the main block. So my attitude would be to allows these kinds of unused declarations, almost like they are notes or comments. As long I was aware that when I decide to go and use them the first time that I will need to double-check everything first. This would be useful also because since they are not being used, then it’s reasonable to say you might go back and alter them before you need to use them anyway. So it wouldn’t do a lot of good to have typechecking here and it could even become a hindrance. Though I’m still curious if it would be practical to optionally output a warning here when passing specific compilation flags.
I would only add that it might have been better if there was already a clear explanation of what’s going on here. Instead of the OP having to learn their lesson from the compiler. So this might be a good topic for a getting started guide or the like.
I also don’t mind this behavior. FWIW, it’s similar to the “unused variable” error except that top-level declarations don’t seem to get the same treatment. I’m sure this is a contentious topic too, but I prefer not to get this error from top-level declarations, as this makes refactoring easier (f.ex., unused imports are not flagged as errors).
Keeping in line with the theme of the Explain category, I would wager that the primary reason for this behavior is performance (a.k.a. gotta go fast). There is a stated goal of the Zig compiler being as fast as possible, given that slow compile times have been the bane of languages like C++ and Rust. So if not evaluating anything that isn’t used or necessary (the branch body of a comptime if that evaluates to false is another example) makes you compile faster, that’s the route Zig will take. I’m not an authority on this but this is the explanation that pops up in my head when I first observed this behavior.
Not exactly a getting started guide, but the Language Reference has several examples of code not being evaluated at all given certain contexts. If you search the page for @compileError you’ll see most of them.