I was trying to mock an interface which takes a DateTimeOffset? as one of its parameters. All of a sudden, Visual Studio started reporting an 'Internal Compiler Error' and that it has 'stopped working'. After a lot of trials, I started removing files one by one, and then code line by line. This reduced to the below code, which reproduces this error:
public class testClass
{
public interface ITest
{
void Test(DateTimeOffset? date);
}
public void test2()
{
var mock = new Mock<ITest>();
mock.Setup(x => x.Test(new DateTime(2012, 1, 1)));
}
}
The issue seems to be the line :
mock.Setup(x => x.Test(new DateTime(2012, 1, 1)));
If I comment it, the compiler works fine. Also, the issues is that I am setting up a new DateTime(), which fits in a DateTimeOffset.
Is this a bug in Moq, or VS2012? Anyone ever got this error before?
UPDATE
The following code sample also results in a compile error, both with the regular Visual Studio 2012 compiler and with Roslyn CTP September 2012:
using System;
using System.Linq.Expressions;
public interface ITest
{
void Test(DateTimeOffset? date);
}
public class TestClass
{
Expression<Action<ITest>> t = x => x.Test(new DateTime(2012, 1, 1));
}
The error:
1>CSC : error CS0583: Internal Compiler Error (0xc0000005 at address
00D77AFB): likely culprit is 'BIND'.
This code has nothing to do with Moq.
It is clearly a bug in the semantic analyzer. (The text "likely culprit is BIND" is characteristic of bugs in the semantic analyzer, which is called the "binder" internally.) The scenario here is that we have a lifted-to-nullable user-defined conversion in a lambda that is being converted to an expression tree. That code was a bug farm. I thought I wrote a test case for this exact scenario, but maybe I didn't.
In any event, the problem is likely my bad, so sorry about that. Not much I can do about it now though.
What is truly bizarre though is that the bug allegedly repros on both Roslyn and the C# 5 compiler. That is a crazy coincidence, because the Roslyn and C# 5 compilers have completely different code for this part of the semantic analysis. We rewrote most of it from scratch. Strange that we'd get it wrong in the same way twice.
Anyway, Kevin will see this since you tagged it Roslyn, and if you want to enter a bug on the Connect site, that would be appreciated by the team I'm sure.
UPDATE:
Wait, you got the exact same error in Roslyn? Then what is happening is probably that the IDE is still using the C# 5 analysis library. If you write code that loads the offending code into a Roslyn compilation and analyzes it, you likely will not get the error. Right?
This is impressive, crashing the C# compiler like this is a very rare feat. You can report it at connect.microsoft.com, albeit that Microsoft ought to have received a bunch of WER reports from it. Several from me anyway :)
You can work around the problem by rewriting the code. Either with:
static DateTimeOffset? arg = new DateTime(2012, 1, 1);
Expression<Action<ITest>> t = x => x.Test(arg);
Or with the cleaner:
public class TestClass
{
Expression<Action<ITest>> t;
public TestClass() {
DateTimeOffset? arg = new DateTime(2012, 1, 1);
t = x => x.Test(arg);
}
}
Related
We recently found an issue in our code base, where VS2019 Compiled code fine but VS 2017 Failed.
I've created an extension method for Union which has a generic ISet as a Generic Constraint
using System;
using System.Collections.Generic;
using System.Linq;
public static class Extensions
{
public static S Union<S, T>(this S self, IEnumerable<T> other) where S : ISet<T>, new()
{
//For simplicity issues since this is a compilation based question
return default(S);
}
public static void Test()
{
var values = new[] { 1, 2, 3 };
var values1 = new[] { 1, 2, 3, 4 };
values.Union(values1);
}
}
Union generates a compilation error stating that the int[] is not convertible to ISet.
It was my understanding that method resolution originally ignored Generic constraints. But it seems that this code Compiles in 2019.
I haven't seen anywhere in the release notes which states that they've resolved this bug or added a new feature to improve method resolution for generic methods.
I'm looking for more information about this matter,
Was this a bug fix by microsoft or an intended feature?
It's part of C# 7.3 (so you can use it in VS 2017 as well if you specify version 7.3). It's documented in the C# 7.3 release notes:
Improved overload candidates
In every release, the overload resolution rules get updated to address situations where ambiguous method invocations have an "obvious" choice. This release adds three new rules to help the compiler pick the obvious choice:
...
When a method group contains some generic methods whose type arguments do not satisfy their constraints, these members are removed from the candidate set.
...
This wasn't a bug before - it was obeying the language specification; I don't know why the specification was originally written the way it was here. Possible reasons include:
Expected implementation complexity
Expected implementation performance
Expected usefulness - anticipation that the previous behavior would be fine or even preferable to the current behavior, without realizing where it would be annoying in reality
Have a look at the following that demonstrates my issue with Visual Studio 2017 compiler
public interface IFoo
{
string Key { get; set; }
}
public class Foo : IFoo
{
public string Key { get; set; }
}
class Program
{
static void Main(string[] args)
{
PrintFoo(new Foo() { Key = "Hello World" });
Console.ReadLine();
}
private static void PrintFoo<T>(T foo) where T : IFoo
{
//set breakpoint here and try to look at foo.Key
Console.WriteLine(foo.Key);
}
}
When I make a breakpoint inside the PrintFoo method and want to look at the Key property of foo Visual Studio wont provide a tooltip for me.
By adding the foo.Key to the watch window I receive the following error:
error CS1061: 'T' does not contain a definition for 'Key' and no
extension method 'Key' accepting a first argument of type 'T' could be
found (are you missing a using directive or an assembly reference?)
When I change the generic declaration to Foo instead of IFoo the compiler can acces the 'Key' property, so this:
private static void PrintFoo<T>(T foo) where T : Foo
{
//set breakpoint here and try to look at foo.Key
Console.WriteLine(foo.Key);
}
Is there a way to make it work?
Edit:
Both, looking at the local window and mouse over foo to get the tooltip and than expanding the properties works.
Adding foo.Key to the watch window or writing ?foo.Key into immediate window brings the mentioned error, and you wont get a tooltip when you mouse over Key of foo.Key
Tested with Visual Studio 2015, 2017.
There are two workarounds for this issue. Use Tools > Options > Debugging > General. You can tick "Use Managed Compatibility Mode" or "Use the legacy C# and VB.NET expression evaluators".
"Use Managed Compatibility Mode" is unnecessarily cryptic, what it actually does is replace the new debugging engine with the one that was last used in VS2010. The good one. It in effect also gives you the legacy expression evaluator. I recommend you use this one since it also avoids a bunch of other bugs in the new debugging engine. Which got especially buggy in VS2015.
Very few reasons I ever discovered to turn it back off. You miss out on recently added debugger features, I only know of method return value inspection, edit+continue for 64-bit code and the new portable PDB format that is used in .NETCore on non-Windows systems. It must be used to debug C++/CLI code. I don't know what is better about the new expression evaluator, never noticed anything. Pretty easy to live without them, at least for me.
I'm not privy enough to the internals of the debugger team to really tell what is going on. But it doesn't look that good, VS2017 added some new nasty failure modes with the new debugging engine collapsing into a pile of rubble at the worst possible time. Take these options at their face value, they surely exist because they know the latest versions are not up to snuff.
Update: as pointed out by Rand, this particular defect does appear to have been addressed. I'm seeing correct behavior in version 15.9.3.
Bug got fixed in Visual Studio 2019:
https://developercommunity.visualstudio.com/content/problem/216341/compiler-doesnt-recognise-property-in-generic-if-d.html
Comment by Ivan Basov [MSFT]:
It seems that the issue is not reproducible in the current Visual
Studio. I tried it with VS 2019 Preview 2. The scenario works fine.
Thank you for your feedback!
Also tried to reproduce it on my Preview Version 1.1 and it is fixed there aswell.
Gave the latest Version of Visual Studio 2017 (15.9.5) a try aswell and can report it got fixed there aswell.
Why does the code below crash the .NET compiler? It was tested on csc.exe version 4.0.
See e.g. here for online demo on different version - it crashes in the same manner while it says dynamic is not supported https://dotnetfiddle.net/FMn59S:
Compilation error (line 0, col 0): Internal Compiler Error (0xc0000005 at address xy): likely culprit is 'TRANSFORM'.
The extension method works fine on List<dynamic> though.
using System;
using System.Collections.Generic;
static class F {
public static void M<T>(this IEnumerable<T> enumeration, Action<T> action){}
static void U(C.K d) {
d.M(kvp => Console.WriteLine(kvp));
}
}
class C {
public class K : Dictionary<string, dynamic>{}
}
Update: this doesn't crash the compiler
static void U(Dictionary<string, dynamic> d)
{
d.M(kvp => Console.WriteLine(kvp));
}
Update 2: the same bug was reported in http://connect.microsoft.com/VisualStudio/feedback/details/892372/compiler-error-with-dynamic-dictinoaries. The bug was reported for FirstOrDefault, but it seems the compiler crashes on any extension method applied to class derived from Dictionary<T1,T2>, where at least one of the parameter types is dynamic. See an even more general description of the problem below by Erik Funkenbusch.
Update 3: another non-standard behaviour. When I try to call extension method as a static method, that is, F.M(d, kvp => Console.WriteLine(kvp));, the compiler doesn't crash, but it cannot find the overload:
Argument 1: cannot convert from 'C.K' to 'System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string,dynamic>>'
Update 4 - SOLUTION (kind of): Hans sketched 2nd workaround, which is semantically equivalent to original code, but works only for extension method call and not for standard call. Since the bug is likely caused by the fact that the compiler fails to cast class derived from generic class with multiple parameters (with one being dynamic) to its supertype, the solution is to provide an explicit cast. See https://dotnetfiddle.net/oNvlcL:
((Dictionary<string, dynamic>)d).M(kvp => Console.WriteLine(kvp));
M((Dictionary<string, dynamic>)d, kvp => Console.WriteLine(kvp));
It is dynamic that is triggering the instability, the crash disappears when you replace it by object.
Which is one workaround, the other is to help it infer the correct T:
static void U(C.K d) {
d.M(new Action<KeyValuePair<string, dynamic>>(kvp => Console.WriteLine(kvp)));
}
The feedback report that you found is a strong match, no need to file your own I'd say.
Well, the answer to your question as to WHY it crashes the compiler, it's because you've encountered a bug that.... crashes the compiler.
The VS2013 compiler says "Internal Compiler Error (0xc0000005 at address 012DC5B5): likely culprit is 'TRANSFORM'", so clearly it's a bug.
C0000005 is typically a null pointer, or referencing unallocated, or deleted memory. It's a general protection fault.
EDIT:
The problem is also present in pretty much any kind of multiple parameter generic type where the any parameter is dynamic. For instance it crashes on:
List<Tuple<string, dynamic>>{}
It also crashes on
List<KeyValuePair<dynamic, string>>{}
But does not crash on
List<dynamic>{}
but does crash on
List<List<dynamic>>{}
① In following C# code, CS1729 occurs but I understand that CS0122 would be more appropriate.
namespace A
{
class Program
{
static void Main()
{
Test test = new Test(1);
}
}
class Test
{
Test(int i) { }
}
}
CS1729: 'A.Test' does not contain a constructor that takes 1 arguments
CS0122: 'A.Test.Test(int) is inaccessible due to its protection level'
② In following C# code, CS0122 occurs but I understand that CS1729 would be more appropriate
namespace A
{
class Program
{
static void Main()
{
Test test = new Test();
}
}
class Test
{
Test(int i) { }
}
}
CS0122: 'A.Test.Test(int) is inaccessible due to its protection level'
CS1729: 'A.Test' does not contain a constructor that takes 0 arguments
Question: Is there any reason why CS0122 and CS1729 are swapped in ① and ② or is this C# compiler bug ?
P.S.: Errors in ① and ② can be reproduced with Microsoft Visual C# 2010 Compiler version 4.030319.1.
Full disclosure: I work on the C# team at Microsoft.
Diagnostic reporting from a compiler is a tricky business! We spend a lot of time trying to ensure that the "best" diagnostic is reported for a particular error condition. However, this sometimes requires taking heuristics into account, and we don't always get that right. In this case, as #Henrik Holterman points out, both errors are reasonable (at least for the second case).
The first example is clearly a bug, though it's of low severity. After all, it's still an error with a somewhat "correct" (I'm being a bit gracious here) diagnostic. In the second example, both errors are correct, but the compiler failed to pick the "best", and hopefully, the most helpful diagnostic.
With the Roslyn C# compiler, we've had an opportunity to take a fresh look at our diagnostic reporting and make better choices. For these particular examples, the Roslyn compilers do in fact produce the errors that you were expecting. In the first example, CS0122 is reported, and in the second case, CS1729 is reported. So, you can rest assured that this is already fixed in a future release.
I've been learning design patterns and I saw such a method call from a class :
class Client: SubjectAccessor {
static void Main() {
Console.WriteLine("Proxy Pattern\n");
ISubject subject = new Proxy();
Console.WriteLine(subject.Requesy());
subject = new(); //Here is what I am asking
COnsole.WriteLine(subject.Request());
}
}
As you can see there is a subject = new(); call there and I am wondering whether it is creating a new instance of Proxy or something else. I've not found anything related to this.
Your help is much appreciated.
If you need, I can paste the whole code or actually it is written on a book so I need to write it down here.
Thanks.
It is a typo in the book. There is no current version of C# in which that is valid (it should raise a "Type expected" compiler error). Without context it is impossible to know what it should be.
AFAIK it's wrong, and that code won't even compile.
The new keyword in C# can have only the 3 meanings described in this link:
http://msdn.microsoft.com/en-us/library/51y09td4%28v=VS.80%29.aspx
I was the technical editor of that book; I have a copy right in front of me now. My copy says:
class Client : SubjectAccessor {
static void Main() {
Console.WriteLine("Proxy Pattern\n");
ISubject subject = new Proxy();
Console.WriteLine(subject.Request());
Console.WriteLine(subject.Request());
ProtectionProxy subject = new ProtectionProxy();
Console.WriteLine(subject.Request());
Now, there is an error here; the variable "subject" has been declared twice. Apparently I did not catch the error when I reviewed the book. (The correct thing to do here is to remove the type from the second declaration of "subject").
However, that is not the error that you are reporting.
Are you sure that is not what your copy says? I have the December 2007 first edition; what edition do you have? Perhaps someone attempted to correct this error in a later edition and messed it up? My guess would be that someone tried to correct the error by removing both mentions of the ProtectionProxy type from the erroneous line rather than removing the first one.
That would be the proxy class. never seen such syntax before tho. Best not to use such things as it will only reduce readability..
I can't see how that compiles. "new" in this context is the new operator and this always expects a typename per C# syntax.