PageRenderTime 25ms CodeModel.GetById 7ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs

http://github.com/icsharpcode/ILSpy
C# | 739 lines | 639 code | 55 blank | 45 comment | 0 complexity | 42f953389141299f3b84bf7a08de39f4 MD5 | raw file
  1// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
  2// 
  3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
  4// software and associated documentation files (the "Software"), to deal in the Software
  5// without restriction, including without limitation the rights to use, copy, modify, merge,
  6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
  7// to whom the Software is furnished to do so, subject to the following conditions:
  8// 
  9// The above copyright notice and this permission notice shall be included in all copies or
 10// substantial portions of the Software.
 11// 
 12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
 15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 17// DEALINGS IN THE SOFTWARE.
 18
 19using System;
 20using System.Linq;
 21using ICSharpCode.NRefactory.Semantics;
 22using ICSharpCode.NRefactory.TypeSystem;
 23using ICSharpCode.NRefactory.TypeSystem.Implementation;
 24using NUnit.Framework;
 25
 26namespace ICSharpCode.NRefactory.CSharp.Resolver
 27{
 28	[TestFixture]
 29	public class InvocationTests : ResolverTestBase
 30	{
 31		[Test]
 32		public void MethodCallTest()
 33		{
 34			string program = @"class A {
 35	void Method() {
 36		$TargetMethod()$;
 37	}
 38	
 39	int TargetMethod() {
 40		return 3;
 41	}
 42}
 43";
 44			InvocationResolveResult result = Resolve<CSharpInvocationResolveResult>(program);
 45			Assert.AreEqual("A.TargetMethod", result.Member.FullName);
 46			Assert.AreEqual("System.Int32", result.Type.ReflectionName);
 47		}
 48		
 49		[Test]
 50		public void InvalidMethodCall()
 51		{
 52			string program = @"class A {
 53	void Method(string b) {
 54		$b.ThisMethodDoesNotExistOnString(b)$;
 55	}
 56}
 57";
 58			UnknownMethodResolveResult result = Resolve<UnknownMethodResolveResult>(program);
 59			Assert.AreEqual("ThisMethodDoesNotExistOnString", result.MemberName);
 60			Assert.AreEqual("System.String", result.TargetType.FullName);
 61			Assert.AreEqual(1, result.Parameters.Count);
 62			Assert.AreEqual("b", result.Parameters[0].Name);
 63			Assert.AreEqual("System.String", result.Parameters[0].Type.ReflectionName);
 64			
 65			Assert.AreSame(SpecialType.UnknownType, result.Type);
 66		}
 67		
 68		[Test]
 69		public void OverriddenMethodCall()
 70		{
 71			string program = @"class A {
 72	void Method() {
 73		$new B().GetRandomNumber()$;
 74	}
 75	
 76	public abstract int GetRandomNumber();
 77}
 78class B : A {
 79	public override int GetRandomNumber() {
 80		return 4; // chosen by fair dice roll.
 81		          // guaranteed to be random
 82	}
 83}
 84";
 85			InvocationResolveResult result = Resolve<CSharpInvocationResolveResult>(program);
 86			Assert.AreEqual("B.GetRandomNumber", result.Member.FullName);
 87		}
 88		
 89		[Test]
 90		public void OverriddenMethodCall2()
 91		{
 92			string program = @"class A {
 93	void Method() {
 94		$new B().GetRandomNumber(""x"", this)$;
 95	}
 96	
 97	public abstract int GetRandomNumber(string a, A b);
 98}
 99class B : A {
100	public override int GetRandomNumber(string b, A a) {
101		return 4;
102	}
103}
104";
105			InvocationResolveResult result = Resolve<CSharpInvocationResolveResult>(program);
106			Assert.AreEqual("B.GetRandomNumber", result.Member.FullName);
107		}
108		
109		[Test]
110		public void ThisMethodCallTest()
111		{
112			string program = @"class A {
113	void Method() {
114		$this.TargetMethod()$;
115	}
116	
117	int TargetMethod() {
118		return 3;
119	}
120}
121";
122			InvocationResolveResult result = Resolve<CSharpInvocationResolveResult>(program);
123			Assert.AreEqual("A.TargetMethod", result.Member.FullName);
124			Assert.AreEqual("System.Int32", result.Type.ReflectionName);
125		}
126		
127		[Test]
128		public void VoidTest()
129		{
130			string program = @"using System;
131class A {
132	void TestMethod() {
133		$TestMethod()$;
134	}
135}
136";
137			Assert.AreEqual("System.Void", Resolve(program).Type.ReflectionName);
138		}
139		
140		[Test]
141		public void EventCallTest()
142		{
143			string program = @"using System;
144class A {
145	void Method() {
146		$TestEvent(this, EventArgs.Empty)$;
147	}
148	
149	public event EventHandler TestEvent;
150}
151";
152			Assert.AreEqual("System.Void", Resolve(program).Type.ReflectionName);
153		}
154		
155		[Test]
156		public void DelegateCallTest()
157		{
158			string program = @"using System; using System.Reflection;
159class A {
160	void Method(ModuleResolveEventHandler eh) {
161		$eh(this, new ResolveEventArgs())$;
162	}
163}
164";
165			Assert.AreEqual("System.Reflection.Module", Resolve(program).Type.ReflectionName);
166		}
167		
168		[Test]
169		public void DelegateReturnedFromMethodCallTest()
170		{
171			string program = @"using System;
172class A {
173	void Method() {
174		$GetHandler()(abc)$;
175	}
176	abstract Predicate<string> GetHandler();
177}
178";
179			Assert.AreEqual("System.Boolean", Resolve(program).Type.ReflectionName);
180		}
181		
182		/* TODO
183		[Test]
184		public void MethodGroupResolveTest()
185		{
186			string program = @"class A {
187	void Method() {
188		
189	}
190	
191	void TargetMethod(int a) { }
192	void TargetMethod<T>(T a) { }
193}
194";
195			MethodGroupResolveResult result = Resolve<MethodGroupResolveResult>(program, "TargetMethod", 3);
196			Assert.AreEqual("TargetMethod", result.Name);
197			Assert.AreEqual(2, result.Methods.Count);
198			
199			result = Resolve<MethodGroupResolveResult>(program, "TargetMethod<string>", 3);
200			Assert.AreEqual("TargetMethod", result.Name);
201			Assert.AreEqual(1, result.Methods[0].Count);
202			Assert.AreEqual("System.String", result.GetMethodIfSingleOverload().Parameters[0].ReturnType.FullyQualifiedName);
203		}
204		 */
205		
206		[Test]
207		public void TestOverloadingByRef()
208		{
209			string program = @"using System;
210class Program {
211	public static void Main() {
212		int a = 42;
213		T(a);
214		T(ref a);
215	}
216	static void T(int x) {}
217	static void T(ref int y) {}
218}";
219			
220			InvocationResolveResult mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("T(a)", "$T(a)$"));
221			Assert.IsFalse(mrr.Member.Parameters[0].IsRef);
222			
223			mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("T(ref a)", "$T(ref a)$"));
224			Assert.IsTrue(mrr.Member.Parameters[0].IsRef);
225		}
226		
227		[Test]
228		public void AddedOverload()
229		{
230			string program = @"class BaseClass {
231	static void Main(DerivedClass d) {
232		$d.Test(3)$;
233	}
234	public void Test(int a) { }
235}
236class DerivedClass : BaseClass {
237	public void Test(object a) { }
238}";
239			InvocationResolveResult mrr = Resolve<CSharpInvocationResolveResult>(program);
240			Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName);
241		}
242		
243		[Test]
244		public void AddedOverloadOnInterface()
245		{
246			string program = @"
247interface IBase { void Method(int a); }
248interface IDerived { void Method(object a); }
249class Test {
250	static void Main(IDerived d) {
251		$d.Method(3)$;
252	}
253}";
254			InvocationResolveResult mrr = Resolve<CSharpInvocationResolveResult>(program);
255			Assert.AreEqual("IDerived.Method", mrr.Member.FullName);
256		}
257		
258		[Test]
259		public void AddedNonApplicableOverload()
260		{
261			string program = @"class BaseClass {
262	static void Main(DerivedClass d) {
263		$d.Test(3)$;
264	}
265	public void Test(int a) { }
266}
267class DerivedClass : BaseClass {
268	public void Test(string a) { }
269}";
270			InvocationResolveResult mrr = Resolve<CSharpInvocationResolveResult>(program);
271			Assert.AreEqual("BaseClass.Test", mrr.Member.FullName);
272			
273			mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("(3)", "(\"3\")"));
274			Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName);
275		}
276		
277		[Test]
278		public void OverrideShadowed()
279		{
280			string program = @"using System;
281class BaseClass {
282	static void Main() {
283		$new DerivedClass().Test(3)$;
284	}
285	public virtual void Test(int a) { }
286}
287class MiddleClass : BaseClass {
288	public void Test(object a) { }
289}
290class DerivedClass : MiddleClass {
291	public override void Test(int a) { }
292}";
293			
294			InvocationResolveResult mrr = Resolve<CSharpInvocationResolveResult>(program);
295			Assert.AreEqual("MiddleClass.Test", mrr.Member.FullName);
296		}
297		
298		[Test]
299		public void SubstituteClassAndMethodTypeParametersAtOnce()
300		{
301			string program = @"class C<X> { static void M<T>(X a, T b) { $C<T>.M(b, a)$; } }";
302			var rr = Resolve<CSharpInvocationResolveResult>(program);
303			Assert.IsFalse(rr.IsError);
304			
305			var m = (SpecializedMethod)rr.Member;
306			Assert.AreEqual("X", m.TypeArguments.Single().Name);
307			Assert.AreEqual("T", m.Parameters[0].Type.Name);
308			Assert.AreEqual("X", m.Parameters[1].Type.Name);
309		}
310		
311		[Test]
312		public void MemberHiddenOnOneAccessPath()
313		{
314			// If a member is hidden in any access path, it is hidden in all access paths
315			string program = @"
316interface IBase { int F { get; } }
317interface ILeft: IBase { new int F { get; } }
318interface IRight: IBase { void G(); }
319interface IDerived: ILeft, IRight {}
320class A {
321   void Test(IDerived d) { var a = $d.F$; }
322}";
323			var rr = Resolve<MemberResolveResult>(program);
324			Assert.AreEqual("ILeft.F", rr.Member.FullName);
325		}
326		
327		[Test]
328		public void PropertyClashesWithMethod()
329		{
330			string program = @"
331interface IList { int Count { get; set; } }
332interface ICounter { void Count(int i); }
333interface IListCounter: IList, ICounter {}
334class A {
335 	void Test(IListCounter x) { var a = $x.Count$; }
336}";
337			var rr = Resolve<MethodGroupResolveResult>(program);
338			Assert.IsFalse(rr.IsError);
339			Assert.AreEqual("ICounter.Count", rr.Methods.Single().FullName);
340		}
341		
342		[Test]
343		public void OverloadAmbiguousWithMethodInTwoInterfaces()
344		{
345			string program = @"
346interface ILeft { void Method(); }
347interface IRight { void Method(); }
348interface IBoth : ILeft, IRight {}
349class A {
350 	void Test(IBoth x) { $x.Method()$; }
351}";
352			var rr = Resolve<CSharpInvocationResolveResult>(program);
353			Assert.IsTrue(rr.IsError);
354			Assert.AreEqual(OverloadResolutionErrors.AmbiguousMatch, rr.OverloadResolutionErrors);
355		}
356		
357		[Test]
358		public void AddedOverloadInOneInterfaceAndBetterOverloadInOtherInterface1()
359		{
360			string program = @"
361interface IBase { void Method(int x); }
362interface ILeft : IBase { void Method(object x); }
363interface IRight { void Method(int x); }
364interface IBoth : ILeft, IRight {}
365class A {
366 	void Test(IBoth x) { $x.Method(1)$; }
367}";
368			// IBase.Method is "hidden" because ILeft.Method is also applicable,
369			// so IRight.Method is unambiguously the chosen overload.
370			var rr = Resolve<CSharpInvocationResolveResult>(program);
371			Assert.IsFalse(rr.IsError);
372			Assert.AreEqual("IRight.Method", rr.Member.FullName);
373		}
374		
375		[Test]
376		public void AddedOverloadInOneInterfaceAndBetterOverloadInOtherInterface2()
377		{
378			// repeat the above test with Left/Right swapped to make sure we aren't order-sensitive
379			string program = @"
380interface IBase { void Method(int x); }
381interface ILeft : IBase { void Method(object x); }
382interface IRight { void Method(int x); }
383interface IBoth : IRight, ILeft {}
384class A {
385 	void Test(IBoth x) { $x.Method(1)$; }
386}";
387			var rr = Resolve<CSharpInvocationResolveResult>(program);
388			Assert.IsFalse(rr.IsError);
389			Assert.AreEqual("IRight.Method", rr.Member.FullName);
390		}
391		
392		[Test]
393		public void AddedOverloadHidesCommonBaseMethod_Generic1()
394		{
395			string program = @"
396interface IBase<T> {
397	void Method(int x);
398}
399interface ILeft : IBase<int> { void Method(object x); }
400interface IRight : IBase<int> { }
401interface IBoth : ILeft, IRight {}
402class A {
403	void Test(IBoth x) { $x.Method(1)$; }
404}";
405			var rr = Resolve<CSharpInvocationResolveResult>(program);
406			Assert.IsFalse(rr.IsError);
407			Assert.AreEqual("ILeft.Method", rr.Member.FullName);
408		}
409		
410		[Test]
411		public void AddedOverloadHidesCommonBaseMethod_Generic2()
412		{
413			string program = @"
414interface IBase<T> {
415	void Method(int x);
416}
417interface ILeft : IBase<int> { void Method(object x); }
418interface IRight : IBase<int> { }
419interface IBoth : ILeft, IRight {}
420class A {
421	void Test(IBoth x) { $x.Method(1)$; }
422}";
423			var rr = Resolve<CSharpInvocationResolveResult>(program);
424			Assert.IsFalse(rr.IsError);
425			Assert.AreEqual("ILeft.Method", rr.Member.FullName);
426		}
427		
428		[Test]
429		public void AddedOverloadDoesNotHideCommonBaseMethodWithDifferentTypeArgument1()
430		{
431			string program = @"
432interface IBase<T> {
433	void Method(int x);
434}
435interface ILeft : IBase<int> { void Method(object x); }
436interface IRight : IBase<long> { }
437interface IBoth : IRight, ILeft {}
438class A {
439	void Test(IBoth x) { $x.Method(1)$; }
440}";
441			var rr = Resolve<CSharpInvocationResolveResult>(program);
442			Assert.IsFalse(rr.IsError);
443			Assert.AreEqual("IBase`1[[System.Int64]]", rr.Member.DeclaringType.ReflectionName);
444		}
445		
446		[Test]
447		public void AddedOverloadDoesNotHideCommonBaseMethodWithDifferentTypeArgument2()
448		{
449			string program = @"
450interface IBase<T> {
451	void Method(int x);
452}
453interface ILeft : IBase<int> { void Method(object x); }
454interface IRight : IBase<long> { }
455interface IBoth : IRight, ILeft {}
456class A {
457	void Test(IBoth x) { $x.Method(1)$; }
458}";
459			var rr = Resolve<CSharpInvocationResolveResult>(program);
460			Assert.IsFalse(rr.IsError);
461			Assert.AreEqual("IBase`1[[System.Int64]]", rr.Member.DeclaringType.ReflectionName);
462		}
463		
464		[Test]
465		public void AmbiguityBetweenMemberAndMethodIsNotAnError()
466		{
467			string program = @"
468interface ILeft { void Method(object x); }
469interface IRight { Action<object> Method { get; } }
470interface IBoth : ILeft, IRight {}
471class A {
472	void Test(IBoth x) { $x.Method(null)$; }
473}";
474			var rr = Resolve<CSharpInvocationResolveResult>(program);
475			Assert.IsFalse(rr.IsError);
476			Assert.AreEqual("ILeft.Method", rr.Member.FullName);
477		}
478		
479		[Test]
480		public void AcceptVisitor()
481		{
482			string program = @"
483interface IVisitor<in T, out S> { }
484class Test : IVisitor<object, object> {
485	void M() {
486		$Accept(this, null)$;
487	}
488	S Accept<T, S>(IVisitor<T, S> v, T input) { }
489}";
490			var rr = Resolve<CSharpInvocationResolveResult>(program);
491			Assert.IsFalse(rr.IsError);
492			var typeArguments = ((SpecializedMethod)rr.Member).TypeArguments;
493			Assert.AreEqual("System.Object", typeArguments[0].ReflectionName);
494			Assert.AreEqual("System.Object", typeArguments[1].ReflectionName);
495		}
496		
497		[Test]
498		public void FirstParameterToExtensionMethod()
499		{
500			string program = @"
501public class X {}
502public static class Ex {
503	public static void F(this X x, int y, int z) {}
504}
505class C {
506	public void M() {
507		X a = null;
508		int b = 0, c = 0;
509		$a.F(b, c)$;
510	}
511}";
512			var rr = Resolve<CSharpInvocationResolveResult>(program);
513			Assert.IsFalse(rr.IsError);
514			Assert.That(rr.IsExtensionMethodInvocation, Is.True);
515			Assert.That(rr.Arguments[0], Is.InstanceOf<LocalResolveResult>());
516			Assert.That(((LocalResolveResult)rr.Arguments[0]).Variable.Name, Is.EqualTo("a"));
517			Assert.That(rr.Arguments[1], Is.InstanceOf<LocalResolveResult>());
518			Assert.That(((LocalResolveResult)rr.Arguments[1]).Variable.Name, Is.EqualTo("b"));
519			Assert.That(rr.Arguments[2], Is.InstanceOf<LocalResolveResult>());
520			Assert.That(((LocalResolveResult)rr.Arguments[2]).Variable.Name, Is.EqualTo("c"));
521			
522			Assert.That(rr.TargetResult, Is.InstanceOf<TypeResolveResult>());
523		}
524		
525		[Test]
526		public void BaseInvocation()
527		{
528			string program = @"
529class B {
530	public virtual void F(int x, int y) {}
531}
532class D : B {
533	public override void F(int x, int y) {}
534	public void M() {
535		$base.F(0, 1)$;
536	}
537}";
538			var rr = Resolve<CSharpInvocationResolveResult>(program);
539			Assert.IsFalse(rr.IsError);
540			Assert.IsFalse(rr.IsVirtualCall);
541		}
542		
543		[Test]
544		public void NamedArgument()
545		{
546			string program = @"
547class Test {
548	public void F(int x) {}
549	public void Test() {
550		F($x: 0$);
551	}
552}";
553			var narr = Resolve<NamedArgumentResolveResult>(program);
554			Assert.IsInstanceOf<ConstantResolveResult>(narr.Argument);
555			Assert.AreEqual("x", narr.ParameterName);
556			Assert.AreEqual("Test.F", narr.Member.FullName);
557			Assert.AreSame(narr.Member.Parameters.Single(), narr.Parameter);
558		}
559		
560		[Test]
561		public void NamedArgumentInInvocation()
562		{
563			string program = @"
564class Test {
565	public void F(int x) {}
566	public void Test() {
567		$F(x: 0)$;
568	}
569}";
570			var rr = Resolve<CSharpInvocationResolveResult>(program);
571			Assert.IsInstanceOf<NamedArgumentResolveResult>(rr.Arguments.Single());
572			var narr = (NamedArgumentResolveResult)rr.Arguments.Single();
573			Assert.IsInstanceOf<ConstantResolveResult>(narr.Argument);
574			Assert.AreEqual("x", narr.ParameterName);
575			Assert.AreEqual("Test.F", narr.Member.FullName);
576			Assert.AreSame(narr.Member.Parameters.Single(), narr.Parameter);
577			
578			// but GetArgumentsForCall() should directly return the constant:
579			Assert.IsInstanceOf<ConstantResolveResult>(rr.GetArgumentsForCall().Single());
580		}
581		
582		[Test]
583		public void UnknownNamedArgument()
584		{
585			string program = @"
586class Test {
587	public void F(int x) {}
588	public void Test() {
589		F($y: 0$);
590	}
591}";
592			var narr = Resolve<NamedArgumentResolveResult>(program);
593			Assert.IsInstanceOf<ConstantResolveResult>(narr.Argument);
594			Assert.AreEqual("y", narr.ParameterName);
595			Assert.IsNull(narr.Parameter);
596		}
597		
598		[Test]
599		public void NamedArgumentInMissingMethod()
600		{
601			string program = @"
602class Test {
603	public void Test() {
604		Missing($x: 0$);
605	}
606}";
607			var narr = Resolve<NamedArgumentResolveResult>(program);
608			Assert.IsInstanceOf<ConstantResolveResult>(narr.Argument);
609			Assert.AreEqual("x", narr.ParameterName);
610			Assert.IsNull(narr.Parameter);
611		}
612		
613		[Test]
614		public void GenericMethodInvocationWithConstraintMismatch()
615		{
616			string program = @"
617interface IA
618{
619}
620class Test
621{
622    void F()
623    {
624        string o = null;
625        $M(o)$;
626    }
627
628    void M<T>(T arg) where T : IA
629    {
630    }
631    void M(object arg) {
632	}
633}";
634			var rr = Resolve<CSharpInvocationResolveResult>(program);
635			Assert.AreEqual(OverloadResolutionErrors.MethodConstraintsNotSatisfied, rr.OverloadResolutionErrors);
636			Assert.IsTrue(rr.IsError);
637		}
638
639		[Test]
640		public void MethodCanBeInvokedWithNullableTypeArgument1() {
641			string program = @"
642public class C {
643	static T F<T>() {
644		return default(T);
645	}
646
647	void M() {
648		$F<int?>()$;
649	}
650}";
651
652			var rr = Resolve<CSharpInvocationResolveResult>(program);
653			Assert.IsFalse(rr.IsError);
654		}
655
656		[Test]
657		public void MethodCanBeInvokedWithNullableTypeArgument2() {
658			string program = @"
659public class C {
660	static T F<T>(T t) {
661		return default(T);
662	}
663
664	void M() {
665		$F((int?)null)$;
666	}
667}";
668
669			var rr = Resolve<CSharpInvocationResolveResult>(program);
670			Assert.IsFalse(rr.IsError);
671		}
672
673		[Test]
674		public void MethodCanBeInvokedWithNullableTypeArgument3() {
675			string program = @"
676public class C {
677	static T F<T, U>() where T : U {
678		return default(T);
679	}
680
681	void M() {
682		$F<int?, object>()$;
683	}
684}";
685
686			var rr = Resolve<CSharpInvocationResolveResult>(program);
687			Assert.IsFalse(rr.IsError);
688		}
689		
690		[Test]
691		public void MethodWithStructContraintCanBeInvokedWithValueType() {
692			string program = @"
693public class C {
694	static T F<T>() where T : struct {
695		return default(T);
696	}
697
698	void M() {
699		$F<int>()$;
700	}
701}";
702
703			var rr = Resolve<CSharpInvocationResolveResult>(program);
704			Assert.IsFalse(rr.IsError);
705		}
706		
707		[Test]
708		public void MethodWithStructContraintCannotBeInvokedWithNullableValueType() {
709			string program = @"
710public class C {
711	static T F<T>() where T : struct {
712		return default(T);
713	}
714
715	void M() {
716		$F<int?>()$;
717	}
718}";
719
720			var rr = Resolve<CSharpInvocationResolveResult>(program);
721			Assert.IsTrue(rr.IsError);
722			Assert.AreEqual(OverloadResolutionErrors.MethodConstraintsNotSatisfied, rr.OverloadResolutionErrors);
723		}
724		
725		[Test]
726		public void CanConstructGenericTypeWithNullableTypeArgument() {
727			string program = @"
728public class X<T> {}
729public class C {
730	void M() {
731		$new X<int?>()$;
732	}
733}";
734
735			var rr = Resolve<CSharpInvocationResolveResult>(program);
736			Assert.IsFalse(rr.IsError);
737		}
738	}
739}