Skip to content
Permalink
Browse files

Merge pull request #38273 from svick/breaking-change-formatting

Improved Markdown formatting of Breaking changes documents
  • Loading branch information...
JoeRobich committed Sep 9, 2019
2 parents e21cfc5 + b7c97eb commit b4c6fe0bea95772be7e48a2c943de700b78e78b1
@@ -104,7 +104,7 @@ This page tracks known cases where the Roslyn compiler intentionally deviates fr
- Breaking Change: CS0012 is now reported when referencing a member whose type or parameter types depend on ModOpt types declared in unreferenced assemblies (Bug 722567).
- Breaking Change: Anonymous type names appearing in metadata may differ from those generated by previous versions of the compilers (727118).
- Escaped identifiers in attribute target specifiers (which are not valid) now produce a new, more specific warning (Bug 2591).
- Breaking Change: CS1734 is now reported when a <paramref> tag in a documentation comment applied to a read only property refers to the 'value' parameter (Bug 738679).
- Breaking Change: CS1734 is now reported when a `<paramref>` tag in a documentation comment applied to a read only property refers to the 'value' parameter (Bug 738679).
- Breaking Change: CS0208 is now generated when the type of a 'ref' or 'out' parameter is or contains a pointer to a managed type (Bug 737715).
- Breaking Change: "long form" metadata signatures are no longer supported. CLI Part II 23.2.16. (Bug vstfdevdiv\DevDiv2\DevDiv 741391)
long-form: (ELEMENT_TYPE_CLASS, TypeRef-to-System.String )
@@ -146,49 +146,52 @@ This page tracks known cases where the Roslyn compiler intentionally deviates fr
### C# Spec deviation: Logical operator overload resolution
from DevDiv #656739:
from DevDiv #656739:
``` cs
using System;
class InputParameter
{
public static implicit operator bool(InputParameter inputParameter)
{
{
throw null;
}
}
public static implicit operator int(InputParameter inputParameter)
{
{
throw null;
}
}
}
class Program
{
static void Main(string[] args)
{
InputParameter i1 = new InputParameter();
InputParameter i2 = new InputParameter();
{
InputParameter i1 = new InputParameter();
InputParameter i2 = new InputParameter();
bool b = i1 || i2;
}
}
}
```
The C# spec, section 7.12, says "An operation of the form x && y or x || y is processed by applying overload resolution (§7.3.4) as if the operation was written x & y or x | y."
Prior to DevDiv #656739, Roslyn reported that || was ambiguous in the example above because | would be. Unfortunately, dev11 only treats || as | when considering user-defined operators (or when one of the operands is dynamic). That is, for built-in operators, it distinguishes between || and |. Since there is no || operator for ints, there is no ambiguity.
### C# Spec deviations: new expressions of enum types can have a constant value
Bug 9510: Error CS0182 (An attribute argument must be a constant expression) should not be issued for 'new' expressions of enum types
As per the specification, new expressions of enum types cannot have a constant value. However native compiler violates this for paramterless value type constructors and Roslyn maintains compatibility by constant folding paramterless value type constructors. This applies also to enum types.
### C# spec deviation: New Int32() treated as constant 0
```c#
// DELIBERATE SPEC VIOLATION:
// The spec does not allow "new int()" to be treated as a constant
// The native compiler treats "new int()" (and so on) as a "zero" constant expression,
// despite the fact that the specification does not include object creation expressions on the
// list of legal constant expressions.
```
// DELIBERATE SPEC VIOLATION:
// The spec does not allow "new int()" to be treated as a constant
// The native compiler treats "new int()" (and so on) as a "zero" constant expression,
// despite the fact that the specification does not include object creation expressions on the
// list of legal constant expressions.
```
### C# spec deviation: Parameterless Constructor
See bug 4424
@@ -204,7 +207,9 @@ class D : C
```
**ACTUAL RESULT**: error CS1729: 'C' does not contain a constructor that takes 0 arguments

**EXPECTED RESULT**: no errors (although the spec requires exactly parameterless ctor, Dev10 and previous versions always supported any ctors that can be invoked with an empty argument list)

