It sure seems like the compiler has enough info to know that the attempted assignment is invalid, since the return type of the
Func<>
is not dynamic.
Caveat: Of course I no longer speak for the C# design team; these are my opinions on language design.
So what you're saying here is "I've disabled a safety system. Why isn't the disabled safety system detecting when I do something dangerous and stopping me?" Well, if that's what you wanted then maybe you shouldn't have disabled that safety system in the first place.
That said, you are correct; the "disabled" type safety system could actually continue to work here and detect that you're doing something dangerous. In fact there are many situations where a sufficiently clever compiler could make a type deduction about a dynamic subexpression. You've found one of them. Implementing the necessary analysis is a feature request.
So now the relevant question is: which feature of C# would you like to cut in order to give the development team the budget to design, spec, implement, test, debug, ship and maintain forever a feature which statically finds a bug in a program where the developer is explicitly asking for static checking to be turned off? Keep in mind that the cost includes ensuring that no future feature of the language ever interferes with the compiler's ability to make this deduction; some of those costs are taxes that are paid by the design team in the future.
There are a small number of scenarios where an expression containing dynamic
is statically analyzed; for example, there are some overload resolution problems involving static methods with dynamic arguments where the compiler can and does figure out that no matter what is provided at runtime, overload resolution is going to fail. But aside from those few cases, the language design team has historically judged that it's simply not good bang for buck to spend its limited budget on scenarios like the one you've identified.