Is this a "WASM" problem or is a "hey we decided to ship all of C# to the browser" problem?
I think this is a fine tradeoff for certain contexts and usages, but I don't think the general usecase for WASM is to build general web applications in C# and ship all of the CLR for things like gmail.
There's some inherent overhead in a .NET runtime which will be hard to get rid of, like the garbage collector. In the end it probably comes down to .NET being "too dynamic", making it hard to identify and eliminate dead code. Also typical high-level C# code tends to use a lot of 'standard library' features, basically the opposite of the 'embedded coding mindset' needed for small WASM apps.
If anything, the BCL or common libraries are too "static", where some pieces of code reference statically all features available.
One great example is JSON.NET: That library has basically one big method that type-checks all possible inputs, making unconditionally reachable every dependency for all features of the library. In this case, JSON.NET pulls the XML reader, DataSets, and many huge libraries that are generally not needed. In Uno, we generally don't AOT those libraries and use the interpreter for that (otherwise the payload would explode).
Such libraries need to be changed to be configurable, and dynamically enable dependencies as per the user's needs.
Conversely, many pieces of code are excluded by configuration because of reflection uses, but the .NET team is improving that scenario (https://devblogs.microsoft.com/dotnet/performance-improvemen...) with attributes to tag dependencies and hint the linker.
A similar problem exists in the C/C++ world: designing a library in a way that supports good dead-code-elimination isn't something that many library authors think about.
Interestingly plain C libraries often do this better than C++ libraries (e.g. too generous use of virtual-method-interfaces in C++ libraries, or making heavy use of C++ stdlib containers when simple C-style arrays would do as well).
The Unity engine also suffered from a similar problem: If you used a simple physics feature like a stabbing collision check somewhere in your code, the entire physics module was pulled in, even though the code needed for stabbing checks is only a few percent of that physics module.
This is why I'm a bit sceptical that improvements in the .NET "machinery" alone can solve this problem. You also need to restrict language features and select the right dependencies. This is a general problem, not just web-specific, it's just that reducing the output binary size typically isn't a high-priority problem outside the web.
Yeah, as you point out C++ libraries are especially hard to do DCE on. If you want to ship ICU in the browser right now it is a very big blob that it's hard to perform DCE on because the vtables retain lots of unused code and every API depends on every other API. A lot of this stuff was designed in an era before anyone could have anticipated the size constraints that would apply in 2020.
I think this is a fine tradeoff for certain contexts and usages, but I don't think the general usecase for WASM is to build general web applications in C# and ship all of the CLR for things like gmail.