### C# spec deviation: Parenthesized null

According to the spec, this is illegal:
@@ -216,57 +221,59 @@ Object o = (null);
Because the null conversion doesn't apply to parenthesized null expressions, only null literals.

Maybe similar issues with lambdas.

### C# spec deviation: ambiguous lookup in multiply-inherited interface

Looking at the spec, the enclosed program would appear to be an error because of the following part of 7.4 (member lookup):

· Finally, having removed hidden members, the result of the lookup is determined:
o If the set consists of a single member that is not a method, then this member is the result of the lookup.
o Otherwise, if the set contains only methods, then this group of methods is the result of the lookup.
o Otherwise, the lookup is ambiguous, and a binding-time error occurs.
 
> - Finally, having removed hidden members, the result of the lookup is determined:
> - If the set consists of a single member that is not a method, then this member is the result of the lookup.
> - Otherwise, if the set contains only methods, then this group of methods is the result of the lookup.
> - Otherwise, the lookup is ambiguous, and a binding-time error occurs.
However, the Dev10 compiler accepts the code and gives only a warning that there is an ambiguity and it is using the method group rather than the property.
 

Roslyn uses the property and ignores the method (thus giving a type error in this particular case).
 

Do you think we should make all three (spec, Dev10, and Roslyn) behave the same?

``` cs 
delegate void MyAction<T>(T x);
 
interface I1
{
    object Y { get; }
}
 
interface I2
{
    void Y(long l);
}
 
interface I3 : I1, I2 { }
 
public class Program : I3
{
    object I1.Y
    {
        get
        {
            return null;
        }
    }
 
    void I2.Y(long l) { }
 
    public static void Main(string[] args)
    {
        I3 p = new Program();
        MyAction<long> o = p.Y; // lookup is ambiguous?
        long l = 12;
        o(l);
    }
}
``` cs
delegate void MyAction<T>(T x);
interface I1
{
    object Y { get; }
}
interface I2
{
    void Y(long l);
}
interface I3 : I1, I2 { }
public class Program : I3
{
    object I1.Y
    {
        get
        {
            return null;
        }
    }
    void I2.Y(long l) { }
    public static void Main(string[] args)
    {
        I3 p = new Program();
        MyAction<long> o = p.Y; // lookup is ambiguous?
        long l = 12;
        o(l);
    }
}
```

### C# spec deviation: Dev10 will not report unreachable empty statements (C#)

Dev10 doesn't report the following unreachable statement, and so we don't either (see bug 3552):
@@ -284,92 +291,101 @@ class Program
```

More precisely, Dev10 will not report when an "empty" statement, a throw statement, or a block statement itself is unreachable. However, Dev10 will complain if an unreachable block contains some other kind of (unreachable) statement.

### C# spec deviation: Static class as an interface method's parameter (C#)

Dev10 allows a static class to be used as the type of an interface method parameter and an interface method return type. This is disallowed by the language spec (10.1.1.3.1) but permitted by the Dev10 compiler.

We follow suit in Roslyn so as not to break compatibility with (probably useless) existing programs.

### C# spec deviation: null??null and other null expressions

            // NOTE: We extend the specification here. The C# 3.0 spec does not describe
            // a "null type". Rather, it says that the null literal is typeless, and is
            // convertible to any reference or nullable type. However, the C# 2.0 and 3.0
            // implementations have a "null type" which some expressions other than the
            // null literal may have. (For example, (null??null), which is also an
            // extension to the specification.)
``` cs
// NOTE: We extend the specification here. The C# 3.0 spec does not describe
// a "null type". Rather, it says that the null literal is typeless, and is
// convertible to any reference or nullable type. However, the C# 2.0 and 3.0
// implementations have a "null type" which some expressions other than the
// null literal may have. (For example, (null??null), which is also an
// extension to the specification.)
```

### C# Spec Deviation: parenthesized lambda expression

