dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
19.02k stars 4.03k forks source link

Encompassing Implicit Conversions misaligned with the C# specification #37134

Open gafter opened 5 years ago

gafter commented 5 years ago

According to the C# language specification, an encompassing implicit conversion is something that may exist from one type to another type. However, in the Roslyn compiler it is defined based on conversions from expression. This is a misalignment with the specification. Either one or the other is confused and should be corrected.

gafter commented 5 years ago

See also the following comment:

        private Conversion ClassifyStandardImplicitConversion(BoundExpression sourceExpression, TypeSymbol source, TypeSymbol destination, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            Debug.Assert(sourceExpression != null || (object)source != null);
            Debug.Assert(sourceExpression == null || (object)sourceExpression.Type == (object)source);
            Debug.Assert((object)destination != null);

            // SPEC: The following implicit conversions are classified as standard implicit conversions:
            // SPEC: Identity conversions
            // SPEC: Implicit numeric conversions
            // SPEC: Implicit nullable conversions
            // SPEC: Implicit reference conversions
            // SPEC: Boxing conversions
            // SPEC: Implicit constant expression conversions
            // SPEC: Implicit conversions involving type parameters
            //
            // and in unsafe code:
            //
            // SPEC: From any pointer type to void*
            //
            // SPEC ERROR: 
            // The specification does not say to take into account the conversion from
            // the *expression*, only its *type*. But the expression may not have a type
            // (because it is null, a method group, or a lambda), or the expression might
            // be convertible to the destination type via a constant numeric conversion.
            // For example, the native compiler allows "C c = 1;" to work if C is a class which
            // has an implicit conversion from byte to C, despite the fact that there is
            // obviously no standard implicit conversion from *int* to *byte*. 
            // Similarly, if a struct S has an implicit conversion from string to S, then
            // "S s = null;" should be allowed. 
            // 
            // We extend the definition of standard implicit conversions to include
            // all of the implicit conversions that are allowed based on an expression,
            // with the exception of the switch expression conversion.
gafter commented 5 years ago

It is possible (perhaps likely) that the ECMA specification should be adjusted.