int myvar, I;
foo(out int mvar); // oops, not myvar; maybe caused by a refactor?
bar(out *); // oops, not I; was up too late coding
I don't really see your example in that way. Let's start with the latter one first:
> bar(out *); // oops, not I; was up too late coding
I'm not sure how this situation is any differnet from any other case where you need to pass some variable, and you pass the incorrect name. This is already possible all over the language. For example, you might have written "bar(out J)" when you meant "bar(out I)". As usual, the recommendations here are to use strong types and good names to help keep your code clear in intent and to allow the compiler to tell you when something seems awry.
Now let's look at your first example:
> foo(out int mvar);
This version immmediately screams at me that something is happening that requires my attention. First off, just the presence of 'out' is an immediate call that this is not a normal call. Nearly all calls pass by value, so out/ref stick out like a sore thumb (esp. in an IDE that classifies them accordingly). Second, the "out int" is another large indicator that this is doing stuff very special.
Finally, i'd point out that the mispelled name problem is really no different than what you might experience today with code like:
// much later and indented a bit ...
Foo (out mvar);
> it's this sort of bug that arises often in languages that allow implicit declaration of variants.
No implicit declarations are allowed. All declarations are explicit. We just don't force you to have to declare in one location and use in another. This is a pattern that many people hate, and which goes against a desire to immediately declare and initialize, and thus not have to track down how a variable is written to.
It's a wildcard. Passing in any other variable name would ideally raise an error about the use of an undeclared variable or a mismatched type. The use of a wildcard disposes of those errors.
> the mispelled name problem is really no different than what you might experience today
Not quite; your modified examples includes two declarations on their own lines. Being on their own line gives them greater visual presence at-a-glance than the new syntax which buries the declarations within a parameter list.
Worth noting is that my trivial example managed to confuse at least one reader who was unable to see the issue.
> All declarations are explicit.
While true, you've muddied the lines a little by moving declarations into the syntax of other expressions. Where previously a declaration sat on its own line or at the beginning of an assignment, they may now be peppered throughout the syntax in ways that are not so easy to observe at-a-glance.
I'm not happy about wild cards. It seems like taking what is a very powerful character in software development and using it for a pretty minor usability improvement. Besides it seems misleading. When I see an asterisk I don't think throwaway. I can see how that aligns with "anything can go here" meaning from regex, but I feel there is a difference in "value". Using a * in a regex seems to increase the power and heft of the regex, where as using it here, seems to decrease the value, which is almost the opposite effect. Another way of putting it is that the point should be to let me ignore this while reading code, but the asterisk draws my attention to it instead.
Compare this to the Haskell convention of using an _ for throwaway items, which disappears just enough, instead of attracting attention. And by simply being a convention, it isn't giving the character too much power.
Not sure if lack of Haskell style type inference prevents C# from using convention for throwaways instead of wildcard chars, but I think it would be much less overhead on the Dev.
You'll get a compiler error if you try and use `I` uninitialized.
Not saying you're wrong, just having trouble getting worried about this. You can make typos now:
int x, y;
foo(out x, out x); // oops, not y; was up too late coding
Sure, you can make typos now, but these changes expand the possibilities of errors arising from typos or incomplete refactoring; while reducing the discoverability of the issue at-a-glance.
This should fail to compile, it's the equivalent of declaring a variable twice int the same scope.