Technically, in the specification a parenthesized lambda expression is not an anonymous function expression (and is therefore never legal). However, Dev10 and Roslyn both ignore the parens (except for precedence), accepting code such as the following:

``` cs
var tmp = (Func<int,int>)( x => x+1 );
```

### Method hiding and overload resolution

The C# language spec says that hidden methods are removed early in the overload resolution process.  However, that is false.  The enclosed program (which works in Dev11 and Roslyn) demonstrates that methods with the same signature are not hidden.

``` cs
using System;
 
class Base
{
    public void M(int x) { Console.WriteLine("Base.M(x:" + x + ")"); }
}
 
class Derived : Base
{
    public new void M(int y) { Console.WriteLine("Derived.M(y:" + y + ")"); }
}
 
public class Test
{
    public static void Main()
    {
        Derived d = new Derived();
        d.M(x: 1);
        d.M(y: 2);
    }
}
using System;
class Base
{
    public void M(int x) { Console.WriteLine("Base.M(x:" + x + ")"); }
}
class Derived : Base
{
    public new void M(int y) { Console.WriteLine("Derived.M(y:" + y + ")"); }
}
public class Test
{
    public static void Main()
    {
        Derived d = new Derived();
        d.M(x: 1);
        d.M(y: 2);
    }
}
```

Clearly this behavior does not agree with the specification, and has been in the product long enough that it probably makes more sense to adjust the specification.
 

This is related to Roslyn bug 12989.

### Reserved Members

The native compiler (improperly) extended the C# language concept of reserved members to type parameters. For example, the following code is rejected by the native compiler:

``` cs
        public abstract class Foo<Item>
        {
            public Item this[int arg] { get { return default(Item); } }
        }
 
Error: The type 'Foo<Item>' already contains a definition for 'Item' 
public abstract class Foo<Item>
{
    public Item this[int arg] { get { return default(Item); } }
}
```

> Error: The type 'Foo\<Item>' already contains a definition for 'Item'
Roslyn does not reject this code.

### Compiling primitive types

The source for the special type Int32 is a struct that contains a member of its own type. That is not allowed by the C# language specification, yet the compiler must allow it and properly compile that source to produce metadata for that primitive type.

Same for other primitive types.

### Right operand of ?? operator is not required to be definitely assigned if left operand is non-null constant

The following test case should “pass” to match Dev10 behavior:

``` cs
using System;
static class Program
{
    static void Main()
    {
        const string x = "pass";
        string y;
        string z = x ?? y;
        Console.WriteLine(z);
    }
}
using System;
static class Program
{
    static void Main()
    {
        const string x = "pass";
        string y;
        string z = x ?? y;
        Console.WriteLine(z);
    }
}
```

However, this is not justified by the current language specification.  Since Dev10 accepts this code, I recommend we modify the specification to allow this.
@@ -381,4 +397,3 @@ Roslyn does not ignore method overloads that reference symbols from assemblies t
### Roslyn sometimes requires the use of the index operator when accessing a VB indexed property

While the Roslyn C# compiler permits the elision of the index operator of an indexed property (declared, for example, in VB) when the property can be invoked with no parameters (e.g., it has a parameter with a default value), the C# compiler will not permit a (second) indexing of the result unless the first index operation was explicit. This is a breaking change from C# 5, which permitted the elision of the indexer that had default parameters. See [#17045](https://github.com/dotnet/roslyn/issues/17045).

@@ -1,4 +1,4 @@
**This document lists known breaking changes in Roslyn 2.0 (VS2017) from Roslyn 1.* (VS2015) and native C# compiler (VS2013 and previous).**
**This document lists known breaking changes in Roslyn 2.0 (VS2017) from Roslyn 1.\* (VS2015) and native C# compiler (VS2013 and previous).**

*Breaks are formatted with a monotonically increasing numbered list to allow them to referenced via shorthand (i.e., "known break #1").
Each entry should include a short description of the break, followed by either a link to the issue describing the full details of the break or the full details of the break inline.*

0 comments on commit b4c6fe0

Please sign in to comment.
You can’t perform that action at this time.