Roslyn failed to compile code

前端 未结 4 2090
臣服心动
臣服心动 2021-01-30 07:46

After I have migrated my project from VS2013 to VS2015 the project no longer builds. A compilation error occurs in the following LINQ statement:

static void Mai         


        
4条回答
  •  终归单人心
    2021-01-30 08:27

    Since I got schooled so hard in the bug report, I'm going to try to explain this myself.


    Imagine T is some user-defined type with an implicit cast to bool that alternates between false and true, starting with false. As far as the compiler knows, the dynamic first argument to the first && might evaluate to that type, so it has to be pessimistic.

    If, then, it let the code compile, this could happen:

    • When the dynamic binder evaluates the first &&, it does the following:
      • Evaluate the first argument
      • It's a T - implicitly cast it to bool.
      • Oh, it's false, so we don't need to evaluate the second argument.
      • Make the result of the && evaluate as the first argument. (No, not false, for some reason.)
    • When the dynamic binder evaluates the second &&, it does the following:
      • Evaluate the first argument.
      • It's a T - implicitly cast it to bool.
      • Oh, it's true, so evaluate the second argument.
      • ... Oh crap, b isn't assigned.

    In spec terms, in short, there are special "definite assignment" rules that let us say not only whether a variable is "definitely assigned" or "not definitely assigned", but also if it is "definitely assigned after false statement" or "definitely assigned after true statement".

    These exist so that when dealing with && and || (and ! and ?? and ?:) the compiler can examine whether variables may be assigned in particular branches of a complex boolean expression.

    However, these only work while the expressions' types remain boolean. When part of the expression is dynamic (or a non-boolean static type) we can no longer reliably say that the expression is true or false - the next time we cast it to bool to decide which branch to take, it may have changed its mind.


    Update: this has now been resolved and documented:

    The definite assignment rules implemented by previous compilers for dynamic expressions allowed some cases of code that could result in variables being read that are not definitely assigned. See https://github.com/dotnet/roslyn/issues/4509 for one report of this.

    ...

    Because of this possibility the compiler must not allow this program to be compiled if val has no initial value. Previous versions of the compiler (prior to VS2015) allowed this program to compile even if val has no initial value. Roslyn now diagnoses this attempt to read a possibly uninitialized variable.

提交回复
热议